ソースを参照

reactor:延期流程优化;

zhangchong 4 ヶ月 前
コミット
7bdc7b3819

+ 13 - 1
src/components/OrderDetail/index.vue

@@ -560,7 +560,7 @@
 				<!-- isCanDelay 为true表示可以发起延期申请并且可以办理工单(当前工单没有发起或者正在延期流程中)-->
 				<el-button
 					type="primary"
-					@click="onSubmit('延期申请', '延期附件')"
+					@click="onDelayApply"
 					:loading="state.loading"
 					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.isCanDelay && state.ruleForm.status !== 9"
 					v-auth="'business:order:delay'"
@@ -649,6 +649,8 @@
 	<l-z-process ref="lzProcessRef" @orderProcessSuccess="orderProcessSuccess" />
 	<!--  市场明细  -->
 	<market-detail ref="marketDetailRef" />
+	<!--  延期申请  -->
+	<delay-apply ref="delayApplyRef" @orderProcessSuccess="orderProcessSuccess" />
 </template>
 
 <script setup lang="ts" name="orderDetail">
@@ -679,6 +681,7 @@ const CopyOrder = defineAsyncComponent(() => import('@/views/todo/seats/accept/C
 const ZGProcess = defineAsyncComponent(() => import('@/components/ProcessAudit/ZGProcess.vue')); // 自贡流程
 const LZProcess = defineAsyncComponent(() => import('@/components/ProcessAudit/LZProcess.vue')); // 泸州流程
 const MarketDetail = defineAsyncComponent(() => import('@/views/business/order/components/Market-detail.vue')); // 市场明细
+const DelayApply = defineAsyncComponent(() => import('@/views/business/delay/components/Delay-apply.vue')); // 延期申请
 
 type ButtonType = '' | 'default' | 'success' | 'warning' | 'info' | 'text' | 'primary' | 'danger';
 const props = defineProps({
@@ -937,6 +940,15 @@ const onRecord = () => {
 	};
 	auditRecordRef.value.openDialog(params);
 };
+// 申请延期
+const delayApplyRef = ref<RefType>();
+const onDelayApply = ()=>{
+	const params = {
+		id: state.ruleForm.workflowId,
+		orderDetail: state.ruleForm,
+	};
+	delayApplyRef.value.openDialog(params);
+}
 // 提交流程
 const lzProcessRef = ref<RefType>();
 const processAuditRef = ref<RefType>(); // 处理流程

+ 1 - 15
src/views/business/delay/audit.vue

@@ -111,8 +111,6 @@
 		</div>
 		<!--  延期详情  -->
 		<delay-detail-com ref="delayDetailRef" @updateList="queryList" />
-		<!--  延期修改  -->
-		<delay-edit ref="delayEditRef" @updateList="queryList" />
 	</div>
 </template>
 <script setup lang="tsx" name="businessDelayAudit">
@@ -123,7 +121,6 @@ import { delayList } from '@/api/todo/delay';
 import { delayDetail } from '@/api/business/delay';
 // 引入组件
 const DelayDetailCom = defineAsyncComponent(() => import('@/views/business/delay/components/Delay-detail.vue')); // 延期详情
-const DelayEdit = defineAsyncComponent(() => import('@/views/business/delay/components/Delay-edit.vue')); // 延期修改
 const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
 const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
@@ -171,19 +168,8 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 };
 // 延期详情
 const delayDetailRef = ref<RefType>();
-const delayEditRef = ref<RefType>();
 const onDetail = async (row: any) => {
-	try {
-		const { result } = await delayDetail(row.id);
-		if (result.handle) {
-			// 退回到了开始 需要重新打开编辑页面在发起流程
-			delayEditRef.value.openDialog(row);
-		} else {
-			delayDetailRef.value.openDialog(row);
-		}
-	} catch (e) {
-		console.log(e);
-	}
+	delayDetailRef.value.openDialog(row);
 };
 const toolbarRef = ref<RefType>();
 const tableRef = ref<RefType>();

+ 341 - 0
src/views/business/delay/components/Delay-apply.vue

@@ -0,0 +1,341 @@
+<template>
+	<el-dialog
+		v-model="state.dialogVisible"
+		draggable
+		title="延期申请"
+		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.delayForm" label-width="110px" ref="delayFormRef">
+				<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="申请人"> {{ userInfos.name }} </el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="申请部门"> {{ userInfos.orgName }} </el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="申请时间"> {{ formatDate(new Date(), '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="当前期满时间"> {{ formatDate(state.orderDetail.expiredTime, '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.delayForm.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>
+						</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.delayForm.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="24" :md="24" :lg="24" :xl="12" v-loading="state.loading">
+						<el-form-item prop="timeLimitCount" :rules="[{ required: true, message: '请填写延期申请数量', trigger: 'blur' }]" label-width="130px">
+							<template #label>
+								<div style="height: 34px; display: flex; align-items: center">
+									延期申请数量
+									<el-tooltip placement="top-start">
+										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
+										<template #content> 延期申请数量为1-{{ AppConfigInfo.applyDelayTime }} </template>
+									</el-tooltip>
+								</div>
+							</template>
+							<el-row :gutter="10" class="w100">
+								<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+									<el-input-number
+										placeholder="延期申请数量"
+										v-model="state.delayForm.timeLimitCount"
+										controls-position="right"
+										class="w100"
+										:min="1"
+										:max="AppConfigInfo.applyDelayTime"
+									></el-input-number>
+								</el-col>
+								<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-loading="state.loading">
+									<el-form-item
+										label=""
+										label-width="0"
+										prop="timeLimitUnit"
+										:rules="[{ required: true, message: '请选择延期申请单位', trigger: 'change' }]"
+									>
+										<el-select disabled v-model="state.delayForm.timeLimitUnit" placeholder="延期申请单位">
+											<el-option v-for="item in timeType" :value="item.key" :key="item.key" :label="item.value" />
+										</el-select>
+									</el-form-item>
+								</el-col>
+							</el-row>
+						</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.delayForm.isSms" label="短信通知" />
+						</el-form-item>
+					</el-col>
+					<!--					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="延期后期满时间"> {{ state.delayForm.endTime }} </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="chooseAdviceDelay"
+								v-model="state.delayForm.content"
+								placeholder="请填写延期申请理由"
+								:loading="state.loading"
+								:commonEnum="commonEnum.Delay"
+								: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="延期附件" v-model:format="handleFilesDelay" :businessId="state.orderDetail.id" 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(delayFormRef)" :loading="state.loading">确定</el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+
+<script setup lang="ts" name="processApproval">
+import { computed, defineAsyncComponent, reactive, ref } from 'vue';
+import { ElMessage, FormInstance } from 'element-plus';
+import other from '@/utils/other';
+import { commonEnum } from '@/utils/constants';
+import { transformFile } from '@/utils/tools';
+import { formatDate } from '@/utils/formatTime';
+import { delayApply, delayApproveParams, delayBaseData, delayDetail, delayModify, workflowDelayParams } from '@/api/business/delay';
+import { useAppConfig } from '@/stores/appConfig';
+import { storeToRefs } from 'pinia';
+import { useUserInfo } from '@/stores/userInfo';
+
+// 引入组件
+const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
+const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue')); // 附件列表
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['orderProcessSuccess', 'orderProcessFailed']);
+
+const storesUserInfo = useUserInfo();
+const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
+const appConfigStore = useAppConfig();
+const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false, // 弹窗显示隐藏
+	delayForm: {
+		content: '', // 意见
+		nextStepCode: '', // 下一节点
+		nextStepName: '', // 下一节点名称
+		backToCountersignEnd: false, // 是否回到会签结束节点
+		nextHandlers: [], // 下一节点办理对象
+		nextMainHandler: '', // 主办人
+		isSms: false, // 是否短信通知
+		isStartCountersign: false, // 是否发起会签
+		stepId: '',
+		timeLimitCount: null, // 延期申请数量
+		timeLimitUnit: 2, // 延期申请单位 默认工作日
+	},
+	nextStepOptions: [], // 下一节点
+	handlerOptions: [], // 办理对象
+	transform: 'translate(0px, 0px)', // 滚动条位置
+	loading: false, // 提交按钮loading
+	workflowId: '', // 流程id
+	handlerClassifies: [], //撤回办理对象
+	handleId: '', // 流程处理ID
+	annexName: '', // 附件标题
+	inputPlaceholder: '', // 意见提示
+	orderDetail: {}, // 工单详情
+});
+const timeType = ref<EmptyArrayType>([]); // 延期申请单位
+// 打开弹窗
+const openDialog = async (val: any) => {
+	state.loading = true;
+	state.dialogVisible = true;
+	try {
+		const [workflowDelayResponse, responseDelay] = await Promise.all([workflowDelayParams(), delayBaseData()]); //获取开启流程参数
+		timeType.value = responseDelay.result?.timeType ?? []; // 延期时间单位
+		handleResult(workflowDelayResponse);
+		state.orderDetail = val.orderDetail;
+		state.loading = false;
+	} finally {
+		state.loading = false;
+	}
+};
+const canStartCountersign = ref<boolean>(false); // 是否可以发起会签
+const handleResult = (res: any) => {
+	state.nextStepOptions = res.result.steps; //办理对象选择内容
+	canStartCountersign.value = res.result.canStartCountersign ?? false; // 是否可以发起会签
+	if (state.nextStepOptions.length === 1) {
+		// 下一节点是否只有一个 默认选中第一个
+		setTimeout(() => {
+			state.delayForm.nextStepCode = state.nextStepOptions[0].key; // 下一节点code
+			state.delayForm.nextStepName = state.nextStepOptions[0].value; // 下一节点name
+			state.delayForm.backToCountersignEnd = state.nextStepOptions[0].backToCountersignEnd ?? false; // 是否回到会签结束节点
+		}, 0);
+		selectNextStep(state.nextStepOptions[0].key); // 查询流程下一节点参数
+	} else {
+		state.delayForm.nextStepCode = '';
+		state.delayForm.nextStepName = '';
+	}
+	state.delayForm.stepId = res.result.stepId;
+	state.loading = false;
+};
+// 流程选择下一环节
+const fastStepName = ref(''); // 推荐派单处理对象
+const fastStepCode = ref(''); // 推荐派单处理对象code
+const nextHandlersRequired = ref<Boolean>(false);
+const selectNextStep = (val: any) => {
+	delayFormRef.value?.resetFields('nextHandlers');
+	const next = state.nextStepOptions.find((item: any) => item.key === val);
+	const items = next.items; //获取下一节点
+	state.delayForm.nextStepName = next.value; // 下一节点name
+	state.delayForm.backToCountersignEnd = next.backToCountersignEnd ?? false; // 是否回到会签结束节点
+	state.delayForm.handlerType = next.handlerType;
+	state.delayForm.businessType = next.businessType;
+	state.delayForm.flowDirection = next.flowDirection;
+	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 multipleLimit = computed(() => {
+	return canStartCountersign.value ? 0 : 1;
+});
+
+// 是否展示办理对象 (只有结束节点不展示 next.stepType===2 表示为结束节点)
+const showHandlers = computed(() => {
+	const next = state.nextStepOptions.find((item: any) => item.key === state.delayForm.nextStepCode);
+	if (!next) return true;
+	return next.stepType !== 2;
+});
+
+// 选择办理对象
+const selectHandlers = () => {
+	if (state.delayForm.nextHandlers.length <= 1) {
+		// 如果只有一个办理对象就不需要发起会签
+		state.delayForm.isStartCountersign = false;
+	}
+};
+// 设置抽屉
+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;
+	formEl.resetFields();
+	formEl.clearValidate();
+};
+// 选择常用意见 填入填写框 延期
+const chooseAdviceDelay = (item: any) => {
+	state.delayForm.content += item.content;
+};
+const afterSubmit = (emitType?: 'orderProcessSuccess' | 'orderProcessFailed', showMessage?: boolean, message?: string) => {
+	state.loading = false;
+	closeDialog();
+	const msg = message ?? '操作成功';
+	if (showMessage) ElMessage.success(msg);
+	if (emitType) emit(emitType);
+};
+const delayFormRef = ref<RefType>();
+const close = () => {
+	restForm(delayFormRef.value);
+};
+// 提交
+const handleFilesDelay = ref<EmptyArrayType>([]); // 延期附件
+const onSubmit = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+		const requestDelay = {
+			data: {
+				orderId: state.orderDetail.id,
+				delayNum: state.delayForm.timeLimitCount,
+				delayUnit: state.delayForm.timeLimitUnit,
+				delayReason: state.delayForm.content,
+				files: handleFilesDelay.value,
+			},
+			workflow: {
+				nextStepCode: state.delayForm.nextStepCode,
+				nextStepName: state.delayForm.nextStepName,
+				backToCountersignEnd: state.delayForm.backToCountersignEnd,
+				nextHandlers: state.delayForm.nextHandlers,
+				flowDirection: state.delayForm.flowDirection,
+				handlerType: state.delayForm.handlerType,
+				stepType: state.delayForm.stepType,
+				businessType: state.delayForm.businessType,
+				isSms: state.delayForm.isSms,
+				opinion: state.delayForm.content,
+				files: handleFilesDelay.value,
+			},
+		};
+		delayApply(requestDelay)
+			.then(() => {
+				afterSubmit('orderProcessSuccess', true, '延期申请成功');
+			})
+			.catch(() => {
+				afterSubmit('orderProcessFailed');
+			});
+	});
+};
+// 暴露变量
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>

