Эх сурвалжийг харах

Merge branch 'master' of http://git.qmth.com.cn/sop/web

刘洋 1 жил өмнө
parent
commit
85b38e01dc
22 өөрчлөгдсөн 336 нэмэгдсэн , 157 устгасан
  1. 18 14
      src/api/resource-guard.js
  2. 4 0
      src/api/user.js
  3. 1 1
      src/components/common/select-area/index.vue
  4. 4 0
      src/components/global/search-form/components/search-form-item.vue
  5. 20 0
      src/hooks/useAuthenRole.js
  6. 0 1
      src/utils/filter.js
  7. 0 1
      src/views/project-quality/project-quality-manage/issues-feedback/index.vue
  8. 75 26
      src/views/resource-guard/person-guard/person-allocate/index.vue
  9. 127 51
      src/views/resource-guard/person-guard/person-allocate/person-deploy-dialog.vue
  10. 47 33
      src/views/resource-guard/person-guard/person-files/add-person-file-dialog.vue
  11. 9 15
      src/views/resource-guard/person-guard/person-files/index.vue
  12. 0 1
      src/views/service-unit/dispatch/dispatch-manage/index.vue
  13. 0 1
      src/views/service-unit/service-unit-manage/add-range/index.vue
  14. 0 1
      src/views/sop/sop-manage/device-out-in/index.vue
  15. 0 1
      src/views/sop/sop-manage/office-sop/index.vue
  16. 0 1
      src/views/sop/sop-manage/project-change-report/index.vue
  17. 0 1
      src/views/sop/sop-manage/student-sop/index.vue
  18. 29 6
      src/views/system/config-manage/service-level-manage/edit-service-level-dialog.vue
  19. 1 0
      src/views/system/config-manage/supplier-manage/edit-supplier-dialog.vue
  20. 1 1
      src/views/system/notice-log/notice-manage/index.vue
  21. 0 1
      src/views/work-hours/work-hours-manage/abnormal-check/wait-check.vue
  22. 0 1
      src/views/work-hours/work-hours-manage/work-attendance/index.vue

+ 18 - 14
src/api/resource-guard.js

@@ -28,44 +28,48 @@ export const personFilesDestroyApi = (ids) =>
     paramsSerializer,
   });
 
-export const personFilesExportApi = (ids) =>
+export const personFilesExportApi = (data) =>
   request({
     url: '/api/admin/user/archives/export',
     params: data,
-    download: true,
   });
 
 // person-allocate
 export const personAllocateListApi = (data) =>
   request({
-    url: '/api/system/person-allocate/list',
+    url: '/api/admin/user/archives/allocation/page',
     params: data,
   });
 export const personAllocateStatisticsApi = (data) =>
   request({
-    url: '/api/system/person-allocate/statistics',
+    url: '/api/admin/user/archives/allocation/sub_total',
     params: data,
   });
-export const personAllocateBatchDeployApi = (ids) =>
+export const personAllocateBatchDeployApi = (serviceUnitId) =>
   request({
-    url: '/api/system/person-allocate/batch-deploy',
-    params: { ids },
+    url: '/api/admin/user/archives/allocation/auto_edit',
+    params: { serviceUnitId },
     paramsSerializer,
   });
+export const personAllocateRoleDetailApi = (crmNo) =>
+  request({
+    url: '/api/admin/user/archives/allocation/detail_by_crm_no',
+    params: { crmNo },
+  });
 export const personAllocateDeployApi = (data) =>
   request({
-    url: '/api/system/person-allocate/deploy',
+    url: '/api/admin/user/archives/allocation/edit',
     data,
   });
-export const personAllocateSubmitSopApi = (id) =>
+export const personAllocateSubmitSopApi = (crmNo) =>
   request({
-    url: '/api/system/person-allocate/submit-sop',
-    param: { id },
+    url: '/api/admin/user/archives/allocation/publish',
+    param: { crmNo },
   });
-export const personAllocateCancelSubmitSopApi = (id) =>
+export const personAllocateCancelSubmitSopApi = (crmNo) =>
   request({
-    url: '/api/system/person-allocate/cancel-submit-sop',
-    param: { id },
+    url: '/api/admin/user/archives/allocation/un_publish',
+    param: { crmNo },
   });
 
 // registration-query

+ 4 - 0
src/api/user.js

@@ -123,4 +123,8 @@ export const fileUploadApi = (data) =>
   request({
     url: '/api/admin/common/file/upload',
     data,
+    headers: {
+      'Content-Type': 'multipart/form-data',
+      'md5': data.get('md5'),
+    },
   });

+ 1 - 1
src/components/common/select-area/index.vue

