feat: 新增运营数据展示组件,优化商城首页数据处理逻辑
- 在商城首页引入 WorkbenchQuickDataShow 组件,展示关键运营数据 - 增加数据获取方法,包括订单、商品和钱包充值数据 - 更新 AnalysisOverview 组件以支持双向绑定 - 优化数据加载逻辑,提升用户体验
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import type {
|
||||
AnalysisOverviewItem,
|
||||
WorkbenchProjectItem,
|
||||
WorkbenchQuickDataShowItem,
|
||||
WorkbenchQuickNavItem,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
AnalysisOverview,
|
||||
DocAlert,
|
||||
Page,
|
||||
WorkbenchQuickDataShow,
|
||||
WorkbenchQuickNav,
|
||||
} from '@vben/common-ui';
|
||||
import {
|
||||
@@ -22,8 +24,10 @@ import {
|
||||
} from '@vben/icons';
|
||||
import { isString, openWindow } from '@vben/utils';
|
||||
|
||||
import { getTabsCount } from '#/api/mall/product/spu';
|
||||
import { getUserCountComparison } from '#/api/mall/statistics/member';
|
||||
import { getOrderComparison } from '#/api/mall/statistics/trade';
|
||||
import { getWalletRechargePrice } from '#/api/mall/statistics/pay';
|
||||
import { getOrderComparison, getOrderCount } from '#/api/mall/statistics/trade';
|
||||
|
||||
/** 商城首页 */
|
||||
defineOptions({ name: 'MallHome' });
|
||||
@@ -31,6 +35,18 @@ defineOptions({ name: 'MallHome' });
|
||||
const loading = ref(true); // 加载中
|
||||
const orderComparison = ref(); // 交易对照数据
|
||||
const userComparison = ref(); // 用户对照数据
|
||||
const data = ref({
|
||||
orderUndelivered: 0,
|
||||
orderAfterSaleApply: 0,
|
||||
orderWaitePickUp: 0,
|
||||
withdrawAuditing: 0,
|
||||
productForSale: 0,
|
||||
productInWarehouse: 0,
|
||||
productAlertStock: 0,
|
||||
rechargePrice: 0,
|
||||
});
|
||||
|
||||
const dataShow = ref(false);
|
||||
|
||||
/** 查询交易对照卡片数据 */
|
||||
const getOrder = async () => {
|
||||
@@ -42,43 +58,87 @@ const getUserCount = async () => {
|
||||
userComparison.value = await getUserCountComparison();
|
||||
};
|
||||
|
||||
/** 查询订单数据 */
|
||||
const getOrderData = async () => {
|
||||
const orderCount = await getOrderCount();
|
||||
if (orderCount.undelivered) {
|
||||
data.value.orderUndelivered = orderCount.undelivered;
|
||||
}
|
||||
if (orderCount.afterSaleApply) {
|
||||
data.value.orderAfterSaleApply = orderCount.afterSaleApply;
|
||||
}
|
||||
if (orderCount.pickUp) {
|
||||
data.value.orderWaitePickUp = orderCount.pickUp;
|
||||
}
|
||||
if (orderCount.auditingWithdraw) {
|
||||
data.value.withdrawAuditing = orderCount.auditingWithdraw;
|
||||
}
|
||||
};
|
||||
|
||||
/** 查询商品数据 */
|
||||
const getProductData = async () => {
|
||||
// TODO: @芋艿:这个接口的返回值,是不是用命名字段更好些?
|
||||
const productCount = await getTabsCount();
|
||||
data.value.productForSale = productCount['0'] || 0;
|
||||
data.value.productInWarehouse = productCount['1'] || 0;
|
||||
data.value.productAlertStock = productCount['3'] || 0;
|
||||
};
|
||||
|
||||
/** 查询钱包充值数据 */
|
||||
const getWalletRechargeData = async () => {
|
||||
const paySummary = await getWalletRechargePrice();
|
||||
data.value.rechargePrice = paySummary.rechargePrice;
|
||||
};
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
loading.value = true;
|
||||
await Promise.all([getOrder(), getUserCount()]);
|
||||
await Promise.all([
|
||||
getOrder(),
|
||||
getUserCount(),
|
||||
getOrderData(),
|
||||
getProductData(),
|
||||
getWalletRechargeData(),
|
||||
]);
|
||||
loading.value = false;
|
||||
dataShow.value = true;
|
||||
loadDataShow();
|
||||
loadOverview();
|
||||
});
|
||||
|
||||
const overviewItems: AnalysisOverviewItem[] = [
|
||||
{
|
||||
icon: SvgCardIcon,
|
||||
title: '今日销售额',
|
||||
totalTitle: '昨日数据',
|
||||
totalValue: orderComparison.value?.reference?.orderPayPrice || 0,
|
||||
value: orderComparison.value?.orderPayPrice || 0,
|
||||
},
|
||||
{
|
||||
icon: SvgCakeIcon,
|
||||
title: '今日用户访问量',
|
||||
totalTitle: '总访问量',
|
||||
totalValue: userComparison.value?.reference?.visitUserCount || 0,
|
||||
value: userComparison.value?.visitUserCount || 0,
|
||||
},
|
||||
{
|
||||
icon: SvgDownloadIcon,
|
||||
title: '今日订单量',
|
||||
totalTitle: '总订单量',
|
||||
totalValue: orderComparison.value?.orderPayCount || 0,
|
||||
value: orderComparison.value?.reference?.orderPayCount || 0,
|
||||
},
|
||||
{
|
||||
icon: SvgBellIcon,
|
||||
title: '今日会员注册量',
|
||||
totalTitle: '总会员注册量',
|
||||
totalValue: userComparison.value?.registerUserCount || 0,
|
||||
value: userComparison.value?.reference?.registerUserCount || 0,
|
||||
},
|
||||
];
|
||||
const overviewItems = ref<AnalysisOverviewItem[]>([]);
|
||||
const loadOverview = () => {
|
||||
overviewItems.value = [
|
||||
{
|
||||
icon: SvgCardIcon,
|
||||
title: '今日销售额',
|
||||
totalTitle: '昨日数据',
|
||||
totalValue: orderComparison.value?.reference?.orderPayPrice || 0,
|
||||
value: orderComparison.value?.orderPayPrice || 0,
|
||||
},
|
||||
{
|
||||
icon: SvgCakeIcon,
|
||||
title: '今日用户访问量',
|
||||
totalTitle: '总访问量',
|
||||
totalValue: userComparison.value?.reference?.visitUserCount || 0,
|
||||
value: userComparison.value?.visitUserCount || 0,
|
||||
},
|
||||
{
|
||||
icon: SvgDownloadIcon,
|
||||
title: '今日订单量',
|
||||
totalTitle: '总订单量',
|
||||
totalValue: orderComparison.value?.orderPayCount || 0,
|
||||
value: orderComparison.value?.reference?.orderPayCount || 0,
|
||||
},
|
||||
{
|
||||
icon: SvgBellIcon,
|
||||
title: '今日会员注册量',
|
||||
totalTitle: '总会员注册量',
|
||||
totalValue: userComparison.value?.registerUserCount || 0,
|
||||
value: userComparison.value?.reference?.registerUserCount || 0,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
// 同样,这里的 url 也可以使用以 http 开头的外部链接
|
||||
const quickNavItems: WorkbenchQuickNavItem[] = [
|
||||
@@ -138,6 +198,69 @@ const quickNavItems: WorkbenchQuickNavItem[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const quickDataShowItems = ref<WorkbenchQuickDataShowItem[]>();
|
||||
|
||||
const loadDataShow = () => {
|
||||
quickDataShowItems.value = [
|
||||
{
|
||||
name: '待发货订单',
|
||||
value: data.value.orderUndelivered,
|
||||
prefix: '',
|
||||
decimals: 0,
|
||||
routerName: 'TradeOrder',
|
||||
},
|
||||
{
|
||||
name: '退款中订单',
|
||||
value: data.value.orderAfterSaleApply,
|
||||
prefix: '',
|
||||
decimals: 0,
|
||||
routerName: 'TradeAfterSale',
|
||||
},
|
||||
{
|
||||
name: '待核销订单',
|
||||
value: data.value.orderWaitePickUp,
|
||||
routerName: 'TradeOrder',
|
||||
prefix: '',
|
||||
decimals: 0,
|
||||
},
|
||||
{
|
||||
name: '库存预警',
|
||||
value: data.value.productAlertStock,
|
||||
routerName: 'ProductSpu',
|
||||
prefix: '',
|
||||
decimals: 0,
|
||||
},
|
||||
{
|
||||
name: '上架商品',
|
||||
value: data.value.productForSale,
|
||||
routerName: 'ProductSpu',
|
||||
prefix: '',
|
||||
decimals: 0,
|
||||
},
|
||||
{
|
||||
name: '仓库商品',
|
||||
value: data.value.productInWarehouse,
|
||||
routerName: 'ProductSpu',
|
||||
prefix: '',
|
||||
decimals: 0,
|
||||
},
|
||||
{
|
||||
name: '提现待审核',
|
||||
value: data.value.withdrawAuditing,
|
||||
routerName: 'TradeBrokerageWithdraw',
|
||||
prefix: '',
|
||||
decimals: 0,
|
||||
},
|
||||
{
|
||||
name: '账户充值',
|
||||
value: data.value.rechargePrice,
|
||||
prefix: '¥',
|
||||
decimals: 2,
|
||||
routerName: 'PayWalletRecharge',
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const router = useRouter();
|
||||
function navTo(nav: WorkbenchProjectItem | WorkbenchQuickNavItem) {
|
||||
if (nav.url?.startsWith('http')) {
|
||||
@@ -164,14 +287,20 @@ function navTo(nav: WorkbenchProjectItem | WorkbenchQuickNavItem) {
|
||||
url="https://doc.iocoder.cn/mall/build/"
|
||||
/>
|
||||
</template>
|
||||
<AnalysisOverview :items="overviewItems" />
|
||||
<div class="mt-5 w-full lg:w-2/5">
|
||||
<AnalysisOverview v-model:model-value="overviewItems" />
|
||||
<div class="mt-5 w-full md:flex">
|
||||
<WorkbenchQuickNav
|
||||
:items="quickNavItems"
|
||||
class="mt-5 lg:mt-0"
|
||||
class="mt-5 md:mr-4 md:mt-0 md:w-1/2"
|
||||
title="快捷导航"
|
||||
@click="navTo"
|
||||
/>
|
||||
<WorkbenchQuickDataShow
|
||||
v-if="dataShow"
|
||||
v-model:model-value="quickDataShowItems"
|
||||
title="运营数据"
|
||||
class="mt-5 md:mr-4 md:mt-0 md:w-1/2"
|
||||
/>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user