+ 0 - 456
src/views/business/delay/components/Delay-edit.vue

@@ -1,456 +0,0 @@
-<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"
-	>
-		<el-steps :active="activeStep" align-center finish-status="success" class="mb20">
-			<el-step title="业务表单" />
-			<el-step title="流程表单" />
-		</el-steps>
-
-		<div v-show="activeStep === 0" v-loading="state.loading">
-			<el-form :model="state.delayForm" label-width="110px" ref="delayFormRef">
-				<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.order?.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="当前期满时间"> {{ formatDate(state.orderDetail.beforeDelay, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" v-loading="state.loading">
-						<el-form-item prop="timeLimitCount" :rules="[{ required: true, message: '请填写延期申请数量', trigger: 'blur' }]" label-width="130px">
-							<template #label>
-								<div style="height: 34px; display: flex; align-items: center">
-									延期申请数量
-									<el-tooltip placement="top-start">
-										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
-										<template #content> 延期申请数量为1-{{ AppConfigInfo.applyDelayTime }} </template>
-									</el-tooltip>
-								</div>
-							</template>
-							<el-row :gutter="10" class="w100">
-								<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-									<el-input-number
-										placeholder="延期申请数量"
-										v-model="state.delayForm.timeLimitCount"
-										controls-position="right"
-										class="w100"
-										:min="1"
-										:max="AppConfigInfo.applyDelayTime"
-									></el-input-number>
-								</el-col>
-								<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-loading="state.loading">
-									<el-form-item
-										label=""
-										label-width="0"
-										prop="timeLimitUnit"
-										:rules="[{ required: true, message: '请选择延期申请单位', trigger: 'change' }]"
-									>
-										<el-select disabled v-model="state.delayForm.timeLimitUnit" placeholder="延期申请单位">
-											<el-option v-for="item in timeType" :value="item.key" :key="item.key" :label="item.value" />
-										</el-select>
-									</el-form-item>
-								</el-col>
-							</el-row>
-						</el-form-item>
-					</el-col>
-					<!--					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="延期后期满时间"> {{ state.delayForm.endTime }} </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="chooseAdviceDelay"
-								v-model="state.delayForm.content"
-								placeholder="请填写延期申请理由"
-								:loading="state.loading"
-								:commonEnum="commonEnum.Delay"
-								: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="延期附件" v-model:format="handleFilesDelay" :businessId="state.orderDetail.id" classify="延期上传" />
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-		</div>
-
-		<el-form :model="state.ruleForm" label-width="110px" ref="ruleFormRef" v-show="activeStep === 1" v-loading="state.loading">
-			<slot name="header"></slot>
-			<el-row :gutter="10">
-				<!-- 非退回流程都需要选择 -->
-				<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.ruleForm.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.ruleForm.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" v-if="showMainHandler">
-					<el-form-item label="主办" prop="nextMainHandler" :rules="[{ required: false, message: '请选择主办', trigger: 'change' }]">
-						<el-select v-model="state.ruleForm.nextMainHandler" placeholder="请选择主办" class="w100" filterable>
-							<el-option v-for="item in state.handlerMainOptions" :key="item.key" :label="item.value" :value="item.key" />
-						</el-select>
-					</el-form-item>
-				</el-col>
-				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="countersignAble">
-					<el-form-item label="发起会签" prop="isStartCountersign" :rules="[{ required: false, message: '请选择发起会签', trigger: 'change' }]">
-						<el-switch
-							v-model="state.ruleForm.isStartCountersign"
-							inline-prompt
-							active-text="是"
-							inactive-text="否"
-							@change="changeStartCountersign"
-							:disabled="countersignDisabled"
-						/>
-					</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.ruleForm.isSms" label="短信通知" />
-					</el-form-item>
-				</el-col>
-			</el-row>
-		</el-form>
-		<template #footer>
-			<span class="dialog-footer">
-				<el-button @click="closeDialog" class="default-button">取 消</el-button>
-				<el-button class="default-button" @click="onPrevious" :loading="state.loading" v-if="activeStep === 1">上一步</el-button>
-				<el-button class="default-button" @click="onNext" :loading="state.loading" v-if="activeStep === 0">下一步</el-button>
-				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading" v-if="activeStep === 1">办理</el-button>
-			</span>
-		</template>
-	</el-dialog>
-</template>
-
-<script setup lang="ts" name="processApproval">
-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 { transformFile } from '@/utils/tools';
-import { formatDate } from '@/utils/formatTime';
-import { delayApproveParams, delayBaseData, delayDetail, delayModify, workflowDelayParams } from '@/api/business/delay';
-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: '',
-	},
-	delayForm: {
-		//延期申请表单
-		timeLimitCount: null, // 延期申请数量
-		content: '', // 延期申请理由
-		timeLimitUnit: 2, // 延期申请单位 默认工作日
-	},
-	nextStepOptions: [], // 下一节点
-	handlerOptions: [], // 办理对象
-	transform: 'translate(0px, 0px)', // 滚动条位置
-	loading: false, // 提交按钮loading
-	workflowId: '', // 流程id
-	handlerClassifies: [], //撤回办理对象
-	handlerMainOptions: [], // 主办人
-	handleId: '', // 流程处理ID
-	dialogTitle: '', // 弹窗标题
-	annexName: '', // 附件标题
-	inputPlaceholder: '', // 意见提示
-	orderDetail: {}, // 工单详情
-});
-const ruleFormRef = ref<RefType>(); //表单组件
-const timeType = ref<EmptyArrayType>([]); // 延期申请单位
-const appConfigStore = useAppConfig();
-const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
-// 打开弹窗
-const openDialog = async (val: any) => {
-	state.loading = true;
-	state.dialogVisible = true;
-	try {
-		state.dialogTitle = '延期编辑'; // 流程标题
-		activeStep.value = 0;
-		if (val.workflowId) {
-			// 如果有流程ID说明已经开启过流程需要获取办理流程的参数
-			const [workflowDelayResponse, responseDelay] = await Promise.all([delayApproveParams(val.workflowId), delayBaseData()]); //获取开启流程参数
-			timeType.value = responseDelay.result?.timeType ?? []; // 延期时间单位
-			handleResult(workflowDelayResponse);
-		} else {
-			const [workflowDelayResponse, responseDelay] = await Promise.all([workflowDelayParams(), delayBaseData()]); //获取开启流程参数
-			timeType.value = responseDelay.result?.timeType ?? []; // 延期时间单位
-			handleResult(workflowDelayResponse);
-		}
-		const { result } = await delayDetail(val.id);
-		state.delayForm.content = result.delayReason ?? {};
-		state.delayForm.timeLimitCount = result.delayNum ?? null;
-		state.delayForm.timeLimitUnit = result.delayUnit ?? 2;
-		state.delayForm.endTime = formatDate(result.afterDelay, 'YYYY-mm-dd HH:MM:SS');
-		state.orderDetail = result;
-		state.ruleForm.files = transformFile(result.files);
-
-		await nextTick(() => {
-			restForm(ruleFormRef.value);
-		});
-		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 onPrevious = () => {
-	activeStep.value = 0;
-};
-const delayFormRef = ref<RefType>(); //甄别申请表单组件
-// 下一步
-const onNext = () => {
-	delayFormRef.value?.validate((valid: boolean) => {
-		if (!valid) return;
-		activeStep.value = 1;
-	});
-};
-const activeStep = ref(0); //步骤条
-// 流程选择下一环节
-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;
-	}
-};
-// 是否展示主办
-const showMainHandler = computed(() => {
-	return state.ruleForm.nextHandlers.length > 1 && isMainHandlerShow.value;
-});
-// 主办从办理对象中选择
-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 chooseAdviceDelay = (item: any) => {
-	state.delayForm.content += item.content;
-};
-const afterSubmit = (emitType?: 'updateList' | 'orderProcessFailed', showMessage?: boolean) => {
-	state.loading = false;
-	closeDialog();
-	if (showMessage) ElMessage.success('延期编辑成功');
-	if (emitType) emit(emitType);
-};
-const close = () => {
-	restForm(ruleFormRef.value);
-	restForm(delayFormRef.value);
-};
-// 提交
-const handleFilesDelay = 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 requestDelay = {
-			data: {
-				orderId: state.orderDetail.order?.id,
-				delayNum: state.delayForm.timeLimitCount,
-				delayUnit: state.delayForm.timeLimitUnit,
-				delayReason: state.delayForm.content,
-				files: handleFilesDelay.value,
-				id: state.orderDetail.id,
-				workflowId: state.orderDetail.workflowId,
-			},
-			nextWorkflow: { ...submitObj, files: handleFilesDelay.value, opinion: state.delayForm.content },
-		};
-		delayModify(requestDelay)
-			.then(() => {
-				afterSubmit('updateList', true);
-			})
-			.catch(() => {
-				afterSubmit('orderProcessFailed');
-			});
-	});
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>

