zhangjie 1 year ago
parent
commit
6f52e10416

+ 5 - 0
src/api/project-quality.js

@@ -17,6 +17,11 @@ export const issuesFeedbackSaveApi = (data) =>
     url: '/api/admin/tb/quality/problem/apply/save',
     data,
   });
+export const issuesFeedbackApproveApi = (data) =>
+  request({
+    url: '/api/admin/tb/quality/problem/apply/approve',
+    data,
+  });
 
 // issues-query
 export const issuesQueryListApi = (data) =>

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

@@ -52,8 +52,27 @@
         <template #update-time="{ col, row }">
           {{ timestampFilter(row[col.colKey]) }}
         </template>
+        <template #operate="{ row }">
+          <div class="table-operations">
+            <t-link
+              theme="primary"
+              hover="color"
+              @click="auditQualityIssueHandle(row)"
+            >
+              审核
+            </t-link>
+          </div>
+        </template>
       </t-table>
     </div>
+
+    <!-- QualityIssueDialog -->
+    <quality-issue-dialog
+      v-model:visible="showQualityIssueDialog"
+      :sop="curSopData"
+      type="fill"
+      @confirm="fetchData"
+    ></quality-issue-dialog>
   </div>
 </template>
 
@@ -61,6 +80,7 @@
 import { computed, reactive, ref } from 'vue';
 import { omit } from 'lodash';
 import { DialogPlugin, MessagePlugin } from 'tdesign-vue-next';
