刘洋 1 tahun lalu
induk
melakukan
0768055e2a

+ 1 - 1
build/config/proxy.js

@@ -9,7 +9,7 @@ export function createViteProxy(isOpenProxy, envConfig) {
   const proxy = {
     [envConfig.proxy]: {
       target: envConfig.url,
-      // changeOrigin: true,
+      changeOrigin: true,
       // rewrite: (path) => path.replace(new RegExp(`^${envConfig.proxy}`), ''),
     },
   };

+ 2 - 1
src/api/service-unit.js

@@ -126,5 +126,6 @@ export const serviceRegionEditApi = (data) =>
 export const serviceRegionRemoveApi = (serviceRegionId) =>
   request({
     url: '/api/service/service/region/remove',
-    params: { serviceRegionId },
+    params: { serviceRegionIdList: serviceRegionId },
+    paramsSerializer,
   });

+ 5 - 0
src/api/user.js

@@ -29,6 +29,11 @@ export const getUserList = (data) =>
     url: '/api/admin/user/list',
     params: data,
   });
+export const getUserListDjr = (data) =>
+  request({
+    url: '/api/admin/device/in/out/registrant_list',
+    params: data,
+  });
 export const getRoleList = (data) =>
   request({
     url: '/api/admin/role/list',

+ 58 - 0
src/components/common/select-filter-user-djr/index.vue

@@ -0,0 +1,58 @@
+<template>
+  <t-select v-model="selected" clearable filterable @change="onChange">
+    <t-option
+      v-for="item in optionList"
+      :key="item.id"
+      :value="item.id"
+      :label="item.value"
+    />
+  </t-select>
+</template>
+
+<script setup name="SelectFilterUserDjr">
+import { ref, watch, computed, onMounted } from 'vue';
+import { getUserListDjr } from '@/api/user';
+
+const emit = defineEmits(['update:modelValue', 'change']);
+const props = defineProps({
+  modelValue: { type: [Number, String, Array], default: '' },
+  defaultList: {
+    type: Array,
+    default() {
+      return [];
+    },
+  },
+  isDjr: { type: Boolean, default: false },
+});
+const isMultiple = computed(() => {
+  const multiple = attrs.multiple;
+  return multiple === '' || multiple;
+});
+
+let optionList = ref([]);
+let selected = ref('');
+let loading = ref(false);
+
+async function search(userInfo) {
+  const res = await getUserListDjr().catch(() => {});
+  if (!res) return;
+
+  optionList.value = res || [];
+}
+onMounted(() => {
+  search();
+});
+const onChange = (id) => {
+  emit('update:modelValue', id);
+};
+
+watch(
+  () => props.modelValue,
+  (val) => {
+    selected.value = val;
+  },
+  {
+    immediate: true,
+  }
+);
+</script>

+ 1 - 1
src/components/global/attachment-view/index.vue

@@ -139,7 +139,7 @@ function checkFileType(filepath) {
 }
 
 watch(
-  () => attachmentIds,
+  [() => attachmentIds, () => props.imageList, () => props.fileList],
   () => {
     getAttachments();
   },

+ 1 - 0
src/layout/index.vue

@@ -152,6 +152,7 @@ watch(
     &-logo {
       height: 52px;
       padding: 12px 8px;
+      text-align: center;
     }
     &-item {
       margin: 4px 0;

+ 1 - 1
src/views/my-workbenches/workbenches/my-waits/waits-list.vue

@@ -16,7 +16,7 @@
           >
           <template v-else>
             <t-tag theme="danger" variant="light">已超时</t-tag>
-            <t-tag theme="danger" variant="light"
+            <t-tag theme="danger" variant="light" class="m-l-5px"
               >超时时长:{{
                 item.diffTime <= 30 ? `${item.diffTime}天` : '大于30天'
               }}</t-tag

+ 6 - 2
src/views/resource-guard/device-guard/registration-query/index.vue

@@ -5,10 +5,14 @@
         <select-service-unit v-model="params[item.prop]"></select-service-unit>
       </template>
       <template #user="{ item, params }">
-        <select-filter-user
+        <!-- <select-filter-user
           v-model="params[item.prop]"
           clearable
-        ></select-filter-user>
+        ></select-filter-user> -->
+        <select-filter-user-djr
+          v-model="params[item.prop]"
+          clearable
+        ></select-filter-user-djr>
       </template>
     </SearchForm>
     <div class="flex-1 page-wrap">

+ 0 - 1
src/views/resource-guard/person-guard/person-allocate/person-deploy-dialog.vue

@@ -177,7 +177,6 @@ let selectedRoleId = ref(null);
 const { roleList, getRoleList } = useAuthenRole();
 
 const getDetail = async () => {
-  regionUseManage.value = false;
   for (let key in formData) {
     formData[key] = props.curRow[key];
   }

+ 51 - 7
src/views/service-unit/service-unit-manage/regional-planning/index.vue

@@ -5,6 +5,16 @@
         <template #icon><svg-icon name="add-circle" color="#fff" /></template
         >新增大区
       </t-button>
+
+      <t-button
+        v-if="perm.LINK_Delete"
+        variant="outline"
+        :disabled="!selectedRowKeys.length"
+        @click="handleBatchDisable"
+      >
+        <template #icon><svg-icon name="delete" color="#262626" /></template>
+        作废
+      </t-button>
     </div>
     <SearchForm :fields="fields" :params="params" :search="search">
       <template #service="{ item, params }">
@@ -23,7 +33,7 @@
     <div class="flex-1 page-wrap">
       <t-table
         size="small"
-        row-key="id"
+        row-key="serviceRegionId"
         :columns="columns"
         :data="tableData"
         bordered
@@ -37,6 +47,8 @@
           current: pagination.pageNumber,
         }"
         v-loading="tableLoading"
+        :selected-row-keys="selectedRowKeys"
+        @select-change="selectChange"
       >
         <template #operate="{ row }">
           <div class="table-operations">
@@ -56,7 +68,7 @@
               :disabled="row.serviceUnitStatus === 'FINISH'"
               @click="handleDelete(row)"
             >
-              删除
+              作废
             </t-link>
           </div>
         </template>
@@ -86,7 +98,10 @@ const { perm } = usePermission();
 
 const curRow = ref(null);
 const showAddRegionDialog = ref(false);
-
+const selectedRowKeys = ref([]);
+const selectChange = (value, { selectedRowData }) => {
+  selectedRowKeys.value = value;
+};
 const fields = ref([
   {
     prop: 'serviceUnitId',
@@ -133,6 +148,12 @@ const params = reactive({
 });
 
 const columns = [
+  {
+    colKey: 'row-select',
+    type: 'multiple',
+    width: 50,
+    fixed: 'left',
+  },
   { colKey: 'serviceUnitName', title: '服务单元', width: 160 },
   { colKey: 'regionName', title: '大区名称', width: 100 },
   { colKey: 'leadName', title: '大区经理', width: 120 },
@@ -165,18 +186,41 @@ const handleEdit = (row) => {
 };
 const handleDelete = (row) => {
   const confirmDia = DialogPlugin({
-    header: '删除提示',
-    body: `您确定要删除当前规划的大区吗?`,
+    header: '作废提示',
+    body: `您确定要作废当前规划的大区吗?`,
+    confirmBtn: '确定',
+    cancelBtn: '取消',
+    theme: 'warning',
+    onConfirm: async () => {
+      confirmDia.hide();
+      const res = await serviceRegionRemoveApi([row.serviceRegionId]).catch(
+        () => {}
+      );
+      if (!res) return;
+      MessagePlugin.success('操作成功');
+      fetchData();
+    },
+  });
+};
+
+const handleBatchDisable = () => {
+  if (!selectedRowKeys.value.length) {
+    MessagePlugin.error('请选择要作废的记录');
+    return;
+  }
+  const confirmDia = DialogPlugin({
+    header: '系统通知',
+    body: `是否作废所选大区?`,
     confirmBtn: '确定',
     cancelBtn: '取消',
     theme: 'warning',
     onConfirm: async () => {
       confirmDia.hide();
-      const res = await serviceRegionRemoveApi(row.serviceRegionId).catch(
+      const res = await serviceRegionRemoveApi(selectedRowKeys.value).catch(
         () => {}
       );
       if (!res) return;
-      MessagePlugin.success('删除成功');
+      MessagePlugin.success('操作成功');
       fetchData();
     },
   });

+ 6 - 2
src/views/sop/sop-manage/device-out-in/index.vue

@@ -23,10 +23,14 @@
         <select-area v-model="params.address" :level="2"></select-area>
       </template>
       <template #user="{ item, params }">
-        <select-filter-user
+        <!-- <select-filter-user
           v-model="params[item.prop]"
           clearable
-        ></select-filter-user>
+        ></select-filter-user> -->
+        <select-filter-user-djr
+          v-model="params[item.prop]"
+          clearable
+        ></select-filter-user-djr>
       </template>
     </SearchForm>
 

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

@@ -47,6 +47,7 @@
               enable-time-picker
               format="YYYY/MM/DD HH:mm"
               :time-picker-props="{ format: 'HH:mm' }"
+              clearable
             />
           </t-form-item>
         </t-col>

+ 124 - 4
src/views/work-hours/work-hours-manage/abnormal-check/abnormal-audit.vue

@@ -2,13 +2,76 @@
   <my-dialog
     :visible="visible"
     header="异常处理审核"
-    :width="800"
+    :width="1100"
     attach="body"
     :closeOnOverlayClick="false"
     @close="emit('update:visible', false)"
   >
     <t-form colon>
-      <t-row :gutter="[0, 0]">
+      <t-row :gutter="[0, 4]">
+        <t-col :span="3">
+          <t-form-item label="异常编号">{{ curRow.code }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="服务单元">{{ curRow.serviceName }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="SOP流水号">{{ tbDingApply.sopNo }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="姓名">{{ curRow.createRealName }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="客户名称">{{ curRow.customName }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="客户类型">{{
+            customerTypeFilter(curRow.customType)
+          }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="异常类型">{{
+            tbDingApply.dingExceptionTypeStr
+          }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="异常日期">{{
+            tbDingApply.exceptionTime
+          }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="补卡时间">{{
+            timestampFilter(tbDingApply.applyTime)
+          }}</t-form-item>
+        </t-col>
+        <t-col :span="12">
+          <t-form-item label="理由">{{ tbDingApply.reason }}</t-form-item>
+        </t-col>
+        <t-col :span="12">
+          <t-form-item label="附件/截图">
+            <attachment-view
+              :imageList="getUrls('image')"
+              :fileList="getUrls('file')"
+              :imgSize="60"
+            ></attachment-view>
+          </t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="审核状态">{{ curRow.statusStr }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="当前审核人">{{
+            tbDingApply.approveUserName
+          }}</t-form-item>
+        </t-col>
+        <t-col :span="3">
+          <t-form-item label="申请时间">{{
+            timestampFilter(tbDingApply.createTime)
+          }}</t-form-item>
+        </t-col>
+      </t-row>
+
+      <t-row :gutter="[0, 8]" style="margin-top: 30px">
         <t-col :span="12">
           <t-form-item label="审核" required-mark>
             <t-radio-group
@@ -30,8 +93,13 @@
 </template>
 
 <script setup name="AbnormalAudit">
-import { ref } from 'vue';
-import { workHoursWaitCheckAuditApi } from '@/api/work-hours';
+import { ref, watch } from 'vue';
+import {
+  workHoursWaitCheckAuditApi,
+  workHoursCheckDetailApi,
+} from '@/api/work-hours';
+import { timeNumberToText } from '@/utils/tool';
+import { timestampFilter, customerTypeFilter } from '@/utils/filter';
 // import { customerTypeFilter, timestampFilter } from '@/utils/filter';
 import { DialogPlugin, MessagePlugin } from 'tdesign-vue-next';
 
@@ -41,6 +109,51 @@ const props = defineProps({
   curRow: Object,
 });
 
+const crmInfo = ref({});
+const tbDingApply = ref({});
+const stepHistoryShow = ref(false);
+const flowApproveHistoryList = ref([]);
+const getUrls = (type) => {
+  const list = tbDingApply.value.attachmentPaths?.split(',') || [];
+  const imgs = ['jpg', 'png', 'jpeg'];
+  if (type === 'image') {
+    return list.filter((item) => {
+      const evt = item.split('.').slice(-1)[0];
+      return imgs.includes(evt);
+    });
+  } else {
+    return list.filter((item) => {
+      const evt = item.split('.').slice(-1)[0];
+      return !imgs.includes(evt);
+    });
+  }
+};
+function getFlowApproveHistoryList(data) {
+  if (!data) return [];
+
+  let lastTime = 0;
+  return data.map((item, index) => {
+    let nitem = { ...item };
+    nitem.duration =
+      index === 0 ? '-' : timeNumberToText(item.createTime - lastTime);
+    lastTime = item.createTime;
+    return nitem;
+  });
+}
+const initDetail = async () => {
+  stepHistoryShow.value = false;
+  flowApproveHistoryList.value = [];
+  const res = await workHoursCheckDetailApi(props.curRow.objId);
+  tbDingApply.value = res.tbDingApply;
+  crmInfo.value = res.crmInfo;
+  flowApproveHistoryList.value = getFlowApproveHistoryList(
+    res.flowApproveHistoryList
+  );
+};
+const toViewHistory = () => {
+  stepHistoryShow.value = !stepHistoryShow.value;
+};
+
 const dingExceptionApprove = ref('PASS');
 const optionList = ref([
   {
@@ -75,4 +188,11 @@ const handleAudit = async () => {
     },
   });
 };
+
+watch(
+  () => props.visible,
+  (val) => {
+    if (val) initDetail();
+  }
+);
 </script>

+ 1 - 1
src/views/work-hours/work-hours-manage/abnormal-check/abnormal-detail-dialog.vue

@@ -184,7 +184,7 @@ const stepHistoryShow = ref(false);
 const flowApproveHistoryList = ref([]);
 
 const getUrls = (type) => {
-  const list = props.row.attachmentPaths.split(',');
+  const list = props.row.attachmentPaths?.split(',') || [];
   const imgs = ['jpg', 'png', 'jpeg'];
   if (type === 'image') {
     return list.filter((item) => {