|
@@ -89,8 +89,8 @@
|
|
|
>
|
|
|
<t-form
|
|
|
ref="form"
|
|
|
- class="sop-step-body"
|
|
|
colon
|
|
|
+ class="sop-step-body"
|
|
|
:rules="rules"
|
|
|
:data="formData"
|
|
|
labelAlign="top"
|
|
@@ -123,7 +123,7 @@
|
|
|
<t-button
|
|
|
v-if="!IS_EDIT_MODE"
|
|
|
theme="primary"
|
|
|
- @click="submitHandle('START')"
|
|
|
+ @click="submitHandle()"
|
|
|
>提交</t-button
|
|
|
>
|
|
|
|
|
@@ -135,6 +135,60 @@
|
|
|
>
|
|
|
</template>
|
|
|
</t-space>
|
|
|
+ <!-- setup history -->
|
|
|
+ <div v-if="flowApproveHistoryList.length" class="sop-step-history">
|
|
|
+ <div class="sop-step-history-label" @click="toViewHistory">
|
|
|
+ <ChevronRightDoubleIcon v-if="stepHistoryShow" />
|
|
|
+ <ChevronLeftDoubleIcon v-else />
|
|
|
+ 流程动态
|
|
|
+ </div>
|
|
|
+ <transition name="fade-slide" mode="out-in" appear>
|
|
|
+ <div v-if="stepHistoryShow" class="sop-step-history-content">
|
|
|
+ <div class="content-head">
|
|
|
+ <h2>
|
|
|
+ {{ sop.statusStr }}
|
|
|
+ </h2>
|
|
|
+ <p>{{ stepDuration }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="content-body">
|
|
|
+ <t-collapse>
|
|
|
+ <t-collapse-panel
|
|
|
+ v-for="(item, findex) in flowApproveHistoryList"
|
|
|
+ :key="findex"
|
|
|
+ :header="item.taskName"
|
|
|
+ >
|
|
|
+ <template #headerRightContent>
|
|
|
+ <t-space size="small">
|
|
|
+ <span class="collapse-head-right">{{
|
|
|
+ timestampFilter(item.createTime)
|
|
|
+ }}</span>
|
|
|
+ <t-tag
|
|
|
+ :theme="
|
|
|
+ item.approveOperation === 'REJECT'
|
|
|
+ ? 'danger'
|
|
|
+ : 'success'
|
|
|
+ "
|
|
|
+ variant="light"
|
|
|
+ >
|
|
|
+ {{ item.approveRemark }}
|
|
|
+ </t-tag>
|
|
|
+ </t-space>
|
|
|
+ </template>
|
|
|
+ <div class="content-detail">
|
|
|
+ <div class="content-detail-head">
|
|
|
+ {{ item.approveUserName }}
|
|
|
+ </div>
|
|
|
+ <div class="content-detail-body">
|
|
|
+ <p>开始处理:{{ timestampFilter(item.createTime) }}</p>
|
|
|
+ <p>处理耗时:{{ item.duration }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </t-collapse-panel>
|
|
|
+ </t-collapse>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </transition>
|
|
|
+ </div>
|
|
|
</t-tab-panel>
|
|
|
</t-tabs>
|
|
|
</div>
|
|
@@ -142,7 +196,11 @@
|
|
|
|
|
|
<script setup name="SopStep">
|
|
|
import { ref, computed, watch } from 'vue';
|
|
|
-import { ErrorCircleFilledIcon } from 'tdesign-icons-vue-next';
|
|
|
+import {
|
|
|
+ ErrorCircleFilledIcon,
|
|
|
+ ChevronLeftDoubleIcon,
|
|
|
+ ChevronRightDoubleIcon,
|
|
|
+} from 'tdesign-icons-vue-next';
|
|
|
import { MessagePlugin } from 'tdesign-vue-next';
|
|
|
|
|
|
import DynamicFormItem from '../../components/dynamic-form-item/index.vue';
|
|
@@ -155,7 +213,7 @@ import {
|
|
|
sopApplyApi,
|
|
|
flowFormPropertiesApi,
|
|
|
} from '@/api/sop';
|
|
|
-import { objCopy } from '@/utils/tool';
|
|
|
+import { objCopy, timeNumberToText } from '@/utils/tool';
|
|
|
import { timestampFilter } from '@/utils/filter';
|
|
|
|
|
|
const props = defineProps({
|
|
@@ -217,10 +275,36 @@ const allFormData = ref({});
|
|
|
const allSteps = ref([]);
|
|
|
const tabs = ref([]);
|
|
|
const curStep = ref('');
|
|
|
+const curStepData = ref({});
|
|
|
const currFlowTaskResultSetup = ref(null);
|
|
|
-const curStepSetup = ref(1);
|
|
|
const flowId = props.sop.flowId;
|
|
|
const crmInfo = ref({});
|
|
|
+const approveRejectFormIds = {
|
|
|
+ // [taskkey]:[formId]
|
|
|
+ f_usertask_office_inside_approve_region_3: 'approve_radio_3',
|
|
|
+ f_usertask_office_inside_approve_engineer_4: 'approve_radio_4',
|
|
|
+};
|
|
|
+const stepHistoryShow = ref(false);
|
|
|
+const flowApproveHistoryList = ref([]);
|
|
|
+const stepDuration = ref('');
|
|
|
+
|
|
|
+function getFlowApproveHistoryList(data, allStepData) {
|
|
|
+ if (!data) return [];
|
|
|
+
|
|
|
+ let setupData = {};
|
|
|
+ allStepData.forEach((item) => {
|
|
|
+ setupData[item.setup] = item.taskName;
|
|
|
+ });
|
|
|
+ let lastTime = 0;
|
|
|
+ return data.map((item, index) => {
|
|
|
+ let nitem = { ...item };
|
|
|
+ nitem.duration =
|
|
|
+ index === 0 ? '-' : timeNumberToText(item.createTime - lastTime);
|
|
|
+ lastTime = item.createTime;
|
|
|
+ nitem.taskName = setupData[item.approveSetup];
|
|
|
+ return nitem;
|
|
|
+ });
|
|
|
+}
|
|
|
|
|
|
const initNew = async () => {
|
|
|
loading.value = true;
|
|
@@ -238,7 +322,8 @@ const initNew = async () => {
|
|
|
label: item.taskName,
|
|
|
};
|
|
|
});
|
|
|
- curStep.value = tabs.value.slice(-1)[0].value;
|
|
|
+ curStep.value = tabs.value[0].value;
|
|
|
+ curStepData.value = allSteps.value[0];
|
|
|
};
|
|
|
const initFill = async () => {
|
|
|
loading.value = true;
|
|
@@ -246,31 +331,31 @@ const initFill = async () => {
|
|
|
crmInfo.value = res.crmInfo;
|
|
|
curStep.value = res.currFlowTaskResult.taskName;
|
|
|
currFlowTaskResultSetup.value = res.currFlowTaskResult.setup;
|
|
|
- curStepSetup.value = res.currFlowTaskResult.setup;
|
|
|
+ curStepData.value = res.currFlowTaskResult;
|
|
|
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 = [...res.flowTaskHistoryList, res.currFlowTaskResult].sort(
|
|
|
+ (a, b) => a.setup - b.setup
|
|
|
+ );
|
|
|
+ tabs.value = allSteps.value.map((item) => {
|
|
|
+ return {
|
|
|
+ value: item.taskName,
|
|
|
+ label: item.taskName,
|
|
|
+ };
|
|
|
+ });
|
|
|
allSteps.value.forEach((item) => {
|
|
|
item.formProperty.forEach((prop) => {
|
|
|
prop.value = prop.value ? JSON.parse(prop.value).value : null;
|
|
|
});
|
|
|
});
|
|
|
+ flowApproveHistoryList.value = getFlowApproveHistoryList(
|
|
|
+ res.flowApproveHistoryList,
|
|
|
+ allSteps.value
|
|
|
+ );
|
|
|
loading.value = false;
|
|
|
};
|
|
|
const initEdit = async () => {
|
|
@@ -284,6 +369,10 @@ const initEdit = async () => {
|
|
|
allSteps.value = Object.values(res.setupMap).sort(
|
|
|
(a, b) => a.setup - b.setup
|
|
|
);
|
|
|
+ flowApproveHistoryList.value = getFlowApproveHistoryList(
|
|
|
+ flowRes.flowApproveHistoryList,
|
|
|
+ allSteps.value
|
|
|
+ );
|
|
|
let allFormMap = {};
|
|
|
allSteps.value.forEach((item) => {
|
|
|
item.formProperty.forEach((prop) => {
|
|
@@ -301,10 +390,10 @@ const initEdit = async () => {
|
|
|
};
|
|
|
});
|
|
|
curStep.value = tabs.value.slice(-1)[0].value;
|
|
|
- const curStepData = allSteps.value.find(
|
|
|
+ const stepData = allSteps.value.find(
|
|
|
(item) => item.taskName === curStep.value
|
|
|
);
|
|
|
- curStepSetup.value = curStepData.setup;
|
|
|
+ curStepData.value = stepData;
|
|
|
};
|
|
|
const init = () => {
|
|
|
if (IS_FILL_MODE.value) {
|
|
@@ -321,12 +410,15 @@ const init = () => {
|
|
|
init();
|
|
|
|
|
|
const showAction = computed(() => {
|
|
|
- if ((IS_EDIT_MODE.value && curStepSetup.value !== 1) || IS_NEW_MODE.value)
|
|
|
+ if (
|
|
|
+ (IS_EDIT_MODE.value && curStepData.value.setup !== 1) ||
|
|
|
+ IS_NEW_MODE.value
|
|
|
+ )
|
|
|
return true;
|
|
|
|
|
|
if (
|
|
|
IS_FILL_MODE.value &&
|
|
|
- curStepSetup.value === currFlowTaskResultSetup.value
|
|
|
+ curStepData.value.setup === currFlowTaskResultSetup.value
|
|
|
)
|
|
|
return true;
|
|
|
|
|
@@ -408,14 +500,19 @@ watch(curFormConfig, (val) => {
|
|
|
}, {});
|
|
|
});
|
|
|
|
|
|
+const toViewHistory = () => {
|
|
|
+ console.log('11');
|
|
|
+ stepHistoryShow.value = !stepHistoryShow.value;
|
|
|
+};
|
|
|
+
|
|
|
const stepChange = () => {
|
|
|
if (IS_EDIT_MODE.value) {
|
|
|
allFormData.value = { ...allFormData.value, ...formData.value };
|
|
|
}
|
|
|
- const curStepData = allSteps.value.find(
|
|
|
+ const stepData = allSteps.value.find(
|
|
|
(item) => item.taskName === curStep.value
|
|
|
);
|
|
|
- curStepSetup.value = curStepData.setup;
|
|
|
+ curStepData.value = stepData;
|
|
|
};
|
|
|
|
|
|
const itemValueChange = ({ prop, value }) => {
|
|
@@ -440,10 +537,10 @@ const getFormData = () => {
|
|
|
}
|
|
|
} else {
|
|
|
// 新增 or 填报
|
|
|
- const curStepData = allSteps.value.find(
|
|
|
+ const stepData = allSteps.value.find(
|
|
|
(item) => item.taskName === curStep.value
|
|
|
);
|
|
|
- data = { ...curStepData };
|
|
|
+ data = { ...stepData };
|
|
|
data.formProperty = data.formProperty.map((item) => {
|
|
|
return {
|
|
|
...item,
|
|
@@ -456,19 +553,35 @@ const getFormData = () => {
|
|
|
};
|
|
|
// 填报-提交
|
|
|
const submitHandle = async (approve = 'START') => {
|
|
|
- if (approve === 'START') {
|
|
|
+ if (approve !== 'DRAFT') {
|
|
|
+ // 提交
|
|
|
const valid = await form.value[0].validate();
|
|
|
if (valid !== true) return;
|
|
|
|
|
|
- approve = curStepSetup.value === 1 ? 'START' : 'PASS';
|
|
|
+ if (curStepData.value.setup === 1) {
|
|
|
+ approve = 'START';
|
|
|
+ } else {
|
|
|
+ const approveRejectFormId =
|
|
|
+ approveRejectFormIds[curStepData.value.taskKey];
|
|
|
+ if (approveRejectFormId && formData.value[approveRejectFormId] === '0') {
|
|
|
+ approve = 'REJECT';
|
|
|
+ } else {
|
|
|
+ approve = 'PASS';
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (IS_FILL_MODE.value) {
|
|
|
- const res = await sopApproveApi({
|
|
|
+ let data = {
|
|
|
taskId: props.sop.taskId,
|
|
|
formProperties: getFormData(),
|
|
|
approve,
|
|
|
- }).catch(() => {});
|
|
|
+ };
|
|
|
+ if (approve === 'REJECT') {
|
|
|
+ // 目前只打回给定的允许打回的第一个选项
|
|
|
+ data.setup = curStepData.value.approveRejectList[0].setup;
|
|
|
+ }
|
|
|
+ const res = await sopApproveApi(data).catch(() => {});
|
|
|
if (!res) return;
|
|
|
} else if (IS_NEW_MODE.value) {
|
|
|
const res = await sopApplyApi({
|