Procházet zdrojové kódy

功能迭代和字段添加

songxy před 9 měsíci
rodič
revize
e62d4e5f9f

+ 85 - 0
client/src/utils/formValidate.ts

@@ -0,0 +1,85 @@
+interface IRuleField {
+  name: string
+  required?: boolean
+  message?: string
+}
+
+export class FormValidate {
+  private rules: IRuleField[] = []
+
+  constructor(rules: IRuleField[]) {
+    this.rules = rules
+  }
+
+  addRule(rule: IRuleField): void {
+    this.rules.push(rule)
+  }
+
+  removeRule(name: string): IRuleField | null {
+    let cRule: IRuleField | null = null
+    for (let i: number = 0; i < this.rules.length; i++) {
+      if (this.rules[i]['name'] === name) {
+        cRule = this.rules[i]
+        this.rules.splice(i, 1)
+        break
+      }
+    }
+    return cRule
+  }
+
+  validate(formData: any, callback: (state: boolean, rule: IRuleField) => void) {
+    const keys = Object.keys(formData)
+    for (let i = 0; i < keys.length; i++) {
+      const key = keys[i]
+      const rule = FormValidate.isArrayField(key, this.rules)
+      if (!rule) continue
+      callback && callback(FormValidate.isNotBlank(formData[key]), rule)
+    }
+  }
+
+  static validate(
+    formData: any,
+    rules: IRuleField[]
+  ): (callback: (state: boolean, rule: IRuleField | null) => void) => void {
+    return (callback: (state: boolean, rule: IRuleField | null) => void) => {
+      const keys = Object.keys(formData)
+      if (keys.length === 0 || rules.length === 0) {
+        callback(true, null)
+        return
+      }
+      for (let i = 0; i < keys.length; i++) {
+        const key = keys[i]
+        const rule = this.isArrayField(key, rules)
+        if (rule && !this.isNotBlank(formData[key])) {
+          callback && callback(false, rule)
+          break
+        }
+        if (i === keys.length - 1) {
+          callback(true, null)
+        }
+      }
+    }
+  }
+
+  static isNotBlank(val: any): boolean {
+    if (typeof val === 'string') {
+      if (val === null) return false
+      if (val === undefined) return false
+      if (val.trim() === '') return false
+    } else {
+      console.log(val)
+    }
+    return true
+  }
+
+  static isArrayField(key: string, rules: IRuleField[]): IRuleField | null {
+    let cRule: IRuleField | null = null
+    for (let i: number = 0; i < rules.length; i++) {
+      if (rules[i]['name'] === key) {
+        cRule = rules[i]
+        break
+      }
+    }
+    return cRule
+  }
+}

+ 1 - 1
client/src/views/OaSystem/personnelManagement/ygdaPage/SchoolTable.vue

@@ -2,7 +2,7 @@
   <div class="casually-name">
     <div class="star-title">
       <i></i>
-      <span>学习经历</span>
+      <span>学习经历(按照时间倒序填写)</span>
     </div>
     <el-tag class="add-tag" type="primary" effect="plain" v-if="!readOnly" @click="onAddItem()"
       >+ 新增</el-tag

+ 1 - 2
client/src/views/OaSystem/personnelManagement/ygdaPage/TechCertificate.vue

@@ -144,7 +144,7 @@ watch(
     tableData.value = newVal.map((item: any) => {
       return {
         ...item,
-        isEdit: false
+        isEdit: typeof item['isEdit'] === 'boolean' ? item['isEdit'] : false
       }
     })
   }