+import QualityIssueDialog from '@/views/sop/sop-manage/quality-issue/quality-issue-dialog.vue';
 
 import {
   issuesFeedbackListApi,
@@ -87,6 +107,7 @@ const selectedRowKeys = ref([]);
 const selectChange = (value) => {
   selectedRowKeys.value = value;
 };
+const curSopData = ref({});
 
 const fields = ref([
   {
@@ -235,6 +256,12 @@ const columns = [
   { colKey: 'status', title: '流程状态', cell: 'flow-status', width: 120 },
   { colKey: 'setup', title: '当前节点', minWidth: 160 },
   { colKey: 'pendApproveUsers', title: '当前负责人', width: 140 },
+  {
+    title: '管理',
+    colKey: 'operate',
+    fixed: 'right',
+    width: 100,
+  },
 ];
 
 const { pagination, tableData, fetchData, search, onChange } = useFetchTable(
@@ -269,4 +296,14 @@ const handleDestroy = () => {
     },
   });
 };
+
+const showQualityIssueDialog = ref(false);
+const auditQualityIssueHandle = (row) => {
+  curSopData.value = {
+    ...row,
+    customManagerTypeStr: row.customTypeStr,
+    customName: row.custom,
+  };
+  showQualityIssueDialog.value = true;
+};
 </script>

+ 1 - 0
src/views/sop/components/dynamic-form-item/index.vue

@@ -48,6 +48,7 @@ const tabComps = {
   SIGN: SIGN,
   TEXT: TEXT,
   NUMBER: NUMBER,
+  POP_SELECT: SELECT,
   SINGLE_SELECT: SELECT,
   MULTIPLE_SELECT: SELECT,
   DATE: DATE,

+ 125 - 53
src/views/sop/sop-manage/quality-issue/index.vue

@@ -4,30 +4,36 @@
       <t-collapse-panel disabled>
         <template #expandIcon></template>
         <template #header> SOP信息 </template>
-        <t-form colon label-width="72px">
+        <t-form colon label-width="85px">
           <t-row :gutter="[0, 4]">
             <t-col :span="3">
-              <t-form-item label="服务单元">{{ sop.serviceName }}</t-form-item>
+              <t-form-item label="服务单元">{{
+                sopInfo.serviceName
+              }}</t-form-item>
             </t-col>
             <t-col :span="3">
-              <t-form-item label="SOP流水号">{{ sop.sopNo }}</t-form-item>
+              <t-form-item label="SOP流水号">{{ sopInfo.sopNo }}</t-form-item>
             </t-col>
             <t-col :span="3">
               <t-form-item label="客户类型">{{
-                sop.customManagerTypeStr
+                sopInfo.customManagerTypeStr
               }}</t-form-item>
             </t-col>
             <t-col :span="3">
-              <t-form-item label="客户名称">{{ sop.customName }}</t-form-item>
+              <t-form-item label="客户名称">{{
+                sopInfo.customName
+              }}</t-form-item>
             </t-col>
             <t-col :span="3">
-              <t-form-item label="项目单号">{{ sop.crmNo }}</t-form-item>
+              <t-form-item label="项目单号">{{ sopInfo.crmNo }}</t-form-item>
             </t-col>
             <t-col :span="3">
-              <t-form-item label="实施产品">{{ sop.productName }}</t-form-item>
+              <t-form-item label="实施产品">{{
+                sopInfo.productName
+              }}</t-form-item>
             </t-col>
             <t-col :span="6">
-              <t-form-item label="项目名称">{{ sop.crmName }}</t-form-item>
+              <t-form-item label="项目名称">{{ sopInfo.crmName }}</t-form-item>
             </t-col>
           </t-row>
         </t-form>
@@ -45,7 +51,6 @@
         :key="item.taskKey"
         :value="item.value"
         :label="item.label"
-        :disabled="item.disabled"
       >
         <t-form
           ref="form"
@@ -78,19 +83,14 @@
           </t-row>
         </t-form>
         <t-space class="sop-step-footer">
-          <t-button
-            v-if="IS_NEW_MODE"
-            theme="primary"
-            @click="submitHandle('START')"
-            >提交</t-button
-          >
-
-          <t-button
-            v-if="IS_NEW_MODE"
-            theme="default"
-            @click="submitHandle('DRAFT')"
-            >保存草稿</t-button
-          >
+          <template v-if="showAction">
+            <t-button theme="primary" @click="submitHandle('START')"
+              >提交</t-button
+            >
+            <t-button theme="default" @click="submitHandle('DRAFT')"
+              >保存草稿</t-button
+            >
+          </template>
         </t-space>
       </t-tab-panel>
     </t-tabs>
@@ -98,12 +98,13 @@
 </template>
 
 <script setup name="QualityIssue">
-import { ref, computed, watch } from 'vue';
+import { ref, computed, watch, reactive } from 'vue';
 import { issuesFeedbackSaveApi } from '@/api/project-quality';
-import { flowFormPropertiesApi } from '@/api/sop';
+import { flowFormPropertiesApi, sopFlowViewApi } from '@/api/sop';
 import { MessagePlugin } from 'tdesign-vue-next';
 
 import DynamicFormItem from '../../components/dynamic-form-item/index.vue';
+import sop from '@/router/modules/sop';
 
 const props = defineProps({
   sop: {
@@ -122,12 +123,26 @@ const emit = defineEmits(['confirm']);
 const IS_NEW_MODE = computed(() => {
   return props.type === 'new';
 });
+const IS_FILL_MODE = computed(() => {
+  return props.type === 'fill';
+});
+
+const sopInfo = reactive({
+  serviceName: props.sop.serviceName,
+  sopNo: props.sop.sopNo,
+  customManagerTypeStr: props.sop.customManagerTypeStr,
+  customName: props.sop.customName,
+  crmNo: props.sop.crmNo,
+  productName: props.sop.productName,
+  crmName: props.sop.crmName,
+});
 
 const needValueCodes = [
   'NUMBER', //新增
   'TEXT',
   'DATE',
-  'SELECT',
+  'SINGLE_SELECT',
+  'MULTIPLE_SELECT',
   'CHECKBOX',
   'TEXTAREA',
   'TABLE',
@@ -152,10 +167,13 @@ const fullWidthCodes = ref([
   'DEVICE_IN_TABLE',
 ]);
 const form = ref(null);
-
 const allSteps = ref([]);
 const tabs = ref([]);
 const curStep = ref('');
+const currFlowTaskResultSetup = ref(null);
+const curStepSetup = ref(1);
+const flowId = props.sop.flowId;
+const crmInfo = ref({});
 
 const initNew = async () => {
   loading.value = true;
@@ -169,31 +187,77 @@ const initNew = async () => {
     return {
       value: item.taskName,
       label: item.taskName,
-      disabled: false,
     };
   });
   curStep.value = tabs.value.slice(-1)[0].value;
 };
+const initFill = async () => {
+  loading.value = true;
+  const res = await sopFlowViewApi({ flowId });
+  crmInfo.value = res.crmInfo;
+  sopInfo.crmName = crmInfo.value.crmName;
+  sopInfo.productName = crmInfo.value.productName;
+  sopInfo.serviceName = crmInfo.value.serviceUnitName;
+
+  curStep.value = res.currFlowTaskResult.taskName;
+  currFlowTaskResultSetup.value = res.currFlowTaskResult.setup;
+  curStepSetup.value = res.currFlowTaskResult.setup;
+  res.flowTaskHistoryList = res.flowTaskHistoryList || [];
+  res.flowTaskHistoryList.forEach((item) => {
+    item.formProperty.forEach((v) => {
+      v.writable = false;
+    });
+  });
+  allSteps.value = [...res.flowTaskHistoryList, res.currFlowTaskResult];
+  tabs.value = [
+    ...res.flowTaskHistoryList.map((item) => {
+      return {
+        value: item.taskName,
+        label: item.taskName,
+      };
+    }),
+    {
+      value: res.currFlowTaskResult.taskName,
+      label: res.currFlowTaskResult.taskName,
+    },
+  ];
+  allSteps.value.forEach((item) => {
+    item.formProperty.forEach((prop) => {
+      prop.value = prop.value ? JSON.parse(prop.value).value : null;
+    });
+  });
+  loading.value = false;
+};
+
 const init = () => {
   if (IS_NEW_MODE.value) {
     // 发起流程
     initNew();
   } else {
-    // initNew();
+    initFill();
   }
 };
 init();
 
+const showAction = computed(() => {
+  if (IS_NEW_MODE.value) return true;
+
+  if (
+    IS_FILL_MODE.value &&
+    curStepSetup.value === currFlowTaskResultSetup.value
+  )
+    return true;
+
+  return false;
+});
+
 const curFormConfig = computed(() => {
-  const formProperty =
-    allSteps.value.find((item) => item.taskName === curStep.value)
-      ?.formProperty || [];
-  formProperty.forEach((item) => {
-    if (IS_NEW_MODE.value) {
-      // item.value = item.value ? JSON.parse(item.value).value : null;
-      item.value = null;
-    }
-  });
+  const stepData = allSteps.value.find(
+    (item) => item.taskName === curStep.value
+  );
+  if (!stepData) return [];
+
+  const formProperty = stepData.formProperty || [];
   return formProperty;
 });
 watch(curFormConfig, (val) => {
@@ -221,9 +285,10 @@ watch(curFormConfig, (val) => {
 });
 
 const stepChange = () => {
-  // if (IS_EDIT_MODE.value) {
-  //   allFormData.value = { ...allFormData.value, ...formData.value };
-  // }
+  const curStepData = allSteps.value.find(
+    (item) => item.taskName === curStep.value
+  );
+  curStepSetup.value = curStepData.setup;
 };
 
 const itemValueChange = ({ prop, value }) => {
@@ -233,18 +298,16 @@ const itemValueChange = ({ prop, value }) => {
 
 const getFormData = () => {
   let data = {};
-  if (IS_NEW_MODE.value) {
-    const curStepData = allSteps.value.find(
-      (item) => item.taskName === curStep.value
-    );
-    data = { ...curStepData };
-    data.formProperty = data.formProperty.map((item) => {
-      return {
-        ...item,
-        value: JSON.stringify({ value: formData.value[item.formName] || null }),
-      };
-    });
-  }
+  const curStepData = allSteps.value.find(
+    (item) => item.taskName === curStep.value
+  );
+  data = { ...curStepData };
+  data.formProperty = data.formProperty.map((item) => {
+    return {
+      ...item,
+      value: JSON.stringify({ value: formData.value[item.formName] || null }),
+    };
+  });
 
   return JSON.stringify(data);
 };
@@ -254,9 +317,18 @@ const submitHandle = async (flowApprove = 'START') => {
   if (flowApprove === 'START') {
     const valid = await form.value[0].validate();
     if (valid !== true) return;
+
+    approve = curStepSetup.value === 1 ? 'START' : 'PASS';
   }
 
-  if (IS_NEW_MODE.value) {
+  if (IS_FILL_MODE.value) {
+    const res = await issuesFeedbackApproveApi({
+      taskId: props.sop.taskId,
+      formProperties: getFormData(),
+      approve,
+    }).catch(() => {});
+    if (!res) return;
+  } else if (IS_NEW_MODE.value) {
     const res = await issuesFeedbackSaveApi({
       serviceId: props.sop.serviceId,
       crmNo: props.sop.crmNo,

+ 42 - 13
src/views/system/config-manage/checkin-manage/edit-checkin-dialog.vue

@@ -33,16 +33,18 @@
           </t-form-item>
         </t-col>
         <t-col :span="12">
-          <t-form-item label="签到时段" name="signInTime">
+          <t-form-item label="签到时段" name="signInOutTime">
             <t-time-range-picker
               v-model="formData.signInTime"
               format="HH:mm"
               class="width-full"
+              clearable
+              @change="signTimeChange"
             />
           </t-form-item>
         </t-col>
         <t-col :span="12">
-          <t-form-item name="signOutTime">
+          <t-form-item name="signInOutTime">
             <template #label>
               <span>签退时段</span>
               <span class="color-warning m-l-5px"
@@ -53,6 +55,8 @@
               v-model="formData.signOutTime"
               format="HH:mm"
               class="width-full"
+              clearable
+              @change="signTimeChange"
             />
           </t-form-item>
         </t-col>
@@ -193,18 +197,39 @@ const rules = {
       trigger: 'change',
     },
   ],
-  signInTime: [
+  // signInTime: [
+  //   {
+  //     required: true,
+  //     message: '签到时段必选',
+  //     type: 'error',
+  //     trigger: 'change',
+  //   },
+  // ],
+  // signOutTime: [
+  //   {
+  //     required: true,
+  //     message: '签退时段必选',
+  //     type: 'error',
+  //     trigger: 'change',
+  //   },
+  // ],
+  signInOutTime: [
     {
-      required: true,
-      message: '签到时段必选',
-      type: 'error',
-      trigger: 'change',
-    },
-  ],
-  signOutTime: [
-    {
-      required: true,
-      message: '签退时段必选',
+      validator: () => {
+        if (
+          (formData.signInTime && !formData.signOutTime) ||
+          (!formData.signInTime && formData.signOutTime)
+        ) {
+          return {
+            result: false,
+            message: '签到时段和签退时段必须同时填写',
+          };
+        }
+        return {
+          result: true,
+          type: 'success',
+        };
+      },
       type: 'error',
       trigger: 'change',
     },
@@ -226,6 +251,10 @@ const rules = {
     },
   ],
 };
+
+const signTimeChange = () => {
+  formRef.value.validate({ fields: ['signInOutTime'] });
+};
 const save = async () => {
   const valid = await formRef.value.validate();
   if (valid !== true) return;