Bläddra i källkod

reactor:245 (泸州+自贡)-和兴唐对接,完善【坐席小休统计表】的数据显示;244 【通讯记录->话机动作统计】优化(泸州+自贡通用);296 增加“当前等待”显示

zhangchong 2 månader sedan
förälder
incheckning
0642f7b059

+ 1 - 1
.env.development

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

+ 22 - 0
src/api/callCenter/index.ts

@@ -90,6 +90,17 @@ export const getCallCenterCallRecord = (params?: object) => {
         params,
     });
 };
+/**
+ * @description 查询呼叫中心通话记录(固定数量)查询总数
+ * @param params
+ */
+export const getCallCenterCallRecordTotal = (params?: object) => {
+    return request({
+        url: `/api/v1/Call/calls-fixed/count`,
+        method: 'get',
+        params,
+    });
+};
 /**
  * @description 查询呼叫中心坐席操作记录基础数据
  * @param params
@@ -112,6 +123,17 @@ export const getCallCenterOperateRecord = (params?: object) => {
         params,
     });
 };
+/**
+ * @description 查询呼叫中心坐席操作记录查询总条数
+ * @param params
+ */
+export const getCallCenterOperateRecordTotal = (params?: object) => {
+    return request({
+        url: `/api/v1/Call/tel-operations-fixed/count`,
+        method: 'get',
+        params,
+    });
+};
 /**
  * @description 校验电话号码外呼是否需要加0
  * @param mobile

+ 43 - 23
src/layout/navBars/breadcrumb/zgTel.vue

@@ -166,28 +166,28 @@
 			</template>
 
 			<!--			&lt;!&ndash; 评价可用 登录并且是呼入 &ndash;&gt;
-			<template v-if="m_bLogin && m_IsCallIn && activeArr.includes('evaluate')">
-				<div class="item active" title="评价" @click="onEvent('evaluate')">
-					<SvgIcon name="ele-Flag" class="icon mr3" size="16px" />
-					评价
-				</div>
-			</template>
-			&lt;!&ndash; 评价不可用 &ndash;&gt;
-			<template v-else>
-				<div class="item disabled" title="评价"><SvgIcon name="ele-Flag" class="icon mr3" size="16px" />评价</div>
-			</template>-->
+      <template v-if="m_bLogin && m_IsCallIn && activeArr.includes('evaluate')">
+        <div class="item active" title="评价" @click="onEvent('evaluate')">
+          <SvgIcon name="ele-Flag" class="icon mr3" size="16px" />
+          评价
+        </div>
+      </template>
+      &lt;!&ndash; 评价不可用 &ndash;&gt;
+      <template v-else>
+        <div class="item disabled" title="评价"><SvgIcon name="ele-Flag" class="icon mr3" size="16px" />评价</div>
+      </template>-->
 		</div>
 		<!-- 等待人数 -->
-		<!--    <div class="wait-box">
-      <div class="today-wait">
-					<span class="today-wait-label">今日等待:</span
+		<div class="wait-box">
+			<!--      <div class="today-wait">
+          <span class="today-wait-label">今日等待:</span
           ><el-text class="today-wait-num ml5" tag="b" type="danger">{{ todayWaitValue.toFixed(0) }}</el-text>
-      </div>
-      <div class="current-wait">
-					<span class="current-wait-label">当前等待:</span
-          ><el-text class="current-wait-time ml5" tag="b" type="danger">{{ currentWaitValue.toFixed(0) }}</el-text>
-      </div>
-    </div>-->
+      </div>-->
+			<div class="current-wait">
+				<span class="current-wait-label">当前等待:</span
+				><el-text class="current-wait-time ml5" tag="b" type="danger">{{ currentWaitValue.toFixed(0) }}</el-text>
+			</div>
+		</div>
 	</div>
 
 	<!-- 签入弹窗 -->
@@ -351,7 +351,7 @@ import { trimCompat } from '@/utils/tools';
 import XEUtils from 'xe-utils';
 import { submitLog } from '@/api/public/log';
 import { useTransition } from '@vueuse/core';
-import { telRestBaseData } from '@/api/public/wex';
+import { busyOff, busyOn, telRestBaseData } from '@/api/public/wex';
 
 const globalState = useGlobalState(); // 全局变量
 const state = reactive<any>({
@@ -926,7 +926,7 @@ const retSignIn = (data: any) => {
 		// 已经处于登录状态
 		// 先签出再签入
 		/*	sendSignOut();
-		userAlreadyLogin.value = false; // 将登录状态重置*/
+    userAlreadyLogin.value = false; // 将登录状态重置*/
 		ElMessage.error('当前分机已签入');
 		userAlreadyLogin.value = false; // 将登录状态重置
 		wsRef.value.close(); // 关闭链接