@@ -177,7 +177,6 @@ const onAddItem = () => {
 const onSaveItem = (item: ITable) => {
   item.isEdit = false
   const changeData = cloneDeep(tableData.value).map((item: any) => {
-    delete item.isEdit
     return item
   })
   $emit('onSave', changeData)

+ 39 - 5
client/src/views/OaSystem/personnelManagement/ygdaPage/WorkTable.vue

@@ -38,8 +38,12 @@
           </el-row>
           <el-row :gutter="66">
             <el-col :span="12">
-              <el-form-item label="离职原因">
-                <el-input v-model="item.resignReason" :disabled="!item.isEdit" />
+              <el-form-item label="工作单位">
+                <el-input
+                  placeholder="请输入单位名称"
+                  v-model="item.workLocation"
+                  :disabled="!item.isEdit"
+                />
               </el-form-item>
             </el-col>
             <el-col :span="12">
@@ -50,8 +54,8 @@
           </el-row>
           <el-row :gutter="66">
             <el-col :span="12">
-              <el-form-item label="单位名称">
-                <el-input v-model="item.workLocation" :disabled="!item.isEdit" />
+              <el-form-item label="离职原因">
+                <el-input v-model="item.resignReason" :disabled="!item.isEdit" />
               </el-form-item>
             </el-col>
             <el-col :span="12">
@@ -95,6 +99,7 @@
 /**
  * @description 工作经历
  */
+import { FormValidate } from '@/utils/formValidate'
 import { cloneDeep } from 'lodash-es'
 
 interface ITable {
@@ -163,9 +168,38 @@ const onAddItem = () => {
     isEdit: true
   })
 }
-
+const ruleFields = [
+  {
+    name: 'startTime',
+    message: '起始时间不能为空!'
+  },
+  {
+    name: 'endTime',
+    message: '终止时间不能为空!'
+  },
+  {
+    name: 'workLocation',
+    message: '工作单位!'
+  },
+  {
+    name: 'post',
+    message: '岗位!'
+  },
+  {
+    name: 'resignReason',
+    message: '离职原因不能为空!'
+  }
+]
 // 保存行
 const onSaveItem = (item: ITable) => {
+  // console.log(item)
+  // FormValidate.validate(
+  //   item,
+  //   ruleFields
+  // )((state, obj) => {
+  //   console.log(state)
+  //   console.log(obj)
+  // })
   item.isEdit = false
   const changeData = cloneDeep(tableData.value).map((item: any) => {
     return item

+ 32 - 2
client/src/views/OaSystem/personnelManagement/ygdaPage/index.ts

@@ -225,10 +225,21 @@ export const formConfigList = [
         type: 'time'
       },
       {
-        name: 'zzsj',
+        name: 'zdr',
+        sname: 'zdrmc',
+        title: '指导人',
+        type: 'user-select'
+      },
+      {
+        name: 'nzzsj',
         title: '拟转正时间',
         type: 'time'
       },
+      {
+        name: 'zzsj',
+        title: '转正时间',
+        type: 'time'
+      },
       {
         name: 'htqdsj',
         title: '合同签订时间',
@@ -244,7 +255,7 @@ export const formConfigList = [
         title: '续签次数'
       },
       {
-        name: 'xqnx',
+        name: 'sl',
         title: '司龄'
       }
     ]
@@ -262,6 +273,25 @@ export const formConfigList = [
       }
     ]
   },
+  {
+    title: '身份证信息',
+    children: [
+      {
+        name: 'cardid',
+        title: '证件号码'
+      },
+      {
+        name: 'sfzyxq',
+        type: 'time',
+        title: '有效期'
+      },
+      {
+        name: 'sfyj',
+        type: 'upload',
+        title: '上传附件'
+      }
+    ]
+  },
   // {
   //   title: '教育信息',
   //   children: [

+ 103 - 11
client/src/views/OaSystem/personnelManagement/ygdaPage/staffDetail.vue

@@ -10,9 +10,10 @@ import { getRecordsDetail, editRecordsDetail, generateStaffNum } from '@/api/oa/
 import { getConfigDict } from './index'
 import { ElRow, FormInstance } from 'element-plus'
 import moment from 'moment'
-// import TechCertificate from './TechCertificate.vue'
+import TechCertificate from './TechCertificate.vue'
 import avatarImg from '@/assets/imgs/avatar.jpg'
 import DeptSelect from '@/components/DeptSelect/index.vue'
+import UserOrgTree from '@/views/OaSystem/components/UserOrgTree/index.vue'
 import { createImageViewer } from '@/components/ImageViewer'
 import WorkTable from './WorkTable.vue'
 import FamilyTable from './familyTable.vue'
@@ -58,7 +59,10 @@ const handleTimeData = (dataSource) => {
   })
   return dataSource
 }
