From 4620ede9b9a82bf195a017359b22b3b9c5f3f030 Mon Sep 17 00:00:00 2001 From: lrl <252048765@qq.com> Date: Thu, 17 Jul 2025 09:53:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=95=86=E5=93=81?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E7=BB=84=E4=BB=B6=E5=92=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入商品排行和商品概况组件,展示商品相关统计信息 - 更新商品统计 API,支持时间范围查询和数据格式化 - 优化数据加载逻辑,提升用户体验 - 添加日期范围选择器,增强统计数据的灵活性 --- .../src/api/mall/statistics/product.ts | 46 ++- .../product/components/product-rank.vue | 153 +++++++++ .../product/components/product-summary.vue | 300 ++++++++++++++++++ .../views/mall/statistics/product/index.vue | 25 +- packages/@core/base/shared/src/utils/index.ts | 15 + .../dashboard/analysis/analysis-overview.vue | 41 ++- .../common-ui/src/ui/dashboard/typing.ts | 1 + packages/icons/src/svg/icons/eye.svg | 33 ++ packages/icons/src/svg/index.ts | 2 + 9 files changed, 587 insertions(+), 29 deletions(-) create mode 100644 apps/web-ele/src/views/mall/statistics/product/components/product-rank.vue create mode 100644 apps/web-ele/src/views/mall/statistics/product/components/product-summary.vue create mode 100644 packages/icons/src/svg/icons/eye.svg diff --git a/apps/web-ele/src/api/mall/statistics/product.ts b/apps/web-ele/src/api/mall/statistics/product.ts index d458d4353..089da4af7 100644 --- a/apps/web-ele/src/api/mall/statistics/product.ts +++ b/apps/web-ele/src/api/mall/statistics/product.ts @@ -2,6 +2,8 @@ import type { PageParam, PageResult } from '@vben/request'; import type { MallDataComparisonResp } from './common'; +import { formatDate2 } from '@vben/utils'; + import { requestClient } from '#/api/request'; export namespace MallProductStatisticsApi { @@ -38,26 +40,58 @@ export namespace MallProductStatisticsApi { /** 浏览转化率 */ browseConvertPercent: number; } + + /** 会员分析 Request */ + export interface ProductStatisticsReq { + times: Date[]; + } } /** 获得商品统计分析 */ -export function getProductStatisticsAnalyse(params: PageParam) { +export function getProductStatisticsAnalyse( + params: MallProductStatisticsApi.ProductStatisticsReq, +) { return requestClient.get< MallDataComparisonResp - >('/statistics/product/analyse', { params }); + >('/statistics/product/analyse', { + params: { + times: [ + formatDate2(params.times[0] || new Date()), + formatDate2(params.times[1] || new Date()), + ], + }, + }); } /** 获得商品状况明细 */ -export function getProductStatisticsList(params: PageParam) { +export function getProductStatisticsList( + params: MallProductStatisticsApi.ProductStatisticsReq, +) { return requestClient.get( '/statistics/product/list', - { params }, + { + params: { + times: [ + formatDate2(params.times[0] || new Date()), + formatDate2(params.times[1] || new Date()), + ], + }, + }, ); } /** 导出获得商品状况明细 Excel */ -export function exportProductStatisticsExcel(params: PageParam) { - return requestClient.download('/statistics/product/export-excel', { params }); +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()), + ], + }, + }); } /** 获得商品排行榜分页 */ diff --git a/apps/web-ele/src/views/mall/statistics/product/components/product-rank.vue b/apps/web-ele/src/views/mall/statistics/product/components/product-rank.vue new file mode 100644 index 000000000..09ba064c5 --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/product/components/product-rank.vue @@ -0,0 +1,153 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/product/components/product-summary.vue b/apps/web-ele/src/views/mall/statistics/product/components/product-summary.vue new file mode 100644 index 000000000..3b8c16cdf --- /dev/null +++ b/apps/web-ele/src/views/mall/statistics/product/components/product-summary.vue @@ -0,0 +1,300 @@ + + + diff --git a/apps/web-ele/src/views/mall/statistics/product/index.vue b/apps/web-ele/src/views/mall/statistics/product/index.vue index cfc1f5ce3..ede53465c 100644 --- a/apps/web-ele/src/views/mall/statistics/product/index.vue +++ b/apps/web-ele/src/views/mall/statistics/product/index.vue @@ -1,7 +1,8 @@ diff --git a/packages/@core/base/shared/src/utils/index.ts b/packages/@core/base/shared/src/utils/index.ts index 7a22c972d..0323d0315 100644 --- a/packages/@core/base/shared/src/utils/index.ts +++ b/packages/@core/base/shared/src/utils/index.ts @@ -22,3 +22,18 @@ 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' }; +}; diff --git a/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue index 65eafa735..9b735707f 100644 --- a/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue +++ b/packages/effects/common-ui/src/ui/dashboard/analysis/analysis-overview.vue @@ -9,6 +9,10 @@ import { CardFooter, CardHeader, CardTitle, + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, VbenCountToAnimator, VbenIcon, } from '@vben-core/shadcn-ui'; @@ -16,6 +20,7 @@ import { interface Props { items?: AnalysisOverviewItem[]; modelValue?: AnalysisOverviewItem[]; + columnsNumber?: number; } defineOptions({ @@ -25,6 +30,7 @@ defineOptions({ const props = withDefaults(defineProps(), { items: () => [], modelValue: () => [], + columnsNumber: 4, }); const emit = defineEmits(['update:modelValue']); @@ -33,14 +39,45 @@ const itemsData = computed({ get: () => (props.modelValue?.length ? props.modelValue : props.items), set: (value) => emit('update:modelValue', value), }); + +// 计算动态的grid列数类名 +const gridColumnsClass = computed(() => { + const colNum = props.columnsNumber; + return { + 'lg:grid-cols-1': colNum === 1, + 'lg:grid-cols-2': colNum === 2, + 'lg:grid-cols-3': colNum === 3, + 'lg:grid-cols-4': colNum === 4, + 'lg:grid-cols-5': colNum === 5, + 'lg:grid-cols-6': colNum === 6, + }; +});