|
|
@@ -0,0 +1,372 @@
|
|
|
+<template>
|
|
|
+ <el-dialog v-model="visible" title="实习信息变更" width="80%" :before-close="handleClose" draggable destroy-on-close>
|
|
|
+ <el-form ref="formRef" :model="form" :rules="rules" label-width="120px" class="form-container">
|
|
|
+ <el-row :gutter="24">
|
|
|
+ <!-- 变更原因 -->
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="form-section-title">变更信息</div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="变更原因" prop="changeReason">
|
|
|
+ <el-input
|
|
|
+ v-model="form.changeReason"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ placeholder="请输入实习信息变更的原因(必填)"
|
|
|
+ maxlength="500"
|
|
|
+ show-word-limit
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 基本信息 -->
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="form-section-title">新实习信息</div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="实习状态" prop="internshipStatus">
|
|
|
+ <el-select v-model="form.internshipStatus" placeholder="请选择实习状态" style="width: 100%">
|
|
|
+ <el-option label="进行中" value="1" />
|
|
|
+ <el-option label="已完成" value="2" />
|
|
|
+ <el-option label="中断" value="3" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 实习单位信息 -->
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="form-section-title">实习单位信息</div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="实习单位名称" prop="companyName">
|
|
|
+ <el-input v-model="form.companyName" placeholder="请输入实习单位名称" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="单位联系人" prop="companyContact">
|
|
|
+ <el-input v-model="form.companyContact" placeholder="请输入单位联系人" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="单位地址" prop="companyAddress">
|
|
|
+ <el-input v-model="form.companyAddress" placeholder="请输入单位地址" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="联系人电话" prop="companyPhone">
|
|
|
+ <el-input v-model="form.companyPhone" placeholder="请输入联系人电话" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="行业类型" prop="companyIndustry">
|
|
|
+ <el-input v-model="form.companyIndustry" placeholder="请输入行业类型" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="单位规模" prop="companyScale">
|
|
|
+ <el-select v-model="form.companyScale" placeholder="请选择单位规模" clearable style="width: 100%">
|
|
|
+ <el-option label="20人以下" value="1" />
|
|
|
+ <el-option label="20-99人" value="2" />
|
|
|
+ <el-option label="100-499人" value="3" />
|
|
|
+ <el-option label="500-999人" value="4" />
|
|
|
+ <el-option label="1000人以上" value="5" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 岗位信息 -->
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="form-section-title">岗位信息</div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="岗位名称" prop="positionName">
|
|
|
+ <el-input v-model="form.positionName" placeholder="请输入岗位名称" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="工作时长" prop="workHours">
|
|
|
+ <el-input v-model="form.workHours" placeholder="请输入工作时长,如:8小时/天" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="岗位职责" prop="positionDuties">
|
|
|
+ <el-input
|
|
|
+ v-model="form.positionDuties"
|
|
|
+ type="textarea"
|
|
|
+ :rows="2"
|
|
|
+ placeholder="请输入岗位职责"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="实习津贴" prop="internshipAllowance">
|
|
|
+ <el-input-number
|
|
|
+ v-model="form.internshipAllowance"
|
|
|
+ :min="0"
|
|
|
+ :precision="2"
|
|
|
+ controls-position="right"
|
|
|
+ placeholder="实习津贴"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 实习周期 -->
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="form-section-title">实习周期</div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="实习开始日期" prop="startDate">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="form.startDate"
|
|
|
+ type="date"
|
|
|
+ placeholder="选择开始日期"
|
|
|
+ style="width: 100%"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="实习结束日期" prop="endDate">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="form.endDate"
|
|
|
+ type="date"
|
|
|
+ placeholder="选择结束日期"
|
|
|
+ style="width: 100%"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 住宿信息 -->
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="form-section-title">住宿信息</div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="住宿地址" prop="accommodationAddress">
|
|
|
+ <el-input v-model="form.accommodationAddress" placeholder="请输入住宿地址" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="住宿类型" prop="accommodationType">
|
|
|
+ <el-select v-model="form.accommodationType" placeholder="请选择住宿类型" clearable style="width: 100%">
|
|
|
+ <el-option label="公司提供" value="1" />
|
|
|
+ <el-option label="自行租房" value="2" />
|
|
|
+ <el-option label="其他" value="3" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="住宿费用" prop="accommodationCost">
|
|
|
+ <el-input-number
|
|
|
+ v-model="form.accommodationCost"
|
|
|
+ :min="0"
|
|
|
+ :precision="2"
|
|
|
+ controls-position="right"
|
|
|
+ placeholder="住宿费用"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 备注 -->
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="备注" prop="remark">
|
|
|
+ <el-input
|
|
|
+ v-model="form.remark"
|
|
|
+ type="textarea"
|
|
|
+ :rows="2"
|
|
|
+ placeholder="请输入备注信息"
|
|
|
+ maxlength="500"
|
|
|
+ show-word-limit
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="handleClose">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="handleSubmit" :loading="submitLoading">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts" name="ChangeDialog">
|
|
|
+import { ref, watch, reactive } from 'vue';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import { changeInternshipInfo, getInternshipInfo } from '@/api/zsjy/internship';
|
|
|
+import type { InternshipInfoChangeBO, InternshipInfoVO } from '@/api/zsjy/types';
|
|
|
+import type { FormInstance, FormRules } from 'element-plus';
|
|
|
+
|
|
|
+// Props
|
|
|
+const props = defineProps<{
|
|
|
+ modelValue: boolean;
|
|
|
+ internshipId: string | number;
|
|
|
+ studentId: string | number;
|
|
|
+}>();
|
|
|
+
|
|
|
+// Emits
|
|
|
+const emit = defineEmits(['update:modelValue', 'success']);
|
|
|
+
|
|
|
+// 响应式数据
|
|
|
+const visible = ref(false);
|
|
|
+const submitLoading = ref(false);
|
|
|
+const formRef = ref<FormInstance>();
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const form = reactive<InternshipInfoChangeBO>({
|
|
|
+ internshipId: '',
|
|
|
+ studentId: '',
|
|
|
+ changeReason: '',
|
|
|
+ internshipStatus: '1',
|
|
|
+ companyName: '',
|
|
|
+ companyAddress: '',
|
|
|
+ companyContact: '',
|
|
|
+ companyPhone: '',
|
|
|
+ companyIndustry: '',
|
|
|
+ companyScale: '',
|
|
|
+ positionName: '',
|
|
|
+ positionDuties: '',
|
|
|
+ internshipAllowance: 0,
|
|
|
+ workHours: '',
|
|
|
+ accommodationAddress: '',
|
|
|
+ accommodationType: '',
|
|
|
+ accommodationCost: 0,
|
|
|
+ startDate: '',
|
|
|
+ endDate: '',
|
|
|
+ remark: ''
|
|
|
+});
|
|
|
+
|
|
|
+// 表单验证规则
|
|
|
+const rules = reactive<FormRules>({
|
|
|
+ changeReason: [
|
|
|
+ { required: true, message: '请输入变更原因', trigger: 'blur' },
|
|
|
+ { min: 10, max: 500, message: '变更原因长度应在10-500个字符之间', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ internshipStatus: [
|
|
|
+ { required: true, message: '请选择实习状态', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ companyName: [
|
|
|
+ { required: true, message: '请输入实习单位名称', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ companyAddress: [
|
|
|
+ { required: true, message: '请输入单位地址', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ companyContact: [
|
|
|
+ { required: true, message: '请输入单位联系人', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ companyPhone: [
|
|
|
+ { required: true, message: '请输入联系人电话', trigger: 'blur' },
|
|
|
+ { pattern: /^1[3-9]\d{9}$|^0\d{2,3}-?\d{7,8}$/, message: '请输入正确的电话号码', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ positionName: [
|
|
|
+ { required: true, message: '请输入岗位名称', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ startDate: [
|
|
|
+ { required: true, message: '请选择实习开始日期', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ endDate: [
|
|
|
+ { required: true, message: '请选择实习结束日期', trigger: 'change' }
|
|
|
+ ]
|
|
|
+});
|
|
|
+
|
|
|
+// 监听弹窗显示状态
|
|
|
+watch(() => props.modelValue, (val) => {
|
|
|
+ visible.value = val;
|
|
|
+ if (val) {
|
|
|
+ loadInternshipData();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+watch(visible, (val) => {
|
|
|
+ emit('update:modelValue', val);
|
|
|
+});
|
|
|
+
|
|
|
+// 加载实习信息数据
|
|
|
+const loadInternshipData = async () => {
|
|
|
+ try {
|
|
|
+ const { data } = await getInternshipInfo(props.studentId);
|
|
|
+ if (data) {
|
|
|
+ // 设置基础信息
|
|
|
+ form.internshipId = props.internshipId;
|
|
|
+ form.studentId = props.studentId;
|
|
|
+
|
|
|
+ // 预填充原实习信息(用户可以修改)
|
|
|
+ form.internshipStatus = data.internshipStatus || '1';
|
|
|
+ form.companyName = data.companyName || '';
|
|
|
+ form.companyAddress = data.companyAddress || '';
|
|
|
+ form.companyContact = data.contactPersonName || '';
|
|
|
+ form.companyPhone = data.contactPersonPhone || '';
|
|
|
+ form.companyIndustry = data.companyIndustry || '';
|
|
|
+ form.companyScale = data.companyScale || '';
|
|
|
+ form.positionName = data.internshipPosition || '';
|
|
|
+ form.positionDuties = data.positionDuties || '';
|
|
|
+ form.internshipAllowance = data.internshipAllowance || 0;
|
|
|
+ form.workHours = data.workHours || '';
|
|
|
+ form.accommodationAddress = data.accommodationAddress || '';
|
|
|
+ form.accommodationType = data.accommodationType || '';
|
|
|
+ form.accommodationCost = data.accommodationCost || 0;
|
|
|
+ form.startDate = data.internshipStartDate || '';
|
|
|
+ form.endDate = data.internshipEndDate || '';
|
|
|
+ form.remark = '';
|
|
|
+ form.changeReason = ''; // 变更原因必须重新填写
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载实习信息失败:', error);
|
|
|
+ ElMessage.error('加载实习信息失败');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 提交表单
|
|
|
+const handleSubmit = async () => {
|
|
|
+ if (!formRef.value) return;
|
|
|
+
|
|
|
+ await formRef.value.validate(async (valid) => {
|
|
|
+ if (valid) {
|
|
|
+ submitLoading.value = true;
|
|
|
+ try {
|
|
|
+ await changeInternshipInfo(form);
|
|
|
+ ElMessage.success('实习信息变更成功');
|
|
|
+ visible.value = false;
|
|
|
+ emit('success');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('实习信息变更失败:', error);
|
|
|
+ ElMessage.error('实习信息变更失败');
|
|
|
+ } finally {
|
|
|
+ submitLoading.value = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 关闭弹窗
|
|
|
+const handleClose = () => {
|
|
|
+ visible.value = false;
|
|
|
+ formRef.value?.resetFields();
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.form-container {
|
|
|
+ max-height: 60vh;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-right: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.form-section-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #303133;
|
|
|
+ border-left: 4px solid #409eff;
|
|
|
+ padding-left: 10px;
|
|
|
+ margin-bottom: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-footer {
|
|
|
+ text-align: right;
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|