Prechádzať zdrojové kódy

refactor:552 调整【话务员办件统计】统计逻辑;自贡,宜宾调整登录加密方式;

zhangchong 3 dní pred
rodič
commit
72bb7bfe93

+ 0 - 1
package.json

@@ -34,7 +34,6 @@
 		"file-saver": "^2.0.5",
 		"html-docx-js-typescript": "^0.1.5",
 		"html2canvas": "^1.4.1",
-		"jsencrypt": "^3.3.2",
 		"jspdf": "^2.5.2",
 		"mitt": "^3.0.0",
 		"nprogress": "^0.2.0",

+ 56 - 0
src/api/statistics/call.ts

@@ -638,4 +638,60 @@ export const callEfficientDetailExport = (data: object) => {
 			reduce_data_format: false,
 		}
 	);
+}
+/**
+ * @description 话务员办件统计 自贡
+ * @param {object} params
+ */
+export const callAgentHandleZG = (params: object) => {
+	return request({
+		url: `/api/v1/BiOrder/centre_data_list`,
+		method: 'get',
+		params,
+	});
+}
+/**
+ * @description 话务员办件统计 自贡 导出
+ * @param {object} data
+ */
+export const callAgentHandleZGExport = (data: object) => {
+	return request(
+		{
+			url: `/api/v1/BiOrder/centre_data_list_export`,
+			method: 'post',
+			data,
+			responseType: 'blob',
+		},
+		{
+			reduce_data_format: false,
+		}
+	);
+}
+/**
+ * @description 话务员办件统计明细 自贡
+ * @param {object} params
+ */
+export const callAgentHandleZGDetail = (params: object) => {
+	return request({
+		url: `/api/v1/BiOrder/centre_data_list_detail`,
+		method: 'get',
+		params,
+	});
+}
+/**
+ * @description 话务员办件统计明细 自贡 导出
+ * @param {object} data
+ */
+export const callAgentHandleZGDetailExport = (data: object) => {
+	return request(
+		{
+			url: `/api/v1/BiOrder/centre_data_list_detail_export`,
+			method: 'post',
+			data,
+			responseType: 'blob',
+		},
+		{
+			reduce_data_format: false,
+		}
+	);
 }

+ 1 - 1
src/api/statistics/order.ts

@@ -986,4 +986,4 @@ export const statisticsOrderHotSatisfyDetailExport = (data: object) => {
 			reduce_data_format: false,
 		}
 	);
-};
+};

+ 9 - 0
src/router/route.ts

@@ -275,6 +275,15 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
 			isKeepAlive: true,
 		},
 	},
