Explorar o código

专家库调整

yanghao hai 6 días
pai
achega
fee050fb3a
Modificáronse 1 ficheiros con 129 adicións e 54 borrados
  1. 129 54
      src/views/expert/list/index.vue

+ 129 - 54
src/views/expert/list/index.vue

@@ -321,60 +321,59 @@
         :rules="formRules"
         v-loading="formLoading"
         label-width="auto"
+        require-asterisk
       >
         <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="部门" prop="deptId">
-              <el-tree-select
-                clearable
-                v-model="formData.deptId"
-                :data="deptList2"
-                :props="defaultProps"
-                :check-strictly="false"
-                node-key="id"
-                filterable
-                placeholder="请选择所在部门"
-              />
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="12">
-            <el-form-item label="专家姓名" prop="expertName">
-              <el-input v-model="formData.expertName" placeholder="请输入专家姓名" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="专家序列" prop="expertRank">
-              <el-select
-                multiple
-                v-model="formData.expertRank"
-                placeholder="请选择专家序列"
-                clearable
+          <el-form-item label="序列" prop="rankEchelonMappings">
+            <div class="rank-echelons">
+              <div
+                v-for="(mapping, index) in formData.rankEchelonMappings"
+                :key="index"
+                class="rank-echelon-row"
               >
-                <el-option
-                  v-for="dict in getStrDictOptions(DICT_TYPE.RD_EXPERT_RANK)"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="Number(dict.value)"
-                />
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="专家梯队" prop="echelon">
-              <el-select v-model="formData.echelon" placeholder="请选择专家梯队" clearable>
-                <el-option
-                  v-for="dict in getStrDictOptions(DICT_TYPE.RD_EXPERT_ECHELON)"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="dict.value"
-                />
-              </el-select>
-            </el-form-item>
-          </el-col>
+                <el-select
+                  style="width: 335px"
+                  v-model="mapping.expertRank"
+                  placeholder="请选择专家序列"
+                  clearable
+                >
+                  <el-option
+                    v-for="dict in getStrDictOptions(DICT_TYPE.RD_EXPERT_RANK)"
+                    :key="dict.value"
+                    :label="dict.label"
+                    :value="Number(dict.value)"
+                  />
+                </el-select>
+                <span class="rank-echelon-arrow" style="padding-left: 20px">选择对应梯队</span>
+                <el-select
+                  v-model="mapping.echelon"
+                  placeholder="请选择专家梯队"
+                  clearable
+                  style="width: 325px"
+                  class="rank-echelon-select"
+                >
+                  <el-option
+                    v-for="dict in getStrDictOptions(DICT_TYPE.RD_EXPERT_ECHELON)"
+                    :key="dict.value"
+                    :label="dict.label"
+                    :value="dict.value"
+                  />
+                </el-select>
+                <el-button
+                  v-if="formData.rankEchelonMappings.length > 1"
+                  type="danger"
+                  link
+                  class="rank-echelon-remove"
+                  @click="removeRankEchelonMapping(index)"
+                >
+                  删除
+                </el-button>
+              </div>
+              <el-button type="primary" link @click="addRankEchelonMapping">
+                <Icon icon="ep:plus" class="mr-5px" />添加序列
+              </el-button>
+            </div>
+          </el-form-item>
         </el-row>
 
         <el-row :gutter="20">