@@ -24,7 +24,7 @@ const props = defineProps({
   clearable: { type: Boolean, default: true },
   disabled: { type: Boolean, default: false },
   placeholder: { type: String, default: '请选择' },
-  valueType: { type: String, default: 'single' },
+  valueType: { type: String, default: 'single' }, // full/single
 });
 
 let options = [];

+ 4 - 0
src/components/global/search-form/components/search-form-item.vue

@@ -35,6 +35,10 @@
   <template v-if="item.type == undefined || item.type == 'text'">
     <t-input v-model="params[item.prop]" v-bind="attrs" />
   </template>
+  <!-- 数字 -->
+  <template v-if="item.type == 'number'">
+    <t-input-number v-model="params[item.prop]" v-bind="attrs" />
+  </template>
   <!-- 下拉选择框 -->
   <template v-if="item.type == 'select' || item.type == 'multipleSelect'">
     <t-select

+ 20 - 0
src/hooks/useAuthenRole.js

@@ -0,0 +1,20 @@
+import { ref } from 'vue';
+import { getAllRoleList } from '@/api/user';
+import { AUTHENTICATION_ROLE } from '@/config/constants';
+
+export default function useAuthenRole() {
+  const roleList = ref([]);
+
+  const getRoleList = async () => {
+    if (roleList.value.length) return;
+    const res = await getAllRoleList().catch(() => {});
+    if (!res) return;
+    const validTypes = Object.keys(AUTHENTICATION_ROLE);
+    roleList.value = res.filter((item) => validTypes.includes(item.type));
+  };
+
+  return {
+    roleList,
+    getRoleList,
+  };
+}

+ 0 - 1
src/utils/filter.js

@@ -38,7 +38,6 @@ export function timestampFilter(val) {
   return val ? dateFormat(val) : DEFAULT_FIELD;
 }
 export function dayCountFilter(val) {
-  console.log(val);
   return Math.ceil(val / (24 * 60 * 60 * 1000));
 }
 // 系统管理

+ 0 - 1
src/views/project-quality/project-quality-manage/issues-feedback/index.vue

@@ -28,7 +28,6 @@
           current: pagination.pageNumber,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
         <template #type="{ col, row }">

+ 75 - 26
src/views/resource-guard/person-guard/person-allocate/index.vue

@@ -4,25 +4,32 @@
       <template #service="{ item, params }">
         <select-service-unit v-model="params[item.prop]"></select-service-unit>
       </template>
-      <template #city>
-        <select-area v-model="areaInfo" @change="areaChange"></select-area>
+      <template #area>
+        <select-area
+          v-model="areaInfo"
+          value-type="full"
+          @change="areaChange"
+        ></select-area>
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">
       <div class="flex justify-between items-center">
         <t-space>
-          <span>已发布派单:{{ statisticsInfo.a }}</span>
           <span
-            >实施工程师配额:{{ statisticsInfo.b }} /
-            {{ statisticsInfo.b }}</span
+            >已发布派单:{{ statisticsInfo.publishedCrmCount }} /
+            {{ statisticsInfo.totalCrmCount }}</span
           >
           <span
-            >助理工程师配额:{{ statisticsInfo.c }}/
-            {{ statisticsInfo.b }}</span
+            >实施工程师配额:{{ statisticsInfo.effectDistributed }} /
+            {{ statisticsInfo.effectQuota }}</span
           >
           <span
-            >区域协调人配额:{{ statisticsInfo.d }} /
-            {{ statisticsInfo.b }}</span
+            >助理工程师配额:{{ statisticsInfo.assistantDistributed }}/
+            {{ statisticsInfo.assistantQuota }}</span
+          >
+          <span
+            >区域协调人配额:{{ statisticsInfo.coordinatorDistributed }} /
+            {{ statisticsInfo.coordinatorQuota }}</span
           >
         </t-space>
         <div class="btn-group">
@@ -36,7 +43,7 @@
       </div>
       <t-table
         size="small"
-        row-key="id"
+        row-key="crmId"
         :columns="columns"
         :data="tableData"
         bordered
@@ -48,21 +55,29 @@
           current: pagination.pageNumber,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
-        <template #custom-type="col, row">
+        <template #custom-type="{ col, row }">
           {{ customerTypeFilter(row[col.colKey]) }}
         </template>
+        <template #roles="{ row }">
+          {{ rolesFilter(row) }}
+        </template>
         <template #operate="{ row }">
           <div class="table-operations">
             <t-link theme="primary" hover="color" @click="handleDeploy(row)">
               调配
             </t-link>
-            <t-link theme="primary" hover="color" @click="handleSubmitSop(row)">
+            <t-link
+              v-if="!row.publish"
+              theme="primary"
+              hover="color"
+              @click="handleSubmitSop(row)"
+            >
               发布SOP
             </t-link>
             <t-link