-
+const treeNodeClick = (item, type) => {
+  formData.value[type] = item['label']
+  console.log(formData.value)
+}
 /**编辑员工档案详情 */
 const { mutate: addUserMutate } = useMutation({
   mutationFn: async (values: any) => {
@@ -128,6 +132,27 @@ const isEdit = computed(() => {
   return type === 'edit'
 })
 
+// 上传路径
+const updateUrl =
+  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + import.meta.env.VITE_UPLOAD_URL
+
+// 回填正确路径
+const imageUrl = (url) => {
+  if (!url) return []
+  return url.split(',').map((item, index) => ({
+    url: item,
+    uid: index
+  }))
+}
+const getImgUrlList = (url) => {
+  if (!url) return []
+  return url.split(',')
+}
+// 附件上传成功
+const onUploadSuccess = (file: any, type: string) => {
+  const fileList = file.map((item) => item.url)
+  formData.value[type] = fileList.join(',')
+}
 // 修改并保存工作经历
 const saveWorkList = (data: any[]) => {
   // console.log('data', data)
@@ -148,6 +173,10 @@ const savePerformanceList = (data: any[]) => {
   // console.log('data', data)
   formData.value['performanceList'] = data.map((item) => ({ ...item, userId: id }))
 }
+//修改病保存职称证书
+const saveTechCertificateList = (data: any[]) => {
+  formData.value['certList'] = data.map((item) => ({ ...item, userId: id }))
+}
 </script>
 <template>
   <div class="staff-files-wrap">
@@ -238,13 +267,17 @@ const savePerformanceList = (data: any[]) => {
           <ul class="my-portrait-nav">
             <li @click="goAnchor('#gsxx')" :class="{ active: tabNav === '#gsxx' }">公司信息</li>
             <li @click="goAnchor('#gzkxx')" :class="{ active: tabNav === '#gzkxx' }">工资卡信息</li>
-            <li @click="goAnchor('#jjlxrxx')" :class="{ active: tabNav === '#jjlxrxx' }"
-              >紧急联系人信息</li
-            >
+            <li @click="goAnchor('#sfzxx')" :class="{ active: tabNav === '#sfzxx' }">
+              身份证信息
+            </li>
+            <li @click="goAnchor('#jjlxrxx')" :class="{ active: tabNav === '#jjlxrxx' }">
+              紧急联系人信息
+            </li>
             <li @click="goAnchor('#gzjl')" :class="{ active: tabNav === '#gzjl' }">工作经历</li>
             <li @click="goAnchor('#jtcy')" :class="{ active: tabNav === '#jtcy' }">家庭成员</li>
             <li @click="goAnchor('#xxjl')" :class="{ active: tabNav === '#xxjl' }">学习经历</li>
             <li @click="goAnchor('#jxkh')" :class="{ active: tabNav === '#jxkh' }">绩效考核</li>
+            <li @click="goAnchor('#zczs')" :class="{ active: tabNav === '#zczs' }">职称证书</li>
           </ul>
           <div class="my-portrait-container">
             <div class="my-portrait-item" id="gsxx">
@@ -266,12 +299,11 @@ const savePerformanceList = (data: any[]) => {
                         value-format="x"
                       />
 
-                      <DeptSelect
-                        v-if="child.type === 'dept-select'"
-                        v-model="formData['deptId']"
-                        :defaultValue="formData['deptId'] ?? ''"
+                      <UserOrgTree
+                        v-if="child.type === 'user-select'"
+                        v-model="formData[child?.name]"
+                        @node-click="(item) => treeNodeClick(item, child?.sname)"
                       />
-
                       <el-select
                         v-if="child.type === 'select'"
                         v-model="formData[child?.name]"
@@ -367,6 +399,59 @@ const savePerformanceList = (data: any[]) => {
                 </ul>
               </div>
             </div>
+            <div class="my-portrait-item" id="sfzxx">
+              <div class="title">
+                <i></i>
+                <span>身份证信息</span>
+              </div>
+              <div class="my-portrait-card">
+                <ul>
+                  <li v-for="(child, c) in formConfigList[3].children" :key="c">
+                    <el-form-item :label="`${child.title}:`" :prop="child.name">
+                      <template v-if="child.type === 'time'">
+                        <el-date-picker
+                          v-model="formData[child?.name]"
+                          style="width: 100%"
+                          :placeholder="isEdit ? child.title : ''"
+                          type="date"
+                          format="YYYY-MM-DD"
+                          value-format="x"
+                        />
+                      </template>
+                      <template v-else-if="child?.type === 'upload'">
+                        <UploadImgs
+                          v-if="isEdit"
+                          :modelValue="imageUrl(formData[child?.name])"
+                          :updateUrl="updateUrl"
+                          height="55px"
+                          :callback="(file) => onUploadSuccess(file, child?.name)"
+                        />
+                        <div v-else>
+                          <span
+                            style="margin-left: 3px"
+                            v-for="(item, index) in getImgUrlList(formData[child?.name])"
+                            :key="index"
+                          >
+                            <el-image
+                              style="width: 100px; height: 100px"
+                              :src="item"
+                              fit="scale-down"
+                              :preview-src-list="[item]"
+                            />
+                          </span>
+                        </div>
+                      </template>
+                      <el-input
+                        v-if="child?.type === undefined"
+                        v-model="formData[child?.name]"
+                        placeholder=""
+                      />
+                    </el-form-item>
+                  </li>
+                  <li></li>
+                </ul>
+              </div>
+            </div>
             <div class="my-portrait-item" id="jjlxrxx">
               <div class="title">
                 <i></i>
@@ -374,7 +459,7 @@ const savePerformanceList = (data: any[]) => {
               </div>
               <div class="my-portrait-card">
                 <ul>
-                  <li v-for="(child, c) in formConfigList[3].children" :key="c">
+                  <li v-for="(child, c) in formConfigList[4].children" :key="c">
                     <el-form-item :label="`${child.title}:`" :prop="child.name">
                       <el-date-picker
                         v-if="child.type === 'time'"
@@ -446,6 +531,13 @@ const savePerformanceList = (data: any[]) => {
                 :onlyRead="type == 'view'"
               />
             </div>
+            <div class="my-portrait-item" id="zczs">
+              <TechCertificate
+                :defaultData="formData['certList']"
+                @onSave="saveTechCertificateList"
+                :onlyRead="type == 'view'"
+              />
+            </div>
           </div>
         </div>
       </el-form>

+ 4 - 2
client/src/views/OaSystem/projectCenter/projectTrack/common.ts

@@ -94,11 +94,13 @@ export const infoList: any = reactive([
   {
     icon: 'xmzx/xmzcz',
     name: '项目总金额',
-    num: 0
+    num: 0,
+    unit: '万元'
   },
   {
     icon: 'xmzx/xmzlr',
     name: '项目总个数',
-    num: 0
+    num: 0,
+    unit: '个'
   }
 ])

+ 21 - 15
client/src/views/OaSystem/projectCenter/projectTrack/index.vue

@@ -31,7 +31,7 @@
         <li v-for="(item, index) in infoList" :key="index" class="mr-40px">
           <img class="mr-8px" :src="getAssetURL(item.icon)" alt="" />
           <p>{{ item.name }}:</p>
-          <h4 class="font-size-18px" v-money:unit="item.num"></h4>
+          <h4 class="font-size-18px">{{ item.num }}{{ item.unit }}</h4>
         </li>
       </ul>
     </div>
@@ -51,34 +51,44 @@
           <el-table-column label="序号" width="80">
             <template #default="scope">{{ scope.$index + 1 }}</template>
           </el-table-column>
+          <el-table-column prop="xzqmc" label="行政区" width="180" :show-overflow-tooltip="true" />
           <el-table-column
             :show-overflow-tooltip="true"
             prop="xmmc"
             label="项目名称"
             :min-width="220"
           />
-          <el-table-column prop="sfjc" label="是否进场" width="140">
+          <el-table-column prop="sfjc" label="是否进场" width="120">
             <template #default="scope">
               {{ scope.row.sfjc == '0' ? '是' : '否' }}
             </template>
           </el-table-column>
-          <el-table-column prop="gzry" label="跟踪人员" width="140" />
+          <el-table-column prop="gzry" label="跟踪人员" width="120" />
           <el-table-column
             prop="ygje"
             label="预估金额(万元)"
             :show-overflow-tooltip="true"
-            width="200"
+            width="160"
           />
           <el-table-column
             prop="zbje"
             label="中标金额(万元)"
             :show-overflow-tooltip="true"
-            width="200"
+            width="160"
+          />
+          <el-table-column prop="jf" label="甲方" width="220" :show-overflow-tooltip="true" />
+          <el-table-column
+            prop="jfdjr"
+            label="甲方对接人"
+            width="120"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column
+            prop="xmbm"
+            label="项目归属部门"
+            width="160"
+            :show-overflow-tooltip="true"
           />
-          <el-table-column prop="jf" label="甲方" width="120" />
-          <el-table-column prop="jfdjr" label="甲方对接人" width="120" />
-          <el-table-column prop="xmbm" label="项目归属部门" width="120" />
-          <el-table-column prop="xzqmc" label="行政区" width="180" />
           <el-table-column prop="zt" label="状态" width="120">
             <template #default="scope">
               {{ getDictLabel(DICT_TYPE.TRACKING_PROJECT_STATE, scope.row.zt) }}
@@ -89,7 +99,7 @@
               {{ formatDate(scope.row.latestModifyTime) }}
             </template>
           </el-table-column>
-          <el-table-column prop="xmjl" label="开关" width="120">
+          <el-table-column prop="xmjl" label="开关" width="100">
             <template #default="scope">
               <el-switch
                 v-model="scope.row.status"
@@ -102,11 +112,7 @@
 
           <el-table-column label="操作" width="80" fixed="right">
             <template #default="scope">
-              <div
-                class="operateBtn"
-                @click="addOrEditHandle(scope.row)"
-                v-if="scope.row.gzryId === user.user.id"
-              >
+              <div class="operateBtn" @click="addOrEditHandle(scope.row)">
                 <span>编辑</span>
               </div>
             </template>