浏览代码

reactor:系统表格重构完成;

zhangchong 4 月之前
父节点
当前提交
d39915d44c

+ 139 - 91
src/views/statistics/order/detailHotspotSatisfied.vue

@@ -1,66 +1,132 @@
 <template>
 	<div class="statistics-order-detail-dispatch-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<ProTable
-				ref="proTableRef"
-				:columns="columns"
-				:data="state.tableData"
-				@updateTable="queryList"
+			<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline>
+				<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"
+						:clearable="false"
+					/>
+				</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"
-				:total="state.total"
-				v-model:page-index="state.queryParams.PageIndex"
-				v-model:page-size="state.queryParams.PageSize"
-				:toolButton="['refresh', 'setting', 'exportCurrent', 'exportAll']"
-				:exportMethod="statisticsOrderHotSatisfyDetailExport"
-				:exportParams="requestParams"
+				custom
+				:refresh="{
+					queryMethod: queryList,
+				}"
+				:tools="[{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }]"
 			>
-				<template #table-search>
-					<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline>
-						<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"
-								:clearable="false"
-							/>
-						</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>
-				</template>
-				<template #expiredStatusText="{ row }">
-					<span :class="'overdue-status-' + row.order?.expiredStatus" :title="row.order?.expiredStatusText"></span>
+				<template #buttons>
+					<el-button type="primary" @click="onJbExport" :disabled="isChecked" :loading="state.loading"
+						><SvgIcon name="iconfont icon-daochu" class="mr5" />交办单导出
+					</el-button>
 				</template>
-				<template #title="{ row }">
-					<order-detail :order="row.order" @updateList="queryList">{{ row.order?.title }}</order-detail>
-				</template>
-			</ProTable>
+			</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 }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:scrollY="{ enabled: true, gt: 0 }"
+					id="statisticsOrderDetailHotspotSatisfied"
+					:custom-config="{
+						storage: true,
+					}"
+					showHeaderOverflow
+					:params="{ exportMethod: statisticsOrderHotSatisfyDetailExport, exportParams: requestParams }"
+					@checkbox-all="selectAllChangeEvent"
+					@checkbox-change="selectChangeEvent"
+				>
+					<vxe-column type="checkbox" width="50" align="center"></vxe-column>
+					<vxe-column field="order.expiredStatusText" title="超期状态" width="90" align="center">
+						<template #default="{ row }">
+							<span :class="'overdue-status-' + row.order?.expiredStatus" :title="row.order.expiredStatusText"></span>
+						</template>
+					</vxe-column>
+					<vxe-column field="order.statusText" title="工单状态" width="100"></vxe-column>
+					<vxe-column field="order.sourceChannel" title="来源渠道" width="110"></vxe-column>
+					<vxe-column field="order.currentStepName" title="当前节点" width="100"></vxe-column>
+					<vxe-column field="order.reTransactNum" title="重办次数" width="100"></vxe-column>
+					<vxe-column field="order.ScreenStatusText" title="甄别" width="100"></vxe-column>
+					<vxe-column field="order.no" title="工单编码" width="140"></vxe-column>
+					<vxe-column field="order.title" title="工单标题" width="200">
+						<template #default="{ row }">
+							<order-detail :order="row.order" @updateList="queryList">{{ row.order?.title }}</order-detail>
+						</template>
+					</vxe-column>
+					<vxe-column field="order.startTime" title="受理时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.order.startTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="order.expiredTime" title="工单期满时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.order?.expiredTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="order.actualHandleOrgName" title="接办部门" width="140"></vxe-column>
+					<vxe-column field="order.actualHandleTime" title="接办时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.order?.actualHandleTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="order.filedTime" title="办结时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.order?.filedTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="order.acceptType" title="受理类型" width="110"></vxe-column>
+					<vxe-column field="order.hotspotSpliceName" title="热点全称" width="150"></vxe-column>
+					<vxe-column field="order.hotspotName" title="热点分类" width="150"></vxe-column>
+					<vxe-column field="order.acceptorName" title="受理人" 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>
 	</div>
 </template>
 
 <script setup lang="tsx" name="statisticsOrderDetailHotspotSatisfied">
-import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import { computed, defineAsyncComponent, onMounted, reactive, ref } from 'vue';
 import { FormInstance } from 'element-plus';
 import { formatDate } from '@/utils/formatTime';
 import { statisticsOrderHotSatisfyDetail, statisticsOrderHotSatisfyDetailExport } from '@/api/statistics/order';
 import { useRoute } from 'vue-router';
-import ProTable from '@/components/ProTable/index.vue';
 import { defaultDateTime, defaultTimeStartEnd, shortcuts } from '@/utils/constants';
+import { exportAssignment } from '@/utils/tools';
 
 // 引入组件
 const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
@@ -80,53 +146,6 @@ const state = reactive<any>({
 	total: 0, // 总数
 });
 
-const proTableRef = ref<RefType>(); // 表格ref
-// 表格配置项
-const columns = ref<any[]>([
-	{ prop: 'order.expiredStatusText', label: '超期状态', align: 'center', width: 80 },
-	{ prop: 'order.statusText', label: '工单状态', width: 100 },
-	{ prop: 'order.sourceChannel', label: '来源渠道', minWidth: 100 },
-	{ prop: 'order.currentStepName', label: '当前节点', minWidth: 120 },
-	{ prop: 'order.reTransactNum', label: '重办次数' },
-	{ prop: 'order.orderScreenStatusText', label: '甄别', minWidth: 100 },
-	{ prop: 'order.no', label: '工单编码', width: 150 },
-	{
-		prop: 'order.creationTime',
-		label: '受理时间',
-		width: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'order.title', label: '工单标题', width: 200 },
-	{
-		prop: 'order.expiredTime',
-		label: '期满时间',
-		width: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.expiredTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'order.actualHandleOrgName', label: '接办部门', width: 140 },
-	{
-		prop: 'order.actualHandleTime',
-		label: '接办时间',
-		width: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.actualHandleTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'order.filedTime',
-		label: '办结时间',
-		width: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.order?.filedTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'order.acceptType', label: '受理类型', width: 100 },
-	{ prop: 'order.hotspotName', label: '热点分类', minWidth: 150 },
-]);
 /** 搜索按钮操作 */
 const handleQuery = () => {
 	state.queryParams.PageIndex = 1;
@@ -165,10 +184,39 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 	formEl.resetFields();
 	queryList();
 };
