فهرست منبع

reactor:修复平移的问题;

zhangchong 4 ماه پیش
والد
کامیت
cd394982ac

+ 1 - 1
.env.development

@@ -3,7 +3,7 @@ VITE_MODE_NAME=development
 # 防止部署多套系统到同一域名不同目录时,变量共用的问题 设置不同的前缀
 VITE_STORAGE_NAME=dev
 # 业务系统基础请求地址
-VITE_API_URL=http://110.188.24.28:50100
+VITE_API_URL=http://110.188.24.28:50300
 # 业务系统socket请求地址
 VITE_API_SOCKET_URL=http://110.188.24.28:50100/hubs/hotline
 # 业务系统文件上传上传请求地址

+ 16 - 11
src/views/business/discern/YBApply.vue

@@ -108,16 +108,6 @@
 				:disabled="state.loading"
 			/>
 		</div>
-		<!-- 流程审批 -->
-		<process-audit ref="processAuditRef" @orderProcessSuccess="queryList" />
-		<!-- 回访详情 -->
-		<visit-detail-com ref="visitDetailRef" @updateList="queryList" />
-		<!-- 甄别详情 -->
-		<discern-detail ref="discernDetailRef" @updateList="queryList" />
-		<!-- 甄别修改 -->
-		<discern-edit ref="discernEditRef" @updateList="queryList" />
-		<!-- 修改甄别提起时限 -->
-		<discern-edit-apply-time ref="discernEditApplyTimeRef" @updateList="queryList" />
 		<!--	更多查询	-->
 		<el-drawer v-model="drawer" title="更多查询" size="500px">
 			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="100px">
@@ -211,6 +201,18 @@
 				<el-button @click="resetQuery(drawerRuleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
 			</template>
 		</el-drawer>
+		<!-- 流程审批 -->
+		<process-audit ref="processAuditRef" @orderProcessSuccess="queryList" />
+		<!-- 回访详情 -->
+		<visit-detail-com ref="visitDetailRef" @updateList="queryList" />
+		<!-- 甄别详情 -->
+		<discern-detail ref="discernDetailRef" @updateList="queryList" />
+		<!-- 甄别修改 -->
+		<discern-edit ref="discernEditRef" @updateList="queryList" />
+		<!-- 修改甄别提起时限 -->
+		<discern-edit-apply-time ref="discernEditApplyTimeRef" @updateList="queryList" />
+		<!--	甄别申请	-->
+		<discern-apply ref="discernApplyRef" @updateList="queryList" />
 	</div>
 </template>
 <script setup lang="tsx" name="businessDiscernYBApply">
@@ -229,6 +231,7 @@ const DiscernDetail = defineAsyncComponent(() => import('@/views/business/discer
 const DiscernEdit = defineAsyncComponent(() => import('@/views/business/discern/components/Discern-edit.vue')); // 甄别修改
 const DiscernEditApplyTime = defineAsyncComponent(() => import('@/views/business/discern/components/Discern-edit-apply-time.vue')); // 修改甄别提起时限
 const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+const DiscernApply = defineAsyncComponent(() => import('@/views/business/discern/components/Discern-apply.vue')); // 甄别申请
 
 const state = reactive<any>({
 	queryParams: {
@@ -346,7 +349,9 @@ const sortChange = (val: any) => {
 // 甄别审批
 const processAuditRef = ref<RefType>(); // 流程审批ref
 const discernEditRef = ref<RefType>(); // 甄别修改ref
+const discernApplyRef = ref<RefType>(); // 甄别申请
 const submitDiscern = (row: any) => {
+	console.log(row,'111')
 	if (row.screenSendBack) {
 		if (row.orderScreens.length) {
 			const editRow = { ...row.orderScreens[0], screenType: 0 };
@@ -372,7 +377,7 @@ const submitDiscern = (row: any) => {
 				screenType: 0,
 			},
 		};
-		processAuditRef.value.openDialog(params);
+		discernApplyRef.value.openDialog(params);
 	}
 };
 // 查看甄别详情

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

@@ -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>

+ 2 - 2
src/views/business/order/index.vue

@@ -169,12 +169,12 @@
 					<vxe-column field="sensitiveText" title="敏感词" width="150"></vxe-column>
 					<vxe-column field="content" title="受理内容" width="200" :visible="false"></vxe-column>
 					<vxe-column field="fileOpinion" title="承办意见" width="200" :visible="false"></vxe-column>
-					<vxe-column field="seatEvaluateTxt" title="坐席满意度" width="150" :v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"></vxe-column>
+					<vxe-column field="seatEvaluateTxt" title="坐席满意度" width="150" v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"></vxe-column>
 					<vxe-column
 						field="orgEvaluateValue"
 						title="部门满意度"
 						width="150"
-						:v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"
+						v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"
 					></vxe-column>
 					<vxe-column title="操作" fixed="right" width="140" align="center">
 						<template #default="{ row }">

+ 1 - 1
src/views/business/visit/index.vue

@@ -80,7 +80,7 @@
 						field="isEffectiveAiVisitText"
 						title="有效智能回访"
 						width="150"
-						:v-if="['YiBin'].includes(themeConfig.appScope)"
+						v-if="['YiBin'].includes(themeConfig.appScope)"
 					></vxe-column>
 					<vxe-column field="order.acceptType" title="受理类型" width="110"></vxe-column>
 					<vxe-column field="order.hotspotName" title="热点分类" width="150"></vxe-column>