Browse Source

reactor:新增信件来源分时统计页面;

zhangchong 10 months ago
parent
commit
1e35b51d9e
2 changed files with 425 additions and 180 deletions
  1. 2 2
      src/views/statistics/order/source.vue
  2. 423 178
      src/views/statistics/order/timeSource.vue

+ 2 - 2
src/views/statistics/order/source.vue

@@ -60,9 +60,8 @@
 	</div>
 </template>
 <script setup lang="tsx" name="statisticsOrderSource">
-import { computed, onMounted, reactive, ref, watch } from "vue";
+import { computed, onMounted, reactive, ref } from "vue";
 import { FormInstance } from 'element-plus';
-import { callPeriodBase } from '@/api/statistics/call';
 import { defaultDate, shortcuts } from '@/utils/constants';
 import Other from '@/utils/other';
 import { orderSource, orderSourceExport } from '@/api/statistics/order';
@@ -125,6 +124,7 @@ const queryList = () => {
 					};
 				})
 				.filter((item: any) => item.name !== '合计');
+      console.log(legendData)
 			setOption(legendData, dataTable.value);
 			state.loading = false;
 		})

+ 423 - 178
src/views/statistics/order/timeSource.vue

@@ -1,60 +1,60 @@
 <template>
-  <div class="statistics-order-time-source-container layout-pd">
-    <!-- 搜索  -->
-    <el-card shadow="never">
-      <el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline>
-        <el-form-item label="来电人身份" prop="IdentityType">
-          <el-select v-model="state.queryParams.IdentityType" placeholder="请选择来电人身份" clearable @change="handleQuery">
-            <el-option v-for="item in identityTypeOptions" :value="item.value" :key="item.value" :label="item.key" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="时间段" prop="crTime">
-          <el-date-picker
-            v-model="state.queryParams.crTime"
-            type="daterange"
-            unlink-panels
-            range-separator="至"
-            start-placeholder="开始时间"
-            end-placeholder="结束时间"
-            :shortcuts="shortcuts"
-            @change="handleQuery"
-            value-format="YYYY-MM-DD"
-            :clearable="false"
-          />
-        </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-button type="info" @click="onDetail" :loading="state.loading"> <SvgIcon name="ele-List" class="mr5" /> 列表明细 </el-button>
-        </el-form-item>
-      </el-form>
-    </el-card>
-    <el-card shadow="never">
-      <el-row :gutter="20">
-        <el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
-          <v-chart class="chart" :option="option" :loading="state.loading" autoresize />
-        </el-col>
-        <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
-          <ProTable
-            ref="proTableRef"
-            :columns="columns"
-            :data="state.tableData"
-            @updateTable="queryList"
-            :loading="state.loading"
-            :pagination="false"
-            border
-            :tool-button="false"
-            max-height="60vh"
-            :toolButton="['refresh', 'setting', 'exportAll']"
-            @export-all="exportTable($event, true)"
-          >
-          </ProTable>
-        </el-col>
-      </el-row>
-    </el-card>
-  </div>
+	<div class="statistics-order-time-source-container layout-pd">
+		<!-- 搜索  -->
+		<el-card shadow="never">
+			<el-form :model="state.queryParams" ref="ruleFormRef" @submit.native.prevent inline>
+				<el-form-item label="来电人身份" prop="IdentityType">
+					<el-select v-model="state.queryParams.IdentityType" placeholder="请选择来电人身份" clearable @change="handleQuery">
+						<el-option v-for="item in identityTypeOptions" :value="item.value" :key="item.value" :label="item.key" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="时间段" prop="crTime">
+					<el-date-picker
+						v-model="state.queryParams.crTime"
+						type="daterange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD"
+						:clearable="false"
+					/>
+				</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-button type="info" @click="onDetail" :loading="state.loading"> <SvgIcon name="ele-List" class="mr5" /> 列表明细 </el-button>
+				</el-form-item>
+			</el-form>
+		</el-card>
+		<el-card shadow="never">
+			<el-row :gutter="20">
+				<el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
+					<v-chart class="chart" :option="option" :loading="state.loading" autoresize />
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
+					<ProTable
+						ref="proTableRef"
+						:columns="columns"
+						:data="state.tableData"
+						@updateTable="queryList"
+						:loading="state.loading"
+						:pagination="false"
+						border
+						:tool-button="false"
+						max-height="60vh"
+						:toolButton="['refresh', 'setting', 'exportAll']"
+						@export-all="exportTable($event, true)"
+					>
+					</ProTable>
+				</el-col>
+			</el-row>
+		</el-card>
+	</div>
 </template>
 <script setup lang="tsx" name="statisticsOrderTimeSource">
 import { onMounted, reactive, ref } from 'vue';