+// 交办单导出
+const onJbExport = () => {
+	const ids = checkTable.value.map((item: any) => item.order.id);
+	exportAssignment(ids);
+};
+const tableRef = ref<RefType>();
+const checkTable = ref<EmptyArrayType>([]);
+const selectAllChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '所有勾选事件' : '所有取消事件', records);
+	}
+};
+
+const selectChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '勾选事件' : '取消事件', records);
+	}
+};
+const isChecked = computed(() => {
+	return !Boolean(checkTable.value.length);
+});
+const toolbarRef = ref<RefType>();
 onMounted(() => {
 	if (routeQueryParams.StartTime && routeQueryParams.EndTime) {
 		state.queryParams.crTime = [routeQueryParams.StartTime, routeQueryParams.EndTime];
 	}
 	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
 });
 </script>

+ 326 - 319
src/views/statistics/order/hotspotAccept.vue

@@ -1,51 +1,32 @@
 <template>
-  <div class="statistics-order-hotspot-accept-container layout-padding">
-    <div class="layout-padding-auto layout-padding-view pd20">
-      <el-tabs v-model="state.queryParams.HotspotLevel" @tab-change="handleQuery">
-        <el-tab-pane name="1" label="第一级别"></el-tab-pane>
-        <el-tab-pane name="2" label="第二级别"></el-tab-pane>
-        <el-tab-pane name="3" label="第三级别"></el-tab-pane>
-        <el-tab-pane name="4" label="第四级别"></el-tab-pane>
-      </el-tabs>
-      <el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline class="search-form mb10">
+	<div class="statistics-order-hotspot-accept-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<el-tabs v-model="state.queryParams.HotspotLevel" @tab-change="handleQuery">
+				<el-tab-pane name="1" label="第一级别"></el-tab-pane>
+				<el-tab-pane name="2" label="第二级别"></el-tab-pane>
+				<el-tab-pane name="3" label="第三级别"></el-tab-pane>
+				<el-tab-pane name="4" label="第四级别"></el-tab-pane>
+			</el-tabs>
+			<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline class="search-form mb10">
 				<el-form-item prop="crTime">
-					<statistical-time v-model="state.queryParams.crTime" @change="handleQuery" ref="statisticalTimeRef" :disabled="state.loading"/>
+					<statistical-time v-model="state.queryParams.crTime" @change="handleQuery" ref="statisticalTimeRef" :disabled="state.loading" />
 				</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>
-        <div class="tool-buttons">
-          <el-button circle @click="queryList" title="刷新表格" :disabled="state.loading">
-            <SvgIcon name="ele-Refresh" />
-          </el-button>
-          <el-button circle @click="exportAll" title="导出全部" :disabled="exportLoading">
-            <SvgIcon name="iconfont icon-export" />
-          </el-button>
-          <el-button v-if="exportLoading" :loading="exportLoading">导出中,请稍后。。。</el-button>
-        </div>
-      </el-form>
-      <!-- 表格 -->
-      <el-auto-resizer class="table" v-loading="state.loading">
-        <template #default="{ height, width }">
-          <el-table-v2
-              :columns="columns"
-              :data="state.tableData"
-              fixed
-              :width="width"
-              :height="height - 5"
-              ref="virtuallyTableRef"
-              :scrollbar-always-on="true"
-              :row-height="40"
-              :header-height="40"
-          >
-          </el-table-v2>
-        </template>
-      </el-auto-resizer>
-    </div>
-  </div>
+				<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>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-grid v-bind="gridOptions" ref="tableRef">
+					<template #toolbar_tools>
+						<VxeButton title="导出全部" circle class="mr10" @click="exportAll"><SvgIcon name="iconfont icon-export" /></VxeButton>
+					</template>
+				</vxe-grid>
+			</div>
+		</div>
+	</div>
 </template>
 <script setup lang="tsx" name="statisticsOrderHotspotAccept">
 import { onMounted, reactive, ref, defineAsyncComponent } from 'vue';
@@ -55,8 +36,9 @@ import Other from '@/utils/other';
 import { statisticsOrderHotAccept, statisticsOrderHotAcceptExport } from '@/api/statistics/order';
 import { useRouter } from 'vue-router';
 import { downloadFileByStream } from '@/utils/tools';
+import { VxeButton, VxeUI } from 'vxe-pc-ui';
+import XEUtils from 'xe-utils';
 
-const TextTooltip = defineAsyncComponent(() => import('@/components/TextTooltip/index.vue'));
 const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
 
 // 表格配置项
@@ -64,298 +46,323 @@ const columns = ref<any[]>([]);
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
 const state = reactive<any>({
-  queryParams: {
-    // 查询条件
-    HotspotLevel: '1',
-    crTime: defaultDate, //
-    StartTime: null,
-    EndTime: null,
-  },
-  tableData: [], //表单
-  loading: false, // 加载
-  total: 0, // 总数
-  callForwardingSource: [],
+	queryParams: {
+		// 查询条件
+		HotspotLevel: '1',
+		crTime: defaultDate, //
+		StartTime: null,
+		EndTime: null,
+	},
+	tableData: [], //表单
+	loading: false, // 加载
+	total: 0, // 总数
+	callForwardingSource: [],
 });
 /** 搜索按钮操作 */
-const virtuallyTableRef = ref();
 const handleQuery = () => {
-  // state.queryParams.PageIndex = 1;
-  queryList();
+	// state.queryParams.PageIndex = 1;
+	queryList();
 };
-/** 获取列表 */
 const requestParams = ref<EmptyObjectType>({});
