Browse Source

Merge branch 'release' into dev

zhangchong 2 weeks ago
parent
commit
679bcb6301
51 changed files with 1991 additions and 437 deletions
  1. 1 1
      .env.development
  2. 2 1
      src/App.vue
  3. 9 0
      src/api/auxiliary/area.ts
  4. 40 1
      src/api/business/order.ts
  5. 83 65
      src/api/callCenter/index.ts
  6. 11 0
      src/api/statistics/order.ts
  7. 24 14
      src/components/CommonAdvice/index.vue
  8. 25 13
      src/components/OrderDetail/index.vue
  9. 37 15
      src/components/ProcessAudit/ZGSSPProcess.vue
  10. 51 20
      src/directive/authDirective.ts
  11. 4 1
      src/directive/index.ts
  12. 56 0
      src/directive/permissionAuth.ts
  13. 9 0
      src/layout/navBars/breadcrumb/zgTel.vue
  14. 9 0
      src/router/route.ts
  15. 3 7
      src/utils/request.ts
  16. 1 1
      src/utils/tools.ts
  17. 21 2
      src/views/auxiliary/message/index.vue
  18. 21 1
      src/views/business/delay/components/Delay-audit.vue
  19. 21 1
      src/views/business/delay/components/Delay-detail.vue
  20. 64 15
      src/views/business/discern/components/Discern-audit.vue
  21. 22 1
      src/views/business/discern/components/Discern-detail.vue
  22. 12 0
      src/views/business/discern/components/Discern-return.vue
  23. 652 0
      src/views/business/order/enterprise.vue
  24. 16 48
      src/views/business/order/index.vue
  25. 3 1
      src/views/business/order/tableHeader.tsx
  26. 21 1
      src/views/business/terminate/components/Terminate-audit.vue
  27. 175 10
      src/views/business/visit/components/Visit-detail.vue
  28. 0 1
      src/views/business/visit/components/Visit-redo.vue
  29. 66 17
      src/views/business/visit/dpSatisfied.vue
  30. 8 1
      src/views/business/visit/todo.vue
  31. 1 1
      src/views/judicial/order/components/orderDetail.vue
  32. 25 12
      src/views/judicial/order/components/verify.vue
  33. 14 18
      src/views/judicial/order/index.vue
  34. 2 2
      src/views/judicial/statistics/detailArea.vue
  35. 1 1
      src/views/judicial/statistics/detailDepartment.vue
  36. 1 1
      src/views/judicial/statistics/detailEventClass.vue
  37. 1 1
      src/views/judicial/statistics/detailSatisfied.vue
  38. 16 25
      src/views/judicial/statistics/eventClass.vue
  39. 26 5
      src/views/knowledge/index/preview.vue
  40. 21 5
      src/views/snapshot/config/industry/components/Industry-edit.vue
  41. 2 2
      src/views/snapshot/reSend/supplyLog.vue
  42. 11 4
      src/views/statistics/department/detailHandle.vue
  43. 5 0
      src/views/statistics/department/detailHandleList.vue
  44. 45 1
      src/views/statistics/department/dpSatisfied.vue
  45. 151 108
      src/views/statistics/order/YBVisitCount.vue
  46. 184 0
      src/views/statistics/order/detailVisitContent.vue
  47. 4 5
      src/views/tels/callLog/zgCallLog.vue
  48. 3 1
      src/views/todo/order/tableHeader.tsx
  49. 7 5
      src/views/todo/seats/accept/lzAccept.vue
  50. 1 1
      src/views/todo/seats/accept/ybAccept.vue
  51. 3 1
      src/views/todo/seats/tableHeader.tsx

+ 1 - 1
.env.development

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

+ 2 - 1
src/App.vue

@@ -239,7 +239,8 @@ const setLockScreen = computed(() => {
 
 // 可同时显示的消息最大数量
 const messageConfig = reactive<any>({
-	max: 3,
+	max: 3, // 最大数量
+	offset: 70, // 距离顶部的距离
 });
 // 自动在两个中文字符之间插入空格
 const buttonConfig = reactive<any>({

+ 9 - 0
src/api/auxiliary/area.ts

@@ -12,6 +12,15 @@ export const treeArea = () => {
 		method: 'get',
 	});
 };
+/**
+ * @description 获取省市区树形 (泸州)
+ */
+export const treeAreaLZ = () => {
+	return request({
+		url: `/api/v1/Sys/area/tree_accepted`,
+		method: 'get',
+	});
+};
 /**
  * @description 导出省市区树形
  */

+ 40 - 1
src/api/business/order.ts

@@ -425,4 +425,43 @@ export const orderAttachmentAdd = (data: object) => {
 		method: 'post',
 		data,
 	});
-}
+}
+/**
+ * @description 工单列表 企业
+ * @param {any} params
+ */
+export const orderListEnterprise = (params: any) => {
+	return request({
+		url: `/api/v1/Order/enterprise/list`,
+		method: 'get',
+		params,
+	});
+};
+/**
+ * @description 查询工单列表总数 企业
+ * @param {any} params
+ */
+export const orderListCountEnterprise = (params: any) => {
+	return request({
+		url: `/api/v1/Order/enterprise/count`,
+		method: 'get',
+		params,
+	});
+};
+/**
+ * @description 导出工单 企业
+ * @param {object} data
+ */
+export const exportOrderEnterprise = (data: object) => {
+	return request(
+		{
+			url: `/api/v1/Order/enterprise/export`,
+			method: 'post',
+			responseType: 'blob',
+			data,
+		},
+		{
+			reduce_data_format: false,
+		}
+	);
+};

+ 83 - 65
src/api/callCenter/index.ts

@@ -8,139 +8,157 @@ import request from '@/utils/request';
  * @param params
  */
 export const getCallCenterList = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/tels`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/tels`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 查询呼叫中心分机组列表
  * @param params
  */
 export const getCallCenterGroupList = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/groups`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/groups`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 呼叫中心签入
  * @param data
  */
 export const callCenterSignIn = (data: object) => {
-    return request({
-        url: `/api/v1/Call/signin`,
-        method: 'post',
-        data,
-    });
+	return request({
+		url: `/api/v1/Call/signin`,
+		method: 'post',
+		data,
+	});
 };
 /**
  * @description 呼叫中心签出
  * @param data
  */
 export const callCenterSignOut = (data: object) => {
-    return request({
-        url: `/api/v1/Call/signout`,
-        method: 'post',
-        data,
-    });
+	return request({
+		url: `/api/v1/Call/signout`,
+		method: 'post',
+		data,
+	});
 };
 /**
  * @description 呼叫中心签出(强制业务系统签出)
  * @param telNo
  */
 export const callCenterSignOutForce = (telNo: string) => {
-    return request({
-        url: `/api/v1/Call/signout/${telNo}`,
-        method: 'post',
-    });
+	return request({
+		url: `/api/v1/Call/signout/${telNo}`,
+		method: 'post',
+	});
 };
 /**
  * @description 查询当前用户的分机状态
  * @param params
  */
 export const getCallCenterStatus = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/tel-state`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/tel-state`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 查询呼叫中心通话记录基础数据
  * @param params
  */
 export const getCallCenterCallRecordBaseData = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/base-data`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/base-data`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 查询呼叫中心通话记录(固定数量)
  * @param params
  */
 export const getCallCenterCallRecord = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/calls-fixed`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/calls-fixed`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 查询呼叫中心通话记录(固定数量)查询总数
  * @param params
  */
 export const getCallCenterCallRecordTotal = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/calls-fixed/count`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/calls-fixed/count`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 查询呼叫中心坐席操作记录基础数据
  * @param params
  */
 export const getCallCenterOperateRecordBaseData = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/base-data-tel-operation`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/base-data-tel-operation`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 查询呼叫中心坐席操作记录
  * @param params
  */
 export const getCallCenterOperateRecord = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/tel-operations-fixed`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/tel-operations-fixed`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 查询呼叫中心坐席操作记录查询总条数
  * @param params
  */
 export const getCallCenterOperateRecordTotal = (params?: object) => {
-    return request({
-        url: `/api/v1/Call/tel-operations-fixed/count`,
-        method: 'get',
-        params,
-    });
+	return request({
+		url: `/api/v1/Call/tel-operations-fixed/count`,
+		method: 'get',
+		params,
+	});
 };
 /**
  * @description 校验电话号码外呼是否需要加0
  * @param mobile
  */
-export const callNumberIsLocal = (mobile ?: number | string | any) => {
-    return request({
-        url: `/api/v1/Sys/vaild_mobile/${mobile}`,
-        method: 'get',
-    });
-};
+export const callNumberIsLocal = (mobile?: number | string | any) => {
+	return request({
+		url: `/api/v1/Sys/vaild_mobile/${mobile}`,
+		method: 'get',
+	});
+};
+/**
+ * @description 分页通话记录列表导出 兴唐
+ * @param {object} data
+ * @return {*}
+ */
+export const callLogXTPagedExport = (data: object) => {
+	return request(
+		{
+			url: `/api/v1/Call/calls-fixed/export`,
+			method: 'post',
+			data,
+			responseType: 'blob',
+		},
+		{
+			reduce_data_format: false,
+		}
+	);
+};

+ 11 - 0
src/api/statistics/order.ts

@@ -243,6 +243,17 @@ export const departmentVisit = (params: object) => {
 		params,
 	});
 };
+/**
+ * @description 只能回访不满意明细
+ * @param {object} params
+ */
+export const departmentVisitDetailSmart = (params: object) => {
+	return request({
+		url: `/api/v1/BiOrder/aivisit-nosatisfied-paeglist`,
+		method: 'get',
+		params,
+	});
+}
 /**
  * @description 回访量统计导出
  * @param {object} data

+ 24 - 14
src/components/CommonAdvice/index.vue

@@ -15,8 +15,10 @@
 			</el-input>
 			<span class="buttons">
 				<el-button @click="textCheck" class="default-button" :disabled="props.disabled" v-if="props.showTextCheck">文本检查</el-button>
-				<el-button @click="showAdvice" class="default-button" :disabled="props.disabled">常用意见</el-button>
-				<el-button type="primary" @click="onAddAdvice" :disabled="props.disabled">添加到常用意见</el-button>
+				<template v-if="props.adviceAble">
+					<el-button @click="showAdvice" class="default-button" :disabled="props.disabled">常用意见</el-button>
+					<el-button type="primary" @click="onAddAdvice" :disabled="props.disabled">添加到常用意见</el-button>
+				</template>
 			</span>
 		</div>
 		<pre v-if="highlightedText" v-html="highlightedText" class="highlighted-text"></pre>
@@ -130,6 +132,11 @@ const props = defineProps({
 		type: String,
 		default: '',
 	},
+	adviceAble: {
+		// 是否展示常用意见
+		type: Boolean,
+		default: true,
+	},
 	disabled: {
 		type: Boolean,
 		default: false,
@@ -321,7 +328,7 @@ const closeDialog = () => {
 	state.showDrawer = false;
 };
 // 字节位置转换为字符位置的函数
-const byteToCharIndex=(text:string, byteIndex:number)=> {
+const byteToCharIndex = (text: string, byteIndex: number) => {
 	let charIndex = 0;
 	let byteCount = 0;
 
@@ -334,11 +341,11 @@ const byteToCharIndex=(text:string, byteIndex:number)=> {
 	}
 
 	return charIndex;
-}
+};
 // 计算属性,生成高亮文本
-const highlightedFn= (text:string, errors:any[]) => {
+const highlightedFn = (text: string, errors: any[]) => {
 	let highlighted = text;
-	const errorPositions = errors.map(error => {
+	const errorPositions = errors.map((error) => {
 		const startCharPos = byteToCharIndex(value.value, error.begPos);
 		const endCharPos = byteToCharIndex(value.value, error.begPos + error.length);
 		return { startCharPos, endCharPos };
@@ -353,15 +360,15 @@ const highlightedFn= (text:string, errors:any[]) => {
 	});
 
 	return highlighted;
-}
+};
 // 文件检查
 const highlightedText = ref('');
 const errorWordsArray = ref([]);
 const textCheck = () => {
-	if(!value.value) {
+	if (!value.value) {
 		ElMessage.warning({
-			message:props.placeholder,
-			grouping:true
+			message: props.placeholder,
+			grouping: true,
 		});
 		return;
 	}
@@ -408,9 +415,12 @@ const textCheck = () => {
 		})
 		.catch(() => {});
 };
-watch(()=>value.value,(val)=>{
-	if(!val) highlightedText.value = '';
-})
+watch(
+	() => value.value,
+	(val) => {
+		if (!val) highlightedText.value = '';
+	}
+);
 // 暴露变量
 defineExpose({
 	openDialog,
@@ -435,7 +445,7 @@ defineExpose({
 		padding-bottom: 40px;
 	}
 	.highlighted-text {
-		margin-top:10px;
+		margin-top: 10px;
 		background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
 		background-image: none;
 		border: none;

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

@@ -43,10 +43,10 @@
 				<div class="collapse-container">
 					<el-form label-width="100px" ref="ruleFormRef">
 						<el-row :gutter="10">
-							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.transferPhone">
+							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm?.transferPhone">
 								<el-form-item label="转接来源"> {{ state.ruleForm.transferPhone }} </el-form-item>
 							</el-col>
-							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.fromPhone">
+							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm?.fromPhone">
 								<el-form-item label="来电号码">
 									{{ state.ruleForm.fromPhone }}
 									<el-button
@@ -188,7 +188,7 @@
 										type="primary"
 										class="ml8"
 										@click="showRepeatInfo"
-										v-if="state.ruleForm.duplicateIds && state.ruleForm.duplicateIds.length > 0"
+										v-if="state.ruleForm.duplicateIds && state.ruleForm?.duplicateIds.length > 0"
 										>查看重复工单</el-button
 									>
 								</el-form-item>
@@ -198,7 +198,9 @@
 							</el-col>
 							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="ZGCenter">
 								<el-form-item label="受理人">
-									<span>{{ state.ruleForm?.acceptorName }} <span v-if="state.ruleForm?.acceptorStaffNo">【{{ state.ruleForm?.acceptorStaffNo }}】</span> </span>
+									<span
+										>{{ state.ruleForm?.acceptorName }} <span v-if="state.ruleForm?.acceptorStaffNo">【{{ state.ruleForm?.acceptorStaffNo }}】</span>
+									</span>
 								</el-form-item>
 							</el-col>
 							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.creationTime">
@@ -646,7 +648,7 @@
 		<div v-if="state.activeName === '6'">
 			<map-view ref="mapViewRef" v-if="mapVisible" :markData="markData" />
 		</div>
-		<template #footer>
+		<template #footer v-if="props.showFooter">
 			<span class="dialog-footer">
 				<el-text
 					v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope) && state.ruleForm?.sendBackAuditEndTime"
@@ -670,14 +672,20 @@
 					>结束会签</el-button
 				>
 				<!-- 有流程信息就可以查询明细 -->
-				<el-button type="primary" @click="onRecord" :loading="state.loading" v-if="state.ruleForm?.workflowId">流程明细(旧)</el-button>
+				<el-button
+					type="primary"
+					@click="onRecord"
+					:loading="state.loading"
+					v-if="state.ruleForm?.workflowId && ['YiBin', 'LuZhou'].includes(themeConfig.appScope)"
+					>流程明细(旧)</el-button
+				>
 				<el-button type="primary" @click="onRecordNew" :loading="state.loading" v-if="state.ruleForm?.workflowId">流程明细(新)</el-button>
 				<!-- 有流程信息就可以撤回 -->
 				<el-button
 					type="primary"
 					@click="onSpecialHandle"
 					:loading="state.loading"
-					v-if="state.ruleForm?.workflowId && state.ruleForm.status !== 9"
+					v-if="state.ruleForm?.workflowId && state.ruleForm?.status !== 9"
 					v-auth="'business:order:teti'"
 					>特 提</el-button
 				>
@@ -686,7 +694,7 @@
 					type="primary"
 					@click="onSupervise"
 					:loading="state.loading"
-					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm.status !== 9"
+					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.status !== 9"
 					v-auth="'business:order:supervise:apply'"
 					>督 办</el-button
 				>
@@ -695,7 +703,7 @@
 					type="primary"
 					@click="onUrge"
 					:loading="state.loading"
-					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm.status !== 9"
+					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.status !== 9"
 					v-auth="'business:order:urge:apply'"
 				>
 					催 办</el-button
@@ -706,7 +714,7 @@
 					type="primary"
 					@click="onDelayApply"
 					:loading="state.loading"
-					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.isCanDelay && state.ruleForm.status !== 9"
+					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.isCanDelay && state.ruleForm?.status !== 9"
 					v-auth="'business:order:delay'"
 					>延 期</el-button
 				>
@@ -717,7 +725,7 @@
 					@click="onCancelDelay"
 					:loading="state.loading"
 					v-auth="'business:order:cancelDelay'"
-					v-if="state.ruleForm?.isCanCancelDelay && state.ruleForm.status !== 9"
+					v-if="state.ruleForm?.isCanCancelDelay && state.ruleForm?.status !== 9"
 					>取消延期</el-button
 				>
 				<!-- 100-200 表示工单正在办理中 并且应该自己办理 -->
@@ -725,7 +733,7 @@
 					type="primary"
 					@click="onSubmit('工单办理')"
 					:loading="state.loading"
-					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.canHandle && state.ruleForm.status !== 9"
+					v-if="isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.canHandle && state.ruleForm?.status !== 9"
 					v-auth="'business:order:handle'"
 					>办 理</el-button
 				>
@@ -749,7 +757,7 @@
 					@click="onReturn"
 					:loading="state.loading"
 					v-if="
-						isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.canHandle && state.ruleForm?.canPrevious && state.ruleForm.status !== 9
+						isInRange(state.ruleForm?.status, 100, 200) && state.ruleForm?.canHandle && state.ruleForm?.canPrevious && state.ruleForm?.status !== 9
 					"
 					v-auth="'business:order:return'"
 					>退 回</el-button
@@ -879,6 +887,10 @@ const props = defineProps({
 		type: Boolean,
 		default: false,
 	},
+	showFooter: {
+		type: Boolean,
+		default: true,
+	},
 });
 const storesUserInfo = useUserInfo();
 const storesThemeConfig = useThemeConfig();

+ 37 - 15
src/components/ProcessAudit/ZGSSPProcess.vue

@@ -51,7 +51,7 @@
 					<!-- 随手拍电气焊申报工单 并且是部门办理时 -->
 					<template v-if="orgDQH">
 						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-							<el-form-item label="核实方式" prop="verifyType" :rules="[{ required: false, message: '请选择核实方式', trigger: 'change' }]">
+							<el-form-item label="核实方式" prop="verifyType" :rules="[{ required: true, message: '请选择核实方式', trigger: 'change' }]">
 								<el-radio-group v-model="state.ruleForm.verifyType">
 									<el-radio value="现场">现场</el-radio>
 									<el-radio value="电话">电话</el-radio>
@@ -70,8 +70,8 @@
 							<el-form-item
 								label="是否按照清单检查"
 								prop="isCheckList"
-								:rules="[{ required: false, message: '请选择是否按照清单检查', trigger: 'change' }]"
-								label-width="130px"
+								:rules="[{ required: true, message: '请选择是否按照清单检查', trigger: 'change' }]"
+								label-width="140px"
 							>
 								<el-radio-group v-model="state.ruleForm.isCheckList">
 									<el-radio :value="true">是</el-radio>
@@ -80,7 +80,7 @@
 							</el-form-item>
 						</el-col>
 						<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-							<el-form-item>
+							<el-form-item label="附件模板">
 								<el-link type="primary" class="mr5" v-for="item in documentFiles" @click="openFile(item)" :key="item.id">{{ item.fileName }}</el-link>
 							</el-form-item>
 						</el-col>
@@ -170,7 +170,7 @@
 								</el-row>
 							</el-col>
 							<el-col>
-								<el-form-item>
+								<el-form-item label="附件模板">
 									<el-link type="primary" class="mr5" v-for="item in documentFiles" @click="openFile(item)" :key="item.id">{{
 										item.fileName
 									}}</el-link>
@@ -709,6 +709,7 @@ import { orderPrevious, workflowNextSteps, workflowNextStepsByOrder, workflowNex
 import { useAppConfig } from '@/stores/appConfig';
 import { VTreeDrop } from '@wsfe/vue-tree';
 import { removeDuplicate } from '@/utils/arrayOperation';
+import { fileDownloadByUrl } from '@/api/public/file';
 
 // 引入组件
 const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
@@ -1001,6 +1002,10 @@ const orgSummaryToEnd = computed(() => {
 		selectNext.value.key === 'end'
 	);
 });
+// 部门流转到归档
+const orgToEnd = computed(() => {
+	return currentParams.value.currentStepBusinessType === 2 && selectNext.value.key === 'end';
+});
 // 判断当前工单是 随手拍电气焊作业申报 并且是部门办理时 并且当前节点是普通节点 并且选择的下一节点是汇总或者归档
 const orgDQH = computed(() => {
 	return (
@@ -1010,19 +1015,21 @@ const orgDQH = computed(() => {
 		state.orderDetail.industryName === '电气焊作业申报'
 	);
 });
-// 会签 部门会签 判断当前工单是 安全隐患 并且是当前在部门会签中 并且是否存在安全隐患没有填写过 并且选择的下一节点是汇总或者归档
+// 会签 部门会签 判断当前工单是 安全隐患 并且当前节点是最初发起会签的节点 并且选择的下一节点是汇总或者归档
 // 非会签 判断当前工单是 安全隐患 并且是部门办理时 并且当前节点是普通节点 并且当前不能是会签汇总节点 并且选择的下一节点是汇总或者归档
 const orgAQYH = computed(() => {
+	// 判断名字是否是以安全隐患开头
+	const isAQYHOrder = state.orderDetail.industryName?.startsWith('安全隐患');
 	return (
 		(currentParams.value.counterSignType === 1 &&
-			currentParams.value.isDangerDepartment === null &&
+			currentParams.value.currentIsTopCountersignEndStep &&
 			(selectNext.value.stepType === 3 || selectNext.value.key === 'end') &&
-			state.orderDetail.industryName === '安全隐患') ||
+			isAQYHOrder) ||
 		(currentParams.value.counterSignType === null &&
-		currentParams.value.currentStepBusinessType === 2 &&
-		currentParams.value.currentStepType === 0 &&
-		(selectNext.value.stepType === 3 || selectNext.value.key === 'end') &&
-		state.orderDetail.industryName === '安全隐患')
+			currentParams.value.currentStepBusinessType === 2 &&
+			currentParams.value.currentStepType === 0 &&
+			(selectNext.value.stepType === 3 || selectNext.value.key === 'end') &&
+			isAQYHOrder)
 	);
 });
 //  currentParams.value.CounterSignType 判断当前节点是否在会签中 0中心会签 1部门会签
@@ -1106,7 +1113,7 @@ const selectNextStep = (val: any) => {
 	// 是否展示短信通知 (话务部到一级部门 派单组到一级部门 部门流转到部门 部门到汇总 部门流转到部门领导 部门退回到部门)
 	isSmsSelectShow.value =
 		seatToOrgOne.value || paidanToOrgOne.value || orgToOrg.value || orgToOrgSummary.value || orgToOrgLeader.value || orgReturnOrg.value;
-	// 是否不展示办理对象  (话务部到一级部门 派单组到一级部门 派单到归档 一级部门到归档 部门到部门 部门到汇总)
+	// 是否不展示办理对象  (话务部到一级部门 派单组到一级部门 派单到归档 一级部门到归档 部门到部门 部门到汇总 部门到归档
 	isNotShowNextHandlers.value =
 		seatToOrgOne.value ||
 		paidanToOrgOne.value ||
@@ -1114,7 +1121,8 @@ const selectNextStep = (val: any) => {
 		orgOneToEnd.value ||
 		orgToOrg.value ||
 		orgToOrgSummary.value ||
-		orgSummaryToEnd.value;
+		orgSummaryToEnd.value ||
+		orgToEnd.value;
 
 	if (seatToOrgOne.value || paidanToOrgOne.value) {
 		// 话务部到一级部门 派单组到一级部门 默认选中主协办
@@ -1582,7 +1590,21 @@ const otherReasonRequired = computed(() => {
 // 打开文件
 const openFile = (file: any) => {
 	console.log(file);
-	window.open(import.meta.env.VITE_API_UPLOAD_URL + file.path);
+	/*	window.open(import.meta.env.VITE_API_UPLOAD_URL + file.path);*/
+	fileDownloadByUrl({
+		Source: 'hotline',
+		Id: file.id,
+	}).then((res: any) => {
+		let blob: Blob = new Blob([res.data], { type: res.data.type }); // 创建blob 设置blob文件类型 data 设置为后端返回的文件(例如mp3,jpeg) type:这里设置后端返回的类型 为 mp3
+		let down: HTMLAnchorElement = document.createElement('a'); // 创建A标签
+		let href: string = window.URL.createObjectURL(blob); // 创建下载的链接
+		down.href = href; // 下载地址
+		down.download = file.fileName; // 下载文件名
+		document.body.appendChild(down);
+		down.click(); // 模拟点击A标签
+		document.body.removeChild(down); // 下载完成移除元素
+		window.URL.revokeObjectURL(href); // 释放blob对象
+	});
 };
 // 办理
 const handleFiles = ref<EmptyArrayType>([]); // 流程附件