+ 1 - 138
src/views/business/delay/index.vue

@@ -131,8 +131,6 @@
 		</div>
 		<!--  延期详情  -->
 		<delay-detail-com ref="delayDetailRef" @updateList="queryList" />
-		<!--  延期修改  -->
-		<delay-edit ref="delayEditRef" @updateList="queryList" />
 		<!--	更多查询	-->
 		<el-drawer v-model="drawer" title="更多查询" size="500px">
 			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="100px">
@@ -181,135 +179,11 @@ import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
 import Other from '@/utils/other';
 // 引入组件
 const DelayDetailCom = defineAsyncComponent(() => import('@/views/business/delay/components/Delay-detail.vue')); // 延期详情
-const DelayEdit = defineAsyncComponent(() => import('@/views/business/delay/components/Delay-edit.vue')); // 延期修改
 const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
 const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
 const storesThemeConfig = useThemeConfig();
 const { themeConfig } = storeToRefs(storesThemeConfig);
-// 表格配置项
-const columns = ref<any[]>([
-	{ prop: 'expiredStatusText', label: '超期状态', align: 'center', width: 80 },
-	{ prop: 'no', label: '工单编码', minWidth: 140 },
-	{ prop: 'order.isProvinceText', label: '省/市工单', minWidth: 90 },
-	{ prop: 'title', label: '工单标题', minWidth: 200 },
-	{ prop: 'currentStepName', label: '当前节点', minWidth: 120 },
-	{ prop: 'actualHandlerName', label: '审批人', minWidth: 120 },
-	{ prop: 'delayStateText', label: '延期申请状态', minWidth: 110 },
-	{
-		prop: 'order.startTime',
-		label: '受理时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.startTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'order.acceptorName', label: '受理人', minWidth: 120 },
-	{ prop: 'order.hotspotName', label: '热点分类', minWidth: 150 },
-	{ prop: 'order.acceptType', label: '受理类型', minWidth: 100 },
-	{ prop: 'order.orgLevelOneName', label: '一级部门', minWidth: 140 },
-	{ prop: 'order.actualHandleOrgName', label: '接办部门', minWidth: 140 },
-	{
-		prop: 'order.actualHandleTime',
-		label: '接办时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.actualHandleTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'creationTime',
-		label: '延期申请时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'creatorName', label: '延期申请人', minWidth: 120 },
-	{ prop: 'creatorOrgName', label: '延期申请部门', minWidth: 140 },
-	{ prop: 'delayNum', label: '延期申请时限', minWidth: 110 },
-	{ prop: 'delayUnitText', label: '延期申请单位', minWidth: 110 },
-	{ prop: 'delayReason', label: '申请理由', minWidth: 150 },
-	{
-		prop: 'beforeDelay',
-		label: '申请前期满时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.beforeDelay, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'afterDelay',
-		label: '通过后期满时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.afterDelay, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 90, align: 'center' },
-]);
-// 表格配置项
-const columns1 = ref<any[]>([
-	{ prop: 'expiredStatusText', label: '超期状态', align: 'center', width: 80 },
-	{ prop: 'no', label: '工单编码', minWidth: 140 },
-	{ prop: 'order.isProvinceText', label: '省/市工单', minWidth: 90 },
-	{ prop: 'title', label: '工单标题', minWidth: 200 },
-	{ prop: 'currentStepName', label: '当前节点', minWidth: 120 },
-	{ prop: 'automaticDelayNum', label: '自动延期次数', minWidth: 110 },
-	{ prop: 'actualHandlerName', label: '审批人', minWidth: 120 },
-	{ prop: 'delayStateText', label: '延期申请状态', minWidth: 110 },
-	{
-		prop: 'order.startTime',
-		label: '受理时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.startTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'order.acceptorName', label: '受理人', minWidth: 120 },
-	{ prop: 'order.hotspotName', label: '热点分类', minWidth: 150 },
-	{ prop: 'order.acceptType', label: '受理类型', minWidth: 100 },
-	{ prop: 'order.orgLevelOneName', label: '一级部门', minWidth: 140 },
-	{ prop: 'order.actualHandleOrgName', label: '接办部门', minWidth: 140 },
-	{
-		prop: 'order.actualHandleTime',
-		label: '接办时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.actualHandleTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'creationTime',
-		label: '延期申请时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'creatorName', label: '延期申请人', minWidth: 120 },
-	{ prop: 'creatorOrgName', label: '延期申请部门', minWidth: 140 },
-	{ prop: 'delayNum', label: '延期申请时限', minWidth: 110 },
-	{ prop: 'delayUnitText', label: '延期申请单位', minWidth: 110 },
-	{ prop: 'delayReason', label: '申请理由', minWidth: 150 },
-	{
-		prop: 'beforeDelay',
-		label: '申请前期满时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.beforeDelay, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'afterDelay',
-		label: '通过后期满时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.afterDelay, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 90, align: 'center' },
-]);
 // 定义变量内容
 const state = reactive<any>({
 	queryParams: {
@@ -386,20 +260,9 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 	queryList();
 };
 const delayDetailRef = ref<RefType>();
-const delayEditRef = ref<RefType>();
 // 延期详情
 const onDetail = async (row: any) => {
-	try {
-		const { result } = await delayDetail(row.id);
-		if (result.handle) {
-			// 退回到了开始 需要重新打开编辑页面在发起流程
-			delayEditRef.value.openDialog(row);
-		} else {
-			delayDetailRef.value.openDialog(row);
-		}
-	} catch (e) {
-		console.log(e);
-	}
+	delayDetailRef.value.openDialog(row);
 };
 const toolbarRef = ref<RefType>();
 const tableRef = ref<RefType>();

+ 6 - 6
src/views/business/discern/components/Discern-apply.vue

@@ -26,7 +26,7 @@
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
 						<el-form-item label="申请部门"> {{ userInfos.orgName }} </el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+					<el-col>
 						<el-form-item label="申请时间"> {{ formatDate(Date(), 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
@@ -58,11 +58,6 @@
 							/>
 						</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">
@@ -70,6 +65,11 @@
 							</el-select>
 						</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="24" :md="24" :lg="24" :xl="24">
 						<el-form-item label="申请理由" prop="content" :rules="[{ required: true, message: '请填写甄别申请理由', trigger: 'blur' }]">
 							<common-advice

+ 6 - 6
src/views/business/discern/components/Discern-edit.vue

@@ -26,7 +26,7 @@
 					<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-col>
 						<el-form-item label="申请时间"> {{ formatDate(state.orderDetail.creationTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
 					</el-col>
 					<!-- 非退回流程都需要选择 -->
@@ -56,11 +56,6 @@
 							/>
 						</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">
@@ -68,6 +63,11 @@
 							</el-select>
 						</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="24" :md="24" :lg="24" :xl="24">
 						<el-form-item label="申请理由" prop="content" :rules="[{ required: true, message: '请填写甄别申请理由', trigger: 'blur' }]">
 							<common-advice

+ 3 - 3
src/views/business/discern/index.vue

@@ -23,15 +23,15 @@
 					<el-segmented
 						:options="[
 							{
-								value: 0,
+								value: -1,
 								label: '全部',
 							},
 							{
-								value: 1,
+								value: 0,
 								label: '部门办件甄别',
 							},
 							{
-								value: -1,
+								value: 1,
 								label: '中心话务甄别',
 							},
 						]"

+ 6 - 1
src/views/business/terminate/apply.vue

@@ -148,6 +148,8 @@
 		<terminate-detail ref="terminateDetailRef" @updateList="queryList" />
 		<!-- 重提申请 -->
 		<terminate-edit ref="terminateEditRef" @updateList="queryList" />
+		<!-- 终止申请 -->
+		<terminate-apply ref="TerminateApplyRef" @updateList="queryList" />
 	</div>
 </template>
 <script setup lang="tsx" name="businessTerminateApply">
@@ -165,6 +167,7 @@ const AuditRecord = defineAsyncComponent(() => import('@/components/AuditRecord/
 const TerminateDetail = defineAsyncComponent(() => import('@/views/business/terminate/components/Terminate-detail.vue')); // 终止详情
 const TerminateEdit = defineAsyncComponent(() => import('@/views/business/terminate/components/Terminate-edit.vue')); // 重提申请
 const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+const TerminateApply = defineAsyncComponent(() => import('@/views/business/terminate/components/Terminate-apply.vue')); // 终止申请
 
 // 定义变量内容
 const state = reactive<any>({
@@ -231,6 +234,7 @@ const onProcessDetail = (row: any) => {
 };
 // 终止申请
 const processAuditRef = ref<RefType>();
+const TerminateApplyRef = ref<RefType>();
 const onApply = (row: any) => {
 	const params = {
 		id: row.id,
@@ -243,7 +247,8 @@ const onApply = (row: any) => {
 			annexName: '终止附件',
 		},
 	};
-	processAuditRef.value.openDialog(params);
+	TerminateApplyRef.value.openDialog(params)
+	// processAuditRef.value.openDialog(params);
 };
 // 终止详情
 const terminateDetailRef = ref<RefType>();

+ 305 - 0
src/views/business/terminate/components/Terminate-apply.vue

@@ -0,0 +1,305 @@
+<template>
+	<el-dialog
+		v-model="state.dialogVisible"
+		draggable
+		title="终止申请"
+		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.terminateForm" label-width="110px" ref="terminateFormRef">
+				<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="申请人"> {{ userInfos.name }} </el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="申请部门"> {{ userInfos.orgName }} </el-form-item>
+					</el-col>
+					<el-col>
+						<el-form-item label="申请时间"> {{ formatDate(Date(), '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.terminateForm.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>
+						</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: false, message: '请选择办理对象', trigger: 'change' }]">
+							<el-select-v2
+								v-model="state.terminateForm.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.terminateForm.isSms" label="短信通知" />
+						</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="chooseAdviceTerminate"
+								v-model="state.terminateForm.content"
+								placeholder="请填写终止申请理由"
+								:loading="state.loading"
+								:commonEnum="commonEnum.OrderCirculation"
+							/>
+						</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="terminateAnnexListRef"
+								v-model:format="handleFilesTerminate"
+								:businessId="state.orderDetail.id"
+								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(terminateFormRef)" :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 { transformFile } from '@/utils/tools';
+import { terminateDetail, terminateNextFlowParams, terminateStartFlow, terminateStartFlowParams } from '@/api/business/terminate';
+import { formatDate } from '@/utils/formatTime';
+import { useUserInfo } from '@/stores/userInfo';
+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 storesUserInfo = useUserInfo();
+const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false, // 弹窗显示隐藏
+	terminateForm: {
+		//流程表单
+		content: '', // 意见
+		nextStepCode: '', // 下一节点
+		nextStepName: '', // 下一节点名称
+		backToCountersignEnd: false, // 是否回到会签结束节点
+		nextHandlers: [], // 下一节点办理对象
+		isSms: false, // 是否短信通知
+		isStartCountersign: false, // 是否发起会签
+	},
+	nextStepOptions: [], // 下一节点
+	handlerOptions: [], // 办理对象
+	transform: 'translate(0px, 0px)', // 滚动条位置
+	loading: false, // 提交按钮loading
+	orderDetail: {}, // 工单详情
+});
+// 打开弹窗
+const openDialog = async (val: any) => {
+	console.log(val);
+	state.dialogVisible = true;
+	state.loading = true;
+	try {
+		const [workflowTerminateResponse] = await Promise.all([terminateStartFlowParams()]); //获取开启流程参数
+		handleResult(workflowTerminateResponse);
+		const { orderDetail } = val;
+		state.orderDetail = orderDetail ?? {}; // 工单详情
+		state.loading = false;
+	}catch (e){
+		console.log(e,'111');
+		state.loading = false;
+		state.dialogVisible = 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.terminateForm.nextStepCode = state.nextStepOptions[0].key; // 下一节点code
+			state.terminateForm.nextStepName = state.nextStepOptions[0].value; // 下一节点name
+			state.terminateForm.backToCountersignEnd = state.nextStepOptions[0].backToCountersignEnd ?? false; // 是否回到会签结束节点
+		}, 0);
+		selectNextStep(state.nextStepOptions[0].key); // 查询流程下一节点参数
+	} else {
+		state.terminateForm.nextStepCode = '';
+		state.terminateForm.nextStepName = '';
+	}
+	state.terminateForm.stepId = res.result.stepId;
+	state.loading = false;
+};
+// 流程选择下一环节
+const selectNextStep = (val: any) => {
+	terminateFormRef.value?.resetFields('nextHandlers');
+	const next = state.nextStepOptions.find((item: any) => item.key === val);
+	const items = next.items; //获取下一节点
+	state.terminateForm.nextStepName = next.value; // 下一节点name
+	state.terminateForm.backToCountersignEnd = next.backToCountersignEnd ?? false; // 是否回到会签结束节点
+	state.terminateForm.handlerType = next.handlerType;
+	state.terminateForm.businessType = next.businessType;
+	state.terminateForm.flowDirection = next.flowDirection;
+	state.handlerOptions = items ?? [];
+	state.handlerOptions = state.handlerOptions.map((item: any) => {
+		return {
+			value: {
+				...item,
+			},
+			label: item.value,
+		};
+	});
+	if (items.length === 1) {
+		// 如果办理对象只有一个默认选中
+		state.terminateForm.nextHandlers = [items[0]];
+	}
+};
+// 办理对象是否能够选择多个(可以发起会签可以选择多个,不能发起会签只能选择一个)
+const multipleLimit = computed(() => {
+	return canStartCountersign.value ? 0 : 1;
+});
+watch(
+	() => state.terminateForm.nextHandlers, // 监听办理对象 多个办理对象自动发起会签
+	(val) => {
+		state.terminateForm.isStartCountersign = val.length > 1;
+	}
+);
+
+// 是否展示办理对象 (只有结束节点不展示 next.stepType===2 表示为结束节点)
+const showHandlers = computed(() => {
+	const next = state.nextStepOptions.find((item: any) => item.key === state.terminateForm.nextStepCode);
+	if (!next) return true;
+	return next.stepType !== 2;
+});
+// 选择办理对象
+const selectHandlers = () => {
+	if (state.terminateForm.nextHandlers.length <= 1) {
+		// 如果只有一个办理对象就不需要发起会签
+		state.terminateForm.isStartCountersign = false;
+	}
+};
+// 设置抽屉
+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;
+	formEl.resetFields();
+	formEl.clearValidate();
+};
+// 选择常用意见 填入填写框 终止
+const chooseAdviceTerminate = (item: any) => {
+	state.terminateForm.content += item.content;
+};
+const afterSubmit = (emitType?: 'updateList' | 'orderProcessFailed', showMessage?: boolean) => {
+	state.loading = false;
+	closeDialog();
+	if (showMessage) ElMessage.success('终止申请成功');
+	if (emitType) emit(emitType);
+};
+const terminateFormRef = ref<RefType>();
+const close = () => {
+	restForm(terminateFormRef.value);
+};
+// 提交
+const handleFilesTerminate = ref<EmptyArrayType>([]); // 终止附件
+const onSubmit = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+
+/*		const requestTerminate = {
+			data: {
+				no: state.orderDetail.no,
+				orderId: state.orderDetail.id,
+				content: state.terminateForm.content,
+				files: handleFilesTerminate.value,
+			},
+			workflow: { ...submitObj, files: handleFilesTerminate.value, opinion: state.terminateForm.content },
+		};
+		terminateStartFlow(requestTerminate)
+			.then(() => {
+				afterSubmit('orderProcessSuccess', true, '终止申请成功');
+			})
+			.catch(() => {
+				afterSubmit('orderProcessFailed');
+			});*/
+
+
+		let submitObj = other.deepClone(state.terminateForm);
+		if (submitObj.nextHandlers && submitObj.nextHandlers.length) {
+			if (submitObj.nextHandlers.length === 1) {
+				submitObj.nextMainHandler = submitObj.nextHandlers[0].key;
+			}
+		}
+		const requestTerminate = {
+			data: {
+				no: state.orderDetail.order?.no,
+				orderId: state.orderDetail.order?.id,
+				content: state.terminateForm.content,
+				files: handleFilesTerminate.value,
+			},
+			workflow: { ...submitObj, files: handleFilesTerminate.value, opinion: state.terminateForm.content },
+		};
+		terminateStartFlow(requestTerminate)
+			.then(() => {
+				afterSubmit('updateList', true);
+			})
+			.catch(() => {
+				afterSubmit('orderProcessFailed');
+			});
+	});
+};
+// 暴露变量
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>