+const gridOptions = reactive<any>({
+	loading: false,
+	border: true,
+	showOverflow: true,
+	printConfig: {},
+	columnConfig: {
+		resizable: true,
+	},
+	scrollY: {
+		enabled: true,
+		gt: 20,
+		mode: 'wheel',
+	},
+	toolbarConfig: {
+		zoom: true,
+		custom: true,
+		refresh: {
+			queryMethod: () => {
+				queryList();
+			},
+		},
+		slots: {
+			tools: 'toolbar_tools',
+		},
+	},
+	showHeaderOverflow: true,
+	customConfig: {
+		storage: true,
+	},
+	showFooter: true,
+	footerMethod: ({ columns, data }) => {
+		return [
+			columns.map((column: any, columnIndex: number) => {
+				if (columnIndex === 0) {
+					return '合计';
+				}
+				return XEUtils.sum(data, column.property);
+			}),
+		];
+	},
+	id: 'statisticsOrderHotspotAccept',
+	rowConfig: { isHover: true, height: 30, isCurrent: true, useKey: true },
+	height: 'auto',
+	columns: [],
+	data: [],
+});
+/** 获取列表 */
 const queryList = async () => {
-  state.loading = true;
-  try {
-    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');
-    const { result } = await statisticsOrderHotAccept(requestParams.value);
-    columns.value = result.areaList.map((item: any) => {
-      return {
-        key: item.dicDataValue,
-        dataKey: item.dicDataValue,
-        title: item.dicDataName,
-        width: 100,
-        align: 'center',
-        cellRenderer: (data: any) => {
-          return (
-              <>
-                {data.rowData.HotspotName1 !== '合计' ? (
-                    <el-button type="primary" link onClick={() => linkDetail(data)}>
-                      {data.rowData[item.dicDataValue]}
-                    </el-button>
-                ) : (
-                    <span>{data.rowData[item.dicDataValue]}</span>
-                )}
-              </>
-          );
-        },
-      };
-    });
-    state.tableData = result.data;
-    state.tableData = state.tableData.map((item: any) => {
-      // 取第一级名称
-      item.HotspotName1 = item.HotspotName?.split('-')[0] ?? '';
-      // 取第二级名称
-      item.HotspotName2 = item.HotspotName?.split('-')[1] ?? '';
-      // 取第三级名称
-      item.HotspotName3 = item.HotspotName?.split('-')[2] ?? '';
-      // 取第四级名称
-      item.HotspotName4 = item.HotspotName?.split('-')[3] ?? '';
-      return { ...item };
-    });
-    switch (state.queryParams.HotspotLevel) {
-      case '1':
-        // 分类级别
-        columns.value.unshift({
-          key: 'HotspotName1',
-          dataKey: 'HotspotName1',
-          title: `一级热点`,
-          width: 150,
-          align: 'center',
-          cellRenderer: (data: any) => {
-            return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-          },
-        });
-        break;
-      case '2':
-        columns.value.unshift(
-            {
-              key: 'HotspotName1',
-              dataKey: 'HotspotName1',
-              title: `一级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-              },
-            },
-            {
-              key: 'HotspotName2',
-              dataKey: 'HotspotName2',
-              title: `二级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName2} effect="dark" placement="top"></TextTooltip>;
-              },
-            }
-        );
-        break;
-      case '3':
-        columns.value.unshift(
-            {
-              key: 'HotspotName1',
-              dataKey: 'HotspotName1',
-              title: `一级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-              },
-            },
-            {
-              key: 'HotspotName2',
-              dataKey: 'HotspotName2',
-              title: `二级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName2} effect="dark" placement="top"></TextTooltip>;
-              },
-            },
-            {
-              key: 'HotspotName3',
-              dataKey: 'HotspotName3',
-              title: `三级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName3} effect="dark" placement="top"></TextTooltip>;
-              },
-            }
-        );
-        break;
-      case '4':
-        columns.value.unshift(
-            {
-              key: 'HotspotName1',
-              dataKey: 'HotspotName1',
-              title: `一级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-              },
-            },
-            {
-              key: 'HotspotName2',
-              dataKey: 'HotspotName2',
-              title: `二级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName2} effect="dark" placement="top"></TextTooltip>;
-              },
-            },
-            {
-              key: 'HotspotName3',
-              dataKey: 'HotspotName3',
-              title: `三级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName3} effect="dark" placement="top"></TextTooltip>;
-              },
-            },
-            {
-              key: 'HotspotName4',
-              dataKey: 'HotspotName4',
-              title: `四级热点`,
-              width: 150,
-              align: 'center',
-              cellRenderer: (data: any) => {
-                return <TextTooltip content={data.rowData.HotspotName4} effect="dark" placement="top"></TextTooltip>;
-              },
-            }
-        );
-        break;
-      default:
-        break;
-    }
+	state.loading = true;
+	gridOptions.loading = true;
+	try {
+		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');
+		const { result } = await statisticsOrderHotAccept(requestParams.value);
+		let columns = result.areaList.map((item: any) => {
+			return {
+				key: item.dicDataValue,
+				dataKey: item.dicDataValue,
+				title: item.dicDataName,
+				field: item.dicDataValue,
+				minWidth: 100,
+				align: 'center',
+				sortable: true,
+				slots: {
+					default(scope: any) {
+						return (
+							<>
+								{scope.row.HotspotName1 !== '合计' ? (
+									<el-button type="primary" link onClick={() => linkDetail(scope)}>
+										{scope.row[item.dicDataValue] ? scope.row[item.dicDataValue] : 0}
+									</el-button>
+								) : (
+									<span>{scope.row[item.dicDataValue]}</span>
+								)}
+							</>
+						);
+					},
+				},
+			};
+		});
+		let tableData = result.data;
+		tableData.map((item: any) => {
+			// 取第一级名称
+			item.HotspotName1 = item.HotspotName?.split('-')[0] ?? '';
+			// 取第二级名称
+			item.HotspotName2 = item.HotspotName?.split('-')[1] ?? '';
+			// 取第三级名称
+			item.HotspotName3 = item.HotspotName?.split('-')[2] ?? '';
+			// 取第四级名称
+			item.HotspotName4 = item.HotspotName?.split('-')[3] ?? '';
+			return { ...item };
+		});
+		switch (state.queryParams.HotspotLevel) {
+			case '1':
+				// 分类级别
+				columns.unshift({
+					key: 'HotspotName1',
+					dataKey: 'HotspotName1',
+					title: `一级热点`,
+					field: 'HotspotName1',
+					width: 150,
+					align: 'center',
+				});
+				break;
+			case '2':
+				columns.unshift(
+					{
+						key: 'HotspotName1',
+						dataKey: 'HotspotName1',
+						title: `一级热点`,
+						field: 'HotspotName1',
+						width: 150,
+						align: 'center',
+					},
+					{
+						key: 'HotspotName2',
+						dataKey: 'HotspotName2',
+						title: `二级热点`,
+						width: 150,
+						align: 'center',
+						field: 'HotspotName2',
+					}
+				);
+				break;
+			case '3':
+				columns.unshift(
+					{
+						key: 'HotspotName1',
+						dataKey: 'HotspotName1',
+						title: `一级热点`,
+						width: 150,
+						align: 'center',
+						field: 'HotspotName1',
+					},
+					{
+						key: 'HotspotName2',
+						dataKey: 'HotspotName2',
+						title: `二级热点`,
+						width: 150,
+						align: 'center',
+						field: 'HotspotName2',
+					},
+					{
+						key: 'HotspotName3',
+						dataKey: 'HotspotName3',
+						title: `三级热点`,
+						width: 150,
+						align: 'center',
+						field: 'HotspotName3',
+					}
+				);
+				break;
+			case '4':
+				columns.unshift(
+					{
+						key: 'HotspotName1',
+						dataKey: 'HotspotName1',
+						title: `一级热点`,
+						width: 150,
+						align: 'center',
+						field: 'HotspotName1',
+					},
+					{
+						key: 'HotspotName2',
+						dataKey: 'HotspotName2',
+						field: 'HotspotName2',
+						title: `二级热点`,
+						width: 150,
+						align: 'center',
+					},
+					{
+						key: 'HotspotName3',
+						dataKey: 'HotspotName3',
+						field: 'HotspotName3',
+						title: `三级热点`,
+						width: 150,
+						align: 'center',
+					},
+					{
+						key: 'HotspotName4',
+						dataKey: 'HotspotName4',
+						field: 'HotspotName4',
+						title: `四级热点`,
+						width: 150,
+						align: 'center',
+					}
+				);
+				break;
+			default:
+				break;
+		}
 
-    // 计算横轴小计
-    state.tableData = result.data.map((item: any) => {
-      let subtotal = 0;
-      for (let i of result.areaList) {
-        const itemI = item[i.dicDataValue] ?? 0;
-        subtotal += itemI;
-      }
-      return {
-        ...item,
-        subtotal,
-      };
-    });
-    columns.value.push({
-      align: 'center',
-      key: 'subtotal',
-      dataKey: 'subtotal',
-      title: '小计',
-      width: 100,
-    });
-    if (result.data.length) {
-      const totals = {};
-      // 计算纵轴合计
-      state.tableData.forEach((row) => {
-        Object.keys(row).forEach((key) => {
-          // 获取每个对象的键名进行遍历
-          if (!totals[key]) {
-            totals[key] = 0;
-          }
-          if (typeof row[key] === 'number') {
-            totals[key] += Number(row[key]);
-          } else {
-            totals[key] = '';
-          }
-        });
-      });
-      totals.HotspotName1 = '合计';
-      state.tableData.push({ ...totals });
-			state.tableData = state.tableData.filter((item) => item.HotspotName1); // 筛选掉空对象
-    }
-    state.loading = false;
-  } catch (e) {
-    state.loading = false;
-    console.log(e);
-  }
+		// 计算横轴小计
+		tableData = result.data.map((item: any) => {
+			let subtotal = 0;
+			for (let i of result.areaList) {
+				const itemI = item[i.dicDataValue] ?? 0;
+				subtotal += itemI;
+			}
+			return {
+				...item,
+				subtotal,
+			};
+		});
+		columns.push({
+			align: 'center',
+			key: 'subtotal',
+			dataKey: 'subtotal',
+			field: 'subtotal',
+			title: '小计',
+			sortable: true,
+			width: 100,
+		});
+		if (result.data.length) {
+			tableData = tableData.filter((item) => item.HotspotName1); // 筛选掉空对象
+		}
+		gridOptions.data = tableData;
+		gridOptions.columns = columns;
+		gridOptions.loading = false;
+		state.loading = false;
+	} catch (e) {
+		state.loading = false;
+		gridOptions.loading = false;
+		console.log(e);
+	}
 };
 /** 重置按钮操作 */
 const statisticalTimeRef = ref<RefType>();
 const resetQuery = (formEl: FormInstance | undefined) => {
-  if (!formEl) return;
-  formEl.resetFields();
+	if (!formEl) return;
+	formEl.resetFields();
 	statisticalTimeRef.value.reset();
-  queryList();
+	queryList();
 };
 // 查看列表明细
 const router = useRouter();
