feat:【ele】mp/statistics 的代码迁移
This commit is contained in:
@@ -1,13 +1,10 @@
|
|||||||
import type { PageParam } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace MpStatisticsApi {
|
export namespace MpStatisticsApi {
|
||||||
/** 统计查询参数 */
|
/** 统计查询参数 */
|
||||||
export interface StatisticsQuery extends PageParam {
|
export interface StatisticsQuery {
|
||||||
accountId: number;
|
accountId: number;
|
||||||
beginDate: string;
|
date: Date[];
|
||||||
endDate: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 消息发送概况数据 */
|
/** 消息发送概况数据 */
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function handleEdit(row: MpAccountApi.Account) {
|
|||||||
|
|
||||||
/** 删除账号 */
|
/** 删除账号 */
|
||||||
async function handleDelete(row: MpAccountApi.Account) {
|
async function handleDelete(row: MpAccountApi.Account) {
|
||||||
const hideLoading = ElLoading.service({
|
const loadingInstance = ElLoading.service({
|
||||||
text: $t('ui.actionMessage.deleting', [row.name]),
|
text: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
@@ -48,13 +48,13 @@ async function handleDelete(row: MpAccountApi.Account) {
|
|||||||
ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
||||||
handleRefresh();
|
handleRefresh();
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading.close();
|
loadingInstance.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 生成二维码 */
|
/** 生成二维码 */
|
||||||
async function handleGenerateQrCode(row: MpAccountApi.Account) {
|
async function handleGenerateQrCode(row: MpAccountApi.Account) {
|
||||||
const hideLoading = ElLoading.service({
|
const loadingInstance = ElLoading.service({
|
||||||
text: '正在生成二维码中...',
|
text: '正在生成二维码中...',
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
@@ -62,20 +62,20 @@ async function handleGenerateQrCode(row: MpAccountApi.Account) {
|
|||||||
ElMessage.success($t('ui.actionMessage.operationSuccess'));
|
ElMessage.success($t('ui.actionMessage.operationSuccess'));
|
||||||
handleRefresh();
|
handleRefresh();
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading.close();
|
loadingInstance.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 清空 API 配额 */
|
/** 清空 API 配额 */
|
||||||
async function handleCleanQuota(row: MpAccountApi.Account) {
|
async function handleCleanQuota(row: MpAccountApi.Account) {
|
||||||
const hideLoading = ElLoading.service({
|
const loadingInstance = ElLoading.service({
|
||||||
text: $t('ui.actionMessage.processing', ['清空 API 配额']),
|
text: $t('ui.actionMessage.processing', ['清空 API 配额']),
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await clearAccountQuota(row.id as number);
|
await clearAccountQuota(row.id as number);
|
||||||
ElMessage.success($t('ui.actionMessage.operationSuccess'));
|
ElMessage.success($t('ui.actionMessage.operationSuccess'));
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading.close();
|
loadingInstance.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
163
apps/web-ele/src/views/mp/statistics/chart-options.ts
Normal file
163
apps/web-ele/src/views/mp/statistics/chart-options.ts
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
import type { MpStatisticsApi } from '#/api/mp/statistics';
|
||||||
|
|
||||||
|
/** 用户增减数据图表配置项 */
|
||||||
|
export function userSummaryOption(
|
||||||
|
data: MpStatisticsApi.UserSummary[],
|
||||||
|
dates: string[],
|
||||||
|
): any {
|
||||||
|
return {
|
||||||
|
color: ['#67C23A', '#E5323E'],
|
||||||
|
legend: {
|
||||||
|
data: ['新增用户', '取消关注的用户'],
|
||||||
|
},
|
||||||
|
tooltip: {},
|
||||||
|
xAxis: {
|
||||||
|
data: dates,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
minInterval: 1,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '新增用户',
|
||||||
|
type: 'bar',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
barGap: 0,
|
||||||
|
data: data.map((item) => item.newUser), // 新增用户的数据
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '取消关注的用户',
|
||||||
|
type: 'bar',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
data: data.map((item) => item.cancelUser), // 取消关注的用户的数据
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 累计用户数据图表配置项 */
|
||||||
|
export function userCumulateOption(
|
||||||
|
data: MpStatisticsApi.UserCumulate[],
|
||||||
|
dates: string[],
|
||||||
|
): any {
|
||||||
|
return {
|
||||||
|
legend: {
|
||||||
|
data: ['累计用户量'],
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: dates,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
minInterval: 1,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '累计用户量',
|
||||||
|
data: data.map((item) => item.cumulateUser), // 累计用户量的数据
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 消息发送概况数据图表配置项 */
|
||||||
|
export function upstreamMessageOption(
|
||||||
|
data: MpStatisticsApi.UpstreamMessage[],
|
||||||
|
dates: string[],
|
||||||
|
): any {
|
||||||
|
return {
|
||||||
|
color: ['#67C23A', '#E5323E'],
|
||||||
|
legend: {
|
||||||
|
data: ['用户发送人数', '用户发送条数'],
|
||||||
|
},
|
||||||
|
tooltip: {},
|
||||||
|
xAxis: {
|
||||||
|
data: dates, // X 轴的日期范围
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
minInterval: 1,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '用户发送人数',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
data: data.map((item) => item.msgUser), // 用户发送人数的数据
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户发送条数',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
data: data.map((item) => item.msgCount), // 用户发送条数的数据
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 接口分析况数据图表配置项 */
|
||||||
|
export function interfaceSummaryOption(
|
||||||
|
data: MpStatisticsApi.InterfaceSummary[],
|
||||||
|
dates: string[],
|
||||||
|
): any {
|
||||||
|
return {
|
||||||
|
color: ['#67C23A', '#E5323E', '#E6A23C', '#409EFF'],
|
||||||
|
legend: {
|
||||||
|
data: ['被动回复用户消息的次数', '失败次数', '最大耗时', '总耗时'],
|
||||||
|
},
|
||||||
|
tooltip: {},
|
||||||
|
xAxis: {
|
||||||
|
data: dates, // X 轴的日期范围
|
||||||
|
},
|
||||||
|
yAxis: {},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '被动回复用户消息的次数',
|
||||||
|
type: 'bar',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
barGap: 0,
|
||||||
|
data: data.map((item) => item.callbackCount), // 被动回复用户消息的次数的数据
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '失败次数',
|
||||||
|
type: 'bar',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
data: data.map((item) => item.failCount), // 失败次数的数据
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '最大耗时',
|
||||||
|
type: 'bar',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
data: data.map((item) => item.maxTimeCost), // 最大耗时的数据
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '总耗时',
|
||||||
|
type: 'bar',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
data: data.map((item) => item.totalTimeCost), // 总耗时的数据
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
43
apps/web-ele/src/views/mp/statistics/data.ts
Normal file
43
apps/web-ele/src/views/mp/statistics/data.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { MpAccountApi } from '#/api/mp/account';
|
||||||
|
|
||||||
|
import { beginOfDay, endOfDay, formatDateTime } from '@vben/utils';
|
||||||
|
|
||||||
|
import { getSimpleAccountList } from '#/api/mp/account';
|
||||||
|
|
||||||
|
/** 关联数据 */
|
||||||
|
let accountList: MpAccountApi.AccountSimple[] = [];
|
||||||
|
getSimpleAccountList().then((data) => (accountList = data));
|
||||||
|
|
||||||
|
/** 列表的搜索表单 */
|
||||||
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'accountId',
|
||||||
|
label: '公众号',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
options: accountList.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
})),
|
||||||
|
placeholder: '请选择公众号',
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
defaultValue: accountList[0]?.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'dateRange',
|
||||||
|
label: '时间范围',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
},
|
||||||
|
defaultValue: [
|
||||||
|
formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))),
|
||||||
|
formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))),
|
||||||
|
] as [Date, Date],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
151
apps/web-ele/src/views/mp/statistics/index.vue
Normal file
151
apps/web-ele/src/views/mp/statistics/index.vue
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
import { ContentWrap, Page } from '@vben/common-ui';
|
||||||
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||||
|
import { addTime, betweenDay, formatDate } from '@vben/utils';
|
||||||
|
|
||||||
|
import { ElCard, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
import {
|
||||||
|
getInterfaceSummary,
|
||||||
|
getUpstreamMessage,
|
||||||
|
getUserCumulate,
|
||||||
|
getUserSummary,
|
||||||
|
} from '#/api/mp/statistics';
|
||||||
|
|
||||||
|
import {
|
||||||
|
interfaceSummaryOption,
|
||||||
|
upstreamMessageOption,
|
||||||
|
userCumulateOption,
|
||||||
|
userSummaryOption,
|
||||||
|
} from './chart-options';
|
||||||
|
import { useGridFormSchema } from './data';
|
||||||
|
|
||||||
|
const userSummaryRef = ref<EchartsUIType>();
|
||||||
|
const { renderEcharts: renderUserSummaryEcharts } = useEcharts(userSummaryRef);
|
||||||
|
|
||||||
|
const userCumulateRef = ref<EchartsUIType>();
|
||||||
|
const { renderEcharts: renderUserCumulateEcharts } =
|
||||||
|
useEcharts(userCumulateRef);
|
||||||
|
|
||||||
|
const upstreamMessageRef = ref<EchartsUIType>();
|
||||||
|
const { renderEcharts: renderUpstreamMessageEcharts } =
|
||||||
|
useEcharts(upstreamMessageRef);
|
||||||
|
|
||||||
|
const interfaceSummaryRef = ref<EchartsUIType>();
|
||||||
|
const { renderEcharts: renderInterfaceSummaryEcharts } =
|
||||||
|
useEcharts(interfaceSummaryRef);
|
||||||
|
|
||||||
|
/** 加载数据 */
|
||||||
|
async function getSummary(values: Record<string, any>) {
|
||||||
|
const accountId = values.accountId;
|
||||||
|
if (!accountId) {
|
||||||
|
ElMessage.warning('请先选择公众号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dateRange = values.dateRange;
|
||||||
|
if (!dateRange) {
|
||||||
|
ElMessage.warning('请先选择时间范围');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 必须选择 7 天内,因为公众号有时间跨度限制为 7
|
||||||
|
if (betweenDay(dateRange[0], dateRange[1]) >= 7) {
|
||||||
|
ElMessage.error('时间间隔 7 天以内,请重新选择');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 处理日期
|
||||||
|
const days = betweenDay(dateRange[0], dateRange[1]);
|
||||||
|
const dates = Array.from(
|
||||||
|
{ length: days },
|
||||||
|
(_, index) =>
|
||||||
|
formatDate(addTime(dateRange[0], index), 'YYYY-MM-DD') as string,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 用户增减数据
|
||||||
|
const userSummaryData = await getUserSummary({
|
||||||
|
accountId,
|
||||||
|
date: dateRange,
|
||||||
|
});
|
||||||
|
await renderUserSummaryEcharts(userSummaryOption(userSummaryData, dates));
|
||||||
|
// 累计用户数据
|
||||||
|
const userCumulateData = await getUserCumulate({
|
||||||
|
accountId,
|
||||||
|
date: dateRange,
|
||||||
|
});
|
||||||
|
await renderUserCumulateEcharts(userCumulateOption(userCumulateData, dates));
|
||||||
|
// 消息发送概况数据
|
||||||
|
const upstreamMessageData = await getUpstreamMessage({
|
||||||
|
accountId,
|
||||||
|
date: dateRange,
|
||||||
|
});
|
||||||
|
await renderUpstreamMessageEcharts(
|
||||||
|
upstreamMessageOption(upstreamMessageData, dates),
|
||||||
|
);
|
||||||
|
// 接口分析数据
|
||||||
|
const interfaceSummaryData = await getInterfaceSummary({
|
||||||
|
accountId,
|
||||||
|
date: dateRange,
|
||||||
|
});
|
||||||
|
await renderInterfaceSummaryEcharts(
|
||||||
|
interfaceSummaryOption(interfaceSummaryData, dates),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [QueryForm, queryFormApi] = useVbenForm({
|
||||||
|
commonConfig: {
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
layout: 'horizontal',
|
||||||
|
schema: useGridFormSchema(),
|
||||||
|
wrapperClass: 'grid-cols-1 md:grid-cols-2',
|
||||||
|
handleSubmit: getSummary,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(() => {
|
||||||
|
queryFormApi.submitForm();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page auto-content-height>
|
||||||
|
<ContentWrap class="h-full w-full">
|
||||||
|
<QueryForm />
|
||||||
|
|
||||||
|
<div class="flex h-1/3 w-full gap-4">
|
||||||
|
<ElCard class="h-full w-1/2">
|
||||||
|
<template #header>
|
||||||
|
<span>用户增减数据</span>
|
||||||
|
</template>
|
||||||
|
<EchartsUI ref="userSummaryRef" />
|
||||||
|
</ElCard>
|
||||||
|
<ElCard class="h-full w-1/2">
|
||||||
|
<template #header>
|
||||||
|
<span>累计用户数据</span>
|
||||||
|
</template>
|
||||||
|
<EchartsUI ref="userCumulateRef" />
|
||||||
|
</ElCard>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 flex h-1/3 w-full gap-4">
|
||||||
|
<ElCard class="h-full w-1/2">
|
||||||
|
<template #header>
|
||||||
|
<span>消息发送概况数据</span>
|
||||||
|
</template>
|
||||||
|
<EchartsUI ref="upstreamMessageRef" />
|
||||||
|
</ElCard>
|
||||||
|
<ElCard class="h-full w-1/2">
|
||||||
|
<template #header>
|
||||||
|
<span>接口分析数据</span>
|
||||||
|
</template>
|
||||||
|
<EchartsUI ref="interfaceSummaryRef" />
|
||||||
|
</ElCard>
|
||||||
|
</div>
|
||||||
|
</ContentWrap>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user