+	{
+		path: '/statistics/order/detailCenterCountZG',
+		name: 'statisticsOrderDetailCenterCountZG',
+		component: () => import('@/views/statistics/order/detailCenterCountZG.vue'),
+		meta: {
+			title: '话务员办件统计明细',
+			isKeepAlive: true,
+		},
+	},
 	{
 		path: '/statistics/call/detailTalkTime',
 		name: 'statisticsCallDetailTalkTime',

+ 27 - 10
src/stores/userInfo.ts

@@ -1,8 +1,8 @@
 import { defineStore } from 'pinia';
 import { Cookie, Session } from '@/utils/storage';
 import { getUserInfo } from '@/api/login/user';
-import { JSEncrypt } from 'jsencrypt';
-import { encryptionLoginKey } from '@/utils/constants';
+import CryptoJS from 'crypto-js';
+import { guid, trimCompat } from '@/utils/tools';
 
 /**
  * @description 用户信息
@@ -59,16 +59,33 @@ export const useUserInfo = defineStore('userInfo', {
 				//授权按钮
 				this.userInfos.showTelControl = buttons.includes('public:seat:panel'); // 查询是否有展示面板权限
 				this.userInfos.authBtnList = buttons;
-				// 新建一个JSEncrypt对象
-				const encryptor = new JSEncrypt({ default_key_size: '2048' });
-				encryptor.setPublicKey(encryptionLoginKey); // publicKey为公钥
+
+				const key = 'qlzeJrbj0CPkHdFBvEAxX47Y4nCbBPZW'; // 加密秘钥
+				const iv = 'JxeDP0sgnPJdH9fE'; // 偏移量
+				const key1 = CryptoJS.enc.Utf8.parse(key);
+				const iv1 = CryptoJS.enc.Utf8.parse(iv);
+
+				const userId = trimCompat(this.userInfos.id);
+				const userName = trimCompat(this.userInfos.name);
+				const orgName = trimCompat(this.userInfos.orgName);
+				const timestamp = Math.floor(new Date().getTime() / 1000); // 秒
+				const guidStr = guid(); // 随机数
 				// 加密数据
-				const submitObj: { userId: string; userName: string; orgName: string } = {
-					userId: this.userInfos.id,
-					userName: this.userInfos.name,
-					orgName: this.userInfos.orgName,
+				const submitObj = {
+					userId: userId, // 用户ID
+					userName: userName, // 用户名
+					orgName: orgName, // 组织名称
+					timestamp, // 时间戳
+					nonce: guidStr, // 随机数
 				};
-				this.userInfos.encryptionHeader = <string>encryptor.encrypt(JSON.stringify(submitObj));
+				const encrypted = CryptoJS.AES.encrypt(JSON.stringify(submitObj), key1, {
+					// 加密
+					iv: iv1,
+					mode: CryptoJS.mode.CBC,
+					padding: CryptoJS.pad.Pkcs7,
+				});
+				const encryptedStr = encrypted.toString(); // 加密后的字符串
+				this.userInfos.encryptionHeader = <string>encryptedStr;
 				Session.set('userInfo', this.userInfos);
 				return this.userInfos;
 			} catch (error) {

+ 0 - 5
src/utils/constants.ts

@@ -148,8 +148,3 @@ export const defaultDateOne = [
 // 默认的起始与结束时刻 (Start date time 00:00:00, end date time 23:59:59)
 // @ts-ignore
 export const defaultTimeStartEnd: [Date, Date] = [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]; // '00:00:00', '23:59:59'
-/**
- * @description  登录密钥
- * */
-export const encryptionLoginKey =
-	'-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgw+/x6IQPkH0A4eoF63jkLThsOXWyNBdcL9LATGy/G1yTHOr1RyKJB//iNug+V8DIoIHuFTlhgLHDbSqxvRWMONxIIF289riS6bDI4Ox/pFmOfmElFRk0lKGihaTE2Aefd6g/N+RfLLaHWztY+/voVeDTiOIw9y3tokIxjKwuJ/mQ66MkKh78AqQjjSD/3jcBP8ZhMyCJOK9XQcqvhD6WBFWkxlAqKOWggDU7YohfrbNkg3bd0oGE6zCE2EHhkcQbzGCh3lu1zf4TfKMXD+PPrr5JWDNYQTXFQklqgae+Puge7xxZGYRoi5YpIUnkQGm6zpPxhIOdxlz+Yb5geSJUQIDAQAB-----END PUBLIC KEY-----';

+ 1 - 1
src/views/examTrain/exam/marking/components/Exam-Marking.vue

@@ -140,7 +140,7 @@ const getExamManageDetailData = async () => {
 const onSave = throttle(() => {
 	// 校验阅卷是否完成
 	for (const item of state.examList) {
-		if (!item.score) {
+		if (item.score === undefined || item.score === null) {
 			ElMessage.warning(`请填写【${item.title}】的分数`);
 			return;
 		}

+ 2 - 44
src/views/login/components/Account.vue

@@ -81,13 +81,11 @@ import { Session, Local, Cookie } from '@/utils/storage';
 import { formatAxis } from '@/utils/formatTime';
 import { NextLoading } from '@/utils/loading';
 import type { FormInstance } from 'element-plus';
-import { sendCode, signIn, signInEncrypt, whiteList } from '@/api/login';
-import { JSEncrypt } from 'jsencrypt'; // rsa加密
+import { sendCode, signInEncrypt, whiteList } from '@/api/login';
 import { getImageUrl, guid, throttle, trimCompat } from '@/utils/tools';
 import CryptoJS from 'crypto-js'; // aes加密
 //引入'vue3-puzzle-vcode'插件
 import PuzzleCode from 'vue3-puzzle-vcode';
-import { encryptionLoginKey } from '@/utils/constants';
 
 // 定义变量内容
 const storesThemeConfig = useThemeConfig(); // 主题配置
@@ -173,47 +171,7 @@ const success = () => {
 	// 验证成功
 	showCode.value = false;
 	state.loading = true;
-	if (['LuZhou'].includes(themeConfig.value.appScope)) {
-		// 泸州先行加密登录
-		encryptionLogin();
-	} else {
-		normalLogin();
-	}
-};
-// 普通登录
-const normalLogin = () => {
-	// 新建一个JSEncrypt对象
-	const encryptor = new JSEncrypt({ default_key_size: '2048' });
-	encryptor.setPublicKey(encryptionLoginKey); // publicKey为公钥
-	const usernameTrim = trimCompat(state.ruleForm.username);
-	const passwordTrim = trimCompat(state.ruleForm.password);
-	const usernameMesCode = trimCompat(state.ruleForm.msgCode);
-	// 加密数据
-	const submitObj = {
-		username: encryptor.encrypt(usernameTrim),
-		password: encryptor.encrypt(passwordTrim),
-		msgCode: encryptor.encrypt(usernameMesCode),
-	};
-	signIn(submitObj)
-		.then(async (res: any) => {
-			//登录
-			// 存储 token 到浏览器缓存
-			Cookie.set('token', res.result);
-			if (!themeConfig.value.isRequestRoutes) {
-				// 前端控制路由,2、请注意执行顺序
-				const isNoPower = await initFrontEndControlRoutes();
-				signInSuccess(isNoPower);
-			} else {
-				// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
-				// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
-				const isNoPower = await initBackEndControlRoutes();
-				// 执行完 initBackEndControlRoutes,再执行 signInSuccess
-				signInSuccess(isNoPower);
-			}
-		})
-		.catch(() => {
-			state.loading = false;
-		});
+	encryptionLogin();
 };
 // 加密登录
 const encryptionLogin = () => {

+ 0 - 254
src/views/login/components/Mobile.vue

@@ -1,254 +0,0 @@
-<template>
-	<el-form size="large" class="login-content-form" ref="ruleFormRef" :model="state.ruleForm" @submit.native.prevent>
-		<el-form-item
-			prop="userName"
-			class="mb30"
-			:rules="[
-				{ required: true, message: '请填写手机号', trigger: 'blur' },
-				{ validator: checkPhone, trigger: 'blur' },
-			]"
-		>
-			<el-input placeholder="请填写手机号" v-model="state.ruleForm.userName" clearable autocomplete="off" class="inputDeep">
-				<template #prefix>
-					<SvgIcon name="ele-Phone" class="el-input__icon" />
-				</template>
-			</el-input>
-		</el-form-item>
-		<el-form-item prop="password" class="mb30" :rules="[{ required: true, message: '请填写短信验证码', trigger: 'blur' }]">
-			<el-col :span="15">
-				<el-input
-					type="text"
-					maxlength="4"
-					placeholder="请填写短信验证码"
-					v-model="state.ruleForm.code"
-					clearable
-					autocomplete="off"
-					class="inputDeep"
-				>
-					<template #prefix>
-						<SvgIcon name="ele-ChatDotSquare" class="el-input__icon" />
-					</template>
-				</el-input>
-			</el-col>
-			<el-col :span="1"></el-col>
-			<el-col :span="8">
-				<el-button class="login-content-code" :disabled="isDisabled" @click="getIdentifyCodeBtn">{{
-					isDisabled ? count + 's后重新获取' : click
-				}}</el-button>
-			</el-col>
-		</el-form-item>
-		<el-form-item>
-			<el-button type="primary" class="login-content-submit" round @click="onSignIn(ruleFormRef)" :loading="state.loading">登录</el-button>
-		</el-form-item>
-			<div>运营管理系统 <span class="color-danger font-bold">v5.0</span></div>
-			<div class="login-msg">
-				<div>联系管理员<b>重置密码</b></div>
-				<!-- <el-button link type="primary" class="font16" @click="forgetPwd">忘记密码</el-button> -->
-			</div>
-	</el-form>
-</template>
-
-<script setup lang="ts" name="loginMobile">
-import { reactive, ref } from 'vue';
-import { ElNotification, FormInstance } from 'element-plus';
-import { throttle } from '@/utils/tools';
-import { JSEncrypt } from 'jsencrypt';
-import { signIn } from '@/api/login';
-import { Cookie, Local, Session } from '@/utils/storage';
-import { storeToRefs } from 'pinia';
-import { useThemeConfig } from '@/stores/themeConfig';
-import { useRoute, useRouter } from 'vue-router';
-import { initFrontEndControlRoutes } from '@/router/frontEnd';
-import { initBackEndControlRoutes } from '@/router/backEnd';
-import { formatAxis } from '@/utils/formatTime';
-import { NextLoading } from '@/utils/loading';
-import { verifyPhone } from '@/utils/toolsValidate';
-import { encryptionLoginKey } from '@/utils/constants';
-
-// 定义变量内容
-const state = reactive({
-	ruleForm: {
-		userName: '',
-		code: '',
-		verifyCode: '',
-	},
-	loading: false,
-});
-const checkPhone = (rule, value, callback) => {
-	if (!value) {
-		return callback(new Error('手机号不能为空'));
-	} else {
-		if (verifyPhone(value)) {
-			callback();
-		} else {
-			return callback(new Error('请填写正确的手机号'));
-		}
-	}
-};
-const count = ref(60);
-const click = ref('获取验证码');
-const isDisabled = ref(false);
-const getIdentifyCodeBtn = () => {
-	if (!state.ruleForm.userName) {
-		ruleFormRef.value?.validateField('userName');
-		return;
-	}
-	if (!verifyPhone(state.ruleForm.userName)) {
-		ruleFormRef.value?.validateField('userName');
-		return;
-	}
-	// state.loading = true;
-	countDown();
-};
-// 倒计时
-const countDown = () => {
-	if (count.value === 0) {
-		isDisabled.value = false;
-		click.value = '获取验证码';
-		count.value = 60;
-		return;
-	} else {
-		count.value--;
-		click.value = count.value + 's后重新获取';
-		isDisabled.value = true;
-		setTimeout(() => {
-			countDown();
-		}, 1000);
-	}
-};
-
-const ruleFormRef = ref<FormInstance>(); // 表单ref
-const storesThemeConfig = useThemeConfig(); // 主题配置
-const { themeConfig } = storeToRefs(storesThemeConfig); // 主题配置
-const route = useRoute(); // 路由
-const router = useRouter(); // 路由
-// 登录
-const onSignIn = throttle(async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.loading = true;
-		// 新建一个JSEncrypt对象
-		const encryptor = new JSEncrypt({ default_key_size: '2048' });
-		encryptor.setPublicKey(encryptionLoginKey); // publicKey为公钥
-		// 加密数据
-		const submitObj = {
-			username: encryptor.encrypt(state.ruleForm.username),
-			password: encryptor.encrypt(state.ruleForm.password),
-		};
-		signIn(submitObj)
-			.then(async (res: any) => {
-				//登录
-				// 存储 token 到浏览器缓存
-				Cookie.set('token', res.result);
-				if (!themeConfig.value.isRequestRoutes) {
-					// 前端控制路由,2、请注意执行顺序
-					const isNoPower = await initFrontEndControlRoutes();
-					signInSuccess(isNoPower);
-				} else {
-					// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
-					// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
-					const isNoPower = await initBackEndControlRoutes();
-					// 执行完 initBackEndControlRoutes,再执行 signInSuccess
-					signInSuccess(isNoPower);
-				}
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	});
-}, 1000);
-// 登录成功后的跳转
-const signInSuccess = (isNoPower: boolean | undefined) => {
-	if (isNoPower) {
-		state.loading = false;
-		ElNotification({
-			title: '提示',
-			message: '抱歉,您没有登录权限,请联系管理员',
-			type: 'warning',
-		});
-		Session.clear();
-		Cookie.clear();
-		Local.clear();
-	} else {
-		// 登录成功,跳到转首页
-		/*// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
-    if (route.query?.redirect) {
-      router.push({
-        path: <string>route.query?.redirect,
-        query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
-      });
-    } else {
-      router.push('/');
-    }*/
-		router.push('/');
-		// 设置登录成功后的时间问候语
-		Cookie.set('userName', state.ruleForm.username);
-		// 登录成功提示
-		// 关闭 loading
-		state.loading = true;
-		const signInText = '欢迎回来!';
-		ElNotification({
-			type: 'success',
-			title: `${formatAxis(new Date())}`,
-			message: `${signInText}`,
-		});
-		NextLoading.start();
-	}
-};
-</script>
-
-<style scoped lang="scss">
-.inputDeep {
-	:deep(.el-input__wrapper) {
-		box-shadow: 0 0 0 0 var(--el-input-border-color, var(--el-border-color)) inset;
-		border-radius: 0;
-		border-bottom: 1px solid var(--el-input-border-color, var(--el-border-color));
-	}
-	:deep(.el-form-item.is-error .el-input__wrapper.is-focus) {
-		box-shadow: 0 0 0 0 var(--el-input-border-color, var(--el-border-color)) inset;
-	}
-}
-.login-content-form {
-	font-size: var(--el-font-size-medium);
-	margin-top: 20px;
-
-	:deep(.el-input--large) {
-		font-size: var(--el-font-size-medium);
-	}
-
-	:deep(.el-form-item__error) {
-		font-size: var(--el-font-size-medium);
-	}
-
-	.login-content-code {
-		width: 100%;
-		padding: 0;
-	}
-	.login-content-submit {
-		width: 100%;
-		letter-spacing: 2px;
-		font-weight: 300;
-		margin-top: 15px;
-	}
-	.login-content-submit {
-		width: 100%;
-		margin-top: 45px;
-		height: 50px;
-		border-radius: 30px;
-		font-size: 16px;
-		letter-spacing: 5px;
-	}
-	.login-msg {
-		margin-top: 10px;
-		display: flex;
-		justify-content: space-between;
-		align-items: center;
-		color: var(--el-color-primary);
-		b {
-			color: #999;
-			padding-left: 4px;
-		}
-	}
-}
-</style>

+ 0 - 10
src/views/login/index.vue

@@ -3,16 +3,7 @@
 		<div class="login-content">
 			<div class="login-content-main">
 					<h4 class="login-content-title">{{ getThemeConfig.globalViceTitle }}</h4>
-					<!--          <div v-if="!state.isScan">-->
-					<!--            <el-tabs v-model="state.tabsActiveName">
-              <el-tab-pane label="账号登录" name="account">-->
 					<account />
-					<!--              </el-tab-pane>
-              <el-tab-pane label="手机号登录" name="mobile">
-                <Mobile />
-              </el-tab-pane>
-            </el-tabs>-->
-					<!--          </div>-->
 			</div>
 		</div>
 		<LayoutFooter v-if="isFooter" class="login-footer" :underline="false" />
@@ -32,7 +23,6 @@ interface LoginState {
 
 // 引入组件
 const Account = defineAsyncComponent(() => import('@/views/login/components/Account.vue'));
-const Mobile = defineAsyncComponent(() => import('@/views/login/components/Mobile.vue'));
 const LayoutFooter = defineAsyncComponent(() => import('@/layout/footer/index.vue'));
 
 const storesThemeConfig = useThemeConfig();

+ 0 - 1
src/views/statistics/call/telephonist.vue

@@ -150,7 +150,6 @@ import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
 import { FormInstance } from 'element-plus';
 import { callAgent, callAgentExport } from '@/api/statistics/call';
 import { defaultDate } from '@/utils/constants';
-import { formatDurationDay } from '@/utils/formatTime';
 import Other from '@/utils/other';
 import { useRouter } from 'vue-router';
 

+ 145 - 0
src/views/statistics/order/YBCenterCount.vue

@@ -0,0 +1,145 @@
+<template>
+	<div class="statistics-order-center-count-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<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="Keyword">
+					<el-input v-model="state.queryParams.Keyword" 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-popover :width="500" trigger="click">
+						<template #reference>
+							<el-button type="primary" title="字段说明"><SvgIcon name="ele-QuestionFilled" class="mr5" />字段说明</el-button>
+						</template>
+						<el-descriptions title="" :column="1" border style="max-height: 400px; overflow: auto">
+							<el-descriptions-item label="姓名">当前登录系统坐席人员名称</el-descriptions-item>
+							<el-descriptions-item label="有效件-中心归档件">工单流转目标为部门归档</el-descriptions-item>
+							<el-descriptions-item label="有效件-转办信件">工单已办理</el-descriptions-item>
+							<el-descriptions-item label="有效件-待转办信件">工单已保存未办理</el-descriptions-item>
+							<el-descriptions-item label="无效信件">单受理类型为无效</el-descriptions-item>
+							<el-descriptions-item label="重复信件">工单选择重复信件</el-descriptions-item>
+							<el-descriptions-item label="所有信件">有效件(中心归档件+转办信件+待转办信件+无效信件+重复信件</el-descriptions-item>
+						</el-descriptions>
+					</el-popover>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.loading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+				:tools="[{ 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
+					:scrollY="{ enabled: true, gt: 100 }"
+					show-overflow
+					id="statisticsOrderCenter"
+					:custom-config="{ storage: true }"
+					show-footer
+					:params="{ exportMethod: centerListExport, exportParams: requestParams }"
+					:sort-config="{ remote: true }"
+					@sort-change="sortChange"
+					:footer-data="state.footerData"
+				>
+					<vxe-column field="userName" title="姓名"></vxe-column>
+					<vxe-colgroup title="有效件" align="center">
+						<vxe-column title="中心归档件" field="centreArchive" sortable></vxe-column>
+						<vxe-column title="转办信件" field="centreCareOf" sortable></vxe-column>
+						<vxe-column title="待转办信件" field="noCentreCareOf" sortable></vxe-column>
+					</vxe-colgroup>
+					<vxe-column field="invalid" title="无效信件" sortable> </vxe-column>
+					<vxe-column field="repeat" title="重复信件" sortable></vxe-column>
+					<vxe-column field="subtotal" title="所有信件" sortable></vxe-column>
+				</vxe-table>
+			</div>
+		</div>
+	</div>
+</template>
+<script setup lang="tsx" name="statisticsOrderCenter">
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import { FormInstance } from 'element-plus';
+import { centerList, centerListExport } from '@/api/statistics/order';
+import { defaultDate } from '@/utils/constants';
+import Other from '@/utils/other';
+import XEUtils from 'xe-utils';
+
+const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
+// 定义变量内容
+const ruleFormRef = ref<RefType>(); // 表单ref
+const state = reactive<any>({
+	queryParams: {
+		// 查询条件
+		Keyword: null, // 关键词
+		crTime: defaultDate,
+		SortField: null,
+		SortRule: null,
+	},
+	tableData: [], //表单
+	loading: false, // 加载
+	footerData: [],
+});
+/** 搜索按钮操作 */
+const handleQuery = () => {
+	// state.queryParams.PageIndex = 1;
+	queryList();
+};
+/** 获取列表 */
+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');
+	centerList(requestParams.value)
+		.then((res: any) => {
+			state.tableData = res.result?.list ?? [];
+			state.footerData = [res.result?.total] ?? [];
+			state.loading = false;
+		})
+		.catch(() => {
+			state.loading = false;
+		});
+};
+// 排序
+const sortChange = (val: any) => {
+	state.queryParams.SortField = val.order ? val.field : null;
+	// 0 升序 1 降序
+	state.queryParams.SortRule = val.order ? (val.order == 'desc' ? 1 : 0) : null;
+	queryList();
+};
+/** 重置按钮操作 */
+const statisticalTimeRef = ref<RefType>();
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	statisticalTimeRef.value.reset();
+	queryList();
+};
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+onMounted(() => {
+	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+});
+</script>

+ 196 - 0
src/views/statistics/order/ZGCenterCount.vue

@@ -0,0 +1,196 @@
+<template>
+	<div class="statistics-order-center-count-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<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="Keyword">
+					<el-input v-model="state.queryParams.Keyword" 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-popover :width="500" trigger="click">
+						<template #reference>
+							<el-button type="primary" title="字段说明"><SvgIcon name="ele-QuestionFilled" class="mr5" />字段说明</el-button>
+						</template>
+						<el-descriptions title="" :column="1" border style="max-height: 400px; overflow: auto">
+							<el-descriptions-item label="姓名">当前登录系统坐席人员名称</el-descriptions-item>
+							<el-descriptions-item label="有效件-中心归档件">工单流转目标为部门归档</el-descriptions-item>
+							<el-descriptions-item label="有效件-转办信件">工单已办理</el-descriptions-item>
+							<el-descriptions-item label="有效件-待转办信件">工单已保存未办理</el-descriptions-item>
+							<el-descriptions-item label="所有信件">有效件(中心归档件+转办信件+待转办信件+无效信件+重复信件</el-descriptions-item>
+						</el-descriptions>
+					</el-popover>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.loading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+				:tools="[{ 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
+					:scrollY="{ enabled: true, gt: 100 }"
+					show-overflow
+					id="statisticsOrderCenter"
+					:custom-config="{ storage: true }"
+					show-footer
+					:params="{ exportMethod: callAgentHandleZGExport, exportParams: requestParams }"
+					:sort-config="{ remote: true }"
+					@sort-change="sortChange"
+					:footer-data="state.footerData"
+				>
+					<vxe-column field="userName" title="姓名"></vxe-column>
+					<vxe-colgroup title="有效件" align="center">
+						<vxe-column title="中心归档件" field="centreArchive" sortable>
+							<template #default="{ row }">
+								<el-button link type="primary" @click="linkDetail(row, 'centreArchive')">{{ row.centreArchive }}</el-button>
+							</template>
+							<template #footer="{ row }">
+								<el-button link type="primary" @click="linkDetail(row, 'centreArchive', true)">{{ row.centreArchive }}</el-button>
+							</template>
+						</vxe-column>
+						<vxe-column title="转办信件" field="centreCareOf" sortable>
+							<template #default="{ row }">
+								<el-button link type="primary" @click="linkDetail(row, 'centreCareOf')">{{ row.centreCareOf }}</el-button>
+							</template>
+							<template #footer="{ row }">
+								<el-button link type="primary" @click="linkDetail(row, 'centreCareOf', true)">{{ row.centreCareOf }}</el-button>
+							</template>
+						</vxe-column>
+						<vxe-column title="待转办信件" field="noCentreCareOf" sortable>
+							<template #default="{ row }">
+								<el-button link type="primary" @click="linkDetail(row, 'noCentreCareOf')">{{ row.noCentreCareOf }}</el-button>
+							</template>
+							<template #footer="{ row }">
+								<el-button link type="primary" @click="linkDetail(row, 'noCentreCareOf', true)">{{ row.noCentreCareOf }}</el-button>
+							</template>
+						</vxe-column>
+					</vxe-colgroup>
+					<vxe-column field="subtotal" title="所有信件" sortable>
+						<template #default="{ row }">
+							<el-button link type="primary" @click="linkDetail(row, 'subtotal')">{{ row.subtotal }}</el-button>
+						</template>
+						<template #footer="{ row }">
+							<el-button link type="primary" @click="linkDetail(row, 'subtotal', true)">{{ row.subtotal }}</el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
+		</div>
+	</div>
+</template>
+<script setup lang="tsx" name="statisticsOrderCenter">
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import { FormInstance } from 'element-plus';
+import { defaultDate } from '@/utils/constants';
+import Other from '@/utils/other';
+import { useRouter } from 'vue-router';
+import { callAgentHandleZG, callAgentHandleZGExport } from '@/api/statistics/call';
+
+const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
+// 定义变量内容
+const ruleFormRef = ref<RefType>(); // 表单ref
+const state = reactive<any>({
+	queryParams: {
+		// 查询条件
+		Keyword: null, // 关键词
+		crTime: defaultDate,
+		SortField: null,
+		SortRule: null,
+	},
+	tableData: [], //表单
+	loading: false, // 加载
+	total: 0, // 总数
+	footerData: [],
+});
+/** 搜索按钮操作 */
+const handleQuery = () => {
+	// state.queryParams.PageIndex = 1;
+	queryList();
+};
+/** 获取列表 */
+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');
+	callAgentHandleZG(requestParams.value)
+		.then((res: any) => {
+			state.tableData = res.result?.list ?? [];
+			state.footerData = [res.result?.total] ?? [];
+			state.loading = false;
+		})
+		.catch(() => {
+			state.loading = false;
+		});
+};
+// 排序
+const sortChange = (val: any) => {
+	state.queryParams.SortField = val.order ? val.field : null;
+	// 0 升序 1 降序
+	state.queryParams.SortRule = val.order ? (val.order == 'desc' ? 1 : 0) : null;
+	queryList();
+};
+/** 重置按钮操作 */
+const statisticalTimeRef = ref<RefType>();
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	statisticalTimeRef.value.reset();
+	queryList();
+};
+// 跳转明细
+const router = useRouter();
+const linkDetail = (row: any, FieldName: string, isFooterData?: boolean) => {
+	if (isFooterData) {
+		router.push({
+			path: '/statistics/order/detailCenterCountZG',
+			query: {
+				StartTime: requestParams.value.StartTime,
+				EndTime: requestParams.value.EndTime,
+				FieldName,
+				tagsViewName: '话务员办件统计明细',
+			},
+		});
+	} else {
+		router.push({
+			path: '/statistics/order/detailCenterCountZG',
+			query: {
+				StartTime: requestParams.value.StartTime,
+				EndTime: requestParams.value.EndTime,
+				FieldName,
+				tagsViewName: '话务员办件统计明细',
+				UserId: row.userId,
+			},
+		});
+	}
+};
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+onMounted(() => {
+	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+});
+</script>

+ 21 - 151
src/views/statistics/order/centerCount.vue

@@ -1,157 +1,27 @@
 <template>
-	<div class="statistics-order-center-count-container layout-padding">
-		<div class="layout-padding-auto layout-padding-view pd20">
-			<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="Keyword">
-					<el-input v-model="state.queryParams.Keyword" 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-popover :width="500" trigger="click">
-						<template #reference>
-							<el-button type="primary" title="字段说明"><SvgIcon name="ele-QuestionFilled" class="mr5"/>字段说明</el-button>
-						</template>
-						<el-descriptions title="" :column="1" border style="max-height: 400px; overflow: auto">
-							<el-descriptions-item label="姓名">当前登录系统坐席人员名称</el-descriptions-item>
-							<el-descriptions-item label="有效件-中心归档件">工单流转目标为部门归档</el-descriptions-item>
-							<el-descriptions-item label="有效件-转办信件">工单已办理</el-descriptions-item>
-							<el-descriptions-item label="有效件-待转办信件">工单已保存未办理</el-descriptions-item>
-							<el-descriptions-item label="无效信件">单受理类型为无效</el-descriptions-item>
-							<el-descriptions-item label="重复信件">工单选择重复信件</el-descriptions-item>
-							<el-descriptions-item label="所有信件">有效件(中心归档件+转办信件+待转办信件+无效信件+重复信件</el-descriptions-item>
-						</el-descriptions>
-					</el-popover>
-				</el-form-item>
-			</el-form>
-			<vxe-toolbar
-				ref="toolbarRef"
-				:loading="state.loading"
-				custom
-				:refresh="{
-					queryMethod: handleQuery,
-				}"
-				:tools="[{ 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
-					:scrollY="{ enabled: true, gt: 100 }"
-					show-overflow
-					id="statisticsOrderCenter"
-					:custom-config="{ storage: true }"
-					show-footer
-					:footer-method="footerMethod"
-					:params="{ exportMethod: centerListExport, exportParams: requestParams }"
-					:sort-config="{ remote: true }"
-					@sort-change="sortChange"
-				>
-					<vxe-column field="userName" title="姓名"></vxe-column>
-					<vxe-colgroup title="有效件">
-						<vxe-column title="中心归档件" field="centreArchive" sortable></vxe-column>
-						<vxe-column title="转办信件" field="centreCareOf" sortable></vxe-column>
-						<vxe-column title="待转办信件" field="noCentreCareOf" sortable></vxe-column>
-					</vxe-colgroup>
-					<vxe-column field="invalid" title="无效信件" sortable> </vxe-column>
-					<vxe-column field="repeat" title="重复信件" sortable></vxe-column>
-					<vxe-column field="subtotal" title="所有信件" sortable></vxe-column>
-				</vxe-table>
-			</div>
-		</div>
-	</div>
+	<component :is="currentCity" />
 </template>
-<script setup lang="tsx" name="statisticsOrderCenter">
-import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
-import { FormInstance } from 'element-plus';
-import { centerList, centerListExport } from '@/api/statistics/order';
-import { defaultDate } from '@/utils/constants';
-import Other from '@/utils/other';
-import XEUtils from 'xe-utils';
 
-const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
-// 定义变量内容
-const ruleFormRef = ref<RefType>(); // 表单ref
-const state = reactive<any>({
-	queryParams: {
-		// 查询条件
-		Keyword: null, // 关键词
-		crTime: defaultDate,
-		SortField: null,
-		SortRule: null,
-	},
-	tableData: [], //表单
-	loading: false, // 加载
-	total: 0, // 总数
-});
-/** 搜索按钮操作 */
-const handleQuery = () => {
-	// state.queryParams.PageIndex = 1;
-	queryList();
-};
-/** 获取列表 */
-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');
-	centerList(requestParams.value)
-		.then((res: any) => {
-			state.tableData = res.result;
-			state.loading = false;
-		})
-		.catch(() => {
-			state.loading = false;
-		});
-};
-// 排序
-const sortChange = (val: any) => {
-	state.queryParams.SortField = val.order ? val.field : null;
-	// 0 升序 1 降序
-	state.queryParams.SortRule = val.order ? (val.order == 'desc' ? 1 : 0) : null;
-	queryList();
-};
-/** 重置按钮操作 */
-const statisticalTimeRef = ref<RefType>();
-const resetQuery = (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	statisticalTimeRef.value.reset();
-	queryList();
-};
-// 计算合计
-const footerMethod = ({ columns, data }) => {
-	return [
-		columns.map((column: any, columnIndex: number) => {
-			if (columnIndex === 0) {
-				return '合计';
-			}
-			if (['centreArchive', 'centreCareOf', 'noCentreCareOf','invalid','repeat','subtotal'].includes(column.property)) {
-				return XEUtils.sum(data, column.property);
-			}
-		}),
-	];
+<script lang="tsx" setup name="statisticsOrderCenter">
+import { defineAsyncComponent, computed } from 'vue';
+import { useThemeConfig } from '@/stores/themeConfig';
+import { storeToRefs } from 'pinia';
+
+// 引入组件
+const YiBin = defineAsyncComponent(() => import('@/views/statistics/order/YBCenterCount.vue')); // 宜宾话务员办件统计
+const ZiGong = defineAsyncComponent(() => import('@/views/statistics/order/ZGCenterCount.vue')); // 自贡话务员办件统计
+const LuZhou = defineAsyncComponent(() => import('@/views/statistics/order/YBCenterCount.vue')); // 泸州话务员办件统计
+
+const storesThemeConfig = useThemeConfig();
+const { themeConfig } = storeToRefs(storesThemeConfig);
+
+const COMPONENT_LIST = {
+	YiBin,
+	ZiGong,
+	LuZhou,
 };
-const toolbarRef = ref<RefType>();
-const tableRef = ref<RefType>();
-onMounted(() => {
-	queryList();
-	if (tableRef.value && toolbarRef.value) {
-		tableRef.value.connect(toolbarRef.value);
-	}
+// 当前地州市
+const currentCity = computed(() => {
+	return COMPONENT_LIST[themeConfig.value.appScope];
 });
 </script>

+ 183 - 0
src/views/statistics/order/detailCenterCountZG.vue

@@ -0,0 +1,183 @@
+<template>
+	<div class="statistics-order-detail-center-count-container layout-padding">
+		<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="Title">
+					<el-input v-model="state.queryParams.Title" placeholder="工单标题" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="工单编码" prop="No">
+					<el-input v-model="state.queryParams.No" 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="statisticsOrderDetailCenterCountZG"
+					:custom-config="{
+						storage: true,
+					}"
+					showHeaderOverflow
+					:sort-config="{ remote: true }"
+					@sort-change="sortChange"
+					:params="{ exportMethod: callAgentHandleZGDetailExport, exportParams: requestParams }"
+				>
+					<vxe-column field="expiredStatusText" title="状态" width="60" align="center">
+						<template #default="{ row }">
+							<span :class="'overdue-status-' + row.expiredStatus" :title="row.expiredStatusText"></span>
+						</template>
+					</vxe-column>
+					<vxe-column field="no" title="工单编码" width="140"></vxe-column>
+					<vxe-column field="isProvinceText" title="省/市工单" width="90"></vxe-column>
+					<vxe-column field="currentStepName" title="当前节点" width="100"></vxe-column>
+					<vxe-column field="statusText" title="工单状态" width="100">
+						<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.statusText }}</el-text>
+							<span v-else>{{ row.statusText }}</span>
+						</template>
+					</vxe-column>
+					<vxe-column field="title" title="工单标题" width="200">
+						<template #default="{ row }">
+							<order-detail :order="row" @updateList="queryList(true)">{{ row.title }}</order-detail>
+						</template>
+					</vxe-column>
+					<vxe-column field="creationTime" title="受理时间" width="160" sortable>
+						<template #default="{ row }">
+							{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="expiredTime" title="期满时间" width="160" sortable>
+						<template #default="{ row }">
+							{{ formatDate(row.expiredTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="filedTime" title="办结时间" width="160" sortable>
+						<template #default="{ row }">
+							{{ formatDate(row.filedTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="orgLevelOneName" title="一级部门" width="140"></vxe-column>
+					<vxe-column field="actualHandleOrgName" title="接办部门" width="140"></vxe-column>
+					<vxe-column field="acceptType" title="受理类型" width="110"></vxe-column>
+					<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
+				@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="statisticsOrderDetailCenterCountZG">
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import type { FormInstance } from 'element-plus';
+import other from '@/utils/other';
+import { useRoute } from 'vue-router';
+import { formatDate } from '@/utils/formatTime';
+import { callAgentHandleZGDetail, callAgentHandleZGDetailExport } from '@/api/statistics/call';
+
+// 引入组件
+const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+
+// 定义变量内容
+const state = reactive<any>({
+	queryParams: {
+		PageIndex: 1, // 当前页
+		PageSize: 20, // 每页条数
+		Title: null, // 工单标题
+		No: null, // 工单编码
+		SortField: null,
+		SortRule: null,
+	},
+	tableData: [], //表单
+	loading: false, // 加载
+	total: 0, // 总数
+});
+const ruleFormRef = ref<RefType>(); // 表单ref
+const route = useRoute(); // 路由
+// 排序
+const sortChange = (val: any) => {
+	state.queryParams.SortField = val.order ? val.field : null;
+	// 0 升序 1 降序
+	state.queryParams.SortRule = val.order ? (val.order == 'desc' ? 1 : 0) : null;
+	queryList();
+};
+// 手动查询,将页码设置为1
+const handleQuery = () => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+};
+const routeQueryParams = route.query;
+/** 获取列表 */
+const requestParams = ref<EmptyObjectType>({});
+const queryList = () => {
+	requestParams.value = other.deepClone(state.queryParams);
+	requestParams.value.StartTime = routeQueryParams.StartTime;
+	requestParams.value.EndTime = routeQueryParams.EndTime;
+	requestParams.value.FieldName = routeQueryParams.FieldName;
+	requestParams.value.UserId = routeQueryParams.UserId;
+	state.loading = true;
+	callAgentHandleZGDetail(requestParams.value)
+		.then((response: any) => {
+			state.tableData = response?.result.items ?? [];
+			state.total = response?.result.total;
+			state.loading = false;
+		})
+		.catch(() => {
+			state.loading = false;
+		});
+};
+/** 重置按钮操作 */
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
+};
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+onMounted(() => {
+	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+});
+</script>

+ 0 - 5
yarn.lock

@@ -2279,11 +2279,6 @@ js-yaml@^4.1.0:
   dependencies:
     argparse "^2.0.1"
 
-jsencrypt@^3.3.2:
-  version "3.3.2"
-  resolved "https://registry.yarnpkg.com/jsencrypt/-/jsencrypt-3.3.2.tgz#b0f1a2278810c7ba1cb8957af11195354622df7c"
-  integrity sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==
-
 jsesc@^3.0.2:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"