@@ -1331,6 +1331,18 @@ const retBusy = (data: any) => {
 		m_strTelState.value = '201';
 		e_TopStateChange(m_strTelState.value);
 		console.log('小休开始了');
+
+		// 小休开始了
+		// const restReasons = state.restReasonOptions.find((item: any) => item.dicDataValue === reason);
+		busyOn({ reason: '' }) // 开始小休 设置示忙 业务系统统计需要
+			.then(() => {
+				console.log(`${getNowDateTime()}:业务系统调用示忙开始成功`);
+				state.loading = false;
+			})
+			.catch((err: any) => {
+				console.log(`${getNowDateTime()}:业务系统调用示忙开始失败,${err}`);
+				state.loading = false;
+			});
 	} else {
 		ElMessage.error('小休失败');
 	}
@@ -1376,6 +1388,14 @@ const retIdle = (data: any) => {
 		e_TopStateChange(m_strTelState.value);
 		m_IsTalkingDeal.value = false;
 		console.log('小休结束');
+		// 结束小休 设置示忙 业务系统统计需要
+		busyOff()
+			.then(() => {
+				console.log(`${getNowDateTime()}:业务系统调用示忙结束成功`);
+			})
+			.catch((err) => {
+				console.log(`${getNowDateTime()}:业务系统调用示忙结束失败,${err}`);
+			}); // 结束小休(调用业务系统接口,统计需要)
 	} else {
 		ElMessage.error('示闲失败');
 	}
@@ -1856,8 +1876,8 @@ const retHangup = (data?: any) => {
 	m_bIsOpen.value = false;
 	m_strConsultType.value = '-1';
 	/*
-	m_strTelState.value = '200';
-	e_TopStateChange(m_strTelState.value);*/
+  m_strTelState.value = '200';
+  e_TopStateChange(m_strTelState.value);*/
 	// 未监听
 	m_IsMonListen.value = '0';
 	// 呼出是否弹屏(用于未接统计“回拨”业务处理)

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

@@ -24,6 +24,7 @@ export const YBTableHeader = [
 			},
 		},
 	},
+	{ field: 'sensitiveText', title: '敏感词', width: 150 },
 	{ field: 'isSecretText', title: '是否保密', width: 100 },
 	{ field: 'currentStepName', title: '当前节点', width: 120 },
 	{ field: 'actualStepAcceptText', title: '受理情况', width: 100 },