@@ -598,6 +597,7 @@ const defaultFormData = () => ({
   expertName: '',
   achievement: '',
   echelon: '',
+  rankEchelonMappings: [{ expertRank: undefined, echelon: '' }],
   education: '',
   specialDirection: [],
   softwareSkills: [],
@@ -641,7 +641,20 @@ const currentExpertDetail = ref<any>(null)
 const formRules = {
   expertName: [{ required: true, message: '请输入专家名称', trigger: 'blur' }],
   // achievement: [{ required: true, message: '请输入成果', trigger: 'blur' }],
-  echelon: [{ required: true, message: '请选择专家层级', trigger: 'blur' }],
+  rankEchelonMappings: [
+    {
+      required: true,
+      validator: (
+        _rule: any,
+        value: Array<{ expertRank?: number; echelon?: string }>,
+        callback: any
+      ) => {
+        const valid = value?.length > 0 && value.every((item) => item.expertRank && item.echelon)
+        callback(valid ? undefined : new Error('请完整选择序列和梯队'))
+      },
+      trigger: 'change'
+    }
+  ],
   education: [{ required: true, message: '请选择专家学历', trigger: 'blur' }],
   specialDirection: [{ required: true, message: '请选择专业方向', trigger: 'blur' }],
   // softwareSkills: [{ required: true, message: '请选择专业软件技能', trigger: 'blur' }],
@@ -649,11 +662,10 @@ const formRules = {
   // school: [{ required: true, message: '请输入毕业院校', trigger: 'blur' }],
   // birthday: [{ required: true, message: '请选择出生日期', trigger: 'blur' }],
   // avatar: [{ required: true, message: '请上传头像', trigger: 'blur' }],
-  deptId: [{ required: true, message: '请选择部门', trigger: 'blur' }],
+  deptId: [{ required: true, message: '请选择部门', trigger: 'blur' }]
   // formerPost: [{ required: true, message: '请输入历任岗位', trigger: 'blur' }],
   // jobTitle: [{ required: true, message: '请输入岗位', trigger: 'blur' }],
   // professionalTitle: [{ required: true, message: '请输入职称', trigger: 'blur' }],
-  expertRank: [{ required: true, message: '请选择专家序列', trigger: 'blur' }]
 }
 
 // 重置表单
@@ -676,6 +688,32 @@ const fillTeamSelection = (teams: any[] = []) => {
   tempSelectedTeamMap.value = Object.fromEntries(teams.map((team) => [team.id, team]))
 }
 
+const addRankEchelonMapping = () => {
+  formData.value.rankEchelonMappings.push({ expertRank: undefined, echelon: '' })
+}
+
+const removeRankEchelonMapping = (index: number) => {
+  if (formData.value.rankEchelonMappings.length <= 1) return
+  formData.value.rankEchelonMappings.splice(index, 1)
+}
+
+const getRankEchelonMappings = (detail: any) => {
+  if (detail?.rankEchelonMappings?.length) {
+    return detail.rankEchelonMappings.map((item: any) => ({
+      expertRank: Number(item.expertRank),
+      echelon: item.echelon || ''
+    }))
+  }
+
+  const expertRanks = detail?.expertRank || []
+  return expertRanks.length
+    ? expertRanks.map((expertRank: number) => ({
+        expertRank: Number(expertRank),
+        echelon: detail?.echelon || ''
+      }))
+    : [{ expertRank: undefined, echelon: detail?.echelon || '' }]
+}
+
 const buildFormDataFromExpertDetail = (detail: any) => {
   const teams = detail?.teams || []
   fillTeamSelection(teams)
@@ -684,6 +722,7 @@ const buildFormDataFromExpertDetail = (detail: any) => {
     expertName: detail?.expertName || '',
     achievement: detail?.achievement || '',
     echelon: detail?.echelon || '',
+    rankEchelonMappings: getRankEchelonMappings(detail),
     education: detail?.education || '',
     specialDirection: detail?.specialDirection || [],
     softwareSkills: detail?.softwareSkills || [],
@@ -1199,8 +1238,14 @@ const submitExpertForm = async () => {
 
   submitLoading.value = true
   try {
+    const rankEchelonMappings = formData.value.rankEchelonMappings.filter(
+      (item) => item.expertRank && item.echelon
+    )
     const payload = {
       ...formData.value,
+      expertRank: rankEchelonMappings.map((item) => item.expertRank),
+      echelon: rankEchelonMappings[0]?.echelon || '',
+      rankEchelonMappings,
       avatar:
         typeof formData.value.avatar === 'string'
           ? formData.value.avatar
@@ -1278,6 +1323,36 @@ onMounted(async () => {
   flex: 1;
 }
 
+.rank-echelons {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  gap: 10px;
+  width: 100%;
+}
+
+.rank-echelon-row {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  width: 100%;
+}
+
+.rank-echelon-select {
+  flex: 1;
+  min-width: 0;
+}
+
+.rank-echelon-arrow {
+  flex: 0 0 auto;
+  color: #7a8a89;
+  font-size: 13px;
+}
+
+.rank-echelon-remove {
+  flex: 0 0 auto;
+}
+
 .team-picker-table-wrap {
   margin-top: 8px;
   // margin-bottom: 12px;