+ 51 - 20
src/directive/authDirective.ts

@@ -1,6 +1,7 @@
 import type { App } from 'vue';
 import { useUserInfo } from '@/stores/userInfo';
 import { judgementSameArr } from '@/utils/arrayOperation';
+import { nextTick } from 'vue';
 
 /**
  * 用户权限指令
@@ -8,39 +9,69 @@ import { judgementSameArr } from '@/utils/arrayOperation';
  * @directive 多个权限验证,满足一个则显示(v-auths="[xxx,xxx]")
  * @directive 多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]")
  */
+
+// 判断数组 A 是否完全包含 B
+function hasAllPermissions(required: string[], actual: string[]) {
+	if (!Array.isArray(required) || required.length === 0) return false;
+	return required.every((perm) => actual.includes(perm));
+}
 export function authDirective(app: App) {
 	// 单个权限验证(v-auth="xxx")
 	app.directive('auth', {
 		mounted(el, binding) {
 			const stores = useUserInfo();
-			if (!stores.userInfos.authBtnList?.some((v: string) => v === binding.value)) el.parentNode.removeChild(el);
+			nextTick(() => {
+				const hasPermission = stores.userInfos.authBtnList?.some((v: string) => v === binding.value);
+				if (!hasPermission) {
+					// ✅ 更安全的做法,确保父节点存在且包含 el
+					const parent = el.parentNode;
+					if (parent && parent.contains(el)) {
+						parent.removeChild(el);
+					}
+				}
+			}).then();
 		},
 	});
 	// 多个权限验证,满足一个则显示(v-auths="[xxx,xxx]")
 	app.directive('auths', {
 		mounted(el, binding) {
-			if (!binding.value) {
-				el.parentNode && el.parentNode.removeChild(el);
-			}
-			let flag = false;
 			const stores = useUserInfo();
-			stores.userInfos.authBtnList?.map((val: string) => {
-				binding.value.map((v: string) => {
-					if (val === v) flag = true;
-				});
-			});
-			if (!flag) el.parentNode.removeChild(el);
+			nextTick(() => {
+				const requiredPerms = binding.value;
+				// 若未传入权限数组,直接隐藏
+				if (!Array.isArray(requiredPerms) || requiredPerms.length === 0) {
+					el.parentNode?.contains(el) && el.parentNode.removeChild(el);
+					return;
+				}
+				const userPerms = stores.userInfos.authBtnList || [];
+				// 是否拥有其中一个权限
+				const hasOne = requiredPerms.some((perm: string) => userPerms.includes(perm));
+				if (!hasOne) {
+					el.parentNode?.contains(el) && el.parentNode.removeChild(el);
+				}
+			}).then();
 		},
 	});
+
+
 	// 多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]")
 	app.directive('auth-all', {
 		mounted(el, binding) {
-			if (!binding.value) {
-				el.parentNode && el.parentNode.removeChild(el);
-			}
-			const stores = useUserInfo();
-			const flag = judgementSameArr(binding.value, stores.userInfos.authBtnList);
-			if (!flag) el.parentNode.removeChild(el);
-		},
-	});
-}
+			nextTick(() => {
+				const required = binding.value;
+				if (!Array.isArray(required) || required.length === 0) {
+					el.parentNode?.contains(el) && el.parentNode.removeChild(el);
+					return;
+				}
+
+				const stores = useUserInfo();
+				const userPerms = stores.userInfos.authBtnList || [];
+
+				const hasAll = hasAllPermissions(required, userPerms);
+				if (!hasAll) {
+					el.parentNode?.contains(el) && el.parentNode.removeChild(el);
+				}
+			});
+		}
+	})
+}

+ 4 - 1
src/directive/index.ts

@@ -1,7 +1,8 @@
 import type { App } from 'vue';
 import { authDirective } from '@/directive/authDirective';
-import { wavesDirective, lazyImgDirective,inputTrimDirective } from '@/directive/customDirective';
+import { wavesDirective, lazyImgDirective, inputTrimDirective } from '@/directive/customDirective';
 import { horizontalScroll } from '@/directive/tableScorll';
+import { permissionDirective } from '@/directive/permissionAuth';
 
 /**
  * 导出指令方法:v-xxx
@@ -14,6 +15,8 @@ import { horizontalScroll } from '@/directive/tableScorll';
 export function directive(app: App) {
 	// 用户权限指令
 	authDirective(app);
+	// 用户权限指令
+	permissionDirective(app);
 	// 按钮波浪指令
 	wavesDirective(app);
 	// 图片懒加载指令

+ 56 - 0
src/directive/permissionAuth.ts

@@ -0,0 +1,56 @@
+import { App, nextTick } from 'vue';
+import { useUserInfo } from '@/stores/userInfo';
+
+// 判断数组 A 是否完全包含 B
+function hasAllPermissions(required: string[], actual: string[]) {
+	return required.every((perm) => actual.includes(perm));
+}
+
+// 判断数组 A 是否有任意一个包含 B
+function hasAnyPermission(required: string[], actual: string[]) {
+	return required.some((perm) => actual.includes(perm));
+}
+
+/**
+ * 用户权限指令
+ * @directive 1. 单个权限判断(v-permission="'edit'")
+ * @directive 2. 任意权限判断(v-permission="['edit', 'create']")
+ * @directive 3. 全部权限判断(v-permission="{ all: ['edit', 'create'] }")
+ * @directive 4. 任意权限判断(v-permission="{ any: ['edit', 'create'] }")
+ */
+export function permissionDirective(app: App) {
+	app.directive('permission', {
+		mounted(el, binding) {
+			nextTick(() => {
+				const stores = useUserInfo();
+				const userPerms = stores.userInfos.authBtnList || [];
+
+				let hasPermission = false;
+
+				const required = binding.value;
+
+				// 1. 如果是单个权限(string 类型)
+				if (typeof required === 'string') {
+					hasPermission = userPerms.includes(required);
+				}
+				// 2. 如果是任意一个权限(数组)
+				else if (Array.isArray(required)) {
+					hasPermission = hasAnyPermission(required, userPerms);
+				}
+				// 3. 如果是必须全有权限(对象形式)
+				else if (typeof required === 'object') {
+					if (required.any) {
+						hasPermission = hasAnyPermission(required.any, userPerms);
+					} else if (required.all) {
+						hasPermission = hasAllPermissions(required.all, userPerms);
+					}
+				}
+
+				// 没有权限时,移除该元素
+				if (!hasPermission) {
+					el.parentNode?.contains(el) && el.parentNode.removeChild(el);
+				}
+			}).then();
+		},
+	});
+}

+ 9 - 0
src/layout/navBars/breadcrumb/zgTel.vue

