-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/home/modules/comparison-card.vue b/apps/web-ele/src/views/mall/home/modules/comparison-card.vue
new file mode 100644
index 000000000..83e4fb578
--- /dev/null
+++ b/apps/web-ele/src/views/mall/home/modules/comparison-card.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+ {{ title }}
+ {{ tag }}
+
+
+
{{ prefix }}{{ formattedValue }}
+
+ {{ Math.abs(percent).toFixed(2) }}%
+
+
+
+
+
+ 昨日数据
+ {{ prefix }}{{ formattedReference }}
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/home/modules/member-statistics-card.vue b/apps/web-ele/src/views/mall/home/modules/member-statistics-card.vue
new file mode 100644
index 000000000..e9e83c86e
--- /dev/null
+++ b/apps/web-ele/src/views/mall/home/modules/member-statistics-card.vue
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+ 用户统计
+
+
+ {{ value.name }}
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/home/modules/member-statistics-chart-options.ts b/apps/web-ele/src/views/mall/home/modules/member-statistics-chart-options.ts
new file mode 100644
index 000000000..d1e8bf08c
--- /dev/null
+++ b/apps/web-ele/src/views/mall/home/modules/member-statistics-chart-options.ts
@@ -0,0 +1,64 @@
+import dayjs from 'dayjs';
+
+/** 时间范围类型枚举 */
+export enum TimeRangeTypeEnum {
+ DAY30 = 1,
+ MONTH = 30,
+ WEEK = 7,
+ YEAR = 365,
+}
+
+/** 会员统计图表配置 */
+export function getMemberStatisticsChartOptions(list: any[]): any {
+ return {
+ dataset: {
+ dimensions: ['date', 'count'],
+ source: list,
+ },
+ grid: {
+ left: 20,
+ right: 20,
+ bottom: 20,
+ top: 80,
+ containLabel: true,
+ },
+ legend: {
+ top: 50,
+ },
+ series: [{ name: '注册量', type: 'line', smooth: true, areaStyle: {} }],
+ toolbox: {
+ feature: {
+ // 数据区域缩放
+ dataZoom: {
+ yAxisIndex: false, // Y轴不缩放
+ },
+ brush: {
+ type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
+ },
+ saveAsImage: { show: true, name: '会员统计' }, // 保存为图片
+ },
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ },
+ padding: [5, 10],
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ axisTick: {
+ show: false,
+ },
+ axisLabel: {
+ formatter: (date: string) => dayjs(date).format('MM-DD'),
+ },
+ },
+ yAxis: {
+ axisTick: {
+ show: false,
+ },
+ },
+ };
+}
diff --git a/apps/web-ele/src/views/mall/home/modules/operation-data-card.vue b/apps/web-ele/src/views/mall/home/modules/operation-data-card.vue
new file mode 100644
index 000000000..c9d0ad078
--- /dev/null
+++ b/apps/web-ele/src/views/mall/home/modules/operation-data-card.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+ 运营数据
+
+
+
+
+ {{ item.name }}
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/home/modules/shortcut-card.vue b/apps/web-ele/src/views/mall/home/modules/shortcut-card.vue
new file mode 100644
index 000000000..8a44c3ea6
--- /dev/null
+++ b/apps/web-ele/src/views/mall/home/modules/shortcut-card.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+ 快捷入口
+
+
+
+
+
+
+
{{ menu.name }}
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/home/modules/trade-trend-card.vue b/apps/web-ele/src/views/mall/home/modules/trade-trend-card.vue
new file mode 100644
index 000000000..5a584cb21
--- /dev/null
+++ b/apps/web-ele/src/views/mall/home/modules/trade-trend-card.vue
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+ 交易量趋势
+
+
+ {{ value.name }}
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/home/modules/trade-trend-chart-options.ts b/apps/web-ele/src/views/mall/home/modules/trade-trend-chart-options.ts
new file mode 100644
index 000000000..3d5ffa0c1
--- /dev/null
+++ b/apps/web-ele/src/views/mall/home/modules/trade-trend-chart-options.ts
@@ -0,0 +1,86 @@
+import dayjs from 'dayjs';
+
+/** 时间范围类型枚举 */
+export enum TimeRangeTypeEnum {
+ DAY30 = 1,
+ MONTH = 30,
+ WEEK = 7,
+ YEAR = 365,
+}
+
+/** 交易量趋势图表配置 */
+export function getTradeTrendChartOptions(
+ dates: string[],
+ series: any[],
+ timeRangeType: TimeRangeTypeEnum,
+): any {
+ return {
+ grid: {
+ left: 20,
+ right: 20,
+ bottom: 20,
+ top: 80,
+ containLabel: true,
+ },
+ legend: {
+ top: 50,
+ data: series.map((item) => item.name),
+ },
+ series,
+ toolbox: {
+ feature: {
+ // 数据区域缩放
+ dataZoom: {
+ yAxisIndex: false, // Y轴不缩放
+ },
+ brush: {
+ type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
+ },
+ saveAsImage: { show: true, name: '订单量趋势' }, // 保存为图片
+ },
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ },
+ padding: [5, 10],
+ },
+ xAxis: {
+ type: 'category',
+ inverse: true,
+ boundaryGap: false,
+ axisTick: {
+ show: false,
+ },
+ data: dates,
+ axisLabel: {
+ formatter: (date: string) => {
+ switch (timeRangeType) {
+ case TimeRangeTypeEnum.DAY30: {
+ return dayjs(date).format('MM-DD');
+ }
+ case TimeRangeTypeEnum.MONTH: {
+ return dayjs(date).format('D');
+ }
+ case TimeRangeTypeEnum.WEEK: {
+ const weekDay = dayjs(date).day();
+ return weekDay === 0 ? '周日' : `周${weekDay}`;
+ }
+ case TimeRangeTypeEnum.YEAR: {
+ return `${dayjs(date).format('M')}月`;
+ }
+ default: {
+ return date;
+ }
+ }
+ },
+ },
+ },
+ yAxis: {
+ axisTick: {
+ show: false,
+ },
+ },
+ };
+}
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
new file mode 100644
index 000000000..340510bec
--- /dev/null
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+ 会员概览
+
+
+
+
+
+
+
+
+ 注册用户数量:
+ {{ analyseData?.comparison?.value?.registerUserCount || 0 }}
+
+
+ 环比增长率:
+ {{
+ calculateRelativeRate(
+ analyseData?.comparison?.value?.registerUserCount,
+ analyseData?.comparison?.reference?.registerUserCount,
+ ).toFixed(2)
+ }}%
+
+
+
+
+
+ {{ analyseData?.visitUserCount || 0 }}
+
+ 访客
+
+
+
+
+
+
+ 活跃用户数量:
+ {{ analyseData?.comparison?.value?.visitUserCount || 0 }}
+
+
+ 环比增长率:
+ {{
+ calculateRelativeRate(
+ analyseData?.comparison?.value?.visitUserCount,
+ analyseData?.comparison?.reference?.visitUserCount,
+ ).toFixed(2)
+ }}%
+
+
+
+
+
+ {{ analyseData?.orderUserCount || 0 }}
+
+ 下单
+
+
+
+
+
+
+
+ 充值用户数量:
+ {{ analyseData?.comparison?.value?.rechargeUserCount || 0 }}
+
+
+ 环比增长率:
+ {{
+ calculateRelativeRate(
+ analyseData?.comparison?.value?.rechargeUserCount,
+ analyseData?.comparison?.reference?.rechargeUserCount,
+ ).toFixed(2)
+ }}%
+
+
+
+
+ 客单价:{{ fenToYuan(analyseData?.atv || 0) }}
+
+
+
+
+
+
+ {{ analyseData?.payUserCount || 0 }}
+
+ 成交用户
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue
new file mode 100644
index 000000000..4ff172296
--- /dev/null
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+ 会员终端
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/terminal-chart-options.ts b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-chart-options.ts
new file mode 100644
index 000000000..c3233bdd1
--- /dev/null
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-chart-options.ts
@@ -0,0 +1,27 @@
+/** 会员终端统计图配置 */
+export function getTerminalChartOptions(data: any[]): any {
+ return {
+ tooltip: {
+ trigger: 'item',
+ confine: true,
+ formatter: '{a}
{b} : {c} ({d}%)',
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'right',
+ },
+ series: [
+ {
+ name: '会员终端',
+ type: 'pie',
+ label: {
+ show: false,
+ },
+ labelLine: {
+ show: false,
+ },
+ data,
+ },
+ ],
+ };
+}
From bd9d8376c2caa4c0e1f32604d55a3ca36738538f Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 16:59:47 +0800
Subject: [PATCH 013/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E5=95=86=E5=9F=8E=E9=A6=96=E9=A1=B5=E7=9A=84?=
=?UTF-8?q?=E8=BF=81=E7=A7=BB=E3=80=90ele=E3=80=91100%=EF=BC=9A=E8=AF=84?=
=?UTF-8?q?=E5=AE=A1=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../web-ele/src/api/mall/statistics/common.ts | 2 +-
.../web-ele/src/api/mall/statistics/member.ts | 78 +++++++------
.../src/api/mall/statistics/product.ts | 50 ++------
apps/web-ele/src/api/mall/statistics/trade.ts | 27 ++---
.../shortcut-date-range-picker/index.ts | 1 +
.../shortcut-date-range-picker.vue | 110 ++++++++++++++++++
.../statistics/member/modules/funnel-card.vue | 44 ++-----
7 files changed, 181 insertions(+), 131 deletions(-)
create mode 100644 apps/web-ele/src/components/shortcut-date-range-picker/index.ts
create mode 100644 apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
diff --git a/apps/web-ele/src/api/mall/statistics/common.ts b/apps/web-ele/src/api/mall/statistics/common.ts
index bb474b5cc..3b1fad6d7 100644
--- a/apps/web-ele/src/api/mall/statistics/common.ts
+++ b/apps/web-ele/src/api/mall/statistics/common.ts
@@ -1,5 +1,5 @@
/** 数据对照 Response */
-export interface MallDataComparisonResp {
+export interface DataComparisonRespVO {
value: T;
reference: T;
}
diff --git a/apps/web-ele/src/api/mall/statistics/member.ts b/apps/web-ele/src/api/mall/statistics/member.ts
index bcc993047..71423b131 100644
--- a/apps/web-ele/src/api/mall/statistics/member.ts
+++ b/apps/web-ele/src/api/mall/statistics/member.ts
@@ -1,73 +1,73 @@
-import type { MallDataComparisonResp } from './common';
+import type { Dayjs } from 'dayjs';
-import { formatDate2 } from '@vben/utils';
+import type { DataComparisonRespVO } from './common';
+
+import { formatDateTime } from '@vben/utils';
import { requestClient } from '#/api/request';
export namespace MallMemberStatisticsApi {
/** 会员分析 Request */
- export interface AnalyseReq {
- times: Date[];
+ export interface MemberAnalyseReqVO {
+ times: Date[] | Dayjs[]; // 时间范围
}
/** 会员分析对照数据 Response */
export interface AnalyseComparison {
- registerUserCount: number;
- visitUserCount: number;
- rechargeUserCount: number;
+ registerUserCount: number; // 注册用户数
+ visitUserCount: number; // 访问用户数
+ rechargeUserCount: number; // 充值用户数
}
/** 会员分析 Response */
export interface Analyse {
- visitUserCount: number;
- orderUserCount: number;
- payUserCount: number;
- atv: number;
- comparison: MallDataComparisonResp;
+ visitUserCount: number; // 访问用户数
+ orderUserCount: number; // 下单用户数
+ payUserCount: number; // 支付用户数
+ atv: number; // 平均客单价
+ comparison: DataComparisonRespVO; // 对照数据
}
/** 会员地区统计 Response */
export interface AreaStatistics {
- areaId: number;
- areaName: string;
- userCount: number;
- orderCreateUserCount: number;
- orderPayUserCount: number;
- orderPayPrice: number;
+ areaId: number; // 地区ID
+ areaName: string; // 地区名称
+ userCount: number; // 用户数
+ orderCreateUserCount: number; // 下单用户数
+ orderPayUserCount: number; // 支付用户数
+ orderPayPrice: number; // 支付金额
}
/** 会员性别统计 Response */
export interface SexStatistics {
- sex: number;
- userCount: number;
+ sex: number; // 性别
+ userCount: number; // 用户数
}
/** 会员统计 Response */
export interface Summary {
- userCount: number;
- rechargeUserCount: number;
- rechargePrice: number;
- expensePrice: number;
+ userCount: number; // 用户数
+ rechargeUserCount: number; // 充值用户数
+ rechargePrice: number; // 充值金额
+ expensePrice: number; // 消费金额
}
/** 会员终端统计 Response */
export interface TerminalStatistics {
- terminal: number;
- userCount: number;
+ terminal: number; // 终端
+ userCount: number; // 用户数
}
/** 会员数量统计 Response */
- export interface Count {
- /** 用户访问量 */
- visitUserCount: string;
- /** 注册用户数量 */
- registerUserCount: number;
+ export interface MemberCountRespVO {
+ visitUserCount: string; // 用户访问量
+ registerUserCount: number; // 注册用户数量
}
/** 会员注册数量 Response */
export interface RegisterCount {
- date: string;
- count: number;
+ date: string; // 日期
+ count: number; // 数量
}
}
@@ -79,14 +79,16 @@ export function getMemberSummary() {
}
/** 查询会员分析数据 */
-export function getMemberAnalyse(params: MallMemberStatisticsApi.AnalyseReq) {
+export function getMemberAnalyse(
+ params: MallMemberStatisticsApi.MemberAnalyseReqVO,
+) {
return requestClient.get(
'/statistics/member/analyse',
{
params: {
times: [
- formatDate2(params.times[0] || new Date()),
- formatDate2(params.times[1] || new Date()),
+ formatDateTime(params.times[0]),
+ formatDateTime(params.times[1]),
],
},
},
@@ -117,7 +119,7 @@ export function getMemberTerminalStatisticsList() {
/** 获得用户数量量对照 */
export function getUserCountComparison() {
return requestClient.get<
- MallDataComparisonResp
+ DataComparisonRespVO
>('/statistics/member/user-count-comparison');
}
@@ -127,7 +129,7 @@ export function getMemberRegisterCountList(beginTime: Date, endTime: Date) {
'/statistics/member/register-count-list',
{
params: {
- times: [formatDate2(beginTime), formatDate2(endTime)],
+ times: [formatDateTime(beginTime), formatDateTime(endTime)],
},
},
);
diff --git a/apps/web-ele/src/api/mall/statistics/product.ts b/apps/web-ele/src/api/mall/statistics/product.ts
index 089da4af7..834ae27d1 100644
--- a/apps/web-ele/src/api/mall/statistics/product.ts
+++ b/apps/web-ele/src/api/mall/statistics/product.ts
@@ -1,8 +1,6 @@
import type { PageParam, PageResult } from '@vben/request';
-import type { MallDataComparisonResp } from './common';
-
-import { formatDate2 } from '@vben/utils';
+import type { DataComparisonRespVO } from './common';
import { requestClient } from '#/api/request';
@@ -40,58 +38,26 @@ export namespace MallProductStatisticsApi {
/** 浏览转化率 */
browseConvertPercent: number;
}
-
- /** 会员分析 Request */
- export interface ProductStatisticsReq {
- times: Date[];
- }
}
/** 获得商品统计分析 */
-export function getProductStatisticsAnalyse(
- params: MallProductStatisticsApi.ProductStatisticsReq,
-) {
+export function getProductStatisticsAnalyse(params: PageParam) {
return requestClient.get<
- MallDataComparisonResp
- >('/statistics/product/analyse', {
- params: {
- times: [
- formatDate2(params.times[0] || new Date()),
- formatDate2(params.times[1] || new Date()),
- ],
- },
- });
+ DataComparisonRespVO
+ >('/statistics/product/analyse', { params });
}
/** 获得商品状况明细 */
-export function getProductStatisticsList(
- params: MallProductStatisticsApi.ProductStatisticsReq,
-) {
+export function getProductStatisticsList(params: PageParam) {
return requestClient.get(
'/statistics/product/list',
- {
- params: {
- times: [
- formatDate2(params.times[0] || new Date()),
- formatDate2(params.times[1] || new Date()),
- ],
- },
- },
+ { params },
);
}
/** 导出获得商品状况明细 Excel */
-export function exportProductStatisticsExcel(
- params: MallProductStatisticsApi.ProductStatisticsReq,
-) {
- return requestClient.download('/statistics/product/export-excel', {
- params: {
- times: [
- formatDate2(params.times[0] || new Date()),
- formatDate2(params.times[1] || new Date()),
- ],
- },
- });
+export function exportProductStatisticsExcel(params: PageParam) {
+ return requestClient.download('/statistics/product/export-excel', { params });
}
/** 获得商品排行榜分页 */
diff --git a/apps/web-ele/src/api/mall/statistics/trade.ts b/apps/web-ele/src/api/mall/statistics/trade.ts
index 0b52be510..3f8d1cb82 100644
--- a/apps/web-ele/src/api/mall/statistics/trade.ts
+++ b/apps/web-ele/src/api/mall/statistics/trade.ts
@@ -1,6 +1,6 @@
-import type { MallDataComparisonResp } from './common';
+import type { DataComparisonRespVO } from './common';
-import { formatDate2 } from '@vben/utils';
+import { formatDate, formatDateTime } from '@vben/utils';
import { requestClient } from '#/api/request';
@@ -15,7 +15,7 @@ export namespace MallTradeStatisticsApi {
/** 交易状况 Request */
export interface TradeTrendReq {
- times: Date[];
+ times: [Date, Date];
}
/** 交易状况统计 Response */
@@ -43,7 +43,7 @@ export namespace MallTradeStatisticsApi {
}
/** 交易订单统计 Response */
- export interface TradeOrderSummary {
+ export interface TradeOrderSummaryRespVO {
/** 支付订单商品数 */
orderPayCount?: number;
/** 总支付金额,单位:分 */
@@ -64,17 +64,14 @@ export namespace MallTradeStatisticsApi {
/** 时间参数需要格式化, 确保接口能识别 */
const formatDateParam = (params: MallTradeStatisticsApi.TradeTrendReq) => {
return {
- times: [
- formatDate2(params.times[0] || new Date()),
- formatDate2(params.times[1] || new Date()),
- ],
- };
+ times: [formatDate(params.times[0]), formatDate(params.times[1])],
+ } as MallTradeStatisticsApi.TradeTrendReq;
};
/** 查询交易统计 */
export function getTradeStatisticsSummary() {
return requestClient.get<
- MallDataComparisonResp
+ DataComparisonRespVO
>('/statistics/trade/summary');
}
@@ -83,7 +80,7 @@ export function getTradeStatisticsAnalyse(
params: MallTradeStatisticsApi.TradeTrendReq,
) {
return requestClient.get<
- MallDataComparisonResp
+ DataComparisonRespVO
>('/statistics/trade/analyse', { params: formatDateParam(params) });
}
@@ -116,7 +113,7 @@ export function getOrderCount() {
/** 获得交易订单数量对照 */
export function getOrderComparison() {
return requestClient.get<
- MallDataComparisonResp
+ DataComparisonRespVO
>('/statistics/trade/order-comparison');
}
@@ -127,12 +124,12 @@ export function getOrderCountTrendComparison(
endTime: Date,
) {
return requestClient.get<
- MallDataComparisonResp[]
+ DataComparisonRespVO[]
>('/statistics/trade/order-count-trend', {
params: {
type,
- beginTime: formatDate2(beginTime),
- endTime: formatDate2(endTime),
+ beginTime: formatDateTime(beginTime),
+ endTime: formatDateTime(endTime),
},
});
}
diff --git a/apps/web-ele/src/components/shortcut-date-range-picker/index.ts b/apps/web-ele/src/components/shortcut-date-range-picker/index.ts
new file mode 100644
index 000000000..a3ee51539
--- /dev/null
+++ b/apps/web-ele/src/components/shortcut-date-range-picker/index.ts
@@ -0,0 +1 @@
+export { default as ShortcutDateRangePicker } from './shortcut-date-range-picker.vue';
diff --git a/apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue b/apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
new file mode 100644
index 000000000..9cf485483
--- /dev/null
+++ b/apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+ {{ option.label }}
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
index 340510bec..1ac8b2cc3 100644
--- a/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
@@ -1,38 +1,30 @@
@@ -65,18 +50,7 @@ onMounted(() => {
会员概览
-
+
From fe62992d785b21253557a63867e08ab5a7c389f5 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 18:40:27 +0800
Subject: [PATCH 014/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BC=9A=E5=91=98=E7=BB=9F=E8=AE=A1=E3=80=90?=
=?UTF-8?q?antd=E3=80=9110%=20=E5=88=9D=E5=A7=8B=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../views/mall/statistics/member/index.vue | 134 ++++++++++++++----
.../statistics/member/modules/area-card.vue | 118 +++++++++++++++
.../member/modules/area-chart-options.ts | 61 ++++++++
.../statistics/member/modules/sex-card.vue | 63 ++++++++
.../member/modules/sex-chart-options.ts | 35 +++++
5 files changed, 386 insertions(+), 25 deletions(-)
create mode 100644 apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
create mode 100644 apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
create mode 100644 apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
create mode 100644 apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts
diff --git a/apps/web-antd/src/views/mall/statistics/member/index.vue b/apps/web-antd/src/views/mall/statistics/member/index.vue
index 3e6a57c00..f25ff3a7f 100644
--- a/apps/web-antd/src/views/mall/statistics/member/index.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/index.vue
@@ -1,32 +1,116 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
new file mode 100644
index 000000000..516e1a149
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts b/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
new file mode 100644
index 000000000..551b18a1d
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
@@ -0,0 +1,61 @@
+import type { EChartsOption } from 'echarts';
+import type { MallMemberStatisticsApi } from '#/api/mall/statistics/member';
+
+import { fenToYuan } from '@vben/utils';
+
+// 地图数据由 @vben/plugins/echarts 自动处理
+
+/** 会员地域分布图表配置 */
+export function getAreaChartOptions(data: MallMemberStatisticsApi.AreaStatistics[]): EChartsOption {
+ let min = 0;
+ let max = 0;
+
+ const mapData = data.map((item) => {
+ min = Math.min(min, item.orderPayUserCount || 0);
+ max = Math.max(max, item.orderPayUserCount || 0);
+ return {
+ ...item,
+ name: item.areaName,
+ value: item.orderPayUserCount || 0,
+ };
+ });
+
+ return {
+ tooltip: {
+ trigger: 'item',
+ formatter: (params: any) => {
+ const data = params?.data;
+ if (!data) return params?.name || '';
+
+ return `${data.areaName || params.name}
+会员数量:${data.userCount || 0}
+订单创建数量:${data.orderCreateUserCount || 0}
+订单支付数量:${data.orderPayUserCount || 0}
+订单支付金额:¥${Number(fenToYuan(data.orderPayPrice || 0)).toFixed(2)}`;
+ },
+ },
+ visualMap: {
+ text: ['高', '低'],
+ realtime: false,
+ calculable: true,
+ top: 'middle',
+ min,
+ max,
+ inRange: {
+ color: ['#fff', '#3b82f6'],
+ },
+ },
+ series: [
+ {
+ name: '会员地域分布',
+ type: 'map',
+ map: 'china',
+ roam: false,
+ selectedMode: false,
+ data: mapData,
+ },
+ ],
+ };
+}
+
+// 地图数据已在 @vben/plugins/echarts 中自动注册
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
new file mode 100644
index 000000000..fad832e1c
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts b/apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts
new file mode 100644
index 000000000..685d21a73
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts
@@ -0,0 +1,35 @@
+import type { EChartsOption } from 'echarts';
+
+interface ChartData {
+ name: string;
+ value: number;
+}
+
+/** 会员性别比例图表配置 */
+export function getSexChartOptions(data: ChartData[]): EChartsOption {
+ return {
+ tooltip: {
+ trigger: 'item',
+ confine: true,
+ formatter: '{a}
{b} : {c} ({d}%)',
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'right',
+ },
+ series: [
+ {
+ name: '会员性别',
+ type: 'pie',
+ roseType: 'area',
+ label: {
+ show: false,
+ },
+ labelLine: {
+ show: false,
+ },
+ data,
+ },
+ ],
+ };
+}
From 01aef369d75d567dba1b67bc1815fb95055cef01 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 18:47:48 +0800
Subject: [PATCH 015/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BC=9A=E5=91=98=E7=BB=9F=E8=AE=A1=E3=80=90?=
=?UTF-8?q?antd=E3=80=9120%=20sex-card.vue=20=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../statistics/member/modules/sex-card.vue | 27 +++++++++----------
.../member/modules/sex-chart-options.ts | 9 +------
2 files changed, 13 insertions(+), 23 deletions(-)
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
index fad832e1c..5880817e9 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
@@ -1,21 +1,17 @@
-
-
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts b/apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts
index 685d21a73..81a7faf87 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/sex-chart-options.ts
@@ -1,12 +1,5 @@
-import type { EChartsOption } from 'echarts';
-
-interface ChartData {
- name: string;
- value: number;
-}
-
/** 会员性别比例图表配置 */
-export function getSexChartOptions(data: ChartData[]): EChartsOption {
+export function getSexChartOptions(data: any[]): any {
return {
tooltip: {
trigger: 'item',
From f6053bd6ca1b6245e9b9a9423b9c82be6fe53af4 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 19:05:41 +0800
Subject: [PATCH 016/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BC=9A=E5=91=98=E7=BB=9F=E8=AE=A1=E3=80=90?=
=?UTF-8?q?antd=E3=80=9130%=20summary-card.vue=20=E4=BC=98=E5=8C=96?=
=?UTF-8?q?=E7=95=8C=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../components/summary-card/summary-card.vue | 81 ++++++++++---------
.../views/mall/statistics/member/index.vue | 8 +-
2 files changed, 45 insertions(+), 44 deletions(-)
diff --git a/apps/web-antd/src/components/summary-card/summary-card.vue b/apps/web-antd/src/components/summary-card/summary-card.vue
index b2fdd3510..c88d33199 100644
--- a/apps/web-antd/src/components/summary-card/summary-card.vue
+++ b/apps/web-antd/src/components/summary-card/summary-card.vue
@@ -4,7 +4,7 @@ import type { SummaryCardProps } from './typing';
import { CountTo } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
-import { Tooltip } from 'ant-design-vue';
+import { Card, Tooltip } from 'ant-design-vue';
/** 统计卡片 */
defineOptions({ name: 'SummaryCard' });
@@ -12,46 +12,49 @@ defineOptions({ name: 'SummaryCard' });
defineProps();
-
-
-
-
-
-
-
{{ title }}
-
-
-
+
+
+
+
-
-
-
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+ {{ Math.abs(Number(percent)) }}%
+
+
-
- {{ Math.abs(Number(percent)) }}%
-
-
-
+
diff --git a/apps/web-antd/src/views/mall/statistics/member/index.vue b/apps/web-antd/src/views/mall/statistics/member/index.vue
index f25ff3a7f..5d0aef9b2 100644
--- a/apps/web-antd/src/views/mall/statistics/member/index.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/index.vue
@@ -8,13 +8,13 @@ import { fenToYuan } from '@vben/utils';
import { Col, Row } from 'ant-design-vue';
-import { SummaryCard } from '#/components/summary-card';
import * as MemberStatisticsApi from '#/api/mall/statistics/member';
+import { SummaryCard } from '#/components/summary-card';
-import MemberFunnelCard from './modules/funnel-card.vue';
-import MemberTerminalCard from './modules/terminal-card.vue';
import MemberAreaCard from './modules/area-card.vue';
+import MemberFunnelCard from './modules/funnel-card.vue';
import MemberSexCard from './modules/sex-card.vue';
+import MemberTerminalCard from './modules/terminal-card.vue';
/** 会员统计 */
defineOptions({ name: 'MemberStatistics' });
@@ -91,7 +91,6 @@ onMounted(async () => {
/>
-
@@ -101,7 +100,6 @@ onMounted(async () => {
-
From 05bc69541b47e77088a7fa8511feda03d033ad2d Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 19:10:09 +0800
Subject: [PATCH 017/156] =?UTF-8?q?feat=EF=BC=9Asummary-card=20=E9=87=8D?=
=?UTF-8?q?=E6=9E=84=E5=88=B0=20common-ui=20=E9=87=8C=EF=BC=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/components/summary-card/index.ts | 2 -
.../components/summary-card/summary-card.vue | 60 --------------
.../src/components/summary-card/typing.ts | 11 ---
.../views/mall/statistics/member/index.vue | 3 +-
.../effects/common-ui/src/components/index.ts | 1 +
.../src/components/summary-card/index.ts | 3 +
.../components/summary-card/summary-card.vue | 79 +++++++++++++++++++
.../src/components/summary-card/types.ts | 22 ++++++
8 files changed, 106 insertions(+), 75 deletions(-)
delete mode 100644 apps/web-antd/src/components/summary-card/index.ts
delete mode 100644 apps/web-antd/src/components/summary-card/summary-card.vue
delete mode 100644 apps/web-antd/src/components/summary-card/typing.ts
create mode 100644 packages/effects/common-ui/src/components/summary-card/index.ts
create mode 100644 packages/effects/common-ui/src/components/summary-card/summary-card.vue
create mode 100644 packages/effects/common-ui/src/components/summary-card/types.ts
diff --git a/apps/web-antd/src/components/summary-card/index.ts b/apps/web-antd/src/components/summary-card/index.ts
deleted file mode 100644
index 598d73d61..000000000
--- a/apps/web-antd/src/components/summary-card/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { default as SummaryCard } from './summary-card.vue';
-export type { SummaryCardProps } from './typing';
diff --git a/apps/web-antd/src/components/summary-card/summary-card.vue b/apps/web-antd/src/components/summary-card/summary-card.vue
deleted file mode 100644
index c88d33199..000000000
--- a/apps/web-antd/src/components/summary-card/summary-card.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
-
-
-
- {{ title }}
-
-
-
-
-
-
-
-
-
- {{ Math.abs(Number(percent)) }}%
-
-
-
-
-
-
-
diff --git a/apps/web-antd/src/components/summary-card/typing.ts b/apps/web-antd/src/components/summary-card/typing.ts
deleted file mode 100644
index 0ef1fdc6f..000000000
--- a/apps/web-antd/src/components/summary-card/typing.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export interface SummaryCardProps {
- title: string;
- tooltip?: string;
- icon?: string;
- iconColor?: string;
- iconBgColor?: string;
- prefix?: string;
- value?: number;
- decimals?: number;
- percent?: number | string;
-}
diff --git a/apps/web-antd/src/views/mall/statistics/member/index.vue b/apps/web-antd/src/views/mall/statistics/member/index.vue
index 5d0aef9b2..da8c8b243 100644
--- a/apps/web-antd/src/views/mall/statistics/member/index.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/index.vue
@@ -3,13 +3,12 @@ import type { MallMemberStatisticsApi } from '#/api/mall/statistics/member';
import { onMounted, ref } from 'vue';
-import { DocAlert, Page } from '@vben/common-ui';
+import { DocAlert, Page, SummaryCard } from '@vben/common-ui';
import { fenToYuan } from '@vben/utils';
import { Col, Row } from 'ant-design-vue';
import * as MemberStatisticsApi from '#/api/mall/statistics/member';
-import { SummaryCard } from '#/components/summary-card';
import MemberAreaCard from './modules/area-card.vue';
import MemberFunnelCard from './modules/funnel-card.vue';
diff --git a/packages/effects/common-ui/src/components/index.ts b/packages/effects/common-ui/src/components/index.ts
index bd12f89f7..efba68250 100644
--- a/packages/effects/common-ui/src/components/index.ts
+++ b/packages/effects/common-ui/src/components/index.ts
@@ -4,6 +4,7 @@ export * from './col-page';
export * from './content-wrap';
export * from './count-to';
export * from './doc-alert';
+export * from './summary-card';
export * from './ellipsis-text';
export * from './icon-picker';
export * from './iframe';
diff --git a/packages/effects/common-ui/src/components/summary-card/index.ts b/packages/effects/common-ui/src/components/summary-card/index.ts
new file mode 100644
index 000000000..fca98f38c
--- /dev/null
+++ b/packages/effects/common-ui/src/components/summary-card/index.ts
@@ -0,0 +1,3 @@
+// add by 芋艿:总结卡片,目前 mall 模块在使用
+export { default as SummaryCard } from './summary-card.vue';
+export * from './types';
diff --git a/packages/effects/common-ui/src/components/summary-card/summary-card.vue b/packages/effects/common-ui/src/components/summary-card/summary-card.vue
new file mode 100644
index 000000000..97cc64b0d
--- /dev/null
+++ b/packages/effects/common-ui/src/components/summary-card/summary-card.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
{{ title }}
+
+
+
+
+
+
+ {{ tooltip }}
+
+
+
+
+
+
+
+
+
+ {{ Math.abs(Number(percent)) }}%
+
+
+
+
+
+
+
diff --git a/packages/effects/common-ui/src/components/summary-card/types.ts b/packages/effects/common-ui/src/components/summary-card/types.ts
new file mode 100644
index 000000000..b05b70889
--- /dev/null
+++ b/packages/effects/common-ui/src/components/summary-card/types.ts
@@ -0,0 +1,22 @@
+import type { Component } from 'vue';
+
+export interface SummaryCardProps {
+ /** 标题 */
+ title: string;
+ /** 提示信息 */
+ tooltip?: string;
+ /** 图标 */
+ icon?: Component | string;
+ /** 图标颜色 */
+ iconColor?: string;
+ /** 图标背景色 */
+ iconBgColor?: string;
+ /** 前缀 */
+ prefix?: string;
+ /** 数值 */
+ value?: number;
+ /** 小数位数 */
+ decimals?: number;
+ /** 百分比 */
+ percent?: number | string;
+}
From f84a2964161cb5d253aa81ccc1a1198af12f8060 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 19:22:03 +0800
Subject: [PATCH 018/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BC=9A=E5=91=98=E7=BB=9F=E8=AE=A1=E3=80=90?=
=?UTF-8?q?antd=E3=80=9140%=20area-card.vue=20=E4=BF=AE=E5=A4=8D=E7=95=8C?=
=?UTF-8?q?=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../statistics/member/modules/area-card.vue | 98 +++++++++++--------
.../member/modules/area-chart-options.ts | 73 ++++++++++----
2 files changed, 109 insertions(+), 62 deletions(-)
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
index 516e1a149..81af46123 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
@@ -1,5 +1,6 @@
-
-
-
+
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts b/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
index 551b18a1d..a82cc2200 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
@@ -1,37 +1,59 @@
-import type { EChartsOption } from 'echarts';
import type { MallMemberStatisticsApi } from '#/api/mall/statistics/member';
import { fenToYuan } from '@vben/utils';
-// 地图数据由 @vben/plugins/echarts 自动处理
-
/** 会员地域分布图表配置 */
-export function getAreaChartOptions(data: MallMemberStatisticsApi.AreaStatistics[]): EChartsOption {
- let min = 0;
- let max = 0;
-
+export function getAreaChartOptions(
+ data: MallMemberStatisticsApi.AreaStatistics[],
+) {
+ if (!data || data.length === 0) {
+ return {
+ title: {
+ text: '暂无数据',
+ left: 'center',
+ top: 'center',
+ textStyle: {
+ color: '#999',
+ fontSize: 14,
+ },
+ },
+ };
+ }
+
+ let min = Number.POSITIVE_INFINITY;
+ let max = Number.NEGATIVE_INFINITY;
+
const mapData = data.map((item) => {
- min = Math.min(min, item.orderPayUserCount || 0);
- max = Math.max(max, item.orderPayUserCount || 0);
+ const payUserCount = item.orderPayUserCount || 0;
+ min = Math.min(min, payUserCount);
+ max = Math.max(max, payUserCount);
return {
...item,
name: item.areaName,
- value: item.orderPayUserCount || 0,
+ value: payUserCount,
};
});
+ // 如果所有值都为0,设置合理的最小最大值
+ if (min === max && min === 0) {
+ min = 0;
+ max = 10;
+ }
+
return {
tooltip: {
trigger: 'item',
formatter: (params: any) => {
- const data = params?.data;
- if (!data) return params?.name || '';
-
- return `${data.areaName || params.name}
-会员数量:${data.userCount || 0}
-订单创建数量:${data.orderCreateUserCount || 0}
-订单支付数量:${data.orderPayUserCount || 0}
-订单支付金额:¥${Number(fenToYuan(data.orderPayPrice || 0)).toFixed(2)}`;
+ const itemData = params?.data;
+ if (!itemData) {
+ return `${params?.name || ''}
暂无数据`;
+ }
+
+ return `${itemData.areaName || params.name}
+会员数量:${itemData.userCount || 0}
+订单创建数量:${itemData.orderCreateUserCount || 0}
+订单支付数量:${itemData.orderPayUserCount || 0}
+订单支付金额:¥${Number(fenToYuan(itemData.orderPayPrice || 0)).toFixed(2)}`;
},
},
visualMap: {
@@ -39,10 +61,11 @@ export function getAreaChartOptions(data: MallMemberStatisticsApi.AreaStatistics
realtime: false,
calculable: true,
top: 'middle',
+ left: 10,
min,
max,
inRange: {
- color: ['#fff', '#3b82f6'],
+ color: ['#e6f3ff', '#1890ff', '#0050b3'],
},
},
series: [
@@ -52,10 +75,18 @@ export function getAreaChartOptions(data: MallMemberStatisticsApi.AreaStatistics
map: 'china',
roam: false,
selectedMode: false,
+ itemStyle: {
+ borderColor: '#389e0d',
+ borderWidth: 0.5,
+ },
+ emphasis: {
+ itemStyle: {
+ areaColor: '#ffec3d',
+ borderWidth: 1,
+ },
+ },
data: mapData,
},
],
};
}
-
-// 地图数据已在 @vben/plugins/echarts 中自动注册
From b2b43f2d19dc7fb8199205a615c9b58135bad0ee Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 19:29:45 +0800
Subject: [PATCH 019/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BC=9A=E5=91=98=E7=BB=9F=E8=AE=A1=E3=80=90?=
=?UTF-8?q?antd=E3=80=9145%=20area-card.vue=20=E4=BC=98=E5=8C=96=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81=E9=A3=8E=E6=A0=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../views/mall/statistics/member/modules/area-card.vue | 7 +------
.../mall/statistics/member/modules/area-chart-options.ts | 9 ++++-----
.../views/mall/statistics/member/modules/sex-card.vue | 1 +
.../mall/statistics/member/modules/terminal-card.vue | 1 +
apps/web-ele/src/views/mall/statistics/member/index.vue | 6 +++---
5 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
index 81af46123..4478d47f1 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
@@ -86,20 +86,15 @@ async function getMemberAreaStatisticsList() {
loading.value = true;
try {
const list = await MemberStatisticsApi.getMemberAreaStatisticsList();
-
areaStatisticsList.value = list.map(
(item: MallMemberStatisticsApi.AreaStatistics) => ({
...item,
areaName: areaReplace(item.areaName),
}),
);
-
// 渲染图表
const chartOptions = getAreaChartOptions(areaStatisticsList.value);
-
await renderEcharts(chartOptions);
- } catch (error) {
- console.error('地域分布数据获取失败:', error);
} finally {
loading.value = false;
}
@@ -116,7 +111,7 @@ onMounted(() => {
-
+
{
const payUserCount = item.orderPayUserCount || 0;
min = Math.min(min, payUserCount);
@@ -33,13 +33,13 @@ export function getAreaChartOptions(
value: payUserCount,
};
});
-
- // 如果所有值都为0,设置合理的最小最大值
+ // 如果所有值都为 0,设置合理的 min 和 max 值
if (min === max && min === 0) {
min = 0;
max = 10;
}
+ // 返回图表配置
return {
tooltip: {
trigger: 'item',
@@ -48,7 +48,6 @@ export function getAreaChartOptions(
if (!itemData) {
return `${params?.name || ''}
暂无数据`;
}
-
return `${itemData.areaName || params.name}
会员数量:${itemData.userCount || 0}
订单创建数量:${itemData.orderCreateUserCount || 0}
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
index 5880817e9..151280744 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
@@ -39,6 +39,7 @@ async function getMemberSexStatisticsList() {
value: userCount || 0,
};
});
+ // 更新 Echarts 数据
await renderEcharts(getSexChartOptions(chartData));
} finally {
loading.value = false;
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/terminal-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/terminal-card.vue
index b2c8c2b8a..fc5075504 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/terminal-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/terminal-card.vue
@@ -34,6 +34,7 @@ const getMemberTerminalStatisticsList = async () => {
value: userCount || 0,
};
});
+ // 更新 Echarts 数据
await renderEcharts(getTerminalChartOptions(chartData));
} finally {
loading.value = false;
diff --git a/apps/web-ele/src/views/mall/statistics/member/index.vue b/apps/web-ele/src/views/mall/statistics/member/index.vue
index c98ec1b2e..381165e02 100644
--- a/apps/web-ele/src/views/mall/statistics/member/index.vue
+++ b/apps/web-ele/src/views/mall/statistics/member/index.vue
@@ -8,9 +8,9 @@ import { DocAlert, Page } from '@vben/common-ui';
import { fenToYuan } from '@vben/utils';
import * as MemberStatisticsApi from '#/api/mall/statistics/member'; // 会员统计数据
-import AnalysisOverviewIcon from '#/views/mall/home/components/analysis-overview-icon.vue';
-import MemberFunnelCard from '#/views/mall/home/components/member-funnel-card.vue';
-import MemberTerminalCard from '#/views/mall/home/components/member-terminal-card.vue';
+// import AnalysisOverviewIcon from '#/views/mall/home/components/analysis-overview-icon.vue';
+// import MemberFunnelCard from '#/views/mall/home/components/member-funnel-card.vue';
+// import MemberTerminalCard from '#/views/mall/home/components/member-terminal-card.vue';
import MemberRegionCard from './components/member-region-card.vue';
import MemberSexCard from './components/member-sex-card.vue';
From 936806bd2d9cee3d6eb724d8682b7b9cc380aacc Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 19:42:07 +0800
Subject: [PATCH 020/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BC=9A=E5=91=98=E7=BB=9F=E8=AE=A1=E3=80=90?=
=?UTF-8?q?antd=E3=80=9150%=20=E5=85=A8=E9=83=A8=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../statistics/member/modules/area-card.vue | 103 +++++++-----------
.../member/modules/area-chart-options.ts | 39 +++++++
2 files changed, 76 insertions(+), 66 deletions(-)
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
index 4478d47f1..9f2440ff4 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/area-card.vue
@@ -6,13 +6,13 @@ import type { MallMemberStatisticsApi } from '#/api/mall/statistics/member';
import { onMounted, ref, shallowRef } from 'vue';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
-import { fenToYuan } from '@vben/utils';
-import { Card, Spin, Table } from 'ant-design-vue';
+import { Card, Spin } from 'ant-design-vue';
+import { useVbenVxeGrid } from '#/adapter/vxe-table';
import * as MemberStatisticsApi from '#/api/mall/statistics/member';
-import { getAreaChartOptions } from './area-chart-options';
+import { getAreaChartOptions, getAreaTableColumns } from './area-chart-options';
/** 会员地域分布卡片 */
defineOptions({ name: 'MemberAreaCard' });
@@ -24,62 +24,24 @@ const areaStatisticsList = shallowRef(
const chartRef = ref();
const { renderEcharts } = useEcharts(chartRef);
-/** 城市名兼容:ercharts 地名存在差异 */
-function areaReplace(areaName: string) {
- if (!areaName) {
- return areaName;
- }
- return areaName
- .replace('维吾尔自治区', '')
- .replace('壮族自治区', '')
- .replace('回族自治区', '')
- .replace('自治区', '')
- .replace('省', '');
-}
-
-/** 表格列配置 */
-const columns = [
- {
- title: '省份',
- dataIndex: 'areaName',
- key: 'areaName',
- width: 80,
- sorter: true,
- ellipsis: true,
+const [Grid, gridApi] = useVbenVxeGrid({
+ gridOptions: {
+ columns: getAreaTableColumns(),
+ height: 300,
+ border: true,
+ showOverflow: true,
+ rowConfig: {
+ keyField: 'id',
+ isHover: true,
+ },
+ pagerConfig: {
+ enabled: false,
+ },
+ toolbarConfig: {
+ enabled: false,
+ },
},
- {
- title: '会员数量',
- dataIndex: 'userCount',
- key: 'userCount',
- width: 100,
- sorter: (a: any, b: any) => (a.userCount || 0) - (b.userCount || 0),
- },
- {
- title: '订单创建数量',
- dataIndex: 'orderCreateUserCount',
- key: 'orderCreateUserCount',
- width: 120,
- sorter: (a: any, b: any) =>
- (a.orderCreateUserCount || 0) - (b.orderCreateUserCount || 0),
- },
- {
- title: '订单支付数量',
- dataIndex: 'orderPayUserCount',
- key: 'orderPayUserCount',
- width: 120,
- sorter: (a: any, b: any) =>
- (a.orderPayUserCount || 0) - (b.orderPayUserCount || 0),
- },
- {
- title: '订单支付金额',
- dataIndex: 'orderPayPrice',
- key: 'orderPayPrice',
- width: 120,
- sorter: (a: any, b: any) => (a.orderPayPrice || 0) - (b.orderPayPrice || 0),
- customRender: ({ record }: any) =>
- `¥${Number(fenToYuan(record.orderPayPrice || 0)).toFixed(2)}`,
- },
-];
+});
/** 按照省份,查询会员统计列表 */
async function getMemberAreaStatisticsList() {
@@ -95,11 +57,27 @@ async function getMemberAreaStatisticsList() {
// 渲染图表
const chartOptions = getAreaChartOptions(areaStatisticsList.value);
await renderEcharts(chartOptions);
+
+ // 加载表格数据
+ await gridApi.grid.loadData(areaStatisticsList.value);
} finally {
loading.value = false;
}
}
+/** 城市名兼容:ECharts 地名存在差异 */
+function areaReplace(areaName: string): string {
+ if (!areaName) {
+ return areaName;
+ }
+ return areaName
+ .replace('维吾尔自治区', '')
+ .replace('壮族自治区', '')
+ .replace('回族自治区', '')
+ .replace('自治区', '')
+ .replace('省', '');
+}
+
/** 初始化 */
onMounted(() => {
getMemberAreaStatisticsList();
@@ -114,14 +92,7 @@ onMounted(() => {
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts b/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
index 65e9dfc62..b2d0c6a66 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/area-chart-options.ts
@@ -1,3 +1,4 @@
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MallMemberStatisticsApi } from '#/api/mall/statistics/member';
import { fenToYuan } from '@vben/utils';
@@ -89,3 +90,41 @@ export function getAreaChartOptions(
],
};
}
+
+/** VXE Grid 表格列配置 */
+export function getAreaTableColumns(): VxeTableGridOptions['columns'] {
+ return [
+ {
+ field: 'areaName',
+ title: '省份',
+ minWidth: 80,
+ sortable: true,
+ showOverflow: 'tooltip',
+ },
+ {
+ field: 'userCount',
+ title: '会员数量',
+ minWidth: 100,
+ sortable: true,
+ },
+ {
+ field: 'orderCreateUserCount',
+ title: '订单创建数量',
+ minWidth: 120,
+ sortable: true,
+ },
+ {
+ field: 'orderPayUserCount',
+ title: '订单支付数量',
+ minWidth: 120,
+ sortable: true,
+ },
+ {
+ field: 'orderPayPrice',
+ title: '订单支付金额',
+ minWidth: 120,
+ sortable: true,
+ formatter: 'formatFenToYuanAmount',
+ },
+ ];
+}
From 6c7af029a2e406d3df97933d01dc68faec5fe9c5 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 20:29:18 +0800
Subject: [PATCH 021/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BC=9A=E5=91=98=E7=BB=9F=E8=AE=A1=E3=80=90?=
=?UTF-8?q?ele=E3=80=91100%=20=E5=85=A8=E9=83=A8=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../member/components/member-region-card.vue | 132 ---------------
.../member/components/member-sex-card.vue | 73 --------
.../views/mall/statistics/member/index.vue | 158 +++++++++++-------
.../statistics/member/modules/area-card.vue | 101 +++++++++++
.../member/modules/area-chart-options.ts | 130 ++++++++++++++
.../statistics/member/modules/funnel-card.vue | 4 +-
.../statistics/member/modules/sex-card.vue | 64 +++++++
.../member/modules/sex-chart-options.ts | 28 ++++
.../member/modules/terminal-card.vue | 5 +-
9 files changed, 421 insertions(+), 274 deletions(-)
delete mode 100644 apps/web-ele/src/views/mall/statistics/member/components/member-region-card.vue
delete mode 100644 apps/web-ele/src/views/mall/statistics/member/components/member-sex-card.vue
create mode 100644 apps/web-ele/src/views/mall/statistics/member/modules/area-card.vue
create mode 100644 apps/web-ele/src/views/mall/statistics/member/modules/area-chart-options.ts
create mode 100644 apps/web-ele/src/views/mall/statistics/member/modules/sex-card.vue
create mode 100644 apps/web-ele/src/views/mall/statistics/member/modules/sex-chart-options.ts
diff --git a/apps/web-ele/src/views/mall/statistics/member/components/member-region-card.vue b/apps/web-ele/src/views/mall/statistics/member/components/member-region-card.vue
deleted file mode 100644
index 9d1549326..000000000
--- a/apps/web-ele/src/views/mall/statistics/member/components/member-region-card.vue
+++ /dev/null
@@ -1,132 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/web-ele/src/views/mall/statistics/member/components/member-sex-card.vue b/apps/web-ele/src/views/mall/statistics/member/components/member-sex-card.vue
deleted file mode 100644
index d4445fcfc..000000000
--- a/apps/web-ele/src/views/mall/statistics/member/components/member-sex-card.vue
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
diff --git a/apps/web-ele/src/views/mall/statistics/member/index.vue b/apps/web-ele/src/views/mall/statistics/member/index.vue
index 381165e02..8b99dbde2 100644
--- a/apps/web-ele/src/views/mall/statistics/member/index.vue
+++ b/apps/web-ele/src/views/mall/statistics/member/index.vue
@@ -1,85 +1,113 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/area-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/area-card.vue
new file mode 100644
index 000000000..43d41aac7
--- /dev/null
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/area-card.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+ 会员地域分布
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/area-chart-options.ts b/apps/web-ele/src/views/mall/statistics/member/modules/area-chart-options.ts
new file mode 100644
index 000000000..b2d0c6a66
--- /dev/null
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/area-chart-options.ts
@@ -0,0 +1,130 @@
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { MallMemberStatisticsApi } from '#/api/mall/statistics/member';
+
+import { fenToYuan } from '@vben/utils';
+
+/** 会员地域分布图表配置 */
+export function getAreaChartOptions(
+ data: MallMemberStatisticsApi.AreaStatistics[],
+): any {
+ if (!data || data.length === 0) {
+ return {
+ title: {
+ text: '暂无数据',
+ left: 'center',
+ top: 'center',
+ textStyle: {
+ color: '#999',
+ fontSize: 14,
+ },
+ },
+ };
+ }
+
+ // 计算 min 和 max 值
+ let min = Number.POSITIVE_INFINITY;
+ let max = Number.NEGATIVE_INFINITY;
+ const mapData = data.map((item) => {
+ const payUserCount = item.orderPayUserCount || 0;
+ min = Math.min(min, payUserCount);
+ max = Math.max(max, payUserCount);
+ return {
+ ...item,
+ name: item.areaName,
+ value: payUserCount,
+ };
+ });
+ // 如果所有值都为 0,设置合理的 min 和 max 值
+ if (min === max && min === 0) {
+ min = 0;
+ max = 10;
+ }
+
+ // 返回图表配置
+ return {
+ tooltip: {
+ trigger: 'item',
+ formatter: (params: any) => {
+ const itemData = params?.data;
+ if (!itemData) {
+ return `${params?.name || ''}
暂无数据`;
+ }
+ return `${itemData.areaName || params.name}
+会员数量:${itemData.userCount || 0}
+订单创建数量:${itemData.orderCreateUserCount || 0}
+订单支付数量:${itemData.orderPayUserCount || 0}
+订单支付金额:¥${Number(fenToYuan(itemData.orderPayPrice || 0)).toFixed(2)}`;
+ },
+ },
+ visualMap: {
+ text: ['高', '低'],
+ realtime: false,
+ calculable: true,
+ top: 'middle',
+ left: 10,
+ min,
+ max,
+ inRange: {
+ color: ['#e6f3ff', '#1890ff', '#0050b3'],
+ },
+ },
+ series: [
+ {
+ name: '会员地域分布',
+ type: 'map',
+ map: 'china',
+ roam: false,
+ selectedMode: false,
+ itemStyle: {
+ borderColor: '#389e0d',
+ borderWidth: 0.5,
+ },
+ emphasis: {
+ itemStyle: {
+ areaColor: '#ffec3d',
+ borderWidth: 1,
+ },
+ },
+ data: mapData,
+ },
+ ],
+ };
+}
+
+/** VXE Grid 表格列配置 */
+export function getAreaTableColumns(): VxeTableGridOptions['columns'] {
+ return [
+ {
+ field: 'areaName',
+ title: '省份',
+ minWidth: 80,
+ sortable: true,
+ showOverflow: 'tooltip',
+ },
+ {
+ field: 'userCount',
+ title: '会员数量',
+ minWidth: 100,
+ sortable: true,
+ },
+ {
+ field: 'orderCreateUserCount',
+ title: '订单创建数量',
+ minWidth: 120,
+ sortable: true,
+ },
+ {
+ field: 'orderPayUserCount',
+ title: '订单支付数量',
+ minWidth: 120,
+ sortable: true,
+ },
+ {
+ field: 'orderPayPrice',
+ title: '订单支付金额',
+ minWidth: 120,
+ sortable: true,
+ formatter: 'formatFenToYuanAmount',
+ },
+ ];
+}
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
index 1ac8b2cc3..e2d3252e2 100644
--- a/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/funnel-card.vue
@@ -46,14 +46,14 @@ const calculateRelativeRate = (value?: number, reference?: number) => {
-
+
会员概览
-
+
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/sex-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/sex-card.vue
new file mode 100644
index 000000000..930555812
--- /dev/null
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/sex-card.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+ 会员性别比例
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/sex-chart-options.ts b/apps/web-ele/src/views/mall/statistics/member/modules/sex-chart-options.ts
new file mode 100644
index 000000000..81a7faf87
--- /dev/null
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/sex-chart-options.ts
@@ -0,0 +1,28 @@
+/** 会员性别比例图表配置 */
+export function getSexChartOptions(data: any[]): any {
+ return {
+ tooltip: {
+ trigger: 'item',
+ confine: true,
+ formatter: '{a}
{b} : {c} ({d}%)',
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'right',
+ },
+ series: [
+ {
+ name: '会员性别',
+ type: 'pie',
+ roseType: 'area',
+ label: {
+ show: false,
+ },
+ labelLine: {
+ show: false,
+ },
+ data,
+ },
+ ],
+ };
+}
diff --git a/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue
index 4ff172296..624dcf25c 100644
--- a/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue
+++ b/apps/web-ele/src/views/mall/statistics/member/modules/terminal-card.vue
@@ -34,6 +34,7 @@ const getMemberTerminalStatisticsList = async () => {
value: userCount || 0,
};
});
+ // 更新 Echarts 数据
await renderEcharts(getTerminalChartOptions(chartData));
} finally {
loading.value = false;
@@ -47,9 +48,9 @@ onMounted(() => {
-
+
- 会员终端
+ 会员终端
From cb717a9d84187cbb99c1cfc4102057a5766c472b Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 20:57:57 +0800
Subject: [PATCH 022/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BA=A4=E6=98=93=E7=BB=9F=E8=AE=A1=E3=80=81?=
=?UTF-8?q?=E5=95=86=E5=93=81=E7=BB=9F=E8=AE=A1=E3=80=90antd=E3=80=9110%?=
=?UTF-8?q?=EF=BC=9A=E5=88=9D=E5=A7=8B=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../views/mall/statistics/product/index.vue | 43 ++-
.../product/modules/product-rank-card.vue | 231 +++++++++++++
.../product/modules/product-summary-card.vue | 296 +++++++++++++++++
.../modules/product-summary-chart-options.ts | 124 +++++++
.../src/views/mall/statistics/trade/index.vue | 137 ++++++--
.../trade/modules/trade-statistic-card.vue | 77 +++++
.../trade/modules/trade-trend-card.vue | 314 ++++++++++++++++++
.../modules/trade-trend-chart-options.ts | 111 +++++++
8 files changed, 1284 insertions(+), 49 deletions(-)
create mode 100644 apps/web-antd/src/views/mall/statistics/product/modules/product-rank-card.vue
create mode 100644 apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue
create mode 100644 apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts
create mode 100644 apps/web-antd/src/views/mall/statistics/trade/modules/trade-statistic-card.vue
create mode 100644 apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-card.vue
create mode 100644 apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-chart-options.ts
diff --git a/apps/web-antd/src/views/mall/statistics/product/index.vue b/apps/web-antd/src/views/mall/statistics/product/index.vue
index df8469a91..6e6001454 100644
--- a/apps/web-antd/src/views/mall/statistics/product/index.vue
+++ b/apps/web-antd/src/views/mall/statistics/product/index.vue
@@ -1,32 +1,27 @@
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/product/modules/product-rank-card.vue b/apps/web-antd/src/views/mall/statistics/product/modules/product-rank-card.vue
new file mode 100644
index 000000000..cfb7b667a
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/product/modules/product-rank-card.vue
@@ -0,0 +1,231 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ record.spuName }}
+
+
+
+
+ ¥{{ formatPrice(record.orderPayPrice) }}
+
+
+
+
+ {{ formatConvertRate(record.browseConvertPercent) }}
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue
new file mode 100644
index 000000000..93ccc17af
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue
@@ -0,0 +1,296 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts
new file mode 100644
index 000000000..7e64c78e6
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts
@@ -0,0 +1,124 @@
+import type { EChartsOption } from 'echarts';
+
+/** 商品统计折线图配置 */
+export function getProductSummaryChartOptions(data: any[]): EChartsOption {
+ return {
+ dataset: {
+ dimensions: [
+ 'time',
+ 'browseCount',
+ 'browseUserCount',
+ 'orderPayPrice',
+ 'afterSaleRefundPrice',
+ ],
+ source: data,
+ },
+ grid: {
+ left: 20,
+ right: 20,
+ bottom: 20,
+ top: 80,
+ containLabel: true,
+ },
+ legend: {
+ top: 50,
+ },
+ series: [
+ {
+ name: '商品浏览量',
+ type: 'line',
+ smooth: true,
+ itemStyle: { color: '#B37FEB' },
+ },
+ {
+ name: '商品访客数',
+ type: 'line',
+ smooth: true,
+ itemStyle: { color: '#FFAB2B' },
+ },
+ {
+ name: '支付金额',
+ type: 'bar',
+ smooth: true,
+ yAxisIndex: 1,
+ itemStyle: { color: '#1890FF' },
+ },
+ {
+ name: '退款金额',
+ type: 'bar',
+ smooth: true,
+ yAxisIndex: 1,
+ itemStyle: { color: '#00C050' },
+ },
+ ],
+ toolbox: {
+ feature: {
+ // 数据区域缩放
+ dataZoom: {
+ yAxisIndex: false, // Y轴不缩放
+ },
+ brush: {
+ type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
+ },
+ saveAsImage: {
+ show: true,
+ name: '商品状况',
+ }, // 保存为图片
+ },
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ },
+ padding: [5, 10],
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: true,
+ axisTick: {
+ show: false,
+ },
+ },
+ yAxis: [
+ {
+ type: 'value',
+ name: '金额',
+ axisLine: {
+ show: false,
+ },
+ axisTick: {
+ show: false,
+ },
+ axisLabel: {
+ color: '#7F8B9C',
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: '#F5F7F9',
+ },
+ },
+ },
+ {
+ type: 'value',
+ name: '数量',
+ axisLine: {
+ show: false,
+ },
+ axisTick: {
+ show: false,
+ },
+ axisLabel: {
+ color: '#7F8B9C',
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: '#F5F7F9',
+ },
+ },
+ },
+ ],
+ };
+}
diff --git a/apps/web-antd/src/views/mall/statistics/trade/index.vue b/apps/web-antd/src/views/mall/statistics/trade/index.vue
index 46ceb7e65..d2261fe71 100644
--- a/apps/web-antd/src/views/mall/statistics/trade/index.vue
+++ b/apps/web-antd/src/views/mall/statistics/trade/index.vue
@@ -1,32 +1,119 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/trade/modules/trade-statistic-card.vue b/apps/web-antd/src/views/mall/statistics/trade/modules/trade-statistic-card.vue
new file mode 100644
index 000000000..af775ac9c
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/trade/modules/trade-statistic-card.vue
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+ 环比
+
+ {{ Math.abs(percentValue).toFixed(2) }}%
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-card.vue b/apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-card.vue
new file mode 100644
index 000000000..113ceabfc
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-card.vue
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-chart-options.ts b/apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-chart-options.ts
new file mode 100644
index 000000000..a9af51446
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/trade/modules/trade-trend-chart-options.ts
@@ -0,0 +1,111 @@
+import type { EChartsOption } from 'echarts';
+
+import type { MallTradeStatisticsApi } from '#/api/mall/statistics/trade';
+
+/** 交易趋势折线图配置 */
+export function getTradeTrendChartOptions(
+ data: MallTradeStatisticsApi.TradeTrendSummary[],
+): EChartsOption {
+ return {
+ dataset: {
+ dimensions: [
+ 'time',
+ 'turnoverPrice',
+ 'orderPayPrice',
+ 'rechargePrice',
+ 'expensePrice',
+ ],
+ source: data,
+ },
+ grid: {
+ left: 20,
+ right: 20,
+ bottom: 20,
+ top: 80,
+ containLabel: true,
+ },
+ legend: {
+ top: 50,
+ },
+ series: [
+ {
+ name: '营业额',
+ type: 'line',
+ smooth: true,
+ itemStyle: { color: '#1890FF' },
+ },
+ {
+ name: '商品支付金额',
+ type: 'line',
+ smooth: true,
+ itemStyle: { color: '#722ED1' },
+ },
+ {
+ name: '充值金额',
+ type: 'line',
+ smooth: true,
+ itemStyle: { color: '#FAAD14' },
+ },
+ {
+ name: '支出金额',
+ type: 'line',
+ smooth: true,
+ itemStyle: { color: '#52C41A' },
+ },
+ ],
+ toolbox: {
+ feature: {
+ // 数据区域缩放
+ dataZoom: {
+ yAxisIndex: false, // Y轴不缩放
+ },
+ brush: {
+ type: ['lineX', 'clear'], // 区域缩放按钮、还原按钮
+ },
+ saveAsImage: {
+ show: true,
+ name: '交易状况',
+ }, // 保存为图片
+ },
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ },
+ padding: [5, 10],
+ formatter(params: any) {
+ let result = `${params[0].data.time}
`;
+ params.forEach((item: any) => {
+ result += `
+
+ ${item.seriesName}: ¥${item.data[item.dimensionNames[item.encode.y[0]]]}
+
`;
+ });
+ return result;
+ },
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ axisTick: {
+ show: false,
+ },
+ },
+ yAxis: {
+ type: 'value',
+ axisTick: {
+ show: false,
+ },
+ axisLabel: {
+ formatter: '¥{value}',
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: '#F5F7F9',
+ },
+ },
+ },
+ };
+}
From b5bc8d24b93b44962b9af258ef0ee106c8b9e247 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sun, 19 Oct 2025 22:14:49 +0800
Subject: [PATCH 023/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BA=A4=E6=98=93=E7=BB=9F=E8=AE=A1=E3=80=81?=
=?UTF-8?q?=E5=95=86=E5=93=81=E7=BB=9F=E8=AE=A1=E3=80=90antd=E3=80=9115%?=
=?UTF-8?q?=EF=BC=9Aproduct-rank-card.vue=20=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../shortcut-date-range-picker.vue | 2 +-
.../views/mall/statistics/product/index.vue | 2 +-
.../product/modules/product-rank-card.vue | 231 ------------------
.../statistics/product/modules/rank-card.vue | 135 ++++++++++
.../shortcut-date-range-picker.vue | 2 +-
packages/@core/base/shared/src/utils/index.ts | 17 +-
.../src/request-client/request-client.ts | 17 ++
7 files changed, 156 insertions(+), 250 deletions(-)
delete mode 100644 apps/web-antd/src/views/mall/statistics/product/modules/product-rank-card.vue
create mode 100644 apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue
diff --git a/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue b/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
index 95e90c6ae..f6a010187 100644
--- a/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
+++ b/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
@@ -81,7 +81,7 @@ onMounted(() => {
:value-format="rangePickerProps.valueFormat"
:placeholder="rangePickerProps.placeholder"
:presets="rangePickerProps.presets"
- class="!w-[240px]"
+ class="!w-[235px]"
@change="handleDateRangeChange"
/>
diff --git a/apps/web-antd/src/views/mall/statistics/product/index.vue b/apps/web-antd/src/views/mall/statistics/product/index.vue
index 6e6001454..f2caa8862 100644
--- a/apps/web-antd/src/views/mall/statistics/product/index.vue
+++ b/apps/web-antd/src/views/mall/statistics/product/index.vue
@@ -1,8 +1,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ record.spuName }}
-
-
-
-
- ¥{{ formatPrice(record.orderPayPrice) }}
-
-
-
-
- {{ formatConvertRate(record.browseConvertPercent) }}
-
-
-
-
-
-
-
-
diff --git a/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue b/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue
new file mode 100644
index 000000000..af7da2583
--- /dev/null
+++ b/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue b/apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
index 9cf485483..fc5028c2c 100644
--- a/apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
+++ b/apps/web-ele/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
@@ -102,7 +102,7 @@ onMounted(() => {
:start-placeholder="rangePickerProps.startPlaceholder"
:end-placeholder="rangePickerProps.endPlaceholder"
:default-time="rangePickerProps.defaultTime as any"
- class="!w-[360px]"
+ class="!w-[215px]"
@change="handleDateRangeChange"
/>
diff --git a/packages/@core/base/shared/src/utils/index.ts b/packages/@core/base/shared/src/utils/index.ts
index 65aadb015..e24456f91 100644
--- a/packages/@core/base/shared/src/utils/index.ts
+++ b/packages/@core/base/shared/src/utils/index.ts
@@ -23,19 +23,4 @@ export * from './window';
export { default as cloneDeep } from 'lodash.clonedeep';
export { default as get } from 'lodash.get';
export { default as isEqual } from 'lodash.isequal';
-export { default as set } from 'lodash.set';
-
-/**
- * 构建排序字段
- * @param prop 字段名称
- * @param order 顺序
- */
-export const buildSortingField = ({
- prop,
- order,
-}: {
- order: 'ascending' | 'descending';
- prop: string;
-}) => {
- return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' };
-};
+export { default as set } from 'lodash.set';
\ No newline at end of file
diff --git a/packages/effects/request/src/request-client/request-client.ts b/packages/effects/request/src/request-client/request-client.ts
index 0c7bcfba2..c764dda68 100644
--- a/packages/effects/request/src/request-client/request-client.ts
+++ b/packages/effects/request/src/request-client/request-client.ts
@@ -162,4 +162,21 @@ class RequestClient {
}
}
+/**
+ * 构建排序字段,处理 vxe 排序条件
+ *
+ * add by 芋艿
+ */
+export const buildSortingField = (sorts: any[]) => {
+ if (!sorts || sorts.length === 0) {
+ return {};
+ }
+ const result: Record = {};
+ sorts.forEach((sort: any, index: number) => {
+ result[`sortingFields[${index}].field`] = sort.field;
+ result[`sortingFields[${index}].order`] = sort.order;
+ });
+ return result;
+};
+
export { RequestClient };
From 3aee96095476f5d19f3599440a87b058fb1d978b Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Mon, 20 Oct 2025 09:29:00 +0800
Subject: [PATCH 024/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BA=A4=E6=98=93=E7=BB=9F=E8=AE=A1=E3=80=81?=
=?UTF-8?q?=E5=95=86=E5=93=81=E7=BB=9F=E8=AE=A1=E3=80=90antd=E3=80=9120%?=
=?UTF-8?q?=EF=BC=9Aproduct-summary-card.vue=20=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/api/mall/statistics/product.ts | 6 +-
.../shortcut-date-range-picker.vue | 4 +-
.../product/modules/product-summary-card.vue | 55 +++++++------------
.../modules/product-summary-chart-options.ts | 13 +++--
.../statistics/product/modules/rank-card.vue | 2 +-
packages/@core/base/shared/src/utils/index.ts | 2 +-
6 files changed, 37 insertions(+), 45 deletions(-)
diff --git a/apps/web-antd/src/api/mall/statistics/product.ts b/apps/web-antd/src/api/mall/statistics/product.ts
index 834ae27d1..2e83f945a 100644
--- a/apps/web-antd/src/api/mall/statistics/product.ts
+++ b/apps/web-antd/src/api/mall/statistics/product.ts
@@ -41,14 +41,14 @@ export namespace MallProductStatisticsApi {
}
/** 获得商品统计分析 */
-export function getProductStatisticsAnalyse(params: PageParam) {
+export function getProductStatisticsAnalyse(params: any) {
return requestClient.get<
DataComparisonRespVO
>('/statistics/product/analyse', { params });
}
/** 获得商品状况明细 */
-export function getProductStatisticsList(params: PageParam) {
+export function getProductStatisticsList(params: any) {
return requestClient.get(
'/statistics/product/list',
{ params },
@@ -56,7 +56,7 @@ export function getProductStatisticsList(params: PageParam) {
}
/** 导出获得商品状况明细 Excel */
-export function exportProductStatisticsExcel(params: PageParam) {
+export function exportProductStatisticsExcel(params: any) {
return requestClient.download('/statistics/product/export-excel', { params });
}
diff --git a/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue b/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
index f6a010187..e5ff39990 100644
--- a/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
+++ b/apps/web-antd/src/components/shortcut-date-range-picker/shortcut-date-range-picker.vue
@@ -19,8 +19,8 @@ const times = ref<[Dayjs, Dayjs]>(); // 日期范围
const rangePickerProps = getRangePickerDefaultProps();
const timeRangeOptions = [
rangePickerProps.presets[3]!, // 昨天
- rangePickerProps.presets[4]!, // 最近 7 天
- rangePickerProps.presets[5]!, // 最近 30 天
+ rangePickerProps.presets[1]!, // 最近 7 天
+ rangePickerProps.presets[2]!, // 最近 30 天
];
const timeRangeType = ref(timeRangeOptions[1]!.label); // 默认选中第一个选项
diff --git a/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue
index 93ccc17af..603307426 100644
--- a/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-card.vue
@@ -11,9 +11,9 @@ import { onMounted, ref } from 'vue';
import { SummaryCard } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
-import { fenToYuan } from '@vben/utils';
+import { fenToYuan, isSameDay } from '@vben/utils';
-import { Button, Card, Col, message, Row, Skeleton } from 'ant-design-vue';
+import { Button, Card, Col, message, Row, Spin } from 'ant-design-vue';
import dayjs from 'dayjs';
import * as ProductStatisticsApi from '#/api/mall/statistics/product';
@@ -24,12 +24,11 @@ import { getProductSummaryChartOptions } from './product-summary-chart-options';
/** 商品概况 */
defineOptions({ name: 'ProductSummaryCard' });
-// 消息弹窗
-
const trendLoading = ref(true); // 商品状态加载中
const exportLoading = ref(false); // 导出的加载中
const trendSummary =
ref>(); // 商品状况统计数据
+// TODO @AI:searchTimes;参考 /Users/yunai/Java/yudao-ui-admin-vben-v5/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue;这样,可以去掉 shortcutDateRangePicker
const shortcutDateRangePicker = ref();
const chartRef = ref();
@@ -39,7 +38,9 @@ const { renderEcharts } = useEcharts(chartRef);
const calculateRelativeRate = (value?: number, reference?: number): string => {
const refValue = Number(reference || 0);
const curValue = Number(value || 0);
- if (!refValue || refValue === 0) return '0.00';
+ if (!refValue || refValue === 0) {
+ return '0.00';
+ }
return (((curValue - refValue) / refValue) * 100).toFixed(2);
};
@@ -47,14 +48,12 @@ const calculateRelativeRate = (value?: number, reference?: number): string => {
const getProductTrendData = async (times?: [Dayjs, Dayjs]) => {
trendLoading.value = true;
try {
+ // 处理时间: 开始与截止在同一天的, 折线图出不来, 需要延长一天
let queryTimes = times;
if (!queryTimes && shortcutDateRangePicker.value?.times) {
queryTimes = shortcutDateRangePicker.value.times;
}
-
- // 1. 处理时间: 开始与截止在同一天的, 折线图出不来, 需要延长一天
if (queryTimes && isSameDay(queryTimes[0], queryTimes[1])) {
- // 前天
queryTimes[0] = dayjs(queryTimes[0]).subtract(1, 'd');
}
@@ -68,13 +67,9 @@ const getProductTrendData = async (times?: [Dayjs, Dayjs]) => {
}
};
-/** 判断是否同一天 */
-const isSameDay = (date1: Dayjs, date2: Dayjs): boolean => {
- return date1.format('YYYY-MM-DD') === date2.format('YYYY-MM-DD');
-};
-
/** 查询商品状况数据统计 */
const getProductTrendSummary = async (times?: [Dayjs, Dayjs]) => {
+ // TODO @AI:是不是 queryTimes 直接使用 searchTimes 完事?!
const queryTimes = times
? [
times[0].format('YYYY-MM-DD HH:mm:ss'),
@@ -88,6 +83,7 @@ const getProductTrendSummary = async (times?: [Dayjs, Dayjs]) => {
/** 查询商品状况数据列表 */
const getProductStatisticsList = async (times?: [Dayjs, Dayjs]) => {
+ // TODO @AI:是不是 queryTimes 直接使用 searchTimes 完事?!
// 查询数据
const queryTimes = times
? [
@@ -98,18 +94,12 @@ const getProductStatisticsList = async (times?: [Dayjs, Dayjs]) => {
const list: MallProductStatisticsApi.ProductStatistics[] =
await ProductStatisticsApi.getProductStatisticsList({ times: queryTimes });
- // 处理数据
- const processedList = list.map((item) => ({
- ...item,
- orderPayPrice: Number(fenToYuan(item.orderPayPrice)),
- afterSaleRefundPrice: Number(fenToYuan(item.afterSaleRefundPrice)),
- }));
-
- // 更新 Echarts 数据
- await renderEcharts(getProductSummaryChartOptions(processedList));
+ // 更新 Echarts 数据,数据转换由图表配置处理
+ await renderEcharts(getProductSummaryChartOptions(list));
};
/** 导出按钮操作 */
+// TODO @AI:导出有问题,参考别的模块的 confirm 更好;
const handleExport = async () => {
try {
// 导出的二次确认
@@ -175,7 +165,7 @@ onMounted(async () => {
-
+
{
"
/>
-
-
+
{
/>
-
+
{
"
/>
-
-
+
{
"
/>
-
-
+
{
/>
-
+
{
-
-
-
+
+
+
diff --git a/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts
index 7e64c78e6..ec6e474e1 100644
--- a/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts
+++ b/apps/web-antd/src/views/mall/statistics/product/modules/product-summary-chart-options.ts
@@ -1,7 +1,12 @@
-import type { EChartsOption } from 'echarts';
-
/** 商品统计折线图配置 */
-export function getProductSummaryChartOptions(data: any[]): EChartsOption {
+export function getProductSummaryChartOptions(data: any[]): any {
+ // 处理数据:将金额从分转换为元
+ const processedData = data.map((item) => ({
+ ...item,
+ orderPayPrice: Number((item.orderPayPrice / 100).toFixed(2)),
+ afterSaleRefundPrice: Number((item.afterSaleRefundPrice / 100).toFixed(2)),
+ }));
+
return {
dataset: {
dimensions: [
@@ -11,7 +16,7 @@ export function getProductSummaryChartOptions(data: any[]): EChartsOption {
'orderPayPrice',
'afterSaleRefundPrice',
],
- source: data,
+ source: processedData,
},
grid: {
left: 20,
diff --git a/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue b/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue
index af7da2583..a2f9fdea5 100644
--- a/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/product/modules/rank-card.vue
@@ -119,7 +119,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
multiple: false,
},
toolbarConfig: {
- refresh: false,
+ enabled: false,
},
} as VxeTableGridOptions,
});
diff --git a/packages/@core/base/shared/src/utils/index.ts b/packages/@core/base/shared/src/utils/index.ts
index e24456f91..2a545447d 100644
--- a/packages/@core/base/shared/src/utils/index.ts
+++ b/packages/@core/base/shared/src/utils/index.ts
@@ -23,4 +23,4 @@ export * from './window';
export { default as cloneDeep } from 'lodash.clonedeep';
export { default as get } from 'lodash.get';
export { default as isEqual } from 'lodash.isequal';
-export { default as set } from 'lodash.set';
\ No newline at end of file
+export { default as set } from 'lodash.set';
From b11b7582c244c8d5a1b9dd2a72805c5c22436861 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Mon, 20 Oct 2025 09:39:41 +0800
Subject: [PATCH 025/156] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=20=E5=95=86?=
=?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BA=A4=E6=98=93=E7=BB=9F=E8=AE=A1=E3=80=81?=
=?UTF-8?q?=E5=95=86=E5=93=81=E7=BB=9F=E8=AE=A1=E3=80=90antd=E3=80=9130%?=
=?UTF-8?q?=EF=BC=9A=E8=BF=81=E7=A7=BB=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../statistics/member/modules/sex-card.vue | 3 +-
.../views/mall/statistics/product/index.vue | 2 +-
...duct-summary-card.vue => summary-card.vue} | 127 +++++++-----------
...rt-options.ts => summary-chart-options.ts} | 0
4 files changed, 51 insertions(+), 81 deletions(-)
rename apps/web-antd/src/views/mall/statistics/product/modules/{product-summary-card.vue => summary-card.vue} (68%)
rename apps/web-antd/src/views/mall/statistics/product/modules/{product-summary-chart-options.ts => summary-chart-options.ts} (100%)
diff --git a/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
index 151280744..2938b8eb3 100644
--- a/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
+++ b/apps/web-antd/src/views/mall/statistics/member/modules/sex-card.vue
@@ -39,7 +39,8 @@ async function getMemberSexStatisticsList() {
value: userCount || 0,
};
});
- // 更新 Echarts 数据
+
+ // 渲染图表
await renderEcharts(getSexChartOptions(chartData));
} finally {
loading.value = false;
diff --git a/apps/web-antd/src/views/mall/statistics/product/index.vue b/apps/web-antd/src/views/mall/statistics/product/index.vue
index f2caa8862..2e3834059 100644
--- a/apps/web-antd/src/views/mall/statistics/product/index.vue
+++ b/apps/web-antd/src/views/mall/statistics/product/index.vue
@@ -1,8 +1,8 @@
@@ -149,10 +122,7 @@ onMounted(async () => {
-
+