@@ -69,162 +69,407 @@ import { useRouter } from 'vue-router';
 const proTableRef = ref<RefType>(); // 表格ref
 // 表格配置项
 const columns = ref<any[]>([
-  { prop: 'source', label: '时间段', align: 'center' },
-  { prop: 'num', label: '数量', align: 'center' },
-  { prop: 'rateText', label: '占比', align: 'center' },
+	{ prop: 'source', label: '时间段', align: 'center' },
+	{ prop: 'num', label: '数量', align: 'center' },
+	{ prop: 'rateText', label: '占比', align: 'center' },
 ]);
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
 const state = reactive<any>({
-  queryParams: {
-    // 查询条件
-    IdentityType: null, // 关键词
-    crTime: defaultDate, //
-    StartTime: null,
-    EndTime: null,
-  },
-  tableData: [], //表单
-  loading: false, // 加载
-  total: 0, // 总数
-  callForwardingSource: [],
+	queryParams: {
+		// 查询条件
+		IdentityType: null, // 关键词
+		crTime: defaultDate, //
+		StartTime: null,
+		EndTime: null,
+	},
+	tableData: [], //表单
+	loading: false, // 加载
+	total: 0, // 总数
+	callForwardingSource: [],
 });
 const identityTypeOptions = [
-  { key: '市民', value: 1 },
-  { key: '企业', value: 2 },
+	{ key: '市民', value: 1 },
+	{ key: '企业', value: 2 },
 ];
 /** 搜索按钮操作 */
 const handleQuery = () => {
-  // state.queryParams.PageIndex = 1;
-  queryList();
+	// state.queryParams.PageIndex = 1;
+	queryList();
 };
 /** 获取列表 */
 const queryList = () => {
-  state.loading = true;
-  let request = Other.deepClone(state.queryParams);
-  request.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
-  request.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
-  Reflect.deleteProperty(request, 'crTime');
-  orderSource(request)
-    .then((res: any) => {
-      state.tableData = res.result;
-      const legendData = state.tableData
-        .map((item: any) => {
-          return item.source;
-        })
-        .filter((item: any) => item !== '合计');
-      const dataTable = state.tableData
-        .map((item: any) => {
-          return {
-            name: item.source,
-            value: item.num,
-            ...item,
-          };
-        })
-        .filter((item: any) => item.name !== '合计');
-      setOption(legendData, dataTable);
-      state.loading = false;
-    })
-    .catch(() => {
-      state.loading = false;
-    });
+	state.loading = true;
+	let request = Other.deepClone(state.queryParams);
+	request.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
+	request.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
+	Reflect.deleteProperty(request, 'crTime');
+	orderSource(request)
+		.then((res: any) => {
+			state.tableData = res.result;
+			const legendData = state.tableData
+				.map((item: any) => {
+					return item.source;
+				})
+				.filter((item: any) => item !== '合计');
+			const dataTable = state.tableData
+				.map((item: any) => {
+					return {
+						name: item.source,
+						value: item.num,
+						...item,
+					};
+				})
+				.filter((item: any) => item.name !== '合计');
+			setOption(legendData, dataTable);
+			state.loading = false;
+		})
+		.catch(() => {
+			state.loading = false;
+		});
 };
 /** 重置按钮操作 */
 const resetQuery = (formEl: FormInstance | undefined) => {
-  if (!formEl) return;
-  formEl.resetFields();
-  queryList();
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
 };
 const option = ref<any>({});
 // 信件来源统计
 const setOption = (legendData: string[], data: any) => {
-  option.value = {
-    title: {
-      text: '信件来源统计',
-      left: 'center',
-    },
-    tooltip: {
-      formatter: '{b}:{d}%',
-    },
-    legend: [
-      {
-        left: 'left',
-        top: '40',
-        orient: 'vertical',
-        data: legendData,
+	option.value = {
+		title: {
+			text: '信件来源分时统计',
+			left: 'center',
+			top: '0',
+		},
+		tooltip: {
+			trigger: 'axis',
+			axisPointer: {
+				type: 'shadow',
+			},
+			confine: true,
+		},
+		legend: {
+			top: '7%',
+			data: [
+				'自建',
+				'string',
+				'市长与网民',
+				'宜宾110平台',
+				'智慧宜宾',
+				'微信',
+				'小程序',
+				'网站',
+				'其他',
+				'App',
+				'因特网',
+				'综治平台',
+				'省政民互动',
+				'市州互转',
+				'微博',
+				'电话',
+				'i宜宾',
+				'省12345平台',
+				'宜宾融媒体',
+			],
+		},
+		grid: {
+			left: '3%',
+			right: '4%',
+			bottom: '3%',
+			top: '20%',
+			containLabel: true,
+		},
+		xAxis: {
+      axisLabel: {
+        rotate:45   //设置的值大于0向右倾斜,小于0向左
       },
-    ],
-    grid: {
-      containLabel: true,
-    },
-    series: [
-      {
-        type: 'pie',
-        radius: ['0%', '80%'],
-        label: {
-          show: true,
-          overflow: 'none',
-          formatter: function (params) {
-            if (params.name !== '') {
-              return `${params.name}:${params.data.value}(${params.percent}%)`;
-            }
-          },
-        },
-        data: data,
-      },
-    ],
-  };
+      data: [
+				'00:00~00:59',
+				'01:00~01:59',
+				'02:00~02:59',
+				'03:00~03:59',
+				'04:00~04:59',
+				'05:00~05:59',
+				'06:00~06:59',
+				'07:00~07:59',
+				'08:00~08:59',
+				'09:00~09:59',
+				'10:00~10:59',
+				'11:00~11:59',
+				'12:00~12:59',
+				'13:00~13:59',
+				'14:00~14:59',
+				'15:00~15:59',
+				'16:00~16:59',
+				'17:00~17:59',
+				'18:00~18:59',
+				'19:00~19:59',
+				'20:00~20:59',
+				'21:00~21:59',
+				'22:00~22:59',
+				'23:00~23:59',
+			],
+		},
+		yAxis: {
+			type: 'value',
+		},
+		series: [
+			{
+				name: '自建',
+				type: 'bar',
+				stack: 'total',
+
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: 'string',
+				type: 'bar',
+				stack: 'total',
+
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '市长与网民',
+				type: 'bar',
+				stack: 'total',
+
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '宜宾110平台',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '智慧宜宾',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '微信',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '小程序',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '网站',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '其他',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: 'App',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '因特网',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '综治平台',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '省政民互动',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '市州互转',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '微博',
+				type: 'bar',
+				stack: 'total',
+
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '电话',
+				type: 'bar',
+				stack: 'total',
+
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: 'i宜宾',
+				type: 'bar',
+				stack: 'total',
+
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '省12345平台',
+				type: 'bar',
+				stack: 'total',
+
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '宜宾融媒体',
+				type: 'bar',
+				stack: 'total',
+				animationDelay: function (idx) {
+					return idx * 50 + 1000;
+				},
+				data: [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210],
+			},
+			{
+				name: '统计',
+				type: 'bar',
+				stack: 'total',
+				data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //默认数据
+				label: {
+					show: true,
+					position: 'top',
+					formatter: function (params) {
+						//合计数据
+						let total = [120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210, 120, 132, 101, 134, 90, 230, 210, 101, 134, 90, 230, 210];
+						return total[params.dataIndex];
+					},
+					fontWeight: 'bold',
+					color: '#000',
+				},
+			},
+		],
+		animationEasing: 'elasticOut',
+		animationDuration: 2000,
+		// animationDelayUpdate: function (idx) {
+		//   return idx * 50 + 1000;
+		// }
+	};
 };
 // 获取基础信息
 const getBaseInfo = async () => {
-  try {
-    const { result } = await callPeriodBase();
-    state.callForwardingSource = result.callForwardingSource ?? [];
-  } catch (e) {
-    console.log(e);
-  }
+	try {
+		const { result } = await callPeriodBase();
+		state.callForwardingSource = result.callForwardingSource ?? [];
+	} catch (e) {
+		console.log(e);
+	}
 };
 // 表格导出
 const exportTable = (val: any, isExportAll = false) => {
-  let request = Other.deepClone(state.queryParams);
-  request.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
-  request.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
-  Reflect.deleteProperty(request, 'crTime');
-  const columnInfos = val.map((item: any) => {
-    return {
-      prop: item.prop,
-      name: item.label,
-    };
-  });
-  const req = {
-    queryDto: request,
-    columnInfos,
-    isExportAll,
-  };
-  state.loading = true;
-  orderSourceExport(req)
-    .then((res: any) => {
-      state.loading = false;
-      downloadFileByStream(res);
-    })
-    .catch(() => {
-      state.loading = false;
-    });
+	let request = Other.deepClone(state.queryParams);
+	request.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
+	request.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
+	Reflect.deleteProperty(request, 'crTime');
+	const columnInfos = val.map((item: any) => {
+		return {
+			prop: item.prop,
+			name: item.label,
+		};
+	});
+	const req = {
+		queryDto: request,
+		columnInfos,
+		isExportAll,
+	};
+	state.loading = true;
+	orderSourceExport(req)
+		.then((res: any) => {
+			state.loading = false;
+			downloadFileByStream(res);
+		})
+		.catch(() => {
+			state.loading = false;
+		});
 };
 // 查看列表明细
 const router = useRouter();
 const onDetail = () => {
-  router.push({
-    name: 'statisticsOrderDetailSource',
-  });
+	router.push({
+		name: 'statisticsOrderDetailSource',
+	});
 };
 onMounted(() => {
-  getBaseInfo();
-  queryList();
+	getBaseInfo();
+	queryList();
 });
 </script>
 <style lang="scss" scoped>
-.chart{
-  height: 60vh;
-  margin-top: 10px;
+.chart {
+	height: 60vh;
+	margin-top: 10px;
 }
 </style>