@@ -1445,6 +1445,7 @@ const retBusy = (data: any) => {
 
 		// 小休开始了
 		// const restReasons = state.restReasonOptions.find((item: any) => item.dicDataValue === reason);
+		onEndRecord('1'); // 结束话后整理
 		busyOn({ reason: '' }) // 开始小休 设置示忙 业务系统统计需要
 			.then(() => {
 				console.log(`${getNowDateTime()}:业务系统调用示忙开始成功`);
@@ -1532,6 +1533,14 @@ const onCancelTalkDeal = () => {
 						Extension: m_strUserNo.value,
 					},
 				};
+				// 结束小休 设置示忙 业务系统统计需要
+				busyOff()
+					.then(() => {
+						console.log(`${getNowDateTime()}:业务系统调用示忙结束成功`);
+					})
+					.catch((err) => {
+						console.log(`${getNowDateTime()}:业务系统调用示忙结束失败,${err}`);
+					});
 			} else {
 				// 默认调用示闲
 				objMsg = {

+ 9 - 0
src/router/route.ts

@@ -709,6 +709,15 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 			isKeepAlive: true,
 		},
 	},
+	{
+		path: '/statistics/order/detailVisitContent',
+		name: 'statisticsOrderDetailVisitContent',
+		component: () => import('@/views/statistics/order/detailVisitContent.vue'),
+		meta: {
+			title: '智能回访不满意明细',
+			isKeepAlive: true,
+		},
+	},
 	{
 		path: '/examTrain/questionBank/edit/:tagsViewName/:id?',
 		name: 'questionEdit',

+ 3 - 7
src/utils/request.ts

@@ -93,7 +93,7 @@ export default function myAxios(axiosConfig: any, customOptions?: customOptionsT
  * @param {*} error
  */
 // 设置一个变量 处理同一时间多个错误重复弹窗口
-let tokenAbnormal: boolean = false;
+let hasShown401 = false;  // 用于判断是否已经弹出过401提示
 function httpErrorStatusHandle(error: any) {
 	// 处理被取消的请求
 	if (axios.isCancel(error)) return;
@@ -109,8 +109,8 @@ function httpErrorStatusHandle(error: any) {
 				message = errStr;
 				break;
 			case 401:
-				if (!tokenAbnormal) {
-					tokenAbnormal = true;
+				if (!hasShown401) {
+					hasShown401 = true;
 					// 弹出框
 					ElMessageBox.alert('登录已过期或该账户已在其他地方登录!', '提示', {
 						type: 'warning',
@@ -132,10 +132,6 @@ function httpErrorStatusHandle(error: any) {
 							location.reload(); //刷新页面
 						})
 						.catch((): void => {});
-					// 设置定时器,确保下次异常时弹出框正常弹出
-					setTimeout(() => {
-						tokenAbnormal = false;
-					}, 2000);
 				}
 				break;
 			case 403:

+ 1 - 1
src/utils/tools.ts

@@ -496,7 +496,7 @@ export function trimCompat(input: string | number | null) {
  * */
 export function exportAssignment(ids: string[]) {
 	return new Promise((resolve, reject) => {
-		ElMessageBox.confirm(`工单已留痕,禁止泄露工单信息,否则将依法依规追究责任。您确定导出选中的工单交办单?`, '提示', {
+		ElMessageBox.confirm(`导出已留痕,禁止泄露工单信息,否则将依法依规追究责任。您确定导出选中的工单交办单?`, '提示', {
 			confirmButtonText: '确认',
 			cancelButtonText: '取消',
 			type: 'warning',

+ 21 - 2
src/views/auxiliary/message/index.vue

@@ -90,7 +90,6 @@
 				<el-form-item label="发送人" prop="SendName">
 					<el-input v-model="state.queryParams.SendName" placeholder="发送人" clearable @keyup.enter="handleQuery" />
 				</el-form-item>
-
 				<el-form-item label="发送部门" prop="SendOrg">
 					<el-input v-model="state.queryParams.SendOrg" placeholder="发送部门" clearable @keyup.enter="handleQuery" />
 				</el-form-item>
@@ -107,6 +106,20 @@
 						<el-option v-for="item in eSendStateData" :value="item.key" :key="item.key" :label="item.value" />
 					</el-select>
 				</el-form-item>
+				<el-form-item label="添加时间" prop="tjTime">
+					<el-date-picker
+						v-model="state.queryParams.tjTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
 			</el-form>
 			<template #footer>
 				<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
@@ -144,6 +157,9 @@ const state = reactive<any>({
 		SendName: null,
 		SendOrg: null,
 		SendContent: null,
+		tjTime:[], // 添加时间
+		CreationStartTime:null, // 添加开始时间
+		CreationEndTime:null , // 添加结束时间
 	},
 	total: 0, // 总条数
 	tableData: [], // 表格数据
@@ -168,9 +184,12 @@ const handleQuery = () => {
 const queryList = () => {
 	state.loading = true;
 	let request = Other.deepClone(state.queryParams);
-	request.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
+	request.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0]; // 发送时间
 	request.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
 	Reflect.deleteProperty(request, 'crTime');
+	request.CreationStartTime = state.queryParams.tjTime === null ? null : state.queryParams.tjTime[0]; // 添加时间
+	request.CreationEndTime = state.queryParams.tjTime === null ? null : state.queryParams.tjTime[1];
+	Reflect.deleteProperty(request, 'tjTime');
 	messageList(request)
 		.then((res) => {
 			state.loading = false;

+ 21 - 1
src/views/business/delay/components/Delay-audit.vue

@@ -62,7 +62,7 @@
 			<vxe-column type="seq" width="70"></vxe-column>
 			<vxe-column type="expand" width="60">
 				<template #content="{ row }">
-					<div class="mb5 formatted-text">审核意见:{{ row.opinion }}</div>
+					<div class="mb5 formatted-text">{{ row.handleModeTypeText }}:{{ row.opinion }}</div>
 					<annex-list name="附件" readonly businessId="" classify="查看附件" v-model="row.files" />
 				</template>
 			</vxe-column>
@@ -229,6 +229,26 @@ const formatTraces = (val: any) => {
 	if (!val || !val.length) return [];
 	val.forEach((item: any) => {
 		item.files = transformFile(item.files);
+		// 需要给意见做一个映射关系 正常就是审核意见 其他状态就是其他意见 比如重办就是重办意见
+		switch (item.handleMode) {
+			case 0:
+				item.handleModeTypeText = '审核意见';
+				break;
+			case 100:
+				item.handleModeTypeText = '退回意见';
+				break;
+			case 200:
+				item.handleModeTypeText = '特提意见';
+				break;
+			case 201:
+				item.handleModeTypeText = '重办意见';
+				break;
+			case 203:
+				item.handleModeTypeText = '发布退回意见';
+				break;
+			default:
+				break;
+		}
 	});
 	return val;
 };

+ 21 - 1
src/views/business/delay/components/Delay-detail.vue

@@ -45,7 +45,7 @@
 			<vxe-column type="seq" width="70"></vxe-column>
 			<vxe-column type="expand" width="60">
 				<template #content="{ row }">
-					<div class="mb5 formatted-text">审核意见:{{ row.opinion }}</div>
+					<div class="mb5 formatted-text">{{row.handleModeTypeText}}:{{ row.opinion }}</div>
 					<annex-list name="附件" readonly businessId="" classify="查看附件" v-model="row.files" />
 				</template>
 			</vxe-column>
@@ -118,6 +118,26 @@ const formatTraces = (val: any) => {
 	if (!val || !val.length) return [];
 	val.forEach((item: any) => {
 		item.files = transformFile(item.files);
+		// 需要给意见做一个映射关系 正常就是审核意见 其他状态就是其他意见 比如重办就是重办意见
+		switch (item.handleMode) {
+			case 0:
+				item.handleModeTypeText = '审核意见';
+				break;
+			case 100:
+				item.handleModeTypeText = '退回意见';
+				break;
+			case 200:
+				item.handleModeTypeText = '特提意见';
+				break;
+			case 201:
+				item.handleModeTypeText = '重办意见';
+				break;
+			case 203:
+				item.handleModeTypeText = '发布退回意见';
+				break;
+			default:
+				break;
+		}
 	});
 	return val;
 };

+ 64 - 15
src/views/business/discern/components/Discern-audit.vue

@@ -57,7 +57,7 @@
 				<vxe-column type="seq" width="70"></vxe-column>
 				<vxe-column type="expand" width="60">
 					<template #content="{ row }">
-						<div class="mb5 formatted-text">审核意见:{{ row.opinion }}</div>
+						<div class="mb5 formatted-text">{{ row.handleModeTypeText }}:{{ row.opinion }}</div>
 						<annex-list name="附件" readonly businessId="" classify="查看附件" v-model="row.files" />
 					</template>
 				</vxe-column>
@@ -174,6 +174,7 @@ import { storeToRefs } from 'pinia';
 import other from '@/utils/other';
 import { useThemeConfig } from '@/stores/themeConfig';
 import { fileDownloadByUrl } from '@/api/public/file';
+import { deleteEnd } from '@/api/query/end';
 
 const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue')); // 附件列表
 const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
@@ -280,6 +281,26 @@ const formatTraces = (val: any) => {
 	if (!val || !val.length) return [];
 	val.forEach((item: any) => {
 		item.files = transformFile(item.files);
+		// 需要给意见做一个映射关系 正常就是审核意见 其他状态就是其他意见 比如重办就是重办意见
+		switch (item.handleMode) {
+			case 0:
+				item.handleModeTypeText = '审核意见';
+				break;
+			case 100:
+				item.handleModeTypeText = '退回意见';
+				break;
+			case 200:
+				item.handleModeTypeText = '特提意见';
+				break;
+			case 201:
+				item.handleModeTypeText = '重办意见';
+				break;
+			case 203:
+				item.handleModeTypeText = '发布退回意见';
+				break;
+			default:
+				break;
+		}
 	});
 	return val;
 };
@@ -477,9 +498,9 @@ 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 (state.ruleForm.isPass) {
+			state.loading = true;
 			// 审批通过 下一步
 			discernApprove({ ...submitObj, reviewResult: 1, files: handleFiles.value, provinceFiles: provinceFiles.value, screenId: discernId.value })
 				.then(() => {
@@ -489,20 +510,48 @@ const onSubmit = (formEl: FormInstance | undefined) => {
 					afterSubmit('updateList');
 				});
 		} else {
-			// 审批拒绝
-			const requestDiscernAudit = {
-				opinion: state.ruleForm.opinion,
-				workflowId: state.ruleForm.workflowId,
-				files: handleFiles.value,
-				stepId: state.ruleForm.stepId,
-			};
-			workflowReject(requestDiscernAudit)
-				.then(() => {
-					afterSubmit('updateList', true);
+			if (['ZiGong'].includes(themeConfig.value.appScope)) {
+				ElMessageBox.confirm(`审批不同意后,申请人无法再次申请甄别,是否确认提交?`, '提示', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					type: 'warning',
+					draggable: true,
+					autofocus: false,
 				})
-				.catch(() => {
-					afterSubmit('updateList');
-				});
+					.then(() => {
+						state.loading = true;
+						// 审批拒绝
+						const requestDiscernAudit = {
+							opinion: state.ruleForm.opinion,
+							workflowId: state.ruleForm.workflowId,
+							files: handleFiles.value,
+							stepId: state.ruleForm.stepId,
+						};
+						workflowReject(requestDiscernAudit)
+							.then(() => {
+								afterSubmit('updateList', true);
+							})
+							.catch(() => {
+								afterSubmit('updateList');
+							});
+					})
+					.catch(() => {});
+			} else {
+				// 审批拒绝
+				const requestDiscernAudit = {
+					opinion: state.ruleForm.opinion,
+					workflowId: state.ruleForm.workflowId,
+					files: handleFiles.value,
+					stepId: state.ruleForm.stepId,
+				};
+				workflowReject(requestDiscernAudit)
+					.then(() => {
+						afterSubmit('updateList', true);
+					})
+					.catch(() => {
+						afterSubmit('updateList');
+					});
+			}
 		}
 	});
 };

+ 22 - 1
src/views/business/discern/components/Discern-detail.vue

@@ -45,7 +45,7 @@
 			<vxe-column type="seq" width="70"></vxe-column>
 			<vxe-column type="expand" width="60">
 				<template #content="{ row }">
-					<div class="mb5 formatted-text">审核意见:{{ row.opinion }}</div>
+					<div class="mb5 formatted-text">{{row.handleModeTypeText}}:{{ row.opinion }}</div>
 					<annex-list name="附件" readonly businessId="" classify="查看附件" v-model="row.files" />
 				</template>
 			</vxe-column>
@@ -131,6 +131,26 @@ const formatTraces = (val: any) => {
 	if (!val || !val.length) return [];
 	val.forEach((item: any) => {
 		item.files = transformFile(item.files);
+		// 需要给意见做一个映射关系 正常就是审核意见 其他状态就是其他意见 比如重办就是重办意见
+		switch (item.handleMode) {
+			case 0:
+				item.handleModeTypeText = '审核意见';
+				break;
+			case 100:
+				item.handleModeTypeText = '退回意见';
+				break;
+			case 200:
+				item.handleModeTypeText = '特提意见';
+				break;
+			case 201:
+				item.handleModeTypeText = '重办意见';
+				break;
+			case 203:
+				item.handleModeTypeText = '发布退回意见';
+				break;
+			default:
+				break;
+		}
 	});
 	return val;
 };
@@ -141,6 +161,7 @@ const getWorkflow = async (workflowId: string) => {
 		// 查询审核记录
 		const { result } = await workflowTraces(workflowId);
 		tableData.value = formatTraces(result?.traces);
+
 	} catch (e) {
 		console.log(e);
 	}

+ 12 - 0
src/views/business/discern/components/Discern-return.vue

@@ -59,6 +59,14 @@
 		<p class="border-title mt20 mb10">退回意见</p>
 		<el-form :model="state.ruleForm" label-width="110px" ref="ruleFormRef" v-loading="state.loading">
 			<el-row :gutter="10">
+				<el-col v-if="['ZiGong'].includes(themeConfig.appScope)">
+					<el-form-item label="退回类型" prop="isRecallToStartStep" :rules="[{ required: false, message: '请选择退回类型', trigger: 'change' }]">
+						<el-radio-group v-model="state.ruleForm.isRecallToStartStep">
+							<el-radio :value="false">逐级退回</el-radio>
+							<el-radio :value="true">退回至申请人</el-radio>
+						</el-radio-group>
+					</el-form-item>
+				</el-col>
 				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 					<el-form-item label="退回意见" prop="opinion" :rules="[{ required: true, message: '请填写退回意见', trigger: 'blur' }]">
 						<common-advice
@@ -97,6 +105,7 @@ import { commonEnum } from '@/utils/constants';
 import { useAppConfig } from '@/stores/appConfig';
 import { storeToRefs } from 'pinia';
 import other from '@/utils/other';
+import { useThemeConfig } from '@/stores/themeConfig';
 
 const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue')); // 附件列表
 const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
@@ -119,12 +128,15 @@ const state = reactive<any>({
 		backToCountersignEnd: false,
 		stepId: null,
 		workflowId: null,
+		isRecallToStartStep: false,
 	},
 	handlerOptions: [],
 	nextStepOptions: [],
 });
 
 const tableData = ref<EmptyArrayType>([]);
+const storesThemeConfig = useThemeConfig();
+const { themeConfig } = storeToRefs(storesThemeConfig);
 /*
  * @params row 工单详情
  * @description 打开弹窗

+ 652 - 0
src/views/business/order/enterprise.vue

@@ -0,0 +1,652 @@
+<template>
+	<div class="business-order-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<vxe-grid v-bind="gridOptions" v-on="gridEvents" ref="gridRef">
+				<template #form>
+					<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline :disabled="state.loading">
+						<el-row>
+							<el-col>
+								<el-form-item label="快捷查询" prop="fastSearch">
+									<el-segmented
+										:options="[
+											{
+												value: 'all',
+												label: '全部',
+											},
+											{
+												value: 'city',
+												label: '市工单',
+											},
+											{
+												value: 'province',
+												label: '省工单',
+											},
+										]"
+										v-model="fastSearch"
+										@change="fastSearchChange"
+										:disabled="state.loading"
+									/>
+									<el-checkbox-group v-model="checkList" @change="changeCheckList" class="ml15">
+										<el-checkbox value="IsSensitiveWord" border>敏感类工单</el-checkbox>
+									</el-checkbox-group>
+								</el-form-item>
+								<el-form-item label="受理内容" prop="ContentRetrieval">
+									<el-input
+										v-model.trim="state.queryParams.ContentRetrieval"
+										placeholder="受理内容"
+										clearable
+										@keyup.enter="handleQuery"
+										class="keyword-input"
+									/>
+								</el-form-item>
+								<el-form-item label="承办意见" prop="FileOption">
+									<el-input
+										v-model.trim="state.queryParams.FileOption"
+										placeholder="承办意见"
+										clearable
+										@keyup.enter="handleQuery"
+										class="keyword-input"
+									/>
+								</el-form-item>
+								<!--								<el-form-item>
+									<el-button @click="contentRetrieval"><SvgIcon name="ele-DocumentCopy" class="mr5" />内容检索</el-button>
+								</el-form-item>-->
+							</el-col>
+						</el-row>
+						<el-form-item label="工单标题" prop="Keyword">
+							<el-input v-model.trim="state.queryParams.Keyword" placeholder="工单标题" clearable @keyup.enter="handleQuery" class="keyword-input" />
+						</el-form-item>
+						<el-form-item label="工单编码" prop="No">
+							<el-input v-model.trim="state.queryParams.No" placeholder="工单编码" clearable @keyup.enter="handleQuery" class="keyword-input" />
+						</el-form-item>
+						<el-form-item label="受理时间" prop="crTime">
+							<el-date-picker
+								v-model="state.queryParams.crTime"
+								type="datetimerange"
+								unlink-panels
+								range-separator="至"
+								start-placeholder="开始时间"
+								end-placeholder="结束时间"
+								:shortcuts="shortcuts"
+								@change="handleQuery"
+								value-format="YYYY-MM-DD[T]HH:mm:ss"
+								:default-time="defaultTimeStartEnd"
+							/>
+						</el-form-item>
+						<el-form-item>
+							<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+							<el-button @click="drawer = true" class="default-button"> <SvgIcon name="ele-Search" class="mr5" />更多查询</el-button>
+						</el-form-item>
+					</el-form>
+				</template>
+				<template #statusText="{ row }">
+					<el-text type="danger" tag="b" v-if="[1, 2, 3, 9, 101, 102, 103, 104, 105, 200].includes(row.status)">{{ row.statusText }}</el-text>
+					<span v-else>{{ row.statusText }}</span>
+				</template>
+				<template #order_detail="{ row }">
+					<order-detail :order="row" @updateList="refreshList" :showFooter="false">{{ row.title }}</order-detail>
+				</template>
+				<template #pager>
+					<pagination
+						@pagination="queryList"
+						:total="state.total"
+						v-model:current-page="state.queryParams.PageIndex"
+						v-model:page-size="state.queryParams.PageSize"
+						:disabled="state.loading"
+					/>
+				</template>
+			</vxe-grid>
+		</div>
+		<!-- 编辑重复性事件 -->
+		<repeat-event-edit ref="repeatEventEditRef" @updateList="refreshList" />
+		<!-- 工单省退回 -->
+		<order-return ref="orderReturnRef" @updateList="refreshList" />
+		<!--	更多查询	-->
+		<el-drawer v-model="drawer" title="更多查询" size="500px">
+			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="100px" :disabled="gridOptions.loading">
+				<el-form-item label="敏感词" prop="SensitiveWord" v-show="checkList.includes('IsSensitiveWord')">
+					<el-input v-model="state.queryParams.SensitiveWord" placeholder="敏感词" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="来电人姓名" prop="FromName">
+					<el-input v-model="state.queryParams.FromName" placeholder="来电人姓名" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="事发地址" prop="AreaCode">
+					<el-cascader
+						:options="state.areaOptions"
+						filterable
+						:props="{ checkStrictly: true, value: 'id', label: 'areaName', emitPath: false }"
+						placeholder="请选择事发地址"
+						clearable
+						v-model="state.queryParams.AreaCode"
+						@change="handleQuery"
+						class="w100"
+					>
+					</el-cascader>
+				</el-form-item>
+				<el-form-item label="是否紧急" prop="IsUrgent">
+					<el-select v-model="state.queryParams.IsUrgent" placeholder="请选择是否紧急" clearable @change="handleQuery">
+						<el-option :value="true" label="紧急" />
+						<el-option :value="false" label="不紧急" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="转接来源" prop="TransferPhone">
+					<el-input v-model="state.queryParams.TransferPhone" placeholder="转接来源" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="工单状态" prop="Status">
+					<el-select v-model="state.queryParams.Status" placeholder="请选择工单状态" clearable @change="handleQuery">
+						<el-option v-for="item in state.orderStatusOptions" :value="item.key" :key="item.key" :label="item.value" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="受理类型" prop="AcceptType">
+					<el-select v-model="state.queryParams.AcceptType" placeholder="请选择受理类型" clearable @change="handleQuery">
+						<el-option v-for="item in state.acceptTypeOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="来源渠道" prop="Channel">
+					<el-select v-model="state.queryParams.Channel" placeholder="请选择来源渠道" clearable @change="handleQuery">
+						<el-option v-for="item in state.channelOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="热点分类" prop="Hotspot">
+					<el-input v-model.trim="state.queryParams.Hotspot" placeholder="热点分类名称" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="接办部门" prop="ActualHandleOrgName">
+					<el-input v-model="state.queryParams.ActualHandleOrgName" placeholder="请填写接办部门名称" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="一级部门" prop="OrgLevelOneName">
+					<el-input v-model="state.queryParams.OrgLevelOneName" placeholder="请填写一级部门名称" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="受理人" prop="NameOrNo">
+					<el-input v-model="state.queryParams.NameOrNo" placeholder="受理人/坐席工号" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="省本地编码" prop="ProvinceNo">
+					<el-input v-model.trim="state.queryParams.ProvinceNo" placeholder="省本地编码" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="来电号码" prop="FromPhone">
+					<el-input v-model.trim="state.queryParams.FromPhone" placeholder="来电号码" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="联系电话" prop="PhoneNo">
+					<el-input v-model.trim="state.queryParams.PhoneNo" placeholder="联系电话" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="推送分类" prop="PushTypeCode">
+					<el-select v-model="state.queryParams.PushTypeCode" placeholder="请选择推送分类" clearable @change="handleQuery">
+						<el-option v-for="item in state.pushTypeOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="重点关注事件" prop="FocusOnEvents" v-if="['YiBin'].includes(themeConfig.appScope)">
+					<el-select v-model="state.queryParams.FocusOnEvents" placeholder="请选择重点关注事件" clearable @change="handleQuery">
+						<el-option v-for="item in state.focusOnEvents" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="归档类型" prop="FiledType">
+					<el-select v-model="state.queryParams.FiledType" placeholder="请选择归档类型" @change="handleQuery" clearable>
+						<el-option label="中心归档" value="10" />
+						<el-option label="部门归档" value="20" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="期满时间" prop="exTime">
+					<el-date-picker
+						v-model="state.queryParams.exTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
+				<el-form-item label="接办人" prop="ActualHandlerName">
+					<el-input v-model="state.queryParams.ActualHandlerName" placeholder="接办人" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="是否甄别" prop="IsScreen">
+					<el-select v-model="state.queryParams.IsScreen" placeholder="请选择是否甄别" clearable @change="handleQuery">
+						<el-option label="是" :value="true" />
+						<el-option label="否" :value="false" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="是否保密" prop="IsSecret">
+					<el-select v-model="state.queryParams.IsSecret" placeholder="请选择是否保密" clearable @change="handleQuery">
+						<el-option label="是" :value="true" />
+						<el-option label="否" :value="false" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="省编码" prop="ReceiveProvinceNo">
+					<el-input v-model="state.queryParams.ReceiveProvinceNo" placeholder="省编码" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="当前节点" prop="CurrentStepCode">
+					<el-select v-model="state.queryParams.CurrentStepCode" placeholder="请选择当前节点" clearable @change="handleQuery">
+						<el-option v-for="item in state.currentStepOptions" :value="item.key" :key="item.key" :label="item.value" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="办结时间" prop="doneTime">
+					<el-date-picker
+						v-model="state.queryParams.doneTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
+				<!--				<el-form-item label="发布时间" prop="fbTime">
+					<el-date-picker
+						v-model="state.queryParams.fbTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
+				<el-form-item label="回访时间" prop="hfTime">
+					<el-date-picker
+						v-model="state.queryParams.hfTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>-->
+				<el-form-item label="受理情况" prop="IsSgin">
+					<el-select v-model="state.queryParams.IsSgin" placeholder="请选择受理情况" clearable @change="handleQuery">
+						<el-option label="已签收" :value="true" />
+						<el-option label="未签收" :value="false" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="是否超期" prop="IsOverTime">
+					<el-select v-model="state.queryParams.IsOverTime" placeholder="请选择是否超期" clearable @change="handleQuery">
+						<el-option label="是" :value="true" />
+						<el-option label="否" :value="false" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="是否重办工单" prop="IsReTransact ">
+					<el-select v-model="state.queryParams.IsReTransact" placeholder="请选择是否重办工单" @change="handleQuery" clearable>
+						<el-option label="是" :value="true" />
+						<el-option label="否" :value="false" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="政治身份" prop="PoliticalIdentityValue" v-if="['ZiGong'].includes(themeConfig.appScope)">
+					<el-select v-model="state.queryParams.PoliticalIdentityValue" placeholder="请选择政治身份" clearable @change="handleQuery">
+						<el-option v-for="item in state.politicalIdentity" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+				<el-button @click="resetQuery(drawerRuleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+			</template>
+		</el-drawer>
+		<!-- 工单撤销 -->
+		<order-revoke ref="orderRevokeRef" @updateList="refreshList" />
+		<!-- 工单催办 -->
+		<order-urge ref="orderUrgeRef" @updateList="refreshList" />
+		<!-- 工单补充 -->
+		<order-supply ref="orderSupplyRef" @onSupplySuccess="refreshList" />
+	</div>
+</template>
+<script setup lang="tsx" name="orderEnterprise">
+import { defineAsyncComponent, onMounted, reactive, ref, onActivated, onBeforeUnmount } from 'vue';
+import type { FormInstance } from 'element-plus';
+import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
+import { exportOrderEnterprise, listBaseData, orderListCountEnterprise, orderListEnterprise } from '@/api/business/order';
+import { treeArea } from '@/api/auxiliary/area';
+import { debounce } from '@/utils/tools';
+import Other from '@/utils/other';
+import mittBus from '@/utils/mitt';
+import { useThemeConfig } from '@/stores/themeConfig';
+import { storeToRefs } from 'pinia';
+
+// 引入组件
+const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const RepeatEventEdit = defineAsyncComponent(() => import('@/views/business/repeatEvent/components/Repeat-event-edit.vue')); // 编辑重复性事件
+const OrderReturn = defineAsyncComponent(() => import('@/views/business/return/components/Apply.vue')); // 工单退回
+const OrderRevoke = defineAsyncComponent(() => import('@/views/business/order/components/Order-revoke.vue')); // 工单撤销
+const OrderUrge = defineAsyncComponent(() => import('@/views/business/order/components/Order-Urge.vue')); // 工单催办
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+const OrderSupply = defineAsyncComponent(() => import('@/views/business/order/components/Order-supply.vue')); // 工单补充
+const storesThemeConfig = useThemeConfig();
+const { themeConfig } = storeToRefs(storesThemeConfig);
+// 定义变量内容
+const state = reactive<any>({
+	queryParams: {
+		PageIndex: 1, // 当前页
+		PageSize: 20, // 每页条数
+		// 查询条件
+		No: null, // 工单编码
+		ProvinceNo: null, // 省本地编码
+		ActualHandlerName: null, // 接办人
+		IsScreen: null, // 是否甄别
+		CurrentStepCode: null, // 办理节点
+		IsOverTime: null, // 是否超期
+		FromName: null, // 来电人姓名
+		AreaCode: null, // 事发地址
+		FromPhone: null, // 来电号码
+		Keyword: null, // 关键字
+		Content: null, // 工单内容
+		AcceptType: null, // 受理类型
+		Channels: null, // 渠道
+		Hotspot: null, //  热点分类名称
+		OrgId: null, // 接办部门
+		ActualHandleOrgName: null, // 接办部门
+		OrgLevelOneName: null, // 一级部门
+		NameOrNo: null, // 受理坐席
+		crTime: [], // 受理时间
+		CreationTimeStart: null, // 创建时间 开始
+		CreationTimeEnd: null, // 创建时间 结束
+		Status: null, // 工单状态
+		TransferPhone: null, // 转接来源
+		exTime: [], // 过期时间
+		ExpiredTimeStart: null, //办理期限 开始
+		ExpiredTimeEnd: null, //办理期限 结束
+		PhoneNo: null, // 手机号
+		doneTime: [], // 办结时间
+		ActualHandleTimeStart: null,
+		ActualHandleTimeEnd: null,
+		PushTypeCode: null, //推送类型
+		IsProvinceOrder: null, // 省市工单
+		IsSensitiveWord: null, // 是否敏感词工单
+		SensitiveWord: null, // 敏感词
+		IsUrgent: null, // 是否加急
+		ContentRetrieval: null, // 内容检索
+		FileOption: null, // 承办意见
+		IsSgin: null, // 受理情况
+		OrderTagCode: null, // 工单标签
+		SortField: null,
+		SortRule: null,
+		FocusOnEvents: null, // 重点关注事件
+		IsSecret: null, // 是否保密
+		ReceiveProvinceNo: null, // 省编码
+		fbTime: [], // 发布时间
+		hfTime: [], // 回访时间
+		IsReTransact: null, // 是否重办工单
+	},
+	tableData: [], //表单
+	loading: false, // 加载
+	total: 0, // 总数
+	acceptTypeOptions: [], //受理类型
+	channelOptions: [], // 来源频道
+	orderStatusOptions: [], // 工单状态
+	currentStepOptions: [], // 办理节点
+	orgsOptions: [], // 部门
+	pushTypeOptions: [], //推送分类
+	orgData: [], // 机构数据
+	areaOptions: [], // 省市区数据
+	focusOnEvents: [], // 重点事项
+	politicalIdentity: [], // 政治身份
+});
+const requestParams = ref<EmptyObjectType>({});
+const gridOptions = reactive<any>({
+	loading: false,
+	border: true,
+	showOverflow: true,
+	columnConfig: {
+		resizable: true,
+	},
+	scrollY: {
+		enabled: true,
+		gt: 100,
+	},
+	toolbarConfig: {
+		zoom: true,
+		custom: true,
+		refresh: {
+			queryMethod: () => {
+				handleQuery();
+			},
+		},
+		tools: [{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }],
+	},
+	customConfig: {
+		storage: true,
+	},
+	id: 'orderEnterprise',
+	rowConfig: { isHover: true, height: 30, isCurrent: true, useKey: true },
+	height: 'auto',
+	columns: [
+		{
+			field: 'expiredStatusText',
+			title: '状态',
+			width: 60,
+			align: 'center',
+			slots: {
+				default: ({ row }) => {
+					return <span class={'overdue-status-' + row.expiredStatus} title={row.expiredStatusText}></span>;
+				},
+			},
+		},
+		{ field: 'no', title: '工单编码', width: 140 },
+		{ field: 'isProvinceText', title: '省/市工单', width: 90 },
+		{ field: 'reTransactNum', title: '部门重办', width: 130 },
+		{ field: 'visitReTransactNum', title: '回访重办', width: 130 },
+		{ field: 'provinceReTransactNum', title: '上级重办', width: 130 },
+		{
+			field: 'isUrgentText',
+			title: '是否紧急',
+			width: 90,
+			slots: {
+				default: ({ row }) => {
+					return <span class="color-danger font-bold">{row.isUrgentText}</span>;
+				},
+			},
+		},
+		{ field: 'sensitiveText', title: '敏感词', width: 150 },
+		{ field: 'isSecretText', title: '是否保密', width: 100 },
+		{ field: 'currentStepName', title: '当前节点', width: 120 },
+		{ field: 'currentStepAcceptText', title: '受理情况', width: 100 },
+		{
+			field: 'statusText',
+			title: '工单状态',
+			width: 110,
+			slots: {
+				default: 'statusText',
+			},
+		},
+		{
+			field: 'title',
+			title: '工单标题',
+			minWidth: 200,
+			slots: { default: 'order_detail' },
+		},
+		{
+			field: 'expiredTime',
+			title: '期满时间',
+			width: 160,
+			sortable: true,
+			formatter: 'formatDate',
+		},
+		{ field: 'actualHandleOrgName', title: '接办部门', width: 140 },
+		/*{
+			field: 'currentStepAcceptTime',
+			title: '接办时间',
+			width: 160,
+			sortable: true,
+			formatter: 'formatDate',
+		},*/
+		{
+			field: 'creationTime',
+			title: '受理时间',
+			width: 160,
+			sortable: true,
+			formatter: 'formatDate',
+		},
+		{
+			field: 'filedTime',
+			title: '办结时间',
+			width: 160,
+			sortable: true,
+			formatter: 'formatDate',
+		},
+		{ field: 'orgLevelOneName', title: '一级部门', width: 140 },
+		{ field: 'acceptType', title: '受理类型', width: 110 },
+		{ field: 'counterSignTypeText', title: '是否会签', width: 110 },
+		{ field: 'sourceChannel', title: '来源渠道', width: 110 },
+		{ field: 'hotspotSpliceName', title: '热点全称', width: 150 },
+		{ field: 'hotspotName', title: '热点分类', width: 150 },
+		{ field: 'acceptorName', title: '受理人', width: 120 },
+		{ field: 'focusOnEventsName', title: '重点关注事件', width: 120 },
+		{ field: 'content', title: '受理内容', width: 200, visible: false },
+		{ field: 'fileOpinion', title: '承办意见', width: 200, visible: false },
+	],
+	data: [],
+	params: {
+		exportMethod: exportOrderEnterprise,
+		exportParams: requestParams,
+	},
+	sortConfig: {
+		remote: true,
+	},
+});
+const fastSearch = ref('all'); // tab位置
+const fastSearchChange = (val: string) => {
+	fastSearch.value = val;
+	switch (val) {
+		case 'all':
+			state.queryParams.IsProvinceOrder = null;
+			break;
+		case 'city':
+			state.queryParams.IsProvinceOrder = false;
+			break;
+		case 'province':
+			state.queryParams.IsProvinceOrder = true;
+			break;
+	}
+	handleQuery();
+};
+const checkList = ref<EmptyObjectType>([]);
+// 多选
+const changeCheckList = () => {
+	if (checkList.value.includes('IsSensitiveWord')) state.queryParams.IsSensitiveWord = true;
+	else state.queryParams.IsSensitiveWord = null;
+	handleQuery();
+};
+// 获取查询条件基础信息
+const getBaseData = async () => {
+	try {
+		const { result } = await listBaseData();
+		const mappings: any = {
+			acceptTypeOptions: 'acceptTypeOptions',
+			channelOptions: 'channelOptions',
+			orgsOptions: 'orgsOptions',
+			pushTypeOptions: 'pushTypeOptions',
+			orderStatusOptions: 'orderStatusOptions',
+			currentStepOptions: 'currentStepOptions',
+			orderTagOptions: 'orderTags',
+			focusOnEvents: 'focusOnEvents',
+			politicalIdentity: 'politicalIdentity',
+		};
+		for (const key in mappings) {
+			state[key] = result?.[mappings[key]] ?? [];
+		}
+		const area = await treeArea();
+		state.areaOptions = area?.result ?? []; //省市区数据
+	} catch (error) {
+		console.log(error);
+	}
+};
+const gridEvents = {
+	sortChange(val: any) {
+		state.queryParams.SortField = val.order ? val.field : null;
+		// 0 升序 1 降序
+		state.queryParams.SortRule = val.order ? (val.order == 'desc' ? 1 : 0) : null;
+		handleQuery();
+	},
+};
+// 手动查询,将页码设置为1
+const handleQuery = () => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+	getTotal();
+};
+// 刷新列表
+const refreshList = () => {
+	queryList();
+	getTotal();
+};
+// 改变页码
+const queryList = () => {
+	return new Promise((resolve, reject) => {
+		requestParams.value = Other.deepClone(state.queryParams);
+		requestParams.value.CreationTimeStart = state.queryParams.crTime === null ? null : state.queryParams.crTime[0]; // 受理时间
+		requestParams.value.CreationTimeEnd = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
+		Reflect.deleteProperty(requestParams.value, 'crTime'); // 删除无用的参数
+		requestParams.value.ExpiredTimeStart = state.queryParams.exTime === null ? null : state.queryParams.exTime[0]; // 期满时间
+		requestParams.value.ExpiredTimeEnd = state.queryParams.exTime === null ? null : state.queryParams.exTime[1];
+		Reflect.deleteProperty(requestParams.value, 'exTime'); // 删除无用的参数
+		requestParams.value.ActualHandleTimeStart = state.queryParams.doneTime === null ? null : state.queryParams.doneTime[0]; // 办结时间
+		requestParams.value.ActualHandleTimeEnd = state.queryParams.doneTime === null ? null : state.queryParams.doneTime[1];
+		Reflect.deleteProperty(requestParams.value, 'doneTime'); // 删除无用的参数
+
+		state.loading = true;
+		gridOptions.loading = true;
+		orderListEnterprise(requestParams.value)
+			.then((response: any) => {
+				gridOptions.data = response?.result ?? [];
+				state.loading = false;
+				gridOptions.loading = false;
+				resolve(response);
+			})
+			.catch(() => {
+				state.loading = false;
+				gridOptions.loading = false;
+				reject();
+			});
+	});
+};
+// 查询总数
+const getTotal = () => {
+	orderListCountEnterprise(requestParams.value)
+		.then((res) => {
+			state.total = res.result ?? 0;
+		})
+		.catch(() => {});
+};
+/** 重置按钮操作 */
+const drawerRuleFormRef = ref();
+const ruleFormRef = ref<RefType>(); // 表单ref
+const drawer = ref(false);
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	state.queryParams.IsSensitiveWord = null;
+	state.queryParams.IsProvinceOrder = null;
+	fastSearch.value = 'all';
+	checkList.value = [];
+	ruleFormRef.value?.resetFields();
+	queryList();
+	getTotal();
+};
+onMounted(() => {
+	queryList().then(() => {
+		getBaseData();
+		getTotal();
+	});
+});
+const handleEvent = debounce(() => {
+	handleQuery();
+}, 1000);
+onActivated(() => {
+	mittBus.on('clearCachePage', () => {
+		//清除缓存
+		handleEvent();
+	});
+});
+onBeforeUnmount(() => {
+	mittBus.off('clearCachePage');
+});
+</script>

+ 16 - 48
src/views/business/order/index.vue

@@ -123,7 +123,14 @@
 					>
 						退回</el-button
 					>
-					<el-button type="primary" link @click="onSupply(row)" v-auth="'business:order:supply'" v-show="['LuZhou','ZiGong'].includes(themeConfig.appScope)">补充备注</el-button>
+					<el-button
+						type="primary"
+						link
+						@click="onSupply(row)"
+						v-auth="'business:order:supply'"
+						v-show="['LuZhou', 'ZiGong'].includes(themeConfig.appScope)"
+						>补充备注</el-button
+					>
 				</template>
 				<template #pager>
 					<pagination
@@ -338,41 +345,17 @@
 						<el-option label="否" :value="false" />
 					</el-select>
 				</el-form-item>
+				<el-form-item label="政治身份" prop="PoliticalIdentityValue" v-if="['ZiGong'].includes(themeConfig.appScope)">
+					<el-select v-model="state.queryParams.PoliticalIdentityValue" placeholder="请选择政治身份" clearable @change="handleQuery">
+						<el-option v-for="item in state.politicalIdentity" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
 			</el-form>
 			<template #footer>
 				<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
 				<el-button @click="resetQuery(drawerRuleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
 			</template>
 		</el-drawer>
-		<!--	内容检索	-->
-		<el-dialog
-			v-model="state.dialogVisible"
-			draggable
-			destroy-on-close
-			:close-on-click-modal="false"
-			modal-class="modal_class"
-			class="dialog_class"
-			append-to-body
-			:modal="false"
-			title="内容检索"
-			width="500px"
-		>
-			<el-form :model="state.ruleForm" ref="ruleFormContentRef" label-width="90px" class="show-info-form" @submit.native.prevent>
-				<el-form-item label="信件内容">
-					<el-input v-model="state.ruleForm.content" placeholder="请填写信件内容" :autosize="{ minRows: 4, maxRows: 10 }" type="textarea"></el-input>
-				</el-form-item>
-				<!--				<el-form-item label="检索范围">
-					<el-checkbox v-model="state.ruleForm.isContent">受理内容</el-checkbox>
-					<el-checkbox v-model="state.ruleForm.isFileOpinion">承办意见</el-checkbox>
-				</el-form-item>-->
-			</el-form>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="state.dialogVisible = false" class="default-button">取 消</el-button>
-					<el-button type="primary" @click="onSearch(ruleFormContentRef)">查 询</el-button>
-				</span>
-			</template>
-		</el-dialog>
 		<!-- 工单撤销 -->
 		<order-revoke ref="orderRevokeRef" @updateList="refreshList" />
 		<!-- 工单催办 -->
@@ -478,12 +461,7 @@ const state = reactive<any>({
 	orgData: [], // 机构数据
 	areaOptions: [], // 省市区数据
 	focusOnEvents: [], // 重点事项
-	dialogVisible: false,
-	ruleForm: {
-		content: null,
-		isContent: true, // 内容检索默认勾选 受理内容
-		isFileOpinion: false, // 内容检索承办意见
-	},
+	politicalIdentity: [], // 政治身份
 });
 const requestParams = ref<EmptyObjectType>({});
 const gridOptions = reactive<any>({
@@ -574,6 +552,7 @@ const getBaseData = async () => {
 			currentStepOptions: 'currentStepOptions',
 			orderTagOptions: 'orderTags',
 			focusOnEvents: 'focusOnEvents',
+			politicalIdentity: 'politicalIdentity',
 		};
 		for (const key in mappings) {
 			state[key] = result?.[mappings[key]] ?? [];
@@ -657,7 +636,6 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 	fastSearch.value = 'all';
 	checkList.value = [];
 	ruleFormRef.value?.resetFields();
-	state.ruleForm.content = null;
 	queryList();
 	getTotal();
 };
@@ -734,18 +712,8 @@ const onUrge = () => {
 };
 // 工单补充
 const orderSupplyRef = ref<RefType>();
-const onSupply = (row:any)=>{
+const onSupply = (row: any) => {
 	orderSupplyRef.value.openDialog(row);
-}
-const ruleFormContentRef = ref<RefType>();
-// 内容检索
-const onSearch = (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		handleQuery();
-		state.dialogVisible = false;
-	});
 };
 const checkTable = ref<EmptyArrayType>([]);
 const gridRef = ref<RefType>();

+ 3 - 1
src/views/business/order/tableHeader.tsx

@@ -13,7 +13,9 @@ export const YBTableHeader = [
 	},
 	{ field: 'no', title: '工单编码', width: 140 },
 	{ field: 'isProvinceText', title: '省/市工单', width: 90 },
-	{ field: 'reTransactNum', title: '重办次数', width: 90 },
+	{ field: 'reTransactNum', title: '部门重办', width: 130 },
+	{ field: 'visitReTransactNum', title: '回访重办', width: 130 },
+	{ field: 'provinceReTransactNum', title: '上级重办', width: 130 },
 	{
 		field: 'isUrgentText',
 		title: '是否紧急',

+ 21 - 1
src/views/business/terminate/components/Terminate-audit.vue

@@ -31,7 +31,7 @@
 			<vxe-column type="seq" width="70"></vxe-column>
 			<vxe-column type="expand" width="60">
 				<template #content="{ row }">
-					<div class="mb5  formatted-text">审核意见:{{ row.opinion }}</div>
+					<div class="mb5  formatted-text">{{row.handleModeTypeText}}:{{ row.opinion }}</div>
 					<annex-list name="附件" readonly businessId="" classify="查看附件" v-model="row.files" />
 				</template>
 			</vxe-column>
@@ -179,6 +179,26 @@ const formatTraces = (val: any) => {
 	if (!val || !val.length) return [];
 	val.forEach((item: any) => {
 		item.files = transformFile(item.files);
+		// 需要给意见做一个映射关系 正常就是审核意见 其他状态就是其他意见 比如重办就是重办意见
+		switch (item.handleMode) {
+			case 0:
+				item.handleModeTypeText = '审核意见';
+				break;
+			case 100:
+				item.handleModeTypeText = '退回意见';
+				break;
+			case 200:
+				item.handleModeTypeText = '特提意见';
+				break;
+			case 201:
+				item.handleModeTypeText = '重办意见';
+				break;
+			case 203:
+				item.handleModeTypeText = '发布退回意见';
+				break;
+			default:
+				break;
+		}
 	});
 	return val;
 };

+ 175 - 10
src/views/business/visit/components/Visit-detail.vue

@@ -541,6 +541,85 @@
 										</div>
 									</el-form-item>
 								</el-col>
+								<!-- 宜宾的重办 -->
+								<template v-if="['YiBin'].includes(themeConfig.appScope)">
+									<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+										<el-form-item label="" prop="isTransact" :rules="[{ required: false, message: '请选择是否重办', trigger: 'change' }]">
+											<el-checkbox v-model="state.ruleForm.isTransact" @change="selectIsTransact">重办</el-checkbox>
+										</el-form-item>
+									</el-col>
+									<template v-if="state.ruleForm.isTransact">
+										<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="w100">
+											<el-row :gutter="10" class="w100">
+												<el-col :xs="24" :sm="12" :md="12" :lg="10" :xl="10">
+													<el-form-item
+														label="流转目标"
+														prop="nextStepCode"
+														:rules="[{ required: true, message: '请选择流转目标', trigger: 'change' }]"
+													>
+														<el-select v-model="state.ruleForm.nextStepCode" placeholder="请选择流转目标" @change="selectNextCode">
+															<el-option v-for="item in steps" :value="item.key" :key="item.key" :label="item.value"> </el-option>
+														</el-select>
+													</el-form-item>
+												</el-col>
+												<el-col :xs="24" :sm="12" :md="12" :lg="10" :xl="10">
+													<el-form-item prop="timeLimit" label-width="0px" :rules="[{ required: true, message: '请填写延期数量', trigger: 'blur' }]">
+														<!--									<el-select
+													v-model="state.ruleForm.timeLimit"
+													placeholder="请选择延期数量"
+													:rules="[{ required: true, message: '请选择延期数量', trigger: 'change' }]"
+													clearable
+												>
+													<el-option v-for="item in delayOptions" :value="item.value" :key="item.value" :label="item.label" />
+												</el-select>-->
+														<el-input-number
+															v-model="state.ruleForm.timeLimit"
+															:min="1"
+															:precision="0"
+															class="w100"
+															:max="10"
+															placeholder="请填写延期数量"
+														/>
+													</el-form-item>
+												</el-col>
+												<el-col :xs="24" :sm="12" :md="12" :lg="4" :xl="4">
+													<el-form-item
+														prop="timeLimitUnit"
+														label-width="0px"
+														:rules="[{ required: true, message: '请选择延期申请单位', trigger: 'change' }]"
+													>
+														<el-select v-model="state.ruleForm.timeLimitUnit" placeholder="延期申请单位" disabled>
+															<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-col>
+										<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+											<el-form-item label="重办原因" :rules="[{ required: true, message: '请选择重办原因', trigger: 'change' }]" prop="error">
+												<el-select
+													v-model="state.ruleForm.error"
+													placeholder="请选择重办原因"
+													value-key="dicDataValue"
+													clearable
+													style="min-width: 240px"
+												>
+													<el-option v-for="items in specialReason" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
+												</el-select>
+											</el-form-item>
+										</el-col>
+										<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+											<el-form-item label="重办意见" prop="reason" :rules="[{ required: true, message: '请填写重办意见', trigger: 'blur' }]">
+												<common-advice
+													@chooseAdvice="chooseAdvice"
+													v-model="state.ruleForm.reason"
+													placeholder="请填写重办意见"
+													:commonEnum="commonEnum.Return"
+												/>
+											</el-form-item>
+										</el-col>
+									</template>
+								</template>
 							</el-row>
 						</template>
 					</el-form>
@@ -580,7 +659,7 @@
 	<visit-redo ref="visitRedoRef" @updateList="onRedoSuccess" />
 </template>
 <script setup lang="tsx" name="orderFollowUpDetail">
-import { computed, defineAsyncComponent, reactive, ref } from 'vue';
+import { computed, defineAsyncComponent, nextTick, reactive, ref } from 'vue';
 import { ElMessage, FormInstance } from 'element-plus';
 import { commonEnum, getNowDateTime } from '@/utils/constants';
 import { storeToRefs } from 'pinia';
@@ -594,6 +673,7 @@ import { specialApplyBase } from '@/api/business/special';
 import { submitLog } from '@/api/public/log';
 import { Local, Session } from '@/utils/storage';
 import { useAppConfig } from '@/stores/appConfig';
+import { publishReturnBaseData } from '@/api/business/publish';
 
 // 引入组件
 const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
@@ -612,6 +692,13 @@ const state = reactive<any>({
 		visitDetails: {},
 		orgJudge: false, // 扭转部门满意度
 		seatJudge: false, // 扭转坐席满意度
+		isTransact: false, // 是否重办
+
+		nextStepCode: null, // 退回节点
+		reason: '', // 重办意见
+		timeLimitUnit: 2,
+		timeLimit: 1,
+		stepType: null,
 	},
 	orderDetail: {}, // 工单详情
 	orderVisitModel: {}, // 回访详情
@@ -730,6 +817,7 @@ const callId = ref<string>('');
 const appConfigStore = useAppConfig();
 const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
 const openDialog = (row: any, type: string = '回访') => {
+	state.ruleForm.isTransact = false;
 	const callIdSession = Session.get(row.id);
 	if (callIdSession) callId.value = callIdSession;
 	mittBus.on('outboundConnect', (data) => {
@@ -806,13 +894,53 @@ const selectReason = (val: any, index: number | string) => {
 			key: item.dicDataValue,
 		};
 	});
-	console.log(state.ruleForm.visitDetails[index].orgNoSatisfiedReason);
 };
 const close = () => {
 	ruleFormRef.value?.clearValidate();
 	ruleFormRef.value?.resetFields();
+	state.ruleForm.isTransact = false;
 	callId.value = '';
 	mittBus.off('outboundConnect');
+	steps.value = [];
+	timeType.value = [];
+	specialReason.value = [];
+};
+// 选择是否重办
+const steps = ref<EmptyArrayType>([]); // 退回节点
+const timeType = ref<EmptyArrayType>([]); // 时间单位
+const specialReason = ref<EmptyArrayType>([]); // 重办原因
+const selectIsTransact = async (val: any) => {
+	if (val) {
+		const baseRes = await publishReturnBaseData(state.orderDetail.id);
+		timeType.value = baseRes.result?.specialTimeType ?? [];
+		steps.value = baseRes.result?.step?.steps ?? [];
+		specialReason.value = baseRes.result?.specialReason ?? [];
+		if (baseRes.result.defaultStepKey) {
+			await nextTick(() => {
+				// 如果有默认值需要默认选中
+				state.ruleForm.nextStepCode = baseRes.result.defaultStepKey;
+				state.ruleForm.nextStepName = steps.value.find((item) => item.key === baseRes.result?.defaultStepKey).value;
+				selectNextCode(baseRes.result.defaultStepKey);
+			});
+		}
+	} else {
+		steps.value = [];
+		timeType.value = [];
+		specialReason.value = [];
+	}
+};
+// 选择重办节点
+const orgId = ref('');
+const orgName = ref('');
+const selectNextCode = (val: any) => {
+	const next = steps.value.find((item: any) => item.key === val);
+	state.ruleForm.nextStepName = next.value; // 下一节点name
+	state.ruleForm.businessType = next.businessType;
+	state.ruleForm.flowDirection = next.flowDirection;
+	state.ruleForm.handlerType = next.handlerType;
+	state.ruleForm.stepType = next.stepType;
+	orgId.value = next.handler.orgId;
+	orgName.value = next.handler.orgName;
 };
 // 提交
 const onSubmit = (formEl: FormInstance | undefined) => {
@@ -820,19 +948,56 @@ const onSubmit = (formEl: FormInstance | undefined) => {
 	formEl.validate((valid: boolean) => {
 		if (!valid) return;
 		state.loading = true;
-		let request = {
-			...state.ruleForm,
-			// isPutThrough: !state.ruleForm.isPutThrough,
-			...state.visitDetails,
-			id: visitId.value,
-			isUpdate: dialogTitle.value === '修改回访结果',
-		};
+		let reTransactError: any;
+		reTransactError = [
+			{
+				orgId: orgId.value,
+				orgName: orgName.value,
+				errorId: state.ruleForm.error?.dicDataValue,
+				errorName: state.ruleForm.error?.dicDataName,
+			},
+		];
+		let request: EmptyObjectType = {};
+		if (state.ruleForm.isTransact) {
+			// 重办
+			request = {
+				...state.ruleForm,
+				// isPutThrough: !state.ruleForm.isPutThrough,
+				...state.visitDetails,
+				id: visitId.value,
+				isUpdate: dialogTitle.value === '修改回访结果',
+				orderReTransact: {
+					workflowId: state.orderDetail.workflowId,
+					orderId: state.orderDetail.id,
+					nextStepCode: state.ruleForm.nextStepCode,
+					nextStepName: state.ruleForm.nextStepName,
+					reason: state.ruleForm.reason,
+					timeLimit: state.ruleForm.timeLimit,
+					timeLimitUnit: state.ruleForm.timeLimitUnit,
+					alterTime: !!state.ruleForm.timeLimit,
+					businessType: state.ruleForm.businessType,
+					flowDirection: state.ruleForm.flowDirection,
+					handlerType: state.ruleForm.handlerType,
+					stepType: state.ruleForm.stepType,
+					reTransactError,
+					specialType: 2, // 1特提 2重办 3退回
+				},
+			};
+		} else {
+			request = {
+				...state.ruleForm,
+				// isPutThrough: !state.ruleForm.isPutThrough,
+				...state.visitDetails,
+				id: visitId.value,
+				isUpdate: dialogTitle.value === '修改回访结果',
+			};
+		}
 		if (callId.value) {
 			request.callId = callId.value;
 		}
 		visitOrder(request)
 			.then(() => {
-				ElMessage.success('操作成功');
+				ElMessage.success('回访成功');
 				Session.remove(visitId.value);
 				state.loading = false;
 				closeDialog();

+ 0 - 1
src/views/business/visit/components/Visit-redo.vue

@@ -41,7 +41,6 @@
 							</el-select>
 						</el-form-item>
 					</el-col>
-
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 						<el-form-item label="重办意见" prop="reason" :rules="[{ required: true, message: '请填写重办意见', trigger: 'blur' }]">
 							<common-advice

+ 66 - 17
src/views/business/visit/dpSatisfied.vue

@@ -87,6 +87,11 @@
 							<order-detail :order="{ ...row, id: row.orderId }" @updateList="handleQuery">{{ row.title }}</order-detail>
 						</template>
 					</vxe-column>
+					<vxe-column field="orderTag" title="工单标签" width="120" v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"></vxe-column>
+					<vxe-column field="sourceChannel" title="来源渠道" width="120"></vxe-column>
+					<vxe-column field="acceptType" title="受理类型" width="120"></vxe-column>
+					<vxe-column field="orgNoSatisfiedReasonText" title="不满意原因" width="120"></vxe-column>
+					<vxe-column field="area" title="事发地址" width="120"></vxe-column>
 					<vxe-column field="visitUser" title="回访人" width="120"></vxe-column>
 					<vxe-column field="visitOrgName" title="回访部门" width="140"></vxe-column>
 					<vxe-column field="visitTypeText" title="回访方式" width="110"></vxe-column>
@@ -142,6 +147,34 @@
 						:default-time="defaultTimeStartEnd"
 					/>
 				</el-form-item>
+				<el-form-item label="来源渠道" prop="SourceChannelCode">
+					<el-select v-model="state.queryParams.SourceChannelCode" placeholder="请选择来源渠道" clearable class="w100" @change="handleQuery">
+						<el-option v-for="item in state.channelOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="受理类型" prop="AcceptTypeCode">
+					<el-select v-model="state.queryParams.AcceptTypeCode" placeholder="请选择受理类型" clearable class="w100" @change="handleQuery">
+						<el-option v-for="item in state.acceptTypeOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="不满意原因" prop="OrgNoSatisfiedReason">
+					<el-select v-model="state.queryParams.OrgNoSatisfiedReason" placeholder="请选择不满意原因" clearable class="w100" @change="handleQuery">
+						<el-option v-for="item in state.dissatisfiedReason" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="事发地址" prop="AreaCode">
+					<el-cascader
+						:options="state.areaOptions"
+						filterable
+						:props="{ checkStrictly: true, value: 'id', label: 'areaName', emitPath: false }"
+						placeholder="请选择事发地址"
+						clearable
+						v-model="state.queryParams.AreaCode"
+						@change="handleQuery"
+						class="w100"
+					>
+					</el-cascader>
+				</el-form-item>
 				<el-form-item label="回访人姓名" prop="VisitUser">
 					<el-input v-model="state.queryParams.VisitUser" placeholder="回访人姓名" clearable @keyup.enter="handleQuery" />
 				</el-form-item>
@@ -196,19 +229,19 @@
 						<el-option :value="2" label="企业" />
 					</el-select>
 				</el-form-item>
-        <el-form-item label="工单标签" prop="OrderTagCode" v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)">
-          <el-cascader
-              :options="state.orderTagOptions"
-              filterable
-              :props="{ value: 'dicDataValue', label: 'dicDataName', emitPath: false, checkStrictly: true }"
-              placeholder="请选择工单标签"
-              class="w100"
-              v-model="state.queryParams.OrderTagCode"
-              @change="handleQuery"
-              clearable
-          >
-          </el-cascader>
-        </el-form-item>
+				<el-form-item label="工单标签" prop="OrderTagCode" v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)">
+					<el-cascader
+						:options="state.orderTagOptions"
+						filterable
+						:props="{ value: 'dicDataValue', label: 'dicDataName', emitPath: false, checkStrictly: true }"
+						placeholder="请选择工单标签"
+						class="w100"
+						v-model="state.queryParams.OrderTagCode"
+						@change="handleQuery"
+						clearable
+					>
+					</el-cascader>
+				</el-form-item>
 			</el-form>
 			<template #footer>
 				<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
@@ -228,6 +261,7 @@ import { exportAssignment } from '@/utils/tools';
 import { useThemeConfig } from '@/stores/themeConfig';
 import { storeToRefs } from 'pinia';
 import { visitDepartmentSatisfactionList, visitDepartmentSatisfactionListExport } from '@/api/business/visit';
+import { treeArea } from '@/api/auxiliary/area';
 
 // 引入组件
 const VisitDetailCom = defineAsyncComponent(() => import('@/views/business/visit/components/Visit-detail.vue')); // 回访
@@ -260,14 +294,23 @@ const state = reactive<any>({
 		SortRule: null,
 		LevelOneOrg: null,
 		VisitType: null,
-    OrderTagCode:null,
+		OrderTagCode: null,
+		SourceChannelCode: null, // 来源渠道
+		AcceptTypeCode: null, // 受理类型
+		OrgNoSatisfiedReason: null, // 不满意原因
+		AreaCode: null, // 区域
 	},
 	tableData: [], //表单
 	loading: false, // 加载
 	total: 0, // 总数
 	attitudeType: [],
-	visitType: [],
-  orderTagOptions: [], // 工单标签
+	channelOptions: [], // 来源渠道
+	acceptTypeOptions: [], // 受理类型
+	dissatisfiedReason: [], // 不满意原因
+	visitSatisfaction: [], // 办件结果
+	visitMananer: [], // 办件态度
+	orderTagOptions: [], // 工单标签
+	areaOptions: [], // 省市区数据
 });
 // 排序
 const sortChange = (val: any) => {
@@ -334,12 +377,18 @@ const getBaseData = async () => {
 			visitSatisfaction: 'visitSatisfaction',
 			orgsOptions: 'orgsOptions',
 			attitudeType: 'attitudeType',
+			channelOptions: 'channelOptions',
+			visitMananer: 'visitMananer',
+			orderTagOptions: 'orderTags',
 			visitType: 'visitType',
-      orderTagOptions: 'orderTags',
+			acceptTypeOptions: 'acceptTypeOptions',
+			dissatisfiedReason: 'dissatisfiedReason',
 		};
 		for (const key in mappings) {
 			state[key] = res.result?.[mappings[key]] ?? [];
 		}
+		const area = await treeArea();
+		state.areaOptions = area?.result ?? []; //省市区数据
 	} catch (error) {
 		console.log(error);
 	}

+ 8 - 1
src/views/business/visit/todo.vue

@@ -190,6 +190,12 @@
 					>
 					</el-cascader>
 				</el-form-item>
+				<el-form-item label="是否分配回访人" prop="isEmployeeNameNull" label-width="120px"  v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)">
+					<el-select v-model="state.queryParams.isEmployeeNameNull" placeholder="请选择是否分配回访人" class="w100" clearable @change="handleQuery">
+						<el-option label="是" :value="true" />
+						<el-option label="否" :value="false" />
+					</el-select>
+				</el-form-item>
 			</el-form>
 			<template #footer>
 				<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
@@ -270,7 +276,8 @@ const state = reactive<any>({
 		IsAiVisit: null, // IsAiVisit
 		SortField: null, // 排序字段
 		SortRule: null, // 排序方式
-		OrderTagCode:null, // 工单标签
+		OrderTagCode: null, // 工单标签
+		isEmployeeNameNull: null, // 回访人是否为空
 	},
 	tableData: [], //表单
 	loading: false, // 加载

+ 1 - 1
src/views/judicial/order/components/orderDetail.vue

@@ -83,7 +83,7 @@
 								<el-form-item label="热点分类"> {{ state.ruleForm.hotspotSpliceName }} </el-form-item>
 							</el-col>
 							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.eventTypeSpliceName">
-								<el-form-item label="事项类型"> {{ state.ruleForm.eventTypeSpliceName }} </el-form-item>
+								<el-form-item label="问题类型"> {{ state.ruleForm.eventTypeSpliceName }} </el-form-item>
 							</el-col>
 							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
 								<el-form-item label="受理人">

+ 25 - 12
src/views/judicial/order/components/verify.vue

@@ -3,15 +3,15 @@
 		<div class="collapse-container">
 			<el-form label-width="110px" ref="ruleFormRef" :model="state.ruleForm">
 				<el-form-item label="线索是否属实" prop="isTheClueTrue" :rules="[{ required: true, message: '请选择线索是否属实', trigger: 'change' }]">
-					<el-radio-group v-model="state.ruleForm.isTheClueTrue" @change="change">
-						<el-radio :value="true">是</el-radio>
-						<el-radio :value="false">否</el-radio>
-					</el-radio-group>
+					<el-switch v-model="state.ruleForm.isTheClueTrue" active-text="属实" inactive-text="不属实" inline-prompt />
+				</el-form-item>
+				<el-form-item label="执法类别">
+					<el-tag>{{ state.ruleForm.isTheClueTrue ? '执法类工单' : '非执法类工单' }}</el-tag>
 				</el-form-item>
 				<el-form-item
-					label="事项类型"
+					label="问题类型"
 					prop="eventTypeId"
-					:rules="[{ required: true, message: '请选择事项类型', trigger: 'change' }]"
+					:rules="[{ required: true, message: '请选择问题类型', trigger: 'change' }]"
 					v-if="state.ruleForm.isTheClueTrue"
 				>
 					<el-tree-select
@@ -29,14 +29,26 @@
 						default-expand-all
 						clearable
 						node-key="id"
+						placeholder="请选择问题类型"
 					/>
 				</el-form-item>
+				<el-form-item
+					label="个案类型"
+					prop="caseType"
+					:rules="[{ required: true, message: '请选择个案类型', trigger: 'change' }]"
+					v-if="state.ruleForm.isTheClueTrue"
+				>
+					<el-radio-group v-model="state.ruleForm.caseType">
+						<el-radio-button label="一般个案例" :value="0" />
+						<el-radio-button label="重点关注个案" :value="1" />
+					</el-radio-group>
+				</el-form-item>
 			</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>
+				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确定</el-button>
 			</span>
 		</template>
 	</el-dialog>
@@ -54,10 +66,11 @@ const state = reactive<any>({
 	dialogVisible: false, // 是否显示弹窗
 	loading: false, // 是否显示加载
 	ruleForm: {
-		isTheClueTrue: null, // 线索是否属实
-		eventTypeId: null, // 事项类型
-		eventTypeName: null, // 事项类型名称
-		eventTypeSpliceName: null, // 事项类型全名
+		isTheClueTrue: false, // 线索是否属实
+		eventTypeId: null, // 问题类型
+		eventTypeName: null, // 问题类型名称
+		eventTypeSpliceName: null, // 问题类型全名
+		caseType: 0, // 个案类型
 	},
 });
 const ruleFormRef = ref<RefType>();
@@ -104,7 +117,7 @@ const close = () => {
 	ruleFormRef.value?.clearValidate();
 	ruleFormRef.value?.resetFields();
 };
-const change = (val) => {
+const change = (val: boolean) => {
 	if (!val) {
 		ruleFormRef.value.resetFields('eventTypeId');
 		state.ruleForm.eventTypeId = null;

+ 14 - 18
src/views/judicial/order/index.vue

@@ -5,29 +5,21 @@
 				<el-form-item label="快捷查询" prop="IsTheClueTrueText">
 					<el-segmented
 						:options="[
-							{
-								value: '0',
-								label: '全部',
-							},
 							{
 								value: '1',
-								label: '待核实',
+								label: '待确认',
 							},
 							{
-								value: '2',
-								label: '线索属实',
+								value: '5',
+								label: '执法类工单',
 							},
 							{
 								value: '3',
-								label: '线索不属实',
+								label: '非执法类工单',
 							},
 							{
-								value: '4',
-								label: '推诿工单',
-							},
-							{
-								value: '5',
-								label: '行政执法类工单',
+								value: '0',
+								label: '全部',
 							},
 						]"
 						v-model="state.queryParams.IsTheClueTrueText"
@@ -54,7 +46,7 @@
 			>
 				<template #buttons>
 					<el-button type="primary" @click="onVerify(null)" v-auth="'judicial:order:verify:multiple'" :disabled="isChecked" :loading="state.loading"
-						>线索核实
+						>线索核实<span v-if="checkTable.length">({{ checkTable.length }})</span>
 					</el-button>
 				</template>
 			</vxe-toolbar>
@@ -99,8 +91,8 @@
 					<vxe-column field="isPassTheBuckOrderText" title="是否推诿工单" width="120"></vxe-column>
 					<vxe-column field="isTheClueTrueText" title="线索是否属实" width="120"></vxe-column>
 					<vxe-column field="isEnforcementOrderText" title="是否行政执法类工单" width="150"></vxe-column>
-					<vxe-column field="eventTypeName" title="事项类型" width="150"></vxe-column>
-					<vxe-column title="操作" fixed="right" width="140" align="center" :show-overflow="false">
+					<vxe-column field="eventTypeName" title="问题类型" width="150"></vxe-column>
+					<vxe-column title="操作" fixed="right" width="120" align="center" :show-overflow="false">
 						<template #default="{ row }">
 							<el-button
 								link
@@ -255,7 +247,7 @@ const state = reactive<any>({
 		CreationTimeStart: null,
 		CreationTimeEnd: null,
 		NameOrNo: null,
-		IsTheClueTrueText: '0', // 快捷查询
+		IsTheClueTrueText: '1', // 快捷查询 默认待确认
 	},
 	tableData: [], //表单
 	loading: false, // 加载
@@ -313,9 +305,13 @@ const queryList = () => {
 			state.tableData = response?.result.items ?? [];
 			state.total = response?.result.total;
 			state.loading = false;
+			tableRef.value.clearCheckboxRow();
+			checkTable.value = [];
 		})
 		.catch(() => {
 			state.loading = false;
+			tableRef.value.clearCheckboxRow();
+			checkTable.value = [];
 		});
 };
 /** 重置按钮操作 */

+ 2 - 2
src/views/judicial/statistics/detailArea.vue

@@ -17,7 +17,7 @@
 					:loading="state.loading"
 					:data="state.tableData"
 					:column-config="{ resizable: true }"
-					:row-config="{ isCurrent: true, isHover: true, height: 30,useKey: true  }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
 					ref="tableRef"
 					height="auto"
 					auto-resize
@@ -47,7 +47,7 @@
 					<vxe-column field="isPassTheBuckOrderText" title="是否推诿工单" width="120"></vxe-column>
 					<vxe-column field="isTheClueTrueText" title="线索是否属实" width="120"></vxe-column>
 					<vxe-column field="isEnforcementOrderText" title="是否行政执法类工单" width="150"></vxe-column>
-					<vxe-column field="eventTypeName" title="事项类型" width="150"></vxe-column>
+					<vxe-column field="eventTypeName" title="问题类型" width="150"></vxe-column>
 				</vxe-table>
 			</div>
 			<pagination

+ 1 - 1
src/views/judicial/statistics/detailDepartment.vue

@@ -47,7 +47,7 @@
 					<vxe-column field="isPassTheBuckOrderText" title="是否推诿工单" width="120"></vxe-column>
 					<vxe-column field="isTheClueTrueText" title="线索是否属实" width="120"></vxe-column>
 					<vxe-column field="isEnforcementOrderText" title="是否行政执法类工单" width="150"></vxe-column>
-					<vxe-column field="eventTypeName" title="事项类型" width="150"></vxe-column>
+					<vxe-column field="eventTypeName" title="问题类型" width="150"></vxe-column>
 				</vxe-table>
 			</div>
 			<pagination

+ 1 - 1
src/views/judicial/statistics/detailEventClass.vue

@@ -47,7 +47,7 @@
 					<vxe-column field="isPassTheBuckOrderText" title="是否推诿工单" width="120"></vxe-column>
 					<vxe-column field="isTheClueTrueText" title="线索是否属实" width="120"></vxe-column>
 					<vxe-column field="isEnforcementOrderText" title="是否行政执法类工单" width="150"></vxe-column>
-					<vxe-column field="eventTypeName" title="事项类型" width="150"></vxe-column>
+					<vxe-column field="eventTypeName" title="问题类型" width="150"></vxe-column>
 				</vxe-table>
 			</div>
 			<pagination

+ 1 - 1
src/views/judicial/statistics/detailSatisfied.vue

@@ -47,7 +47,7 @@
 					<vxe-column field="isPassTheBuckOrderText" title="是否推诿工单" width="120"></vxe-column>
 					<vxe-column field="isTheClueTrueText" title="线索是否属实" width="120"></vxe-column>
 					<vxe-column field="isEnforcementOrderText" title="是否行政执法类工单" width="150"></vxe-column>
-					<vxe-column field="eventTypeName" title="事项类型" width="150"></vxe-column>
+					<vxe-column field="eventTypeName" title="问题类型" width="150"></vxe-column>
 					<vxe-column title="操作" width="90" fixed="right">
 						<template #default="{ row }">
 							<el-button link type="primary" @click="visitDetail(row)" title="查看回访详情"> 回访详情 </el-button>

+ 16 - 25
src/views/judicial/statistics/eventClass.vue

@@ -31,25 +31,25 @@
 			</el-form>
 		</el-card>
 		<el-row :gutter="20">
-			<el-col :xs="24" :sm="12" :md="12" :lg="4" :xl="4">
+			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
 				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.orderCount.theClueIsTrue">
+					<el-statistic :value="state.orderCount.totalOrder">
 						<template #title>
-							<span class="color-info font14">线索属实</span>
+							<span class="color-info font14">总工单</span>
 						</template>
 					</el-statistic>
 				</el-card>
 			</el-col>
-			<el-col :xs="24" :sm="12" :md="12" :lg="4" :xl="4">
+			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
 				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.orderCount.theClueIsNotTrue">
+					<el-statistic :value="state.orderCount.passTheBuckOrder">
 						<template #title>
-							<span class="color-info font14">线索不属实</span>
+							<span class="color-info font14">推诿工单</span>
 						</template>
 					</el-statistic>
 				</el-card>
 			</el-col>
-			<el-col :xs="24" :sm="12" :md="12" :lg="4" :xl="4">
+			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
 				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
 					<el-statistic :value="state.orderCount.enforcementOrder">
 						<template #title>
@@ -58,20 +58,12 @@
 					</el-statistic>
 				</el-card>
 			</el-col>
-			<el-col :xs="24" :sm="12" :md="12" :lg="4" :xl="4">
-				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.orderCount.passTheBuckOrder">
-						<template #title>
-							<span class="color-info font14">推诿工单</span>
-						</template>
-					</el-statistic>
-				</el-card>
-			</el-col>
-			<el-col :xs="24" :sm="12" :md="12" :lg="4" :xl="4">
+
+			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
 				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.orderCount.toBeVerified">
+					<el-statistic :value="state.orderCount.theClueIsNotTrue">
 						<template #title>
-							<span class="color-info font14">待核实</span>
+							<span class="color-info font14">非执法类工单</span>
 						</template>
 					</el-statistic>
 				</el-card>
@@ -102,7 +94,7 @@
 					show-footer
 					:footer-method="footerMethod"
 				>
-					<vxe-column field="name" title="事项类型" min-width="200" tree-node></vxe-column>
+					<vxe-column field="name" title="问题类型" min-width="200" tree-node></vxe-column>
 					<vxe-column field="num" title="工单总量" width="100">
 						<template #default="{ row }">
 							<el-button type="primary" link @click="linkDetail(row)">
@@ -134,11 +126,10 @@ const state = reactive<any>({
 	loading: false, // 加载
 	totalCount: {},
 	orderCount: {
-		theClueIsTrue: 0,
-		theClueIsNotTrue: 0,
-		enforcementOrder: 0,
-		passTheBuckOrder: 0,
-		toBeVerified: 0,
+		theClueIsNotTrue: 0, // 非执法类工单
+		enforcementOrder: 0, // 行政执法工单
+		passTheBuckOrder: 0, // 推诿工单
+		totalOrder: 0, // 总工单
 	},
 	AreaCode: null,
 });

+ 26 - 5
src/views/knowledge/index/preview.vue

@@ -22,7 +22,7 @@
 						</template>
 					</el-skeleton>
 				</el-col>
-				<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" style="display: flex; align-items: center; justify-content: center">
+				<el-col :xs="24" :sm="12" :md="12" :lg="10" :xl="10" style="display: flex; align-items: center; justify-content: center">
 					<el-skeleton :loading="loading" animated>
 						<template #template>
 							<el-skeleton-item />
@@ -37,12 +37,21 @@
 									</template>
 								</el-tooltip>
 							</span>
-							<span class="mr30">是否公开:{{ state.info.isPublic ? '是' : '否' }}</span>
-							<span>已阅:{{ state.info.pageView }}</span>
+							<span class="mr20">是否公开:{{ state.info.isPublic ? '是' : '否' }}</span>
+							<span class="mr20">已阅:{{ state.info.pageView }}</span>
+							<span class="flex-center-align" v-if="hotspotName && ['LuZhou'].includes(themeConfig.appScope)"
+								>热点分类:
+								<el-tooltip effect="dark" content="Top Left prompts info" :disabled="hotspotName.length < 8">
+									<span style="display: block; width: 100px" class="text-no-wrap">{{ hotspotName }}</span>
+									<template #content>
+										{{ hotspotName }}
+									</template>
+								</el-tooltip>
+							</span>
 						</template>
 					</el-skeleton>
 				</el-col>
-				<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8" style="display: flex; align-items: center; justify-content: flex-end">
+				<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6" style="display: flex; align-items: center; justify-content: flex-end">
 					<el-skeleton :loading="loading" animated>
 						<template #template>
 							<el-skeleton-item />
@@ -202,7 +211,8 @@ import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
 import mittBus from '@/utils/mitt';
 import { downloadFileByStream, transformFile } from '@/utils/tools';
 import { getCollectList } from '@/api/knowledge/collect';
-
+import { storeToRefs } from 'pinia';
+import { useThemeConfig } from '@/stores/themeConfig';
 // 引入组件
 const ErrorAdd = defineAsyncComponent(() => import('@/views/knowledge/error/components/Error-add.vue')); // 知识纠错
 const QuestionAdd = defineAsyncComponent(() => import('@/views/knowledge/question/components/Question-add.vue')); // 知识提问
@@ -229,6 +239,8 @@ const state = reactive<any>({
 	},
 	groupDialogVisible: false,
 });
+const storesThemeConfig = useThemeConfig();
+const { themeConfig } = storeToRefs(storesThemeConfig);
 const loading = ref<Boolean>(false); // 加载状态
 // 查询知识详情
 const route = useRoute(); //  获取路由参数
@@ -334,6 +346,15 @@ const collectFormClose = () => {
 	collectFormRef.value?.resetFields();
 	collectFormRef.value?.clearValidate();
 };
+// 热点名称
+const hotspotName = computed(() => {
+	console.log(state.info.knowledgeTypes);
+	if (state.info.knowledgeTypes && state.info.knowledgeTypes.length) {
+		return state.info.knowledgeTypes.map((item: any) => item.spliceName).join('、');
+	} else {
+		return '';
+	}
+});
 // 确认选择收藏分组
 const collectConfirm = (formEl: FormInstance | undefined) => {
 	if (!formEl) return;

+ 21 - 5
src/views/snapshot/config/industry/components/Industry-edit.vue

@@ -248,12 +248,20 @@
 					</el-form-item>
 				</el-col>
 				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-					<el-form-item label="上报积分" prop="reportPoints" :rules="[{ required: true, message: '请填写上报积分', trigger: 'blur' }]">
+					<el-form-item
+						label="上报积分"
+						prop="reportPoints"
+						:rules="[{ required: state.ruleForm.isPoints, message: '请填写上报积分', trigger: 'blur' }]"
+					>
 						<el-input-number v-model="state.ruleForm.reportPoints" :min="0" :precision="2" class="w100" placeholder="请填写上报积分" />
 					</el-form-item>
 				</el-col>
 				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-					<el-form-item label="审核同意积分" prop="argeePoints" :rules="[{ required: true, message: '请填写审核同意积分', trigger: 'blur' }]">
+					<el-form-item
+						label="审核同意积分"
+						prop="argeePoints"
+						:rules="[{ required: state.ruleForm.isPoints, message: '请填写审核同意积分', trigger: 'blur' }]"
+					>
 						<el-input-number v-model="state.ruleForm.argeePoints" :min="0" :precision="2" class="w100" placeholder="请填写审核同意积分" />
 					</el-form-item>
 				</el-col>
@@ -262,13 +270,17 @@
 						label="审核不同意扣除积分"
 						label-width="150px"
 						prop="refusePoints"
-						:rules="[{ required: true, message: '请填写审核不同意扣除积分', trigger: 'blur' }]"
+						:rules="[{ required: state.ruleForm.isPoints, message: '请填写审核不同意扣除积分', trigger: 'blur' }]"
 					>
 						<el-input-number v-model="state.ruleForm.refusePoints" :min="0" :precision="2" class="w100" placeholder="请填写审核不同意扣除积分" />
 					</el-form-item>
 				</el-col>
 				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-					<el-form-item label="额外扣除积分" prop="extraDeductedPoints" :rules="[{ required: true, message: '请填写额外扣除积分', trigger: 'blur' }]">
+					<el-form-item
+						label="额外扣除积分"
+						prop="extraDeductedPoints"
+						:rules="[{ required: state.ruleForm.isPoints, message: '请填写额外扣除积分', trigger: 'blur' }]"
+					>
 						<el-input-number v-model="state.ruleForm.extraDeductedPoints" :min="0" :precision="2" class="w100" placeholder="请填写额外扣除积分" />
 					</el-form-item>
 				</el-col>
@@ -501,7 +513,11 @@ const onSubmit = throttle(async (formEl: FormInstance | undefined) => {
 	await formEl.validate((valid: boolean) => {
 		if (!valid) return;
 		loading.value = true;
-		editIndustry(state.ruleForm)
+		const requestData = {
+			...state.ruleForm,
+			files: filesFormat.value,
+		};
+		editIndustry(requestData)
 			.then(() => {
 				ElMessage({
 					message: '操作成功',

+ 2 - 2
src/views/snapshot/reSend/supplyLog.vue

@@ -26,7 +26,7 @@
 					<span v-else>{{ row.statusTxt }}</span>
 				</template>
 				<template #order_detail="{ row }">
-					<order-detail :order="{ id: row.orderId }" @updateList="queryList">{{ row.no }}</order-detail>
+					<order-detail :order="{ id: row.orderId }" @updateList="queryList">{{ row.title }}</order-detail>
 				</template>
 				<template #pager>
 					<pagination
@@ -179,7 +179,7 @@ const gridOptions = reactive<any>({
 			width: 120,
 		},
 		{
-			field: 'replenishType',
+			field: 'auditType',
 			title: '补充奖励类型',
 			width: 120,
 		},

+ 11 - 4
src/views/statistics/department/detailHandle.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="statistics-department-detail-handle-container layout-padding">
-    <div class="layout-padding-auto layout-padding-view pd20">
+		<div class="layout-padding-auto layout-padding-view pd20">
 			<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline>
 				<el-form-item label="来电主体" prop="TypeId">
 					<el-select v-model="state.queryParams.TypeId" placeholder="请选择来电主体" @change="handleQuery">
@@ -32,7 +32,7 @@
 					:loading="state.loading"
 					:data="state.tableData"
 					:column-config="{ resizable: true }"
-					:row-config="{ isCurrent: true, isHover: true, height: 30,useKey: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
 					ref="tableRef"
 					height="auto"
 					auto-resize
@@ -87,7 +87,14 @@
 					<vxe-column field="sourceChannel" title="来源渠道" width="100"></vxe-column>
 					<vxe-column field="hotspotSpliceName" title="热点全称" width="150"></vxe-column>
 					<vxe-column field="hotspotName" title="热点分类" width="150"></vxe-column>
+					<vxe-column field="oneHotspotName" title="一级热点" width="150"></vxe-column>
+					<vxe-column field="twoHotspotName" title="二级热点" width="150"></vxe-column>
+					<vxe-column field="threeHotspotName" title="三级热点" width="150"></vxe-column>
+					<vxe-column field="fourHotspotName" title="四级热点" width="150"></vxe-column>
+					<vxe-column field="fiveHotspotName" title="五级热点" width="150"></vxe-column>
 					<vxe-column field="acceptorName" title="受理人" width="100"></vxe-column>
+					<vxe-column field="content" title="受理内容" min-width="200"></vxe-column>
+					<vxe-column field="fileOpinion" title="承办意见" min-width="200"></vxe-column>
 				</vxe-table>
 			</div>
 			<pagination
@@ -118,8 +125,8 @@ const state = reactive<any>({
 		PageIndex: 1, // 当前页
 		PageSize: 20, // 每页条数
 		TypeId: 0,
-		SortField:null,
-		SortRule:null,
+		SortField: null,
+		SortRule: null,
 	},
 	tableData: [], //表单
 	loading: false, // 加载

+ 5 - 0
src/views/statistics/department/detailHandleList.vue

@@ -98,6 +98,11 @@
 					<vxe-column field="sourceChannel" title="来源渠道" width="100"></vxe-column>
 					<vxe-column field="hotspotSpliceName" title="热点全称" width="150"></vxe-column>
 					<vxe-column field="hotspotName" title="热点分类" width="150"></vxe-column>
+					<vxe-column field="oneHotspotName" title="一级热点" width="150"></vxe-column>
+					<vxe-column field="twoHotspotName" title="二级热点" width="150"></vxe-column>
+					<vxe-column field="threeHotspotName" title="三级热点" width="150"></vxe-column>
+					<vxe-column field="fourHotspotName" title="四级热点" width="150"></vxe-column>
+					<vxe-column field="fiveHotspotName" title="五级热点" width="150"></vxe-column>
 					<vxe-column field="acceptorName" title="受理人" width="100"></vxe-column>
 				</vxe-table>
 			</div>

+ 45 - 1
src/views/statistics/department/dpSatisfied.vue

@@ -89,6 +89,10 @@
 						</template>
 					</vxe-column>
 					<vxe-column field="orderTag" title="工单标签" width="120" v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"></vxe-column>
+					<vxe-column field="sourceChannel" title="来源渠道" width="120"></vxe-column>
+					<vxe-column field="acceptType" title="受理类型" width="120"></vxe-column>
+					<vxe-column field="orgNoSatisfiedReasonText" title="不满意原因" width="120"></vxe-column>
+					<vxe-column field="area" title="事发地址" width="120"></vxe-column>
 					<vxe-column field="visitUser" title="回访人" width="120"></vxe-column>
 					<vxe-column field="visitOrgName" title="回访部门" width="140"></vxe-column>
 					<vxe-column field="visitTypeText" title="回访方式" width="110"></vxe-column>
@@ -221,6 +225,34 @@
 						<el-option :value="false" label="市工单" />
 					</el-select>
 				</el-form-item>
+				<el-form-item label="来源渠道" prop="SourceChannelCode">
+					<el-select v-model="state.queryParams.SourceChannelCode" placeholder="请选择来源渠道" clearable class="w100" @change="handleQuery">
+						<el-option v-for="item in state.channelOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="受理类型" prop="AcceptTypeCode">
+					<el-select v-model="state.queryParams.AcceptTypeCode" placeholder="请选择受理类型" clearable class="w100" @change="handleQuery">
+						<el-option v-for="item in state.acceptTypeOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="不满意原因" prop="OrgNoSatisfiedReason">
+					<el-select v-model="state.queryParams.OrgNoSatisfiedReason" placeholder="请选择不满意原因" clearable class="w100" @change="handleQuery">
+						<el-option v-for="item in state.dissatisfiedReason" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="事发地址" prop="AreaCode">
+					<el-cascader
+						:options="state.areaOptions"
+						filterable
+						:props="{ checkStrictly: true, value: 'id', label: 'areaName', emitPath: false }"
+						placeholder="请选择事发地址"
+						clearable
+						v-model="state.queryParams.AreaCode"
+						@change="handleQuery"
+						class="w100"
+					>
+					</el-cascader>
+				</el-form-item>
 				<el-form-item label="回访内容" prop="ContentRetrieval">
 					<el-input v-model="state.queryParams.ContentRetrieval" placeholder="回访内容" clearable @keyup.enter="handleQuery" />
 				</el-form-item>
@@ -268,6 +300,7 @@ import Other from '@/utils/other';
 import { exportAssignment } from '@/utils/tools';
 import { useThemeConfig } from '@/stores/themeConfig';
 import { storeToRefs } from 'pinia';
+import { treeArea } from '@/api/auxiliary/area';
 
 // 引入组件
 const VisitDetailCom = defineAsyncComponent(() => import('@/views/business/visit/components/Visit-detail.vue')); // 回访
@@ -308,15 +341,22 @@ const state = reactive<any>({
 		VisitType: null,
 		ActualHandleOrgName: null,
 		IsScreen: null, // 是否甄别
+		SourceChannelCode:null, // 来源渠道
+		AcceptTypeCode:null, // 受理类型
+		OrgNoSatisfiedReason:null, // 不满意原因
+		AreaCode:null, // 区域
 	},
 	tableData: [], //表单
 	loading: false, // 加载
 	total: 0, // 总数
 	attitudeType: [],
-	channelOptions: [],
+	channelOptions: [], // 来源渠道
+	acceptTypeOptions:[], // 受理类型
+	dissatisfiedReason:[], // 不满意原因
 	visitSatisfaction: [], // 办件结果
 	visitMananer: [], // 办件态度
 	orderTagOptions: [], // 工单标签
+	areaOptions: [], // 省市区数据
 });
 // 排序
 const sortChange = (val: any) => {
@@ -396,10 +436,14 @@ const getBaseData = async () => {
 			visitMananer: 'visitMananer',
 			orderTagOptions: 'orderTags',
 			visitType: 'visitType',
+			acceptTypeOptions:'acceptTypeOptions',
+			dissatisfiedReason:'dissatisfiedReason',
 		};
 		for (const key in mappings) {
 			state[key] = res.result?.[mappings[key]] ?? [];
 		}
+		const area = await treeArea();
+		state.areaOptions = area?.result ?? []; //省市区数据
 	} catch (error) {
 		console.log(error);
 	}

+ 151 - 108
src/views/statistics/order/YBVisitCount.vue

@@ -1,94 +1,65 @@
 <template>
-	<div class="statistics-order-yb-visit-count-container layout-pd">
-		<el-card shadow="never">
-			<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline>
-				<el-form-item prop="crTime">
-					<statistical-time v-model="state.queryParams.crTime" @change="handleQuery" ref="statisticalTimeRef" :disabled="state.loading" />
-				</el-form-item>
-				<el-form-item label="回访员" prop="VisitName">
-					<el-input v-model="state.queryParams.VisitName" placeholder="回访员名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
-				</el-form-item>
-				<el-form-item>
-					<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-					<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.loading">
-						<SvgIcon name="ele-Refresh" class="mr5" />重置
-					</el-button>
-				</el-form-item>
-			</el-form>
-		</el-card>
-		<el-row :gutter="20">
-			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
-				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.data.aiVisitCount">
-						<template #title>
-							<span class="color-info font14">智能回访量</span>
-						</template>
-					</el-statistic>
-				</el-card>
-			</el-col>
-			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
-				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.data.aiVisitSatisfiedCount">
-						<template #title>
-							<span class="color-info font14">智能回访满意量</span>
-						</template>
-					</el-statistic>
-				</el-card>
-			</el-col>
-			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
-				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.data.aiVisitNoSatisfiedCount">
-						<template #title>
-							<span class="color-info font14">智能回访不满意量</span>
-						</template>
-					</el-statistic>
-				</el-card>
-			</el-col>
-			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
-				<el-card shadow="never" v-loading="state.loading" class="statistics-item">
-					<el-statistic :value="state.data.aiVisitFailCount">
-						<template #title>
-							<span class="color-info font14">智能回访失败</span>
-						</template>
-					</el-statistic>
-				</el-card>
-			</el-col>
-		</el-row>
-		<el-card shadow="never">
-			<vxe-toolbar
-				ref="toolbarRef"
-				:loading="state.loading"
-				custom
-				:refresh="{
-					queryMethod: handleQuery,
-				}"
-				:tools="[{ toolRender: { name: 'exportAll' } }]"
-			>
-			</vxe-toolbar>
-			<vxe-table
-				border
-				:loading="state.loading"
-				:data="state.tableData"
-				:column-config="{ resizable: true }"
-				:row-config="{ isCurrent: true, isHover: true, height: 30, useKey:true }"
-				ref="tableRef"
-				auto-resize
-				:scrollY="{ enabled: true, gt: 100 }"
-				show-overflow
-				id="statisticsOrderYBVisitCount"
-				:custom-config="{ storage: true }"
-				show-footer
-				:footer-method="footerMethod"
-				max-height="600px"
-				:params="{ exportMethod: departmentVisitExport, exportParams: requestParams }"
-				showHeaderOverflow
-			>
-				<vxe-column field="visitName" title="回访员"></vxe-column>
-				<vxe-column field="callVisitCount" title="电话回访量" sortable> </vxe-column>
-				<vxe-column field="artificialVisitCount" title="人工回访量" sortable></vxe-column>
-				<vxe-column field="sumCount" title="总回访量" sortable></vxe-column>
-			</vxe-table>
-		</el-card>
+	<div class="statistics-order-yb-visit-count-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<vxe-grid v-bind="gridOptions" ref="gridRef">
+				<template #form>
+					<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline :disabled="gridOptions.loading">
+						<el-form-item prop="crTime">
+							<statistical-time v-model="state.queryParams.crTime" @change="handleQuery" ref="statisticalTimeRef" :disabled="gridOptions.loading" />
+						</el-form-item>
+						<el-form-item label="回访员" prop="VisitName">
+							<el-input v-model="state.queryParams.VisitName" placeholder="回访员名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
+						</el-form-item>
+						<el-form-item>
+							<el-button type="primary" @click="handleQuery" :loading="gridOptions.loading">
+								<SvgIcon name="ele-Search" class="mr5" />查询
+							</el-button>
+							<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="gridOptions.loading">
+								<SvgIcon name="ele-Refresh" class="mr5" />重置
+							</el-button>
+						</el-form-item>
+					</el-form>
+					<el-row :gutter="20" class="mt10">
+						<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
+							<el-card shadow="hover" v-loading="gridOptions.loading" class="statistics-item">
+								<el-statistic :value="state.data.aiVisitCount">
+									<template #title>
+										<span class="color-info font14">智能回访量</span>
+									</template>
+								</el-statistic>
+							</el-card>
+						</el-col>
+						<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
+							<el-card shadow="hover" v-loading="gridOptions.loading" class="statistics-item">
+								<el-statistic :value="state.data.aiVisitSatisfiedCount">
+									<template #title>
+										<span class="color-info font14">智能回访满意量</span>
+									</template>
+								</el-statistic>
+							</el-card>
+						</el-col>
+						<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
+							<el-card shadow="hover" v-loading="gridOptions.loading" class="statistics-item cursor-pointer" @click="linkDetail">
+								<el-statistic :value="state.data.aiVisitNoSatisfiedCount">
+									<template #title>
+										<span class="color-info font14">智能回访不满意量</span>
+									</template>
+								</el-statistic>
+							</el-card>
+						</el-col>
+						<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
+							<el-card shadow="hover" v-loading="gridOptions.loading" class="statistics-item">
+								<el-statistic :value="state.data.aiVisitFailCount">
+									<template #title>
+										<span class="color-info font14">智能回访失败</span>
+									</template>
+								</el-statistic>
+							</el-card>
+						</el-col>
+					</el-row>
+				</template>
+			</vxe-grid>
+		</div>
 	</div>
 </template>
 <script setup lang="tsx" name="statisticsOrderYBVisitCount">
@@ -98,6 +69,7 @@ import { departmentVisit, departmentVisitExport } from '@/api/statistics/order';
 import { defaultDate } from '@/utils/constants';
 import Other from '@/utils/other';
 import XEUtils from 'xe-utils';
+import { useRouter } from 'vue-router';
 
 const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
 const ruleFormRef = ref<RefType>(); // 表单ref
@@ -117,15 +89,87 @@ const state = reactive<any>({
 		aiVisitFailCount: 0,
 	},
 });
+
+const requestParams = ref<EmptyObjectType>({});
+const gridOptions = reactive<any>({
+	loading: false,
+	border: true,
+	showOverflow: true,
+	columnConfig: {
+		resizable: true,
+	},
+	scrollY: {
+		enabled: true,
+		gt: 100,
+	},
+	toolbarConfig: {
+		zoom: true,
+		custom: true,
+		refresh: {
+			queryMethod: () => {
+				handleQuery();
+			},
+		},
+		tools: [{ toolRender: { name: 'exportAll' } }],
+	},
+	customConfig: {
+		storage: true,
+	},
+	id: 'statisticsOrderYBVisitCount',
+	rowConfig: { isHover: true, height: 30, isCurrent: true, useKey: true },
+	height: 'auto',
+	columns: [
+		{
+			field: 'visitName',
+			title: '回访员',
+			minWidth: 100,
+		},
+		{
+			field: 'callVisitCount',
+			title: '电话回访量',
+			minWidth: 100,
+			sortable: true,
+		},
+		{
+			field: 'artificialVisitCount',
+			title: '人工回访量',
+			minWidth: 100,
+			sortable: true,
+		},
+		{
+			field: 'sumCount',
+			title: '总回访量',
+			minWidth: 100,
+			sortable: true,
+		},
+	],
+	data: [],
+	params: {
+		exportMethod: departmentVisitExport,
+		exportParams: requestParams,
+	},
+	showFooter: true,
+	footerMethod: ({ columns, data }) => {
+		return [
+			columns.map((column: any, columnIndex: number) => {
+				if (columnIndex === 0) {
+					return '合计';
+				}
+				if (['callVisitCount', 'artificialVisitCount', 'sumCount'].includes(column.property)) {
+					return XEUtils.sum(data, column.property);
+				}
+			}),
+		];
+	},
+});
 /** 搜索按钮操作 */
 const handleQuery = () => {
 	// state.queryParams.PageIndex = 1;
 	queryList();
 };
 /** 获取列表 */
-const requestParams = ref<EmptyObjectType>({});
 const queryList = () => {
-	state.loading = true;
+	gridOptions.loading = true;
 	requestParams.value = Other.deepClone(state.queryParams);
 	requestParams.value.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
 	requestParams.value.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
@@ -134,10 +178,11 @@ const queryList = () => {
 		.then((res: any) => {
 			state.tableData = res.result?.visitMeasureStatisticsModelList ?? [];
 			state.data = res.result ?? {};
-			state.loading = false;
+			gridOptions.data = res.result?.visitMeasureStatisticsModelList ?? [];
+			gridOptions.loading = false;
 		})
 		.catch(() => {
-			state.loading = false;
+			gridOptions.loading = false;
 		});
 };
 /** 重置按钮操作 */
@@ -148,18 +193,17 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 	statisticalTimeRef.value.reset();
 	queryList();
 };
-// 计算合计
-const footerMethod = ({ columns, data }) => {
-	return [
-		columns.map((column: any, columnIndex: number) => {
-			if (columnIndex === 0) {
-				return '合计';
-			}
-			if (['callVisitCount', 'artificialVisitCount', 'sumCount'].includes(column.property)) {
-				return XEUtils.sum(data, column.property);
-			}
-		}),
-	];
+// 查看详情
+const router = useRouter();
+const linkDetail = () => {
+	router.push({
+		path: '/statistics/order/detailVisitContent',
+		query: {
+			tagsViewName: '智能回访不满意明细',
+			StartTime: requestParams.value.StartTime,
+			EndTime: requestParams.value.EndTime,
+		},
+	});
 };
 const toolbarRef = ref<RefType>();
 const tableRef = ref<RefType>();
@@ -174,9 +218,8 @@ onMounted(() => {
 :deep(.el-statistic__content) {
 	font-size: 32px;
 	font-weight: bold;
-	margin-top: 15px;
 }
 .statistics-item {
-	margin-bottom: 10px;
+	border: var(--el-border);
 }
 </style>

+ 184 - 0
src/views/statistics/order/detailVisitContent.vue

@@ -0,0 +1,184 @@
+<template>
+	<div class="statistics-order-detail-visit-content-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline :disabled="state.loading">
+				<el-form-item label="查询时间段" prop="crTime">
+					<el-date-picker
+						v-model="state.queryParams.crTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						:clearable="false"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
+				<el-form-item label="回访人" prop="VisitName">
+					<el-input v-model="state.queryParams.VisitName" placeholder="回访人" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.loading">
+						<SvgIcon name="ele-Refresh" class="mr5" />重置
+					</el-button>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.loading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+			>
+<!--
+				:tools="[{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }]"-->
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					border
+					:loading="state.loading"
+					:data="state.tableData"
+					:column-config="{ resizable: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:scrollY="{ enabled: true, gt: 100 }"
+					id="statisticsOrderDetailVisitContent"
+					:custom-config="{ storage: true }"
+					showHeaderOverflow
+					:sort-config="{ remote: true }"
+					:params="{ exportMethod: departmentOverdueDetailExport, exportParams: requestParams }"
+				>
+					<vxe-column field="order.expiredStatusText" title="状态" width="60" align="center">
+						<template #default="{ row }">
+							<span :class="'overdue-status-' + row.order?.expiredStatus" :title="row.order.expiredStatusText"></span>
+						</template>
+					</vxe-column>
+					<vxe-column field="statusText" title="工单状态" width="110">
+						<template #default="{ row }">
+							<el-text type="danger" tag="b" v-if="[1, 2, 3, 9, 101, 102, 103, 104, 105, 200].includes(row.status)">{{ row.order?.statusText }}</el-text>
+							<span v-else>{{ row.order?.statusText }}</span>
+						</template>
+					</vxe-column>
+					<vxe-column field="order.sourceChannel" title="来源渠道" width="110"></vxe-column>
+					<vxe-column field="order.no" title="工单编码" width="140"></vxe-column>
+					<vxe-column field="order.creationTime" title="受理时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.order?.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="title" title="工单标题" min-width="200">
+						<template #default="{ row }">
+							<order-detail :order="row.order" @updateList="queryList">{{ row.order?.title }}</order-detail>
+						</template>
+					</vxe-column>
+					<vxe-column field="order.contact" title="联系电话" width="120"></vxe-column>
+					<vxe-column field="employeeName" title="回访人" width="120"></vxe-column>
+					<vxe-column field="visitTime" title="回复时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.visitTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="visitContent" title="回复内容" min-width="200"></vxe-column>
+					<vxe-column field="seatEvaluateText" title="坐席满意度" width="140"></vxe-column>
+					<vxe-column field="orgProcessingResults.value" title="部门满意度" width="140"></vxe-column>
+				</vxe-table>
+			</div>
+			<pagination
+				@pagination="queryList"
+				:total="state.total"
+				v-model:current-page="state.queryParams.PageIndex"
+				v-model:page-size="state.queryParams.PageSize"
+				:disabled="state.loading"
+			/>
+		</div>
+	</div>
+</template>
+<script setup lang="tsx" name="statisticsOrderDetailVisitContent">
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import { FormInstance } from 'element-plus';
+import { formatDate } from '@/utils/formatTime';
+import { useRoute } from 'vue-router';
+import { departmentOverdueDetailExport } from '@/api/statistics/department';
+import { defaultDate, defaultTimeStartEnd, shortcuts } from '@/utils/constants';
+import { departmentVisitDetailSmart } from '@/api/statistics/order';
+import other from '@/utils/other';
+
+// 引入组件
+const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+
+// 定义变量内容
+const ruleFormRef = ref<RefType>(); // 表单ref
+const state = reactive<any>({
+	queryParams: {
+		// 查询条件
+		PageIndex: 1,
+		PageSize: 20,
+		VisitName: null, //
+		crTime: defaultDate,
+		StartTime: null,
+		EndTime: null,
+	},
+	tableData: [], //表单
+	loading: false, // 加载
+	total: 0, // 总数
+});
+// 手动查询,将页码设置为1
+const handleQuery = () => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+};
+/** 获取列表 */
+const route = useRoute();
+const routeQueryParams = route.query;
+const requestParams = ref<EmptyObjectType>({});
+const queryList = () => {
+	state.loading = true;
+	requestParams.value = other.deepClone(state.queryParams);
+	requestParams.value.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
+	requestParams.value.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
+	Reflect.deleteProperty(requestParams.value, 'crTime');
+	departmentVisitDetailSmart(requestParams.value)
+		.then((res) => {
+			state.tableData = res.result?.items ?? [];
+			state.tableData = state.tableData.map((item: any) => {
+				return {
+					...item.orderVisit,
+				};
+			});
+			state.total = res.result?.total ?? 0;
+			state.loading = false;
+		})
+		.catch((err) => {
+			console.log(err);
+		})
+		.finally(() => {
+			state.loading = false;
+		});
+};
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+/** 重置按钮操作 */
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
+};
+onMounted(async () => {
+	if (routeQueryParams.StartTime && routeQueryParams.EndTime) {
+		state.queryParams.crTime = [routeQueryParams.StartTime, routeQueryParams.EndTime];
+	}
+	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+});
+</script>

+ 4 - 5
src/views/tels/callLog/zgCallLog.vue

@@ -30,6 +30,7 @@
 				:refresh="{
 					queryMethod: handleQuery,
 				}"
+				:tools="[{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }]"
 			>
 			</vxe-toolbar>
 			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
@@ -62,6 +63,7 @@
 						},
 					}"
 					@sort-change="sortChange"
+					:params="{ exportMethod: callLogXTPagedExport, exportParams: requestParams }"
 				>
 					<vxe-column field="fromNo" title="主叫号码" min-width="120"></vxe-column>
 					<vxe-column field="toNo" title="被叫号码" min-width="120"></vxe-column>
@@ -203,8 +205,7 @@ import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
 import { useRouter } from 'vue-router';
 import mittBus from '@/utils/mitt';
 import Other from '@/utils/other';
-import { getCallCenterCallRecord, getCallCenterCallRecordBaseData, getCallCenterCallRecordTotal } from '@/api/callCenter';
-import { useThemeConfig } from '@/stores/themeConfig';
+import { getCallCenterCallRecord, getCallCenterCallRecordBaseData, getCallCenterCallRecordTotal, callLogXTPagedExport } from '@/api/callCenter';
 import { storeToRefs } from 'pinia';
 import { useAppConfig } from '@/stores/appConfig';
 
@@ -236,7 +237,7 @@ const state = reactive<any>({
 		SortField: null,
 		SortRule: null,
 		StaffNo: null, // 工号
-		CallNo:null, // 通话ID
+		CallNo: null, // 通话ID
 	},
 	tableData: [], // 列表数据
 	loading: false, // 加载
@@ -312,8 +313,6 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 };
 // 播放录音
 const playRecordRef = ref<RefType>();
-const storesThemeConfig = useThemeConfig();
-const { themeConfig } = storeToRefs(storesThemeConfig);
 const appConfigStore = useAppConfig();
 const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
 const onPlaySoundRecording = (val: any) => {

+ 3 - 1
src/views/todo/order/tableHeader.tsx

@@ -14,7 +14,9 @@ export const YBTableHeader = [
 	{ field: 'acceptorName', title: '受理人', width: 120 },
 	{ field: 'no', title: '工单编码', width: 140 },
 	{ field: 'isProvinceText', title: '省/市工单', width: 90 },
-	{ field: 'reTransactNum', title: '重办次数', width: 90 },
+	{ field: 'reTransactNum', title: '部门重办', width: 130 },
+	{ field: 'visitReTransactNum', title: '回访重办', width: 130 },
+	{ field: 'provinceReTransactNum', title: '上级重办', width: 130 },
 	{
 		field: 'isUrgentText',
 		title: '是否紧急',

+ 7 - 5
src/views/todo/seats/accept/lzAccept.vue

@@ -425,7 +425,7 @@
 <script setup lang="ts" name="orderAccept">
 import { computed, defineAsyncComponent, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
 import type { FormInstance } from 'element-plus';
-import { ElMessage, ElMessageBox } from 'element-plus';
+import { ElMessage } from 'element-plus';
 import { storeToRefs } from 'pinia';
 import { useRoute } from 'vue-router';
 import { useAppConfig } from '@/stores/appConfig';
@@ -433,7 +433,7 @@ import { throttle, transformFile } from '@/utils/tools';
 import { commonEnum } from '@/utils/constants';
 import { orderAdd, orderBaseDataAdd, orderBaseExt, orderDetail, orderEdit } from '@/api/business/order';
 import { useUserInfo } from '@/stores/userInfo';
-import { treeArea } from '@/api/auxiliary/area';
+import { treeAreaLZ } from '@/api/auxiliary/area';
 import mittBus from '@/utils/mitt';
 import { orderRepeatEvent } from '@/api/business/repeatEvent';
 import { removeDuplicate } from '@/utils/arrayOperation';
@@ -489,8 +489,10 @@ const state = reactive<any>({
 		eventCategoryId: null, // 事件分类
 		incidentTime: null, // 事发时间
 		incidentPurpose: null, // 事件目的
-		areaCode: themeConfig.value.cityCode, // 区域编码
-		city: themeConfig.value.cityName, // 市
+/*		areaCode: themeConfig.value.cityCode, // 区域编码
+		city: themeConfig.value.cityName, // 市*/
+		areaCode: null, // 区域编码
+		city: null, // 市
 		street: null, // 街道
 		isRepeat: 'false', // 是否重复工单 默认否
 		pushType: null, // 推送类型
@@ -1283,7 +1285,7 @@ const addressLoading = ref<boolean>(false);
 const loadAddress = async () => {
 	addressLoading.value = true;
 	try {
-		const area = await treeArea();
+		const area = await treeAreaLZ();
 		state.areaOptions = area.result ?? []; //省市区数据
 		addressLoading.value = false;
 		await loadExtra();

+ 1 - 1
src/views/todo/seats/accept/ybAccept.vue

@@ -554,7 +554,7 @@
 <script setup lang="ts" name="orderAccept">
 import { computed, defineAsyncComponent, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
 import type { FormInstance } from 'element-plus';
-import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';
+import { ElMessage, ElNotification } from 'element-plus';
 import { storeToRefs } from 'pinia';
 import { onBeforeRouteLeave, useRoute } from 'vue-router';
 import { useAppConfig } from '@/stores/appConfig';

+ 3 - 1
src/views/todo/seats/tableHeader.tsx

@@ -58,7 +58,9 @@ export const YBTableHeader = [
 	{ field: 'acceptType', title: '受理类型', width: 110 },
 	{ field: 'sourceChannel', title: '来源渠道', width: 110 },
 	{ field: 'hotspotName', title: '热点分类', width: 150 },
-	{ field: 'reTransactNum', title: '重办次数', width: 130 },
+	{ field: 'reTransactNum', title: '部门重办', width: 130 },
+	{ field: 'visitReTransactNum', title: '回访重办', width: 130 },
+	{ field: 'provinceReTransactNum', title: '上级重办', width: 130 },
 	{ title: '操作', width: 90, fixed: 'right', align: 'center', slots: { default: 'action' } },
 ]