-const linkDetail = (data:any) => {
-  router.push({
-    path: '/statistics/order/detailHotspotArea',
-    query: {
-			AcceptTypeCode: data.column.dataKey,
-      HotspotId: data.rowData.HotspotId,
-      StartTime: requestParams.value.StartTime,
-      EndTime: requestParams.value.EndTime,
-      type: 'hotspotAccept',
-			tagsViewName:`${data.rowData.HotspotName}-${data.column.title}`
-    },
-  });
+const linkDetail = (data: any) => {
+	router.push({
+		path: '/statistics/order/detailHotspotArea',
+		query: {
+			AcceptTypeCode: data.column.field,
+			HotspotId: data.row.HotspotId,
+			StartTime: requestParams.value.StartTime,
+			EndTime: requestParams.value.EndTime,
+			type: 'hotspotAccept',
+			tagsViewName: `${data.row.HotspotName}-${data.column.title}`,
+		},
+	});
 };
-const exportLoading = ref(false);
 // 导出
+const tableRef = ref();
 const exportAll = () => {
-  ElMessageBox.confirm(`您确定要导出全部数据,是否继续?`, '提示', {
-    confirmButtonText: '确认',
-    cancelButtonText: '取消',
-    type: 'warning',
-    draggable: true,
-    cancelButtonClass: 'default-button',
-    autofocus: false,
-  })
-      .then(() => {
-        exportLoading.value = true;
-        const AddColumnName = columns.value.map((item: any) => item.title).filter(item => !['一级热点', '二级热点', '三级热点', '四级热点'].includes(item))
-        AddColumnName.unshift('热点分类');
-        const specialRequest = {
-          ...requestParams.value,
-          AddColumnName
-        };
-				statisticsOrderHotAcceptExport(specialRequest)
-            .then((res: any) => {
-              downloadFileByStream(res);
-              exportLoading.value = false;
-            })
-            .catch((e) => {
-              console.log(`导出失败:${e}`);
-              exportLoading.value = false;
-            });
-      })
-      .catch(() => {});
+	const columns = tableRef.value.getColumns();
+	ElMessageBox.confirm(`您确定要导出全部数据,是否继续?`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		cancelButtonClass: 'default-button',
+		autofocus: false,
+	})
+		.then(() => {
+			const AddColumnName = columns
+				.map((item: any) => item.title)
+				.filter((item: any) => !['一级热点', '二级热点', '三级热点', '四级热点'].includes(item));
+			AddColumnName.unshift('热点分类');
+			const specialRequest = {
+				...requestParams.value,
+				AddColumnName,
+			};
+			VxeUI.modal.message({
+				content: `导出中,请稍等`,
+				status: 'loading',
+				id: 'exportAll',
+				duration: -1,
+			});
+			statisticsOrderHotAcceptExport(specialRequest)
+				.then((res: any) => {
+					downloadFileByStream(res);
+					VxeUI.modal.close('exportAll');
+					VxeUI.modal.message({
+						content: `导出成功`,
+						status: 'success',
+					});
+				})
+				.catch((e) => {
+					console.log(`导出失败:${e}`);
+					VxeUI.modal.close('exportAll');
+					VxeUI.modal.message({
+						content: `导出失败`,
+						status: 'error',
+					});
+				});
+		})
+		.catch(() => {});
 };
 onMounted(() => {
-  queryList();
+	queryList();
 });
 </script>
