|
@@ -0,0 +1,387 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ v-model="state.dialogVisible"
|
|
|
+ draggable
|
|
|
+ :title="state.dialogTitle"
|
|
|
+ ref="dialogRef"
|
|
|
+ @mouseup="mouseup"
|
|
|
+ :style="'transform: ' + state.transform + ';'"
|
|
|
+ append-to-body
|
|
|
+ destroy-on-close
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @close="close"
|
|
|
+ >
|
|
|
+ <div v-loading="state.loading">
|
|
|
+ <el-form :model="state.discernForm" label-width="110px" ref="discernFormRef">
|
|
|
+ <el-row :gutter="10">
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="工单编码"> {{ state.orderDetail.no }} </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="工单标题"> {{ state.orderDetail.title }} </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="申请人"> {{ state.orderDetail.creatorName }} </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="申请部门"> {{ state.orderDetail.creatorOrgName }} </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="申请时间"> {{ formatDate(state.orderDetail.creationTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="下一环节" prop="nextStepCode" :rules="[{ required: true, message: '请选择下一环节', trigger: 'change' }]">
|
|
|
+ <el-select v-model="state.discernForm.nextStepCode" placeholder="请选择下一环节" class="w100" @change="selectNextStep">
|
|
|
+ <el-option v-for="item in state.nextStepOptions" :key="item.key" :label="item.value" :value="item.key" />
|
|
|
+ </el-select>
|
|
|
+ <p class="flex-center-align color-danger" v-if="showFastSendOrder">
|
|
|
+ 当前推荐派单办理对象:{{ fastStepName }} <el-button type="primary" link class="ml4" @click="fastSendOrder">快捷派单</el-button>
|
|
|
+ </p>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="showHandlers">
|
|
|
+ <el-form-item
|
|
|
+ label="办理对象"
|
|
|
+ prop="nextHandlers"
|
|
|
+ :rules="[{ required: nextHandlersRequired, message: '请选择办理对象', trigger: 'change' }]"
|
|
|
+ >
|
|
|
+ <el-select-v2
|
|
|
+ v-model="state.discernForm.nextHandlers"
|
|
|
+ :options="state.handlerOptions"
|
|
|
+ placeholder="请选择办理对象"
|
|
|
+ class="w100"
|
|
|
+ multiple
|
|
|
+ clearable
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ filterable
|
|
|
+ value-key="key"
|
|
|
+ @change="selectHandlers"
|
|
|
+ :multiple-limit="multipleLimit"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="" prop="isSms">
|
|
|
+ <el-checkbox v-model="state.discernForm.isSms" label="短信通知" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
|
|
+ <el-form-item label="申请类型" prop="type" :rules="[{ required: true, message: '请选择申请类型', trigger: 'change' }]">
|
|
|
+ <el-select v-model="state.discernForm.type" placeholder="请选择申请类型" class="w100" value-key="dicDataValue">
|
|
|
+ <el-option v-for="item in screenTypeOptions" :value="item" :key="item.dicDataValue" :label="item.dicDataName" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
|
|
+ <el-form-item label="申请理由" prop="content" :rules="[{ required: true, message: '请填写甄别申请理由', trigger: 'blur' }]">
|
|
|
+ <common-advice
|
|
|
+ @chooseAdvice="chooseAdviceDiscern"
|
|
|
+ v-model="state.discernForm.content"
|
|
|
+ placeholder="请填写甄别申请理由"
|
|
|
+ :loading="state.loading"
|
|
|
+ :commonEnum="commonEnum.Discriminate"
|
|
|
+ :maxlength="AppConfigInfo.handleOpinionWordLimit"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
|
|
+ <el-form-item label="附件">
|
|
|
+ <annex-list
|
|
|
+ name="甄别附件"
|
|
|
+ ref="discernAnnexListRef"
|
|
|
+ v-model:format="handleFilesDiscern"
|
|
|
+ :businessId="state.orderDetail.orderId"
|
|
|
+ v-model="state.ruleForm.files"
|
|
|
+ classify="甄别上传"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <span class="dialog-footer">
|
|
|
+ <el-button @click="closeDialog" class="default-button">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">办理</el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed, defineAsyncComponent, nextTick, reactive, ref, watch } from 'vue';
|
|
|
+import { ElMessage, FormInstance } from 'element-plus';
|
|
|
+import other from '@/utils/other';
|
|
|
+import { commonEnum } from '@/utils/constants';
|
|
|
+import { discernApproveParams, discernUpdate, screenBaseData, screenDetail, workflowDiscernParams } from '@/api/business/discern';
|
|
|
+import { transformFile } from '@/utils/tools';
|
|
|
+import { formatDate } from '@/utils/formatTime';
|
|
|
+import { useAppConfig } from '@/stores/appConfig';
|
|
|
+import { storeToRefs } from 'pinia';
|
|
|
+
|
|
|
+// 引入组件
|
|
|
+const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
|
|
|
+const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue')); // 附件列表
|
|
|
+// 定义子组件向父组件传值/事件
|
|
|
+const emit = defineEmits(['updateList', 'orderProcessFailed']);
|
|
|
+// 定义变量内容
|
|
|
+const state = reactive<any>({
|
|
|
+ dialogVisible: false, // 弹窗显示隐藏
|
|
|
+ ruleForm: {
|
|
|
+ isPass: true, // 审批结果
|
|
|
+ //流程表单
|
|
|
+ opinion: '', // 意见
|
|
|
+ nextStepCode: '', // 下一节点
|
|
|
+ nextStepName: '', // 下一节点名称
|
|
|
+ backToCountersignEnd: false, // 是否回到会签结束节点
|
|
|
+ nextHandlers: [], // 下一节点办理对象
|
|
|
+ nextMainHandler: '', // 主办人
|
|
|
+ isSms: false, // 是否短信通知
|
|
|
+ isStartCountersign: false, // 是否发起会签
|
|
|
+ stepId: '',
|
|
|
+ },
|
|
|
+ discernForm: {
|
|
|
+ // 甄别表单
|
|
|
+ content: '', // 甄别理由
|
|
|
+ },
|
|
|
+ nextStepOptions: [], // 下一节点
|
|
|
+ handlerOptions: [], // 办理对象
|
|
|
+ transform: 'translate(0px, 0px)', // 滚动条位置
|
|
|
+ loading: false, // 提交按钮loading
|
|
|
+ workflowId: '', // 流程id
|
|
|
+ handlerClassifies: [], //撤回办理对象
|
|
|
+ handlerMainOptions: [], // 主办人
|
|
|
+ handleId: '', // 流程处理ID
|
|
|
+ dialogTitle: '甄别申请', // 弹窗标题
|
|
|
+ annexName: '', // 附件标题
|
|
|
+ inputPlaceholder: '', // 意见提示
|
|
|
+ orderDetail: {}, // 工单详情
|
|
|
+});
|
|
|
+const ruleFormRef = ref<RefType>(); //表单组件
|
|
|
+const screenTypeOptions = ref<EmptyArrayType>([]); // 甄别类型
|
|
|
+const appConfigStore = useAppConfig();
|
|
|
+const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
|
|
|
+// 打开弹窗
|
|
|
+const openDialog = async (val: any) => {
|
|
|
+ console.log(val);
|
|
|
+ state.dialogVisible = true;
|
|
|
+ state.loading = true;
|
|
|
+ try {
|
|
|
+ if (val.workflowId) {
|
|
|
+ // 如果有流程ID说明已经开启过流程需要获取办理流程的参数
|
|
|
+ const [workflowDiscernResponse, responseDiscern] = await Promise.all([discernApproveParams(val.workflowId), screenBaseData()]); //甄别审批参数
|
|
|
+ screenTypeOptions.value = responseDiscern.result?.screenType ?? []; // 甄别理由
|
|
|
+ handleResult(workflowDiscernResponse);
|
|
|
+
|
|
|
+ /* const { result } = await screenDetail(val.id);
|
|
|
+ state.discernForm.content = result.content ?? {};
|
|
|
+ state.discernForm.type = {
|
|
|
+ dicDataValue: result.typeDicId,
|
|
|
+ dicDataName: result.typeDicName,
|
|
|
+ };
|
|
|
+ state.ruleForm.screenType = val.screenType ?? null;
|
|
|
+ state.orderDetail = result;
|
|
|
+ state.ruleForm.files = transformFile(result.files);
|
|
|
+
|
|
|
+ await nextTick(() => {
|
|
|
+ restForm(ruleFormRef.value);
|
|
|
+ });*/
|
|
|
+ } else {
|
|
|
+ const [workflowDiscernResponse, responseDiscern] = await Promise.all([workflowDiscernParams(), screenBaseData()]); //获取开启流程参数
|
|
|
+ screenTypeOptions.value = responseDiscern.result?.screenType ?? []; // 甄别理由
|
|
|
+ handleResult(workflowDiscernResponse);
|
|
|
+ const { id, processType, extra, orderDetail } = val;
|
|
|
+ state.orderDetail = orderDetail ?? {}; // 工单详情
|
|
|
+ }
|
|
|
+ state.loading = false;
|
|
|
+ } finally {
|
|
|
+ state.loading = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+const canStartCountersign = ref<boolean>(false); // 是否可以发起会签
|
|
|
+const isMainHandlerShow = ref<boolean>(false); // 是否展示主办人
|
|
|
+const handleResult = (res: any) => {
|
|
|
+ state.nextStepOptions = res.result.steps; //办理对象选择内容
|
|
|
+ canStartCountersign.value = res.result.canStartCountersign ?? false; // 是否可以发起会签
|
|
|
+ isMainHandlerShow.value = res.result.isMainHandlerShow ?? false; // 是否展示主办人
|
|
|
+ if (state.nextStepOptions.length === 1) {
|
|
|
+ // 下一节点是否只有一个 默认选中第一个
|
|
|
+ setTimeout(() => {
|
|
|
+ state.ruleForm.nextStepCode = state.nextStepOptions[0].key; // 下一节点code
|
|
|
+ state.ruleForm.nextStepName = state.nextStepOptions[0].value; // 下一节点name
|
|
|
+ state.ruleForm.backToCountersignEnd = state.nextStepOptions[0].backToCountersignEnd ?? false; // 是否回到会签结束节点
|
|
|
+ }, 0);
|
|
|
+ selectNextStep(state.nextStepOptions[0].key); // 查询流程下一节点参数
|
|
|
+ } else {
|
|
|
+ state.ruleForm.nextStepCode = '';
|
|
|
+ state.ruleForm.nextStepName = '';
|
|
|
+ }
|
|
|
+ state.ruleForm.stepId = res.result.stepId;
|
|
|
+ state.loading = false;
|
|
|
+};
|
|
|
+// 流程选择下一环节
|
|
|
+const fastStepName = ref(''); // 推荐派单处理对象
|
|
|
+const fastStepCode = ref(''); // 推荐派单处理对象code
|
|
|
+const nextHandlersRequired = ref<Boolean>(false);
|
|
|
+const selectNextStep = (val: any) => {
|
|
|
+ ruleFormRef.value?.resetFields('nextHandlers');
|
|
|
+ ruleFormRef.value?.resetFields('nextMainHandler');
|
|
|
+ const next = state.nextStepOptions.find((item: any) => item.key === val);
|
|
|
+ const items = next.items; //获取下一节点
|
|
|
+ state.ruleForm.nextStepName = next.value; // 下一节点name
|
|
|
+ state.ruleForm.backToCountersignEnd = next.backToCountersignEnd ?? false; // 是否回到会签结束节点
|
|
|
+ state.handlerOptions = items ?? [];
|
|
|
+ state.handlerOptions = state.handlerOptions.map((item: any) => {
|
|
|
+ return {
|
|
|
+ value: {
|
|
|
+ ...item,
|
|
|
+ },
|
|
|
+ label: item.value,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ fastStepName.value = next.recommendOrgName; // 推荐派单处理对象
|
|
|
+ fastStepCode.value = next.recommendOrgId; // 推荐派单处理对象code
|
|
|
+ // 办理对象是否必填
|
|
|
+ // nextHandlersRequired.value = ![0].includes(next.handlerType) && !showStepsArr.includes(state.processType);
|
|
|
+ nextHandlersRequired.value = ![0].includes(next.handlerType);
|
|
|
+};
|
|
|
+// 会签是否可用 (多个办理对象,并且配置可以会签)
|
|
|
+const countersignAble = computed(() => {
|
|
|
+ return canStartCountersign.value;
|
|
|
+});
|
|
|
+// 办理对象是否能够选择多个(可以发起会签可以选择多个,不能发起会签只能选择一个)
|
|
|
+const multipleLimit = computed(() => {
|
|
|
+ return canStartCountersign.value ? 0 : 1;
|
|
|
+});
|
|
|
+watch(
|
|
|
+ () => state.ruleForm.nextHandlers, // 监听办理对象 多个办理对象自动发起会签
|
|
|
+ (val) => {
|
|
|
+ state.ruleForm.isStartCountersign = val.length > 1;
|
|
|
+ }
|
|
|
+);
|
|
|
+const countersignDisabled = computed(() => {
|
|
|
+ // 是否可以发起会签
|
|
|
+ return state.ruleForm.nextHandlers.length <= 1;
|
|
|
+});
|
|
|
+// 是否发起会签
|
|
|
+const changeStartCountersign = (val: boolean) => {
|
|
|
+ if (!val) {
|
|
|
+ // 如果不能会签清空办理对象
|
|
|
+ state.ruleForm.nextHandlers = [];
|
|
|
+ ruleFormRef.value?.resetFields('nextHandlers');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 是否展示办理对象 (只有结束节点不展示 next.stepType===2 表示为结束节点)
|
|
|
+const showHandlers = computed(() => {
|
|
|
+ const next = state.nextStepOptions.find((item: any) => item.key === state.ruleForm.nextStepCode);
|
|
|
+ if (!next) return true;
|
|
|
+ return next.stepType !== 2;
|
|
|
+});
|
|
|
+// 是否显示快捷派单
|
|
|
+const showFastSendOrder = computed(() => {
|
|
|
+ const next = state.nextStepOptions.find((item: any) => item.key === state.ruleForm.nextStepCode);
|
|
|
+ if (!next) return false;
|
|
|
+ return next?.recommendOrgName && next?.recommendOrgId;
|
|
|
+});
|
|
|
+// 快速派单
|
|
|
+const fastSendOrder = () => {
|
|
|
+ if (!fastStepCode.value) return;
|
|
|
+ // 如果办理对象中没有推荐派单的对象就添加
|
|
|
+ if (!state.ruleForm.nextHandlers.find((item: any) => item.key === fastStepCode.value)) {
|
|
|
+ state.ruleForm.nextHandlers = [...state.ruleForm.nextHandlers, { key: fastStepCode.value, value: fastStepName.value }];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 选择办理对象
|
|
|
+const selectHandlers = () => {
|
|
|
+ ruleFormRef.value?.resetFields('nextMainHandler');
|
|
|
+ if (state.ruleForm.nextHandlers.length > 1) {
|
|
|
+ // 多个办理对象 主办
|
|
|
+ state.ruleForm.nextMainHandler = state.ruleForm.nextHandlers[0].key;
|
|
|
+ }
|
|
|
+ if (state.ruleForm.nextHandlers.length <= 1) {
|
|
|
+ // 如果只有一个办理对象就不需要发起会签
|
|
|
+ state.ruleForm.isStartCountersign = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+// 主办从办理对象中选择
|
|
|
+state.handlerMainOptions = computed(() => {
|
|
|
+ return state.ruleForm.nextHandlers;
|
|
|
+});
|
|
|
+// 设置抽屉
|
|
|
+const dialogRef = ref<RefType>();
|
|
|
+const mouseup = () => {
|
|
|
+ state.transform = dialogRef.value.dialogContentRef.$el.style.transform;
|
|
|
+};
|
|
|
+// 关闭弹窗
|
|
|
+const closeDialog = () => {
|
|
|
+ state.dialogVisible = false;
|
|
|
+};
|
|
|
+// 重置表单方法
|
|
|
+const restForm = (formEl: FormInstance | undefined) => {
|
|
|
+ if (!formEl) return;
|
|
|
+ state.ruleForm.opinion = '';
|
|
|
+ formEl.resetFields();
|
|
|
+ formEl.clearValidate();
|
|
|
+};
|
|
|
+// 选择常用意见 填入填写框 甄别
|
|
|
+const chooseAdviceDiscern = (item: any) => {
|
|
|
+ state.discernForm.content += item.content;
|
|
|
+};
|
|
|
+const afterSubmit = (emitType?: 'updateList' | 'orderProcessFailed', showMessage?: boolean) => {
|
|
|
+ state.loading = false;
|
|
|
+ closeDialog();
|
|
|
+ if (showMessage) ElMessage.success('甄别申请成功');
|
|
|
+ if (emitType) emit(emitType);
|
|
|
+};
|
|
|
+const discernFormRef = ref<RefType>();
|
|
|
+const close = () => {
|
|
|
+ restForm(ruleFormRef.value);
|
|
|
+ restForm(discernFormRef.value);
|
|
|
+};
|
|
|
+// 提交
|
|
|
+const handleFilesDiscern = ref<EmptyArrayType>([]); // 甄别附件
|
|
|
+const onSubmit = (formEl: FormInstance | undefined) => {
|
|
|
+ if (!formEl) return;
|
|
|
+ formEl.validate((valid: boolean) => {
|
|
|
+ if (!valid) return;
|
|
|
+ state.loading = true;
|
|
|
+ let submitObj = other.deepClone(state.ruleForm);
|
|
|
+ if (submitObj.nextHandlers && submitObj.nextHandlers.length) {
|
|
|
+ if (submitObj.nextHandlers.length === 1) {
|
|
|
+ submitObj.nextMainHandler = submitObj.nextHandlers[0].key;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const requestDiscern = {
|
|
|
+ data: {
|
|
|
+ id: state.orderDetail.id,
|
|
|
+ no: state.orderDetail.no,
|
|
|
+ visitId: state.orderDetail.visitId,
|
|
|
+ visitDetailId: state.orderDetail.visitDetailId,
|
|
|
+ orderId: state.orderDetail.orderId,
|
|
|
+ typeDicId: state.discernForm.type.dicDataValue,
|
|
|
+ typeDicName: state.discernForm.type.dicDataName,
|
|
|
+ content: state.discernForm.content,
|
|
|
+ screenType: state.ruleForm.screenType,
|
|
|
+ files: handleFilesDiscern.value,
|
|
|
+ },
|
|
|
+ nextWorkflow: { ...submitObj, files: handleFilesDiscern.value, opinion: state.discernForm.content },
|
|
|
+ };
|
|
|
+ discernUpdate(requestDiscern)
|
|
|
+ .then(() => {
|
|
|
+ afterSubmit('updateList', true);
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ afterSubmit('orderProcessFailed');
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+// 暴露变量
|
|
|
+defineExpose({
|
|
|
+ openDialog,
|
|
|
+ closeDialog,
|
|
|
+});
|
|
|
+</script>
|