@@ -78,7 +79,6 @@ export const YBTableHeader = [
 	{ field: 'hotspotName', title: '热点分类', width: 150 },
 	{ field: 'acceptorName', title: '受理人', width: 120 },
 	{ field: 'focusOnEventsName', title: '重点关注事件', width: 120 },
-	{ field: 'sensitiveText', title: '敏感词', width: 150 },
 	{ field: 'content', title: '受理内容', width: 200, visible: false },
 	{ field: 'fileOpinion', title: '承办意见', width: 200, visible: false },
 	{ title: '操作', width: 140, fixed: 'right', align: 'center', slots: { default: 'action' } },
@@ -140,6 +140,8 @@ export const ZGTableHeader = [
 		width: 160,
 		sortable: true,
 		formatter: 'formatDate',
+
+		
 	},
 	{
 		field: 'filedTime',
@@ -216,6 +218,8 @@ export const LZTableHeader = [
 		formatter: 'formatDate',
 	},
 	{ field: 'acceptorName', title: '受理人', width: 120 },
+	{ field: 'fromName', title: '来电人姓名', width: 120 },
+	{ field: 'contact', title: '联系电话', width: 120 },
 	{ field: 'currentStepName', title: '当前节点', width: 120 },
 	{ field: 'acceptType', title: '受理类型', width: 110 },
 	{ field: 'actualStepAcceptText', title: '受理情况', width: 100 },

+ 154 - 0
src/views/statistics/call/YBSeatsRecord.vue

@@ -0,0 +1,154 @@
+<template>
+  <div class="statistics-call-seats-record-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="TelNo">
+          <el-input v-model="state.queryParams.TelNo" placeholder="分机号" clearable @keyup.enter="handleQuery" class="keyword-input" />
+        </el-form-item>
+        <el-form-item label="动作类型" prop="ActionTtype">
+          <el-select v-model="state.queryParams.ActionTtype" placeholder="请选择动作类型" clearable @change="handleQuery">
+            <el-option v-for="item in actionTypeOptions" :value="item.key" :key="item.key" :label="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="坐席" prop="UserName">
+          <el-input v-model="state.queryParams.UserName" placeholder="坐席" clearable @keyup.enter="handleQuery" class="keyword-input" />
+        </el-form-item>
+        <el-form-item label-width="0">
+          <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: queryList,
+				}"
+      >
+      </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="statisticsCallSeatsRecord"
+            :custom-config="{ storage: true }"
+            showHeaderOverflow
+        >
+          <vxe-column field="userName" title="坐席"></vxe-column>
+          <vxe-column field="telNo" title="分机号"></vxe-column>
+          <vxe-column field="queueId" title="分机组"></vxe-column>
+          <vxe-column field="actionTypeText" title="动作类型"></vxe-column>
+          <vxe-column field="startTime" title="开始时间" width="160">
+            <template #default="{ row }">
+              {{ formatDate(row.startTime, 'YYYY-mm-dd HH:MM:SS') }}
+            </template>
+          </vxe-column>
+          <vxe-column field="endTime" title="结束时间" width="160">
+            <template #default="{ row }">
+              {{ formatDate(row.endTime, 'YYYY-mm-dd HH:MM:SS') }}
+            </template>
+          </vxe-column>
+          <vxe-column field="duration" title="时长(秒)"></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="statisticsCallSeatsRecord">
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import { FormInstance } from 'element-plus';
+import { callAction, callActionBase } from "@/api/statistics/call";
+import { defaultDate } from '@/utils/constants';
+import { formatDate } from "@/utils/formatTime";
+import Other from "@/utils/other";
+
+const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+// 定义变量内容
+const ruleFormRef = ref<RefType>(); // 表单ref
+const state = reactive({
+  queryParams: {
+    // 查询条件
+    PageIndex: 1,
+    PageSize: 20,
+    TelNo: null, // 分级号
+    UserName: null, // 坐席
+    ActionTtype: null, // 动作类型
+    crTime: defaultDate, // 时间默认今天开始到今天结束
+  },
+  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');
+  callAction(requestParams.value)
+      .then((res: any) => {
+        state.tableData = res.result?.items ?? [];
+        state.total = res.result?.total ?? 0;
+        state.loading = false;
+      })
+      .catch(() => {
+        state.loading = false;
+      });
+};
+/** 重置按钮操作 */
+const statisticalTimeRef = ref<RefType>();
+const resetQuery = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.resetFields();
+  statisticalTimeRef.value.reset();
+  queryList();
+};
+// 获取基础数据
+const actionTypeOptions = ref<EmptyArrayType>([])
+const getBaseData = async () => {
+  try {
+    const {result} = await callActionBase();
+    actionTypeOptions.value = result.actionType;
+  }catch (e){
+    console.log(e);
+  }
+}
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+onMounted(() => {
+  queryList();
+  if (tableRef.value && toolbarRef.value) {
+    tableRef.value.connect(toolbarRef.value);
+  }
+  getBaseData();
+});
+</script>

+ 186 - 0
src/views/statistics/call/ZGSeatsRecord.vue

@@ -0,0 +1,186 @@
+<template>
+  <div class="statistics-call-seats-record-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 prop="crTime">
+          <statistical-time v-model="state.queryParams.crTime" @change="handleQuery" ref="statisticalTimeRef" :disabled="state.loading" />
+        </el-form-item>
+        <el-form-item label="分机号" prop="TelNo">
+          <el-input v-model="state.queryParams.TelNo" placeholder="分机号" clearable @keyup.enter="handleQuery" class="keyword-input" />
+        </el-form-item>
+        <el-form-item prop="UserName" label="坐席人员">
+          <el-input v-model="state.queryParams.UserName" 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="drawer = true" class="default-button"> <SvgIcon name="ele-Search" class="mr5" />更多查询</el-button>
+        </el-form-item>
+      </el-form>
+      <vxe-toolbar
+          ref="toolbarRef"
+          :loading="state.loading"
+          custom
+          :refresh="{
+					queryMethod: handleQuery,
+				}"
+      >
+      </vxe-toolbar>
+      <div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+        <vxe-table
+            border
+            :loading="state.loading"
+            :data="state.tableData"
+            :sort-config="{ remote: true }"
+            :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="telsPhoneAction"
+            :custom-config="{ storage: true }"
+        >
+          <vxe-column field="userName" title="坐席人员" min-width="140"></vxe-column>
+          <vxe-column field="telNo" title="分机号" min-width="140"></vxe-column>
+          <vxe-column field="staffNo" title="工号" min-width="140"></vxe-column>
+          <vxe-column field="groupId" title="工作组" min-width="140"></vxe-column>
+          <vxe-column field="operateStateText" title="动作类型" min-width="200"></vxe-column>
+          <vxe-column field="operateTime" title="开始时间" width="160">
+            <template #default="{ row }">
+              {{ formatDate(row.operateTime, 'YYYY-mm-dd HH:MM:SS') }}
+            </template>
+          </vxe-column>
+          <vxe-column field="operateTime" title="结束时间" width="160">
+            <template #default="{ row }">
+              {{ formatDate(row.operateTime, 'YYYY-mm-dd HH:MM:SS') }}
+            </template>
+          </vxe-column>
+          <vxe-column field="operateTime" title="时长(秒)" min-width="120"> </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>
+    <!--	更多查询	-->
+    <el-drawer v-model="drawer" title="更多查询" size="500px">
+      <el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="90px" :disabled="state.loading">
+        <el-form-item prop="StaffNo" label="工号">
+          <el-input v-model="state.queryParams.StaffNo" placeholder="工号" clearable @keyup.enter="handleQuery" class="keyword-input" />
+        </el-form-item>
+        <el-form-item prop="GroupId" label="工作组">
+          <el-input v-model="state.queryParams.GroupId" placeholder="工作组" clearable @keyup.enter="handleQuery" class="keyword-input" />
+        </el-form-item>
+        <el-form-item prop="OperateState" label="动作类型">
+          <el-select v-model="state.queryParams.OperateState" placeholder="动作类型" clearable class="w100" @change="handleQuery">
+            <el-option v-for="item in state.operations" :value="item.key" :key="item.key" :label="item.value" />
+          </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>
+  </div>
+</template>
+
+<script lang="tsx" setup name="statisticsCallSeatsRecord">
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import type { FormInstance } from 'element-plus';
+import { formatDate } from '@/utils/formatTime';
+import Other from '@/utils/other';
+import { getCallCenterOperateRecord, getCallCenterOperateRecordBaseData, getCallCenterOperateRecordTotal } from '@/api/callCenter';
+import { defaultDate } from '@/utils/constants';
+
+const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+
+// 定义变量内容
+const state = reactive<any>({
+  queryParams: {
+    PageIndex: 1, // 当前页
+    PageSize: 20, // 每页条数
+    UserName: null, // 话务员名称
+    StaffNo: null, // 工号
+    GroupId: null, // 工作组
+    OperateState: null, // 操作类型
+    crTime: defaultDate,
+    StartTime: null,
+    EndTime: null,
+    TelNo: null,
+  },
+  tableData: [], // 列表数据
+  loading: false, // 加载
+  total: 0, // 总条数
+  callDirection: [],
+  operations: [],
+});
+// 手动查询,将页码设置为1
+const handleQuery = () => {
+  state.queryParams.PageIndex = 1;
+  queryList();
+  getTotal();
+};
+/** 很滑稽动作列表 */
+const requestParams = ref<EmptyObjectType>({});
+const queryList = async () => {
+  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');
+  getCallCenterOperateRecord(requestParams.value)
+      .then((response: any) => {
+        state.tableData = response?.result ?? [];
+        state.loading = false;
+      })
+      .catch(() => {
+        state.loading = false;
+      });
+};
+// 查询总数
+const getTotal = () => {
+  getCallCenterOperateRecordTotal(requestParams.value)
+      .then((res) => {
+        state.total = res.result ?? 0;
+      })
+      .catch(() => {});
+};
+/** 重置按钮操作 */
+const statisticalTimeRef = ref<RefType>();
+const drawerRuleFormRef = ref();
+const ruleFormRef = ref<RefType>(); // 表单ref
+const drawer = ref(false);
+const resetQuery = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.resetFields();
+  statisticalTimeRef.value.reset();
+  ruleFormRef.value?.resetFields();
+  queryList();
+};
+// 基础信息
+const getBaseData = async () => {
+  try {
+    const { result } = await getCallCenterOperateRecordBaseData();
+    state.operations = result.operations;
+  } catch (e) {
+    console.log(e);
+  }
+};
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+onMounted(() => {
+  getBaseData();
+  queryList();
+  getTotal();
+  if (tableRef.value && toolbarRef.value) {
+    tableRef.value.connect(toolbarRef.value);
+  }
+});
+</script>