-<style lang="scss" scoped>
-.search-form {
-  position: relative;
-  .tool-buttons {
-    position: absolute;
-    right: 0;
-    top: 5px;
-  }
-}
-</style>

+ 124 - 122
src/views/statistics/order/hotspotArea.vue

@@ -17,33 +17,14 @@
 						<SvgIcon name="ele-Refresh" class="mr5" />重置
 					</el-button>
 				</el-form-item>
-				<div class="tool-buttons">
-					<el-button circle @click="queryList" title="刷新表格" :disabled="state.loading">
-						<SvgIcon name="ele-Refresh" />
-					</el-button>
-					<el-button circle @click="exportAll" title="导出全部" :disabled="exportLoading">
-						<SvgIcon name="iconfont icon-export" />
-					</el-button>
-					<el-button v-if="exportLoading" :loading="exportLoading">导出中,请稍后。。。</el-button>
-				</div>
 			</el-form>
-			<!-- 表格 -->
-			<el-auto-resizer class="table" v-loading="state.loading">
-				<template #default="{ height, width }">
-					<el-table-v2
-						:columns="columns"
-						:data="state.tableData"
-						fixed
-						:width="width"
-						:height="height - 5"
-						ref="virtuallyTableRef"
-						:scrollbar-always-on="true"
-            :row-height="40"
-            :header-height="40"
-					>
-					</el-table-v2>
-				</template>
-			</el-auto-resizer>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-grid v-bind="gridOptions" ref="tableRef">
+					<template #toolbar_tools>
+						<VxeButton title="导出全部" circle class="mr10" @click="exportAll"><SvgIcon name="iconfont icon-export" /></VxeButton>
+					</template>
+				</vxe-grid>
+			</div>
 		</div>
 	</div>
 </template>
@@ -54,13 +35,12 @@ import { defaultDate } from '@/utils/constants';
 import Other from '@/utils/other';
 import { statisticsOrderHot, statisticsOrderHotExport } from '@/api/statistics/order';
 import { useRouter } from 'vue-router';
+import { VxeButton, VxeUI } from 'vxe-pc-ui';
 import { downloadFileByStream } from '@/utils/tools';
+import XEUtils from 'xe-utils';
 
-const TextTooltip = defineAsyncComponent(() => import('@/components/TextTooltip/index.vue'));
 const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
 