+              v-if="row.publish"
               theme="danger"
               hover="color"
               @click="handleCancelSubmitSop(row)"
@@ -104,7 +119,7 @@ let areaInfo = ref(['', '', '']);
 let statisticsInfo = ref({});
 const getStatisticsInfo = async () => {
   const res = await personAllocateStatisticsApi(params);
-  statisticsInfo = res || {};
+  statisticsInfo.value = res || {};
 };
 
 const selectedRowKeys = ref([]);
@@ -130,17 +145,24 @@ const fields = ref([
     cell: 'area',
   },
   {
-    prop: 'costomer',
+    prop: 'customName',
     label: '客户名称',
     labelWidth: 100,
     colSpan: 4,
   },
   {
-    prop: 'count',
+    prop: 'gap',
     label: '分配差额≤',
     labelWidth: 100,
     colSpan: 4,
     type: 'number',
+    attrs: {
+      theme: 'column',
+      decimalPlaces: 0,
+      max: 1000000,
+      min: 0,
+      style: 'width: 100%',
+    },
   },
   {
     type: 'buttons',
@@ -163,8 +185,8 @@ const params = reactive({
   province: '',
   city: '',
   area: '',
-  costomer: '',
-  count: '',
+  customName: '',
+  gap: null,
 });
 
 const columns = [
@@ -176,16 +198,16 @@ const columns = [
   },
   { colKey: 'serviceUnitName', title: '服务单元' },
   { colKey: 'crmNo', title: '项目单号' },
-  { colKey: 'custom', title: '客户名称' },
+  { colKey: 'customName', title: '客户名称' },
   { colKey: 'customType', title: '客户类型', cell: 'custom-type', width: 100 },
   { colKey: 'province', title: '省份' },
   { colKey: 'city', title: '城市' },
   { colKey: 'area', title: '区县' },
   { colKey: 'level', title: '服务挡位' },
-  { colKey: 'roleList', title: '项目角色配置', minWidth: 140 },
-  { colKey: 'j', title: '配额(人)', width: 80 },
-  { colKey: 'k', title: '已分配(人)', width: 100 },
-  { colKey: 'l', title: '分配差额(人)', width: 120 },
+  { colKey: 'roles', title: '项目角色配置', cell: 'roles', width: 200 },
+  { colKey: 'quota', title: '配额(人)', width: 100 },
+  { colKey: 'distributed', title: '已分配(人)', width: 120 },
+  { colKey: 'unDistributed', title: '分配差额(人)', width: 140 },
   {
     title: '操作',
     colKey: 'operate',
@@ -205,6 +227,31 @@ const { pagination, tableData, fetchData, search, onChange } = useFetchTable(
   }
 );
 
+const rolesFilter = (row) => {
+  // data = {
+  //   coordinatorQuota: 1,
+  //   effectQuota: 3,
+  //   assistantQuota: 3,
+  //   coordinatorDistributed: 1,
+  //   effectDistributed: 1,
+  //   assistantDistributed: 1,
+  //   coordinatorUnDistributed: 0,
+  //   effectUnDistributed: 2,
+  //   assistantUnDistributed: 2,
+  // };
+  let data = [];
+  if (row.coordinatorQuota) {
+    data.push(['区域协调人', row.coordinatorQuota, row.coordinatorDistributed]);
+  }
+  if (row.effectQuota) {
+    data.push(['实施工程师', row.effectQuota, row.effectDistributed]);
+  }
+  if (row.assistantQuota) {
+    data.push(['助理工程师', row.assistantQuota, row.assistantDistributed]);
+  }
+  return data.map((item) => `${item[0]}(${item[2]}/${item[1]})`).join(',');
+};
+
 const personDeploySuccess = () => {
   fetchData();
   getStatisticsInfo();
@@ -228,7 +275,9 @@ const handleBatchDeploy = () => {
     cancelBtn: '取消',
     onConfirm: async () => {
       confirmDia.hide();
-      const res = await personAllocateBatchDeployApi(row.id).catch(() => {});
+      const res = await personAllocateBatchDeployApi(
+        selectedRowKeys.value
+      ).catch(() => {});
       if (!res) return;
       MessagePlugin.success('操作成功');
       fetchData();
@@ -247,7 +296,7 @@ const handleSubmitSop = (row) => {
     cancelBtn: '取消',
     onConfirm: async () => {
       confirmDia.hide();
-      const res = await personAllocateSubmitSopApi(row.id).catch(() => {});
+      const res = await personAllocateSubmitSopApi(row.crmNo).catch(() => {});
       if (!res) return;
       MessagePlugin.success('操作成功');
       fetchData();
@@ -262,7 +311,7 @@ const handleCancelSubmitSop = (row) => {
     cancelBtn: '取消',
     onConfirm: async () => {
       confirmDia.hide();
-      const res = await personAllocateCancelSubmitSopApi(row.id).catch(
+      const res = await personAllocateCancelSubmitSopApi(row.crmNo).catch(
         () => {}
       );
       if (!res) return;

+ 127 - 51
src/views/resource-guard/person-guard/person-allocate/person-deploy-dialog.vue

@@ -19,10 +19,12 @@
           <t-form-item label="项目单号">{{ formData.crmNo }} </t-form-item>
         </t-col>
         <t-col :span="4">
-          <t-form-item label="客户类型">{{ formData.customType }} </t-form-item>
+          <t-form-item label="客户类型"
+            >{{ customerTypeFilter(formData.customType) }}
+          </t-form-item>
         </t-col>
         <t-col :span="8">
-          <t-form-item label="客户名称">{{ formData.custom }} </t-form-item>
+          <t-form-item label="客户名称">{{ formData.customName }} </t-form-item>
         </t-col>
         <t-col :span="4">
           <t-form-item label="服务档位">{{ formData.level }} </t-form-item>
@@ -30,7 +32,7 @@
         <t-col :span="12">
           <t-form-item label="客户地址">
             <t-space>
-              <span>{{ formData.privince }}</span>
+              <span>{{ formData.province }}</span>
               <span>{{ formData.city }}</span>
               <span>{{ formData.area }}</span>
               <span>{{ formData.address }}</span>
@@ -44,27 +46,27 @@
                 size="small"
                 row-key="roleId"
                 :columns="roleColumns"
-                :data="formData.roleList"
+                :data="formData.roleConfigInfo"
+                bordered
               >
                 <template #num="{ row }">
-                  <span>{{ row.users.length }}</span>
+                  <span>{{ row.userIdList.length }}</span>
                   <span>/</span>
                   <span>{{ row.quota }}</span>
                 </template>
                 <template #users="{ row }">
                   <select-type-user
+                    v-model="row.userIdList"
                     :type="row.roleType"
                     :multiple="row.roleType !== 'REGION_COORDINATOR'"
                   ></select-type-user>
                 </template>
                 <template #operate="{ row }">
-                  <div
-                    v-if="row.roleType !== 'REGION_COORDINATOR'"
-                    class="table-operations"
-                  >
+                  <div class="table-operations">
                     <t-button
-                      shape="circle"
                       theme="danger"
+                      shape="square"
+                      variant="text"
                       @click="handleDelete(row)"
                     >
                       <template #icon> <MinusCircleFilledIcon /></template>
@@ -76,10 +78,15 @@
           </t-form-item>
           <t-form-item>
             <div class="flex justify-between items-center" style="width: 100%">
-              <select-role
-                v-model="selectedRoleId"
-                @change="roleChange"
-              ></select-role>
+              <t-select v-model="selectedRoleId" @change="roleChange">
+                <t-option
+                  v-for="item in roleList"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.name"
+                  :disabled="configRoleIds.includes(item.id)"
+                ></t-option>
+              </t-select>
               <t-button
                 class="m-l-10px"
                 theme="primary"
@@ -101,10 +108,16 @@
   </my-dialog>
 </template>
 <script setup name="PersonDeployDialog">
-import { ref } from 'vue';
-import { MessagePlugin, MinusCircleFilledIcon } from 'tdesign-vue-next';
+import { computed, onMounted, ref } from 'vue';
+import { MessagePlugin } from 'tdesign-vue-next';
+import { MinusCircleFilledIcon } from 'tdesign-icons-vue-next';
 import useClearDialog from '@/hooks/useClearDialog';
-import { personAllocateDeployApi } from '@/api/resource-guard';
+import useAuthenRole from '@/hooks/useAuthenRole';
+import {
+  personAllocateDeployApi,
+  personAllocateRoleDetailApi,
+} from '@/api/resource-guard';
+import { customerTypeFilter } from '@/utils/filter';
 
 const emit = defineEmits(['update:visible', 'success']);
 const props = defineProps({
@@ -112,44 +125,83 @@ const props = defineProps({
   curRow: Object,
 });
 
+const configRoleIds = computed(() => {
+  return formData.roleConfigInfo.map((item) => item.roleId);
+});
+
 const formRef = ref(null);
 let selectedRole = ref(null);
 let selectedRoleId = ref(null);
 
+const { roleList, getRoleList } = useAuthenRole();
+
+const getDetail = async () => {
+  for (let key in formData) {
+    formData[key] = props.curRow[key];
+  }
+  formData.roleConfigInfo = formData.roleConfigInfo || [];
+
+  const res = await personAllocateRoleDetailApi(props.curRow.crmNo).catch(
+    () => {}
+  );
+  if (!res) return;
+
+  const roleQuota = {
+    REGION_COORDINATOR: props.curRow.coordinatorQuota,
+    EFFECT_ENGINEER: props.curRow.effectQuota,
+    ASSISTANT_ENGINEER: props.curRow.assistantQuota,
+  };
+
+  if (res.length) {
+    let roleConfigMap = {};
+
+    res.forEach((item) => {
+      if (!roleConfigMap[item.roleResult.roleId]) {
+        roleConfigMap[item.roleResult.roleId] = {
+          quota: roleQuota[item.roleResult.roleType],
+          userIdList: [],
+          ...item.roleResult,
+        };
+      }
+      roleConfigMap[item.roleResult.roleId].userIdList.push(item.userId);
+    });
+    formData.roleConfigInfo = Object.values(roleConfigMap);
+  } else {
+    const validRoleTypes = Object.keys(roleQuota).filter(
+      (item) => roleQuota[item]
+    );
+    formData.roleConfigInfo = roleList.value
+      .filter((item) => validRoleTypes.includes(item.type))
+      .map((item) => {
+        return {
+          quota: roleQuota[item.type],
+          userIdList: [],
+          roleId: item.id,
+          roleName: item.name,
+          roleType: item.type,
+        };
+      });
+  }
+};
+
 const { formData } = useClearDialog(
   {
     id: null,
+    serviceUnitId: null,
+    serviceUnitName: '',
+    crmNo: '',
+    customName: '',
+    customType: '',
+    province: '',
+    city: '',
+    area: '',
     level: '',
-    type: '',
-    devices: null,
-    enable: true,
-    roleList: [],
+    roleConfigInfo: [],
   },
   props,
   formRef,
-  () => {
-    for (let key in formData) {
-      formData[key] = props.curRow[key];
-    }
-  }
+  getDetail
 );
-const rules = {
-  roleList: [
-    {
-      validator: (val) => {
-        if (!val || !val.length)
-          return { result: false, message: '请填写至少一个角色' };
-
-        if (val.some((item) => !item.quota))
-          return { result: false, message: '有角色未设置配额' };
-
-        return { result: true, type: 'success' };
-      },
-      type: 'error',
-      trigger: 'change',
-    },
-  ],
-};
 
 const roleColumns = [
   { colKey: 'roleName', title: '项目角色', width: 120 },
@@ -163,31 +215,40 @@ const dialogOpened = () => {
   selectedRoleId.value = null;
 };
 
-const roleChange = (role) => {
-  selectedRole.value = role;
+const roleChange = () => {
+  selectedRole.value = roleList.value.find(
+    (item) => item.id === selectedRoleId.value
+  );
 };
 const toAddRole = () => {
-  if (formData.roleList.some((item) => item.roleId === selectedRole.value.id)) {
+  if (
+    formData.roleConfigInfo.some(
+      (item) => item.roleId === selectedRole.value.id
+    )
+  ) {
     MessagePlugin.error('当前角色已经被选过!');
     return;
   }
 
-  formData.roleList.push({
+  formData.roleConfigInfo.push({
     quota: 1,
-    users: [],
+    userIdList: [],
     roleId: selectedRole.value.id,
     roleName: selectedRole.value.name,
     roleType: selectedRole.value.type,
   });
+
+  selectedRole.value = null;
+  selectedRoleId.value = null;
 };
 const handleDelete = (row) => {
-  formData.roleList = formData.roleList.filter(
+  formData.roleConfigInfo = formData.roleConfigInfo.filter(
     (item) => item.roleId !== row.roleId
   );
 };
 
 const checkRoleList = () => {
-  const val = formData.roleList;
+  const val = formData.roleConfigInfo;
   if (!val || !val.length)
     return { result: false, message: '至少配置一个角色' };
 
@@ -203,11 +264,26 @@ const save = async () => {
     return;
   }
 
-  const res = await personAllocateDeployApi(formData).catch(() => {});
+  let data = {
+    serviceUnitId: formData.serviceUnitId,
+    crmNo: formData.crmNo,
+    allocationParams: formData.roleConfigInfo.map((item) => {
+      return {
+        roleId: item.roleId,
+        userIdList: item.userIdList,
+      };
+    }),
+  };
+
+  const res = await personAllocateDeployApi(data).catch(() => {});
   if (!res) return;
 
   MessagePlugin.success('保存成功');
   emit('update:visible', false);
   emit('success');
 };
+
+onMounted(() => {
+  getRoleList();
+});
 </script>

+ 47 - 33
src/views/resource-guard/person-guard/person-files/add-person-file-dialog.vue

@@ -7,7 +7,7 @@
     @close="emit('update:visible', false)"
     @opened="dialogOpened"
   >
-    <t-form ref="formRef" :model="formData" :rules="rules" labelWidth="120px">
+    <t-form ref="formRef" :data="formData" :rules="rules" labelWidth="120px">
       <t-row :gutter="[0, 20]">
         <t-col :span="4">
           <t-form-item label="人员档案编号">
@@ -19,19 +19,12 @@
             <t-input v-model="formData.name"></t-input>
           </t-form-item>
         </t-col>
-        <t-col :span="4">
-          <t-form-item label="常住区域" name="city">
-            <select-area
-              v-model="areaInfo"
-              :level="2"
-              value-type="full"
-              @change="areaChange"
-            ></select-area>
-          </t-form-item>
-        </t-col>
         <t-col :span="4">
           <t-form-item label="身份证号" name="identity">
-            <t-input v-model="formData.identity"></t-input>
+            <t-input
+              v-model="formData.identity"
+              @change="identityChange"
+            ></t-input>
           </t-form-item>
         </t-col>
         <t-col :span="4">
@@ -60,10 +53,19 @@
         </t-col>
         <t-col :span="4">
           <t-form-item label="手机号" name="mobileNumber">
-            <t-input v-model="formData.f"></t-input>
+            <t-input v-model="formData.mobileNumber"></t-input>
           </t-form-item>
         </t-col>
         <t-col :span="8">
+          <t-form-item label="常住区域" name="city">
+            <select-area
+              v-model="areaInfo"
+              value-type="full"
+              @change="areaChange"
+            ></select-area>
+          </t-form-item>
+        </t-col>
+        <t-col :span="4">
           <t-form-item label="电子邮箱" name="email">
             <t-input v-model="formData.email"></t-input>
           </t-form-item>
@@ -74,8 +76,8 @@
               ref="uploadRef"
               v-model="photos"
               theme="image"
-              tips="请上传近期清晰免冠一寸登记照,图片格式:JPEG、JPG、PNG、GIF格式,文件大小不超过2M,推荐尺寸大小:295*412,上传不符合要求的照片将影响现场服务人员正常的打卡签到。"
-              accept="image/*"
+              tips="请上传近期清晰免冠一寸登记照,图片格式:JPEG、JPG、PNG格式,文件大小不超过2M,推荐尺寸大小:295*412,上传不符合要求的照片将影响现场服务人员正常的打卡签到。"
+              accept="image/jpg,image/jpeg,image/png"
               :locale="{
                 triggerUploadText: {
                   image: '请选择图片',
@@ -104,10 +106,10 @@
           <t-form-item label="认证项目角色" name="roleIds">
             <t-checkbox-group v-model="formData.roleIds" :max="1">
               <t-checkbox
-                v-for="(val, key) in AUTHENTICATION_ROLE"
-                :key="key"
-                :value="key"
-                :label="val"
+                v-for="item in roleList"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
               ></t-checkbox>
             </t-checkbox-group>
           </t-form-item>
@@ -163,13 +165,10 @@
 import { ref, computed } from 'vue';
 import { MessagePlugin } from 'tdesign-vue-next';
 import useClearDialog from '@/hooks/useClearDialog';
+import useAuthenRole from '@/hooks/useAuthenRole';
 import { personFilesEditApi, personFilesCodeApi } from '@/api/resource-guard';
 import { fileUploadApi } from '@/api/user';
-import {
-  GENDER_TYPE,
-  AUTHENTICATION_ROLE,
-  EDUCATION_TYPE,
-} from '@/config/constants';
+import { GENDER_TYPE, EDUCATION_TYPE } from '@/config/constants';
 import { getFileMD5 } from '@/utils/crypto';
 
 const emit = defineEmits(['update:visible']);
@@ -185,12 +184,15 @@ const title = computed(() => {
 let areaInfo = ref(['', '']);
 let photos = ref([]);
 
+const { roleList, getRoleList } = useAuthenRole();
+
 const { formData, isEdit } = useClearDialog(
   {
-    id: '',
+    code: '',
     name: '',
     province: '',
     city: '',
+    area: '',
     identity: '',
     gender: '',
     education: '',
@@ -211,6 +213,7 @@ const { formData, isEdit } = useClearDialog(
     for (let key in formData) {
       formData[key] = props.curRow[key];
     }
+    formData.roleIds = props.curRow.roleInfoList.map((item) => item.roleId);
   }
 );
 
@@ -270,8 +273,9 @@ const rules = {
       trigger: 'change',
     },
     {
-      pattern: /^1\d{10}$/,
+      telnumber: true,
       message: '请输入合适的手机号码',
+      type: 'error',
       trigger: 'change',
     },
   ],
@@ -324,10 +328,9 @@ const rules = {
 };
 
 const requestMethod = async (file) => {
-  const md5Str = await getFileMD5(file);
-
+  const md5Str = await getFileMD5(file.raw);
   let data = new FormData();
-  data.append('file', file);
+  data.append('file', file.raw);
   data.append('md5', md5Str);
   data.append('type', 'FILE');
 
@@ -335,12 +338,21 @@ const requestMethod = async (file) => {
   if (!res) return { status: 'fail', error: '上传失败' };
 
   formData.basePhotoPath = res.url;
-  return { status: 'success' };
+  return { status: 'success', response: { url: res.url } };
+};
+
+const identityChange = () => {
+  if (!formData.identity || formData.identity.length !== 18) return;
+
+  const genderCode = formData.identity[16] * 1;
+
+  formData.gender = genderCode % 2 ? 'MAN' : 'WOMAN';
 };
 
 const areaChange = (data) => {
   formData.province = data[0];
   formData.city = data[1];
+  formData.area = data[2];
 };
 
 const save = async () => {
@@ -359,10 +371,12 @@ const dialogOpened = async () => {
   if (!props.curRow) {
     const res = await personFilesCodeApi();
     formData.code = res || '';
-    areaInfo.value = ['', ''];
+    areaInfo.value = ['', '', ''];
+    photos.value = [];
   } else {
-    areaInfo.value = [formData.province, formData.city];
-    photos.value = [formData.basePhotoPath];
+    areaInfo.value = [formData.province, formData.city, formData.area];
+    photos.value = [{ url: formData.basePhotoPath }];
   }
+  getRoleList();
 };
 </script>

+ 9 - 15
src/views/resource-guard/person-guard/person-files/index.vue

@@ -59,7 +59,6 @@
           current: pagination.pageNumber,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
         <template #archives-time="{ col, row }">
@@ -79,9 +78,7 @@
         </template>
         <template #remain-day="{ row }">
           <span>
-            {{
-              dayCountFilter(row.authenticationValidTime - row.archivesTime)
-            }}天
+            {{ dayCountFilter(row.authenticationValidTime - Date.now()) }}天
           </span>
         </template>
         <template #photo="{ col, row }">
@@ -91,12 +88,8 @@
             :style="{ width: '100px', height: '100px' }"
           ></t-image>
         </template>
-        <template #roles="{ row }">
-          {{
-            row.roleTypeList
-              .map((item) => authenticationRoleFilter(item))
-              .join(',')
-          }}
+        <template #roles="{ col, row }">
+          {{ row[col.colKey].map((item) => item.roleName).join(',') }}
         </template>
         <template #operate="{ row }">
           <div class="table-operations" @click.stop>
@@ -132,7 +125,6 @@ import {
 import { dictToOptionList } from '@/utils/tool';
 import { AUTHENTICATION_ROLE, AUTHENTICATION_STATUS } from '@/config/constants';
 import {
-  authenticationRoleFilter,
   authenticationStatusFilter,
   timestampFilter,
   dayCountFilter,
@@ -267,7 +259,7 @@ const columns = [
     width: 170,
   },
   {
-    colKey: 'roleTypeList',
+    colKey: 'roleInfoList',
     title: '认证项目角色',
     cell: 'roles',
     minWidth: 110,
@@ -279,7 +271,7 @@ const columns = [
     cell: 'valid-time',
     width: 170,
   },
-  { colKey: 'r', title: '剩余有效天数', cell: 'remainDay', width: 110 },
+  { colKey: 'r', title: '剩余有效天数', cell: 'remain-day', width: 110 },
   { colKey: 'authenticationStatus', title: '认证状态', cell: 'status' },
   { colKey: 'remark', title: '备注' },
   {
@@ -350,9 +342,11 @@ const multExport = () => {
     cancelBtn: '取消',
     onConfirm: async () => {
       confirmDia.hide();
-      const res = await personFilesExportApi(computedParams).catch(() => {});
+      const res = await personFilesExportApi(computedParams.value).catch(
+        () => {}
+      );
       if (!res) return;
-      MessagePlugin.success('开始下载');
+      MessagePlugin.success('导出任务提交成功,请前往任务管理中下载');
     },
   });
 };

+ 0 - 1
src/views/service-unit/dispatch/dispatch-manage/index.vue

@@ -48,7 +48,6 @@
         }"
         v-loading="tableLoading"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
         <template #type="{ col, row }">

+ 0 - 1
src/views/service-unit/service-unit-manage/add-range/index.vue

@@ -32,7 +32,6 @@
         }"
         v-loading="tableLoading"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
         <template #type="{ col, row }">

+ 0 - 1
src/views/sop/sop-manage/device-out-in/index.vue

@@ -24,7 +24,6 @@
           total: pagination.total,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
       </t-table>

+ 0 - 1
src/views/sop/sop-manage/office-sop/index.vue

@@ -21,7 +21,6 @@
           total: pagination.total,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
       </t-table>

+ 0 - 1
src/views/sop/sop-manage/project-change-report/index.vue

@@ -21,7 +21,6 @@
           total: pagination.total,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
       </t-table>

+ 0 - 1
src/views/sop/sop-manage/student-sop/index.vue

@@ -21,7 +21,6 @@
           total: pagination.total,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
       </t-table>

+ 29 - 6
src/views/system/config-manage/service-level-manage/edit-service-level-dialog.vue

@@ -50,8 +50,9 @@
                 <template #operate="{ row }">
                   <div class="table-operations">
                     <t-button
-                      shape="circle"
                       theme="danger"
+                      shape="square"
+                      variant="text"
                       @click="handleDelete(row)"
                     >
                       <template #icon> <MinusCircleFilledIcon /></template>
@@ -63,10 +64,19 @@
           </t-form-item>
           <t-form-item>
             <div class="flex justify-between items-center" style="width: 100%">
-              <select-role
+              <!-- <select-role
                 v-model="selectedRoleId"
                 @change="roleChange"
-              ></select-role>
+              ></select-role> -->
+              <t-select v-model="selectedRoleId" @change="roleChange">
+                <t-option
+                  v-for="item in roleList"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.name"
+                  :disabled="configRoleIds.includes(item.id)"
+                ></t-option>
+              </t-select>
               <t-button
                 class="m-l-10px"
                 theme="primary"
@@ -101,8 +111,10 @@
 </template>
 <script setup name="EditServiceLevelDialog">
 import { ref, computed } from 'vue';
-import { MessagePlugin, MinusCircleFilledIcon } from 'tdesign-vue-next';
+import { MessagePlugin } from 'tdesign-vue-next';
+import { MinusCircleFilledIcon } from 'tdesign-icons-vue-next';
 import useClearDialog from '@/hooks/useClearDialog';
+import useAuthenRole from '@/hooks/useAuthenRole';
 import { CUSTOMER_TYPE } from '@/config/constants';
 import { serviceLevelEditApi } from '@/api/system';
 
@@ -119,6 +131,11 @@ let selectedRoleId = ref(null);
 const title = computed(() => {
   return (isEdit.value ? '编辑' : '新增') + '服务档位';
 });
+const configRoleIds = computed(() => {
+  return formData.roleList.map((item) => item.roleId);
+});
+
+const { roleList, getRoleList } = useAuthenRole();
 
 const { formData, isEdit } = useClearDialog(
   {
@@ -187,10 +204,13 @@ const roleColumns = [
 const dialogOpened = () => {
   selectedRole.value = null;
   selectedRoleId.value = null;
+  getRoleList();
 };
 
-const roleChange = (role) => {
-  selectedRole.value = role;
+const roleChange = () => {
+  selectedRole.value = roleList.value.find(
+    (item) => item.id === selectedRoleId.value
+  );
 };
 const toAddRole = () => {
   if (formData.roleList.some((item) => item.roleId === selectedRole.value.id)) {
@@ -203,6 +223,9 @@ const toAddRole = () => {
     roleId: selectedRole.value.id,
     roleName: selectedRole.value.name,
   });
+
+  selectedRole.value = null;
+  selectedRoleId.value = null;
 };
 const handleDelete = (row) => {
   formData.roleList = formData.roleList.filter(

+ 1 - 0
src/views/system/config-manage/supplier-manage/edit-supplier-dialog.vue

@@ -71,6 +71,7 @@ const { formData, isEdit } = useClearDialog(
     name: '',
     type: '',
     remark: '',
+    sync: true,
     enable: true,
   },
   props,

+ 1 - 1
src/views/system/notice-log/notice-manage/index.vue

@@ -17,7 +17,6 @@
         :columns="columns"
         :data="tableData"
         bordered
-        :selected-row-keys="selectedRowKeys"
         :pagination="{
           defaultCurrent: 1,
           defaultPageSize: 10,
@@ -26,6 +25,7 @@
           current: pagination.pageNumber,
         }"
         v-loading="tableLoading"
+        :selected-row-keys="selectedRowKeys"
         @select-change="selectChange"
       >
         <template #type="{ col, row }">

+ 0 - 1
src/views/work-hours/work-hours-manage/abnormal-check/wait-check.vue

@@ -36,7 +36,6 @@
         current: pagination.pageNumber,
       }"
       :selected-row-keys="selectedRowKeys"
-      select-on-row-click
       @select-change="selectChange"
     >
       <template #backup-time="{ col, row }">

+ 0 - 1
src/views/work-hours/work-hours-manage/work-attendance/index.vue

@@ -51,7 +51,6 @@
           current: pagination.pageNumber,
         }"
         :selected-row-keys="selectedRowKeys"
-        select-on-row-click
         @select-change="selectChange"
       >
         <template #user="{ row }">