+ 21 - 148
src/views/statistics/call/seatsRecord.vue

@@ -1,154 +1,27 @@
 <template>
-	<div class="statistics-call-seats-record-out-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="TelNo">
-					<el-input v-model="state.queryParams.TelNo" placeholder="分机号" clearable @keyup.enter="handleQuery" class="keyword-input" />
-				</el-form-item>
-				<el-form-item label="动作类型" prop="ActionTtype">
-					<el-select v-model="state.queryParams.ActionTtype" placeholder="请选择动作类型" clearable @change="handleQuery">
-						<el-option v-for="item in actionTypeOptions" :value="item.key" :key="item.key" :label="item.value" />
-					</el-select>
-				</el-form-item>
-				<el-form-item label="坐席" prop="UserName">
-					<el-input v-model="state.queryParams.UserName" placeholder="坐席" clearable @keyup.enter="handleQuery" class="keyword-input" />
-				</el-form-item>
-				<el-form-item label-width="0">
-					<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: queryList,
-				}"
-			>
-			</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="statisticsCallSeatsRecord"
-					:custom-config="{ storage: true }"
-					showHeaderOverflow
-				>
-					<vxe-column field="userName" title="坐席"></vxe-column>
-					<vxe-column field="telNo" title="分机号"></vxe-column>
-					<vxe-column field="queueId" title="分机组"></vxe-column>
-					<vxe-column field="actionTypeText" title="动作类型"></vxe-column>
-					<vxe-column field="startTime" title="开始时间" width="160">
-						<template #default="{ row }">
-							{{ formatDate(row.startTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</template>
-					</vxe-column>
-					<vxe-column field="endTime" title="结束时间" width="160">
-						<template #default="{ row }">
-							{{ formatDate(row.endTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</template>
-					</vxe-column>
-					<vxe-column field="duration" title="时长(秒)"></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>
+  <component :is="currentCity" />
 </template>
-<script setup lang="tsx" name="statisticsCallSeatsRecord">
-import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
-import { FormInstance } from 'element-plus';
-import { callAction, callActionBase } from "@/api/statistics/call";
-import { defaultDate } from '@/utils/constants';
-import { formatDate } from "@/utils/formatTime";
-import Other from "@/utils/other";
 
-const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
-const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
-// 定义变量内容
-const ruleFormRef = ref<RefType>(); // 表单ref
-const state = reactive({
-	queryParams: {
-		// 查询条件
-		PageIndex: 1,
-		PageSize: 20,
-    TelNo: null, // 分级号
-    UserName: null, // 坐席
-    ActionTtype: null, // 动作类型
-		crTime: defaultDate, // 时间默认今天开始到今天结束
-	},
-	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');
-  callAction(requestParams.value)
-		.then((res: any) => {
-			state.tableData = res.result?.items ?? [];
-			state.total = res.result?.total ?? 0;
-			state.loading = false;
-		})
-		.catch(() => {
-			state.loading = false;
-		});
-};
-/** 重置按钮操作 */
-	const statisticalTimeRef = ref<RefType>();
-const resetQuery = (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	statisticalTimeRef.value.reset();
-	queryList();
+<script lang="tsx" setup name="statisticsCallSeatsRecord">
+import { defineAsyncComponent, computed } from 'vue';
+import { useThemeConfig } from '@/stores/themeConfig';
+import { storeToRefs } from 'pinia';
+
+// 引入组件
+const YiBin = defineAsyncComponent(() => import('@/views/statistics/call/YBSeatsRecord.vue')); // 宜宾坐席动作统计
+const ZiGong = defineAsyncComponent(() => import('@/views/statistics/call/ZGSeatsRecord.vue')); // 自贡坐席动作统计
+const LuZhou = defineAsyncComponent(() => import('@/views/statistics/call/ZGSeatsRecord.vue')); // 泸州坐席动作统计
+
+const storesThemeConfig = useThemeConfig();
+const { themeConfig } = storeToRefs(storesThemeConfig);
+
+const COMPONENT_LIST = {
+  YiBin,
+  ZiGong,
+  LuZhou,
 };
-// 获取基础数据
-const actionTypeOptions = ref<EmptyArrayType>([])
-const getBaseData = async () => {
-	try {
-    const {result} = await callActionBase();
-    actionTypeOptions.value = result.actionType;
-  }catch (e){
-    console.log(e);
-  }
-}
-const toolbarRef = ref<RefType>();
-const tableRef = ref<RefType>();
-onMounted(() => {
-	queryList();
-	if (tableRef.value && toolbarRef.value) {
-		tableRef.value.connect(toolbarRef.value);
-	}
-	getBaseData();
+// 当前地州市
+const currentCity = computed(() => {
+  return COMPONENT_LIST[themeConfig.value.appScope];
 });
 </script>

+ 24 - 41
src/views/tels/callLog/zgCallLog.vue

@@ -118,15 +118,13 @@
 					</vxe-column>
 				</vxe-table>
 			</div>
-			<div class="flex-end">
-				<el-pagination
-					layout="prev, pager, next"
-					:total="state.total"
-					@current-change="handleCurrentChange"
-					:page-size="state.queryParams.PageSize"
-					:current-page="state.queryParams.PageIndex"
-				/>
-			</div>
+			<pagination
+				@pagination="queryList"
+				:total="state.total"
+				v-model:current-page="state.queryParams.PageIndex"
+				v-model:page-size="state.queryParams.PageSize"
+				:disabled="state.loading"
+			/>
 			<el-drawer v-model="drawer" title="更多查询" size="500px">
 				<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="100px">
 					<el-form-item prop="TelNo" label="响应分机">
@@ -197,13 +195,14 @@ import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
 import { useRouter } from 'vue-router';
 import mittBus from '@/utils/mitt';
 import Other from '@/utils/other';
-import { getCallCenterCallRecord, getCallCenterCallRecordBaseData } from '@/api/callCenter';
+import {getCallCenterCallRecord, getCallCenterCallRecordBaseData, getCallCenterCallRecordTotal} from '@/api/callCenter';
 import { useThemeConfig } from '@/stores/themeConfig';
 import { storeToRefs } from 'pinia';
 
 // 引入组件
 const PlayRecord = defineAsyncComponent(() => import('@/components/PlayRecord/index.vue')); // 播放录音
 const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
 // 表格配置项
 // 定义变量内容
@@ -242,46 +241,21 @@ const changeTba = () => {
 // 手动查询,将页码设置为1
 const handleQuery = () => {
 	state.queryParams.PageIndex = 1;
-	queryIndex.value = 0;
-	queryList(true);
-};
-// 改变页码
-const queryIndex = ref(0); // 数据批次
-const totalTable = ref([]); // 数据总数
-const handleCurrentChange = (val: number) => {
-	state.queryParams.PageIndex = val;
-	// 判断当前页是否是数据的最后一页
-	if (val === Math.ceil(state.total / state.queryParams.PageSize)) {
-		queryList();
-	} else {
-		state.tableData = getNeedArr(totalTable.value, state.queryParams.PageSize)[state.queryParams.PageIndex - 1]; //当前页的表格数据
-	}
+	queryList();
+  getTotal();
 };
 /** 通话记录列表 */
 const requestParams = ref<EmptyObjectType>({});
-const queryList = async (isQuery: boolean = false) => {
+const queryList = async () => {
 	state.loading = true;
 	requestParams.value = Other.deepClone(state.queryParams);
 	requestParams.value.CallStartTimeStart = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
 	requestParams.value.CallStartTimeEnd = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
 	Reflect.deleteProperty(requestParams.value, 'crTime'); // 通话开始和结束时间段
-	requestParams.value.QueryIndex = queryIndex.value; // 数据批次
 	state.loading = true;
 	getCallCenterCallRecord(requestParams.value)
 		.then((response: any) => {
-			if (isQuery) {
-				// 如果是查询
-				totalTable.value = []; // 先清空
-				totalTable.value = response?.result;
-				state.total = totalTable.value.length;
-				state.tableData = getNeedArr(totalTable.value, state.queryParams.PageSize)[state.queryParams.PageIndex - 1]; //当前页的表格数据
-				queryIndex.value = 1;
-			} else {
-				if (response?.result.length) queryIndex.value++;
-				totalTable.value = totalTable.value.concat(response?.result);
-				state.total = totalTable.value.length;
-				state.tableData = getNeedArr(totalTable.value, state.queryParams.PageSize)[state.queryParams.PageIndex - 1]; //当前页的表格数据
-			}
+			state.tableData = response?.result ?? [];
 			state.loading = false;
 			tableRef.value.clearCheckboxRow();
 		})
@@ -290,6 +264,14 @@ const queryList = async (isQuery: boolean = false) => {
 			tableRef.value.clearCheckboxRow();
 		});
 };
+// 查询总数
+const getTotal = () => {
+  getCallCenterCallRecordTotal(requestParams.value)
+      .then((res) => {
+        state.total = res.result ?? 0;
+      })
+      .catch(() => {});
+};
 // 失联工单
 const IsMissOrder = ref(false);
 const changeMissOrder = (val: any) => {
@@ -303,10 +285,10 @@ const drawerRuleFormRef = ref();
 const resetQuery = (formEl: FormInstance | undefined) => {
 	if (!formEl) return;
 	formEl.resetFields();
-	queryIndex.value = 0;
 	ruleFormRef.value?.resetFields();
 	IsMissOrder.value = false;
-	queryList(true);
+	queryList();
+  getTotal();
 };
 // 播放录音
 const playRecordRef = ref<RefType>();
@@ -357,6 +339,7 @@ const getBaseData = async () => {
 onMounted(() => {
 	getBaseData();
 	queryList();
+  getTotal();
 	if (tableRef.value && toolbarRef.value) {
 		tableRef.value.connect(toolbarRef.value);
 	}

+ 76 - 62
src/views/tels/phoneAction.vue

@@ -1,26 +1,21 @@
 <template>
 	<div class="tels-callLog-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="UserName">
-					<el-input v-model="state.queryParams.UserName" placeholder="坐席人员" clearable @keyup.enter="handleQuery" class="keyword-input" />
-				</el-form-item>
-				<el-form-item prop="StaffNo">
-					<el-input v-model="state.queryParams.StaffNo" placeholder="工号" clearable @keyup.enter="handleQuery" class="keyword-input" />
+			<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline :disabled="state.loading">
+				<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 prop="GroupId">
-					<el-input v-model="state.queryParams.GroupId" placeholder="工作组" clearable @keyup.enter="handleQuery" class="keyword-input" />
-				</el-form-item>
-				<el-form-item prop="OperateState">
-					<el-select v-model="state.queryParams.OperateState" placeholder="动作类型" clearable class="w100" @change="handleQuery">
-						<el-option v-for="item in state.operations" :value="item.key" :key="item.key" :label="item.value" />
-					</el-select>
+        <el-form-item prop="OperateState" label="动作类型">
+          <el-select v-model="state.queryParams.OperateState" placeholder="动作类型" clearable class="w100" @change="handleQuery">
+            <el-option v-for="item in state.operations" :value="item.key" :key="item.key" :label="item.value" />
+          </el-select>
+        </el-form-item>
+				<el-form-item prop="UserName" label="坐席人员">
+					<el-input v-model="state.queryParams.UserName" 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-button @click="drawer = true" class="default-button"> <SvgIcon name="ele-Search" class="mr5" />更多查询</el-button>
 				</el-form-item>
 			</el-form>
 			<vxe-toolbar
@@ -58,28 +53,53 @@
 							{{ formatDate(row.operateTime, 'YYYY-mm-dd HH:MM:SS') }}
 						</template>
 					</vxe-column>
+					<vxe-column field="operateTime" title="结束时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.operateTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="operateTime" title="时长(秒)" min-width="120"> </vxe-column>
 				</vxe-table>
 			</div>
-			<div class="flex-end">
-				<el-pagination
-					layout="prev, pager, next"
-					:total="state.total"
-					@current-change="handleCurrentChange"
-					:page-size="state.queryParams.PageSize"
-					:current-page="state.queryParams.PageIndex"
-				/>
-			</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>
+		<!--	更多查询	-->
+		<el-drawer v-model="drawer" title="更多查询" size="500px">
+      <el-form-item label="分机号" prop="TelNo">
+        <el-input v-model="state.queryParams.TelNo" placeholder="分机号" clearable @keyup.enter="handleQuery" class="keyword-input" />
+      </el-form-item>
+			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="90px" :disabled="state.loading">
+				<el-form-item prop="StaffNo" label="工号">
+					<el-input v-model="state.queryParams.StaffNo" placeholder="工号" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item prop="GroupId" label="工作组">
+					<el-input v-model="state.queryParams.GroupId" placeholder="工作组" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</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>
 	</div>
 </template>
 
 <script lang="tsx" setup name="telsPhoneAction">
-import { onMounted, reactive, ref } from 'vue';
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
 import type { FormInstance } from 'element-plus';
-import { getNeedArr } from '@/utils/tools';
 import { formatDate } from '@/utils/formatTime';
 import Other from '@/utils/other';
-import { getCallCenterOperateRecord, getCallCenterOperateRecordBaseData } from '@/api/callCenter';
+import { getCallCenterOperateRecord, getCallCenterOperateRecordBaseData, getCallCenterOperateRecordTotal } from '@/api/callCenter';
+import { defaultDate } from '@/utils/constants';
+
+const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
 // 定义变量内容
 const state = reactive<any>({
@@ -90,6 +110,10 @@ const state = reactive<any>({
 		StaffNo: null, // 工号
 		GroupId: null, // 工作组
 		OperateState: null, // 操作类型
+		crTime: defaultDate,
+		StartTime: null,
+		EndTime: null,
+		TelNo: null,
 	},
 	tableData: [], // 列表数据
 	loading: false, // 加载
@@ -97,59 +121,48 @@ const state = reactive<any>({
 	callDirection: [],
 	operations: [],
 });
-const ruleFormRef = ref<FormInstance>(); // 表单ref
 // 手动查询,将页码设置为1
 const handleQuery = () => {
 	state.queryParams.PageIndex = 1;
-	queryIndex.value = 0;
-	queryList(true);
-};
-// 改变页码
-const queryIndex = ref(0); // 数据批次
-const totalTable = ref([]); // 数据总数
-const handleCurrentChange = (val: number) => {
-	state.queryParams.PageIndex = val;
-	// 判断当前页是否是数据的最后一页
-	if (val === Math.ceil(state.total / state.queryParams.PageSize)) {
-		queryList();
-	} else {
-		state.tableData = getNeedArr(totalTable.value, state.queryParams.PageSize)[state.queryParams.PageIndex - 1]; //当前页的表格数据
-	}
+	queryList();
+	getTotal();
 };
-/** 通话记录列表 */
+/** 很滑稽动作列表 */
 const requestParams = ref<EmptyObjectType>({});
-const queryList = async (isQuery: boolean = false) => {
+const queryList = async () => {
 	state.loading = true;
 	requestParams.value = Other.deepClone(state.queryParams);
-	requestParams.value.QueryIndex = queryIndex.value; // 数据批次
-	state.loading = true;
+	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');
 	getCallCenterOperateRecord(requestParams.value)
 		.then((response: any) => {
-			if (isQuery) {
-				// 如果是查询
-				totalTable.value = []; // 先清空
-				totalTable.value = response?.result;
-				state.total = totalTable.value.length;
-				state.tableData = getNeedArr(totalTable.value, state.queryParams.PageSize)[state.queryParams.PageIndex - 1]; //当前页的表格数据
-				queryIndex.value = 1;
-			} else {
-				if (response?.result.length) queryIndex.value++;
-				totalTable.value = totalTable.value.concat(response?.result);
-				state.total = totalTable.value.length;
-				state.tableData = getNeedArr(totalTable.value, state.queryParams.PageSize)[state.queryParams.PageIndex - 1]; //当前页的表格数据
-			}
+			state.tableData = response?.result ?? [];
 			state.loading = false;
 		})
 		.catch(() => {
 			state.loading = false;
 		});
 };
+// 查询总数
+const getTotal = () => {
+	getCallCenterOperateRecordTotal(requestParams.value)
+		.then((res) => {
+			state.total = res.result ?? 0;
+		})
+		.catch(() => {});
+};
 /** 重置按钮操作 */
+const statisticalTimeRef = ref<RefType>();
+const drawerRuleFormRef = ref();
+const ruleFormRef = ref<RefType>(); // 表单ref
+const drawer = ref(false);
 const resetQuery = (formEl: FormInstance | undefined) => {
 	if (!formEl) return;
 	formEl.resetFields();
-	queryIndex.value = 0;
-	queryList(true);
+	statisticalTimeRef.value.reset();
+	ruleFormRef.value?.resetFields();
+	queryList();
 };
 // 基础信息
 const getBaseData = async () => {
@@ -165,6 +178,7 @@ const tableRef = ref<RefType>();
 onMounted(() => {
 	getBaseData();
 	queryList();
+	getTotal();
 	if (tableRef.value && toolbarRef.value) {
 		tableRef.value.connect(toolbarRef.value);
 	}