-// 表格配置项
-const columns = ref<any[]>([]);
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
 const state = reactive<any>({
@@ -76,46 +56,95 @@ const state = reactive<any>({
 	total: 0, // 总数
 	callForwardingSource: [],
 });
-/** 搜索按钮操作 */
-const virtuallyTableRef = ref();
 const handleQuery = () => {
 	// state.queryParams.PageIndex = 1;
 	queryList();
 };
-/** 获取列表 */
 const requestParams = ref<EmptyObjectType>({});
+const gridOptions = reactive<any>({
+	loading: false,
+	border: true,
+	showOverflow: true,
+	printConfig: {},
+	columnConfig: {
+		resizable: true,
+	},
+	scrollY: {
+		enabled: true,
+		gt: 20,
+		mode: 'wheel',
+	},
+	toolbarConfig: {
+		zoom: true,
+		custom: true,
+		refresh: {
+			queryMethod: () => {
+				queryList();
+			},
+		},
+		slots: {
+			tools: 'toolbar_tools',
+		},
+	},
+	showFooter: true,
+	footerMethod: ({ columns, data }) => {
+		return [
+			columns.map((column: any, columnIndex: number) => {
+				if (columnIndex === 0) {
+					return '合计';
+				}
+				return XEUtils.sum(data, column.property);
+			}),
+		];
+	},
+	showHeaderOverflow: true,
+	customConfig: {
+		storage: true
+	},
+	id: 'statisticsOrderHotspotArea',
+	rowConfig: { isHover: true, height: 30,isCurrent:true,useKey:true },
+	height: 'auto',
+	columns: [],
+	data: [],
+});
+/** 获取列表 */
 const queryList = async () => {
 	state.loading = true;
+	gridOptions.loading = true;
 	try {
 		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');
 		const { result } = await statisticsOrderHot(requestParams.value);
-		columns.value = result.areaList.map((item: any) => {
+		let columns = result.areaList.map((item: any) => {
 			return {
 				key: item.id,
 				dataKey: item.id,
 				title: item.areaName,
-				width: 95,
+				minWidth: 100,
 				align: 'center',
-				cellRenderer: (data: any) => {
-					return (
-						<>
-							{data.rowData.HotspotName1 !== '合计' ? (
-								<el-button type="primary" link onClick={() => linkDetail(data)}>
-									{data.rowData[item.id] ? data.rowData[item.id] : 0}
-								</el-button>
-							) : (
-								<span>{data.rowData[item.id]}</span>
-							)}
-						</>
-					);
-				},
+				field: item.id,
+				sortable:true,
+				slots: {
+					default (scope:any) {
+						return (
+							<>
+								{scope.row.HotspotName1 !== '合计' ? (
+									<el-button type="primary" link onClick={() => linkDetail(scope)}>
+										{scope.row[item.id] ? scope.row[item.id] : 0}
+									</el-button>
+								) : (
+									<span>{scope.row[item.id]}</span>
+								)}
+							</>
+						);
+					}
+				}
 			};
 		});
-		state.tableData = result.data;
-		state.tableData = state.tableData.map((item: any) => {
+		let tableData = result.data;
+		tableData.map((item: any) => {
 			// 取第一级名称
 			item.HotspotName1 = item.HotspotName?.split('-')[0] ?? '';
 			// 取第二级名称
@@ -129,28 +158,24 @@ const queryList = async () => {
 		switch (state.queryParams.HotspotLevel) {
 			case '1':
 				// 分类级别
-				columns.value.unshift({
+				columns.unshift({
 					key: 'HotspotName1',
 					dataKey: 'HotspotName1',
 					title: `一级热点`,
+					field: 'HotspotName1',
 					width: 150,
 					align: 'center',
-					cellRenderer: (data: any) => {
-						return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-					},
 				});
 				break;
 			case '2':
-				columns.value.unshift(
+				columns.unshift(
 					{
 						key: 'HotspotName1',
 						dataKey: 'HotspotName1',
 						title: `一级热点`,
+						field: 'HotspotName1',
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-						},
 					},
 					{
 						key: 'HotspotName2',
@@ -158,23 +183,19 @@ const queryList = async () => {
 						title: `二级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName2} effect="dark" placement="top"></TextTooltip>;
-						},
+						field: 'HotspotName2',
 					}
 				);
 				break;
 			case '3':
-				columns.value.unshift(
+				columns.unshift(
 					{
 						key: 'HotspotName1',
 						dataKey: 'HotspotName1',
 						title: `一级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-						},
+						field: 'HotspotName1',
 					},
 					{
 						key: 'HotspotName2',
@@ -182,9 +203,7 @@ const queryList = async () => {
 						title: `二级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName2} effect="dark" placement="top"></TextTooltip>;
-						},
+						field: 'HotspotName2',
 					},
 					{
 						key: 'HotspotName3',
@@ -192,53 +211,43 @@ const queryList = async () => {
 						title: `三级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName3} effect="dark" placement="top"></TextTooltip>;
-						},
+						field: 'HotspotName3',
 					}
 				);
 				break;
 			case '4':
-				columns.value.unshift(
+				columns.unshift(
 					{
 						key: 'HotspotName1',
 						dataKey: 'HotspotName1',
 						title: `一级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName1} effect="dark" placement="top"></TextTooltip>;
-						},
+						field: 'HotspotName1',
 					},
 					{
 						key: 'HotspotName2',
 						dataKey: 'HotspotName2',
+						field: 'HotspotName2',
 						title: `二级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName2} effect="dark" placement="top"></TextTooltip>;
-						},
 					},
 					{
 						key: 'HotspotName3',
 						dataKey: 'HotspotName3',
+						field: 'HotspotName3',
 						title: `三级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName3} effect="dark" placement="top"></TextTooltip>;
-						},
 					},
 					{
 						key: 'HotspotName4',
 						dataKey: 'HotspotName4',
+						field: 'HotspotName4',
 						title: `四级热点`,
 						width: 150,
 						align: 'center',
-						cellRenderer: (data: any) => {
-							return <TextTooltip content={data.rowData.HotspotName4} effect="dark" placement="top"></TextTooltip>;
-						},
 					}
 				);
 				break;
@@ -247,7 +256,7 @@ const queryList = async () => {
 		}
 
 		// 计算横轴小计
-		state.tableData = result.data.map((item: any) => {
+		tableData = result.data.map((item: any) => {
 			let subtotal = 0;
 			for (let i of result.areaList) {
 				const itemI = item[i.id] ?? 0;
@@ -258,36 +267,25 @@ const queryList = async () => {
 				subtotal,
 			};
 		});
-		columns.value.push({
+		columns.push({
 			align: 'center',
 			key: 'subtotal',
 			dataKey: 'subtotal',
 			title: '小计',
+			field: 'subtotal',
 			width: 100,
+			sortable:true
 		});
 		if (result.data.length) {
-			const totals = {};
-			// 计算纵轴合计
-			state.tableData.forEach((row) => {
-				Object.keys(row).forEach((key) => {
-					// 获取每个对象的键名进行遍历
-					if (!totals[key]) {
-						totals[key] = 0;
-					}
-					if (typeof row[key] === 'number') {
-						totals[key] += Number(row[key]);
-					} else {
-						totals[key] = '';
-					}
-				});
-			});
-			totals.HotspotName1 = '合计';
-			state.tableData.push({ ...totals });
-			state.tableData = state.tableData.filter((item) => item.HotspotName1); // 筛选掉空对象
+			tableData = tableData.filter((item) => item.HotspotName1); // 筛选掉空对象
 		}
+		gridOptions.data = tableData;
+		gridOptions.columns = columns;
 		state.loading = false;
+		gridOptions.loading = false;
 	} catch (e) {
 		state.loading = false;
+		gridOptions.loading = false;
 		console.log(e);
 	}
 };
@@ -305,18 +303,19 @@ const linkDetail = (data:any) => {
 	router.push({
 		path: '/statistics/order/detailHotspotArea',
 		query: {
-			AreaCode: data.column.dataKey,
-			HotspotId: data.rowData.HotspotId,
+			AreaCode: data.column.field,
+			HotspotId: data.row.HotspotId,
 			StartTime: requestParams.value.StartTime,
 			EndTime: requestParams.value.EndTime,
 			type: 'hotspotArea',
-			tagsViewName:`${data.rowData.HotspotName}-${data.column.title}`
+			tagsViewName:`${data.row.HotspotName}-${data.column.title}`
 		},
 	});
 };
-const exportLoading = ref(false);
 // 导出
+const tableRef = ref();
 const exportAll = () => {
+	const columns = tableRef.value.getColumns();
 	ElMessageBox.confirm(`您确定要导出全部数据,是否继续?`, '提示', {
 		confirmButtonText: '确认',
 		cancelButtonText: '取消',
@@ -326,23 +325,36 @@ const exportAll = () => {
 		autofocus: false,
 	})
 		.then(() => {
-			exportLoading.value = true;
-			const AddColumnName = columns.value
+			const AddColumnName = columns
 				.map((item: any) => item.title)
-				.filter((item) => !['一级热点', '二级热点', '三级热点', '四级热点'].includes(item));
+				.filter((item: any) => !['一级热点', '二级热点', '三级热点', '四级热点'].includes(item));
 			AddColumnName.unshift('热点分类');
 			const specialRequest = {
 				...requestParams.value,
 				AddColumnName,
 			};
+			VxeUI.modal.message({
+				content: `导出中,请稍等`,
+				status: 'loading',
+				id: 'exportAll',
+				duration: -1,
+			});
 			statisticsOrderHotExport(specialRequest)
 				.then((res: any) => {
 					downloadFileByStream(res);
-					exportLoading.value = false;
+					VxeUI.modal.close('exportAll');
+					VxeUI.modal.message({
+						content: `导出成功`,
+						status: 'success',
+					});
 				})
 				.catch((e) => {
 					console.log(`导出失败:${e}`);
-					exportLoading.value = false;
+					VxeUI.modal.close('exportAll');
+					VxeUI.modal.message({
+						content: `导出失败`,
+						status: 'error',
+					});
 				});
 		})
 		.catch(() => {});
@@ -351,13 +363,3 @@ onMounted(() => {
 	queryList();
 });
 </script>
-<style lang="scss" scoped>
-.search-form {
-	position: relative;
-	.tool-buttons {
-		position: absolute;
-		right: 0;
-		top: 5px;
-	}
-}
-</style>

+ 134 - 253
src/views/statistics/order/hotspotSatisfied.vue

@@ -1,51 +1,32 @@
 <template>
 	<div class="statistics-order-hotspot-satisfied-container layout-padding">
     <div class="layout-padding-auto layout-padding-view pd20">
-			<ProTable
-				ref="proTableRef"
-				:columns="columns"
-				:data="state.tableData"
-				@updateTable="queryList"
-				:loading="state.loading"
-				show-summary
-				:summary-method="getSummaries"
-				:pagination="false"
-				:toolButton="['refresh', 'setting', 'exportCurrent', 'exportAll']"
-				:exportMethod="statisticsOrderHotSatisfyExport"
-				:exportParams="requestParams"
-				border
-			>
-        <template #table-search>
-          <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="HotspotName">
-              <el-input v-model="state.queryParams.HotspotName" placeholder="热点名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
-            </el-form-item>
-            <el-form-item label="归档类型" prop="TypeId">
-              <el-select v-model="state.queryParams.TypeId" placeholder="归档类型" @change="handleQuery">
-                <el-option label="办件结果" value="1" />
-                <el-option label="办件态度" value="2" />
-              </el-select>
-            </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>
-        </template>
-				<template #description>
+			<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="HotspotName">
+					<el-input v-model="state.queryParams.HotspotName" placeholder="热点名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="归档类型" prop="TypeId">
+					<el-select v-model="state.queryParams.TypeId" placeholder="归档类型" @change="handleQuery">
+						<el-option label="办件结果" value="1" />
+						<el-option label="办件态度" value="2" />
+					</el-select>
+				</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 circle title="口径说明"><SvgIcon name="ele-QuestionFilled" /></el-button>
+							<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
 							>
 							<el-descriptions-item label="总满意率">(非常满意+满意+视为满意+默认满意)/(非常满意+满意+视为满意+默认满意+不满意)</el-descriptions-item>
 							<el-descriptions-item label="非常满意"> 已回访-部门评价-办件结果为非常满意 </el-descriptions-item>
@@ -66,8 +47,101 @@
 							<el-descriptions-item label="未做评价率"> 未接通/小计 </el-descriptions-item>
 						</el-descriptions>
 					</el-popover>
-				</template>
-			</ProTable>
+				</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
+					show-overflow
+					:scrollY="{ enabled: true, gt: 20, mode: 'wheel' }"
+					id="statisticsOrderHotspotSatisfied"
+					:custom-config="{
+						storage: true,
+					}"
+					showHeaderOverflow
+					:params="{ exportMethod: statisticsOrderHotSatisfyExport, exportParams: requestParams }"
+					show-footer
+					:footer-method="footerMethod"
+				>
+					<vxe-column field="hotspotName" title="热点名称" min-width="200" fixed="left">
+					</vxe-column>
+					<vxe-column field="totalSumCount" title="小计" min-width="90" fixed="left"> </vxe-column>
+					<vxe-column field="totalSumRateText" title="总满意率" min-width="120"> </vxe-column>
+					<vxe-column field="verySatisfiedCount" title="非常满意"  min-width="100">
+						<template #default="scope">
+							<el-button type="primary" link @click="linkDetail(scope)">
+								{{ scope.row.verySatisfiedCount }}
+							</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="verySatisfiedRateText" title="非常满意率" min-width="120"> </vxe-column>
+					<vxe-column field="satisfiedCount" title="满意"  min-width="100">
+						<template #default="scope">
+							<el-button type="primary" link @click="linkDetail( scope)">
+								{{ scope.row.satisfiedCount }}
+							</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="satisfiedRateText" title="满意率" min-width="120"> </vxe-column>
+					<vxe-column field="regardedAsSatisfiedCount" title="视为满意"  min-width="100">
+						<template #default="scope">
+							<el-button type="primary" link @click="linkDetail( scope.row)">
+								{{ scope.row.regardedAsSatisfiedCount }}
+							</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="regardedAsSatisfiedRateText" title="视为满意率" min-width="120"> </vxe-column>
+					<vxe-column field="defaultSatisfiedCount" title="默认满意"  min-width="100">
+						<template #default="scope">
+							<el-button type="primary" link @click="linkDetail( scope)">
+								{{ scope.row.defaultSatisfiedCount }}
+							</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="defaultSatisfiedRateText" title="默认满意率" min-width="120"> </vxe-column>
+					<vxe-column field="noSatisfiedCount" title="不满意"  min-width="100">
+						<template #default="scope">
+							<el-button type="primary" link @click="linkDetail(scope)">
+								{{ scope.row.noSatisfiedCount }}
+							</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="noSatisfiedRateText" title="不满意率" min-width="120"> </vxe-column>
+					<vxe-column field="noEvaluateCount" title="未作评价"  min-width="100">
+						<template #default="scope">
+							<el-button type="primary" link @click="linkDetail(scope)">
+								{{ scope.row.noEvaluateCount }}
+							</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="noEvaluateRateText" title="未作评价率" min-width="120"> </vxe-column>
+					<vxe-column field="noPutThroughCount" title="未接通"  min-width="100">
+						<template #default="scope">
+							<el-button type="primary" link @click="linkDetail(scope)">
+								{{ scope.row.noPutThroughCount }}
+							</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="noPutThroughRateText" title="未接通率" min-width="120"> </vxe-column>
+				</vxe-table>
+			</div>
 		</div>
 	</div>
 </template>
@@ -78,141 +152,9 @@ import { defaultDate } from '@/utils/constants';
 import Other from '@/utils/other';
 import { statisticsOrderHotSatisfy, statisticsOrderHotSatisfyExport } from '@/api/statistics/order';
 import { useRouter } from 'vue-router';
+import XEUtils from 'xe-utils';
 
 const StatisticalTime = defineAsyncComponent(() => import('@/components/StatisticalTime/index.vue')); // 日期类型选择组件
-// 表格配置项
-const columns = ref<any[]>([
-	{
-		prop: 'hotspotName',
-		label: '热点名称',
-		minWidth: 150,
-	},
-	{ prop: 'totalSumCount', label: '小计' },
-	{
-		prop: 'totalSumRateText',
-		label: '总满意率',
-		minWidth: 100,
-	},
-	{
-		prop: 'verySatisfiedCount',
-		label: '非常满意',
-		minWidth: 100,
-		render: (scope) => {
-			return (
-				<el-button type="primary" link onClick={() => onDetail(scope)}>
-					{scope.row.verySatisfiedCount}
-				</el-button>
-			);
-		},
-	},
-	{
-		prop: 'verySatisfiedRateText',
-		label: '非常满意率',
-		minWidth: 100,
-	},
-	{
-		prop: 'satisfiedCount',
-		label: '满意',
-		minWidth: 100,
-		render: (scope) => {
-			return (
-				<el-button type="primary" link onClick={() => onDetail(scope)}>
-					{scope.row.satisfiedCount}
-				</el-button>
-			);
-		},
-	},
-	{
-		prop: 'satisfiedRateText',
-		label: '满意率',
-		minWidth: 100,
-	},
-	{
-		prop: 'regardedAsSatisfiedCount',
-		label: '视为满意',
-		minWidth: 100,
-		render: (scope) => {
-			return (
-				<el-button type="primary" link onClick={() => onDetail(scope)}>
-					{scope.row.regardedAsSatisfiedCount}
-				</el-button>
-			);
-		},
-	},
-	{
-		prop: 'regardedAsSatisfiedRateText',
-		label: '视为满意率',
-		minWidth: 120,
-	},
-	{
-		prop: 'defaultSatisfiedCount',
-		label: '默认满意',
-		minWidth: 100,
-		render: (scope) => {
-			return (
-				<el-button type="primary" link onClick={() => onDetail(scope)}>
-					{scope.row.defaultSatisfiedCount}
-				</el-button>
-			);
-		},
-	},
-	{
-		prop: 'defaultSatisfiedRateText',
-		label: '默认满意率',
-		minWidth: 100,
-	},
-	{
-		prop: 'noSatisfiedCount',
-		label: '不满意',
-		minWidth: 100,
-		render: (scope) => {
-			return (
-				<el-button type="primary" link onClick={() => onDetail(scope)}>
-					{scope.row.noSatisfiedCount}
-				</el-button>
-			);
-		},
-	},
-	{
-		prop: 'noSatisfiedRateText',
-		label: '不满意率',
-		minWidth: 100,
-	},
-	{
-		prop: 'noEvaluateCount',
-		label: '未作评价',
-		minWidth: 100,
-		render: (scope) => {
-			return (
-				<el-button type="primary" link onClick={() => onDetail(scope)}>
-					{scope.row.noEvaluateCount}
-				</el-button>
-			);
-		},
-	},
-	{
-		prop: 'noEvaluateRateText',
-		label: '未作评价率',
-		minWidth: 100,
-	},
-	{
-		prop: 'noPutThroughCount',
-		label: '未接通',
-		minWidth: 100,
-		render: (scope) => {
-			return (
-				<el-button type="primary" link onClick={() => onDetail(scope)}>
-					{scope.row.noPutThroughCount}
-				</el-button>
-			);
-		},
-	},
-	{
-		prop: 'noPutThroughRateText',
-		label: '未接通率',
-		minWidth: 100,
-	},
-]);
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
 const state = reactive<any>({
@@ -260,77 +202,21 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 	statisticalTimeRef.value.reset();
 	queryList();
 };
-// 合计
-const getSummaries = (param: any) => {
-	const { columns } = param;
-	const sums: string[] = [];
-	columns.forEach((column: { property: string }, index: number) => {
-		if (index === 0) {
-			sums[index] = '合计';
-			return;
-		}
-		switch (column.property) {
-			case 'orgTypeText':
-				sums[index] = state.totalCount?.orgTypeText;
-				break;
-			case 'totalSumCount':
-				sums[index] = state.totalCount?.totalSumCount;
-				break;
-			case 'totalSumRateText':
-				sums[index] = state.totalCount?.totalSumRateText;
-				break;
-			case 'verySatisfiedCount':
-				sums[index] = state.totalCount?.verySatisfiedCount;
-				break;
-			case 'verySatisfiedRateText':
-				sums[index] = state.totalCount?.verySatisfiedRateText;
-				break;
-			case 'satisfiedCount':
-				sums[index] = state.totalCount?.satisfiedCount;
-				break;
-			case 'satisfiedRateText':
-				sums[index] = state.totalCount?.satisfiedRateText;
-				break;
-			case 'regardedAsSatisfiedCount':
-				sums[index] = state.totalCount?.regardedAsSatisfiedCount;
-				break;
-			case 'regardedAsSatisfiedRateText':
-				sums[index] = state.totalCount?.regardedAsSatisfiedRateText;
-				break;
-			case 'defaultSatisfiedCount':
-				sums[index] = state.totalCount?.defaultSatisfiedCount;
-				break;
-			case 'defaultSatisfiedRateText':
-				sums[index] = state.totalCount?.defaultSatisfiedRateText;
-				break;
-			case 'noSatisfiedCount':
-				sums[index] = state.totalCount?.noSatisfiedCount;
-				break;
-			case 'noSatisfiedRateText':
-				sums[index] = state.totalCount?.noSatisfiedRateText;
-				break;
-			case 'noEvaluateCount':
-				sums[index] = state.totalCount?.noEvaluateCount;
-				break;
-			case 'noEvaluateRateText':
-				sums[index] = state.totalCount?.noEvaluateRateText;
-				break;
-			case 'noPutThroughCount':
-				sums[index] = state.totalCount?.noPutThroughCount;
-				break;
-			case 'noPutThroughRateText':
-				sums[index] = state.totalCount?.noPutThroughRateText;
-				break;
-			default:
-				sums[index] = '';
-				break;
-		}
-	});
-	return sums;
+// 计算合计
+const footerMethod = ({ columns, data }) => {
+	return [
+		columns.map((column: any, columnIndex: number) => {
+			if (columnIndex === 0) {
+				return '合计';
+			}
+			// 后端返回了数据集合 state.totalCount 所以不需要计算 直接进行赋值
+			return XEUtils.get(state.totalCount, column.property);
+		}),
+	];
 };
 // 查看列表明细
 const router = useRouter();
-const onDetail = (data) => {
+const linkDetail = (data:any) => {
 	router.push({
 		path: '/statistics/order/detailHotspotSatisfied',
 		query: {
@@ -340,21 +226,16 @@ const onDetail = (data) => {
 			EndTime: requestParams.value.EndTime,
 			TypeId: requestParams.value.TypeId,
 			TitleCode: data.column.property,
-			tagsViewName:`${data.row.hotspotName}-${data.column.label}`
+			tagsViewName:`${data.row.hotspotName}-${data.column.title}`
 		},
 	});
 };
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
 onMounted(() => {
 	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
 });
 </script>
-<style lang="scss" scoped>
-.search-form {
-	position: relative;
-	.tool-buttons {
-		position: absolute;
-		right: 0;
-		top: 5px;
-	}
-}
-</style>