Browse Source

feat(cms): 重构内容管理统计功能

- 修改统计卡片的标题和图标
- 增加素材(文件)数量统计- 优化统计数据的获取逻辑
- 更新仪表盘和统计页面的数据展示
- 新增统计测试工具
master
科技小王子 2 months ago
parent
commit
238a737272
  1. 58
      src/store/modules/statistics.ts
  2. 90
      src/utils/statistics-test.ts
  3. 54
      src/views/cms/cmsStatistics/index.vue
  4. 18
      src/views/cms/dashboard/index.vue

58
src/store/modules/statistics.ts

@ -4,6 +4,7 @@
import { defineStore } from 'pinia';
import { pageUsers } from '@/api/system/user';
import { pageCmsArticle } from '@/api/cms/cmsArticle';
import { pageFiles } from '@/api/system/file';
import {
addCmsStatistics,
listCmsStatistics,
@ -49,12 +50,19 @@ export const useStatisticsStore = defineStore({
},
/**
*
*
*/
orderCount: (state): number => {
articleCount: (state): number => {
return safeNumber(state.statistics?.orderCount);
},
/**
* ()
*/
fileCount: (state): number => {
return safeNumber(state.statistics?.todayOrders);
},
/**
*
*/
@ -114,14 +122,21 @@ export const useStatisticsStore = defineStore({
this.loading = true;
try {
// 并行获取各种统计数据
const [users, orders, total, statisticsData] = await Promise.all([
pageUsers({}),
pageCmsArticle({}),
listCmsStatistics({})
const [users, allArticles, files, statisticsData] = await Promise.all([
pageUsers({}).catch(() => null),
pageCmsArticle({}).catch(() => null),
pageFiles({}).catch(() => null), // 文件素材
listCmsStatistics({}).catch(() => null)
]);
let statistics: CmsStatistics;
// 计算统计数据
const totalArticleCount = isValidApiResponse(allArticles)
? allArticles.count
: 0;
const totalFileCount = isValidApiResponse(files) ? files.count : 0;
if (statisticsData && statisticsData.length > 0) {
// 更新现有统计数据
const existingStatistics = statisticsData[0];
@ -133,10 +148,8 @@ export const useStatisticsStore = defineStore({
userCount: safeNumber(
isValidApiResponse(users) ? users.count : 0
),
orderCount: safeNumber(
isValidApiResponse(orders) ? orders.count : 0
),
totalSales: safeNumber(total)
orderCount: safeNumber(totalArticleCount), // 使用文章总数
todayOrders: safeNumber(totalFileCount) // 使用文件总数
};
// 异步更新数据库
@ -154,20 +167,16 @@ export const useStatisticsStore = defineStore({
userCount: safeNumber(
isValidApiResponse(users) ? users.count : 0
),
orderCount: safeNumber(
isValidApiResponse(orders) ? orders.count : 0
),
totalSales: safeNumber(total)
orderCount: safeNumber(totalArticleCount),
todayOrders: safeNumber(totalFileCount)
};
}
} else {
// 创建新的统计数据
statistics = {
userCount: safeNumber(isValidApiResponse(users) ? users.count : 0),
orderCount: safeNumber(
isValidApiResponse(orders) ? orders.count : 0
),
totalSales: safeNumber(total)
orderCount: safeNumber(totalArticleCount),
todayOrders: safeNumber(totalFileCount)
};
// 异步保存到数据库
@ -184,7 +193,18 @@ export const useStatisticsStore = defineStore({
return statistics;
} catch (error) {
console.error('获取统计数据失败:', error);
throw error;
// 即使出错也要提供基础的统计数据
const fallbackStatistics: CmsStatistics = {
userCount: 0,
orderCount: 0,
todayOrders: 0
};
this.statistics = fallbackStatistics;
this.lastUpdateTime = Date.now();
return fallbackStatistics;
} finally {
this.loading = false;
}

90
src/utils/statistics-test.ts

@ -0,0 +1,90 @@
/**
*
*
*/
import { pageUsers } from '@/api/system/user';
import { pageCmsArticle } from '@/api/cms/cmsArticle';
import { pageFiles } from '@/api/system/file';
/**
*
*/
export async function testStatistics() {
console.log('开始测试统计数据获取...');
try {
// 测试用户数据获取
console.log('测试用户数据获取...');
const users = await pageUsers({}).catch(err => {
console.warn('用户数据获取失败:', err.message);
return null;
});
console.log('用户数据:', users ? `${users.count} 个用户` : '获取失败');
// 测试文章总数获取
console.log('测试文章总数获取...');
const allArticles = await pageCmsArticle({}).catch(err => {
console.warn('文章数据获取失败:', err.message);
return null;
});
console.log('文章总数:', allArticles ? `${allArticles.count} 篇文章` : '获取失败');
// 测试文件数获取
console.log('测试文件数获取...');
const files = await pageFiles({}).catch(err => {
console.warn('文件数据获取失败:', err.message);
return null;
});
console.log('文件数:', files ? `${files.count} 个文件` : '获取失败');
// 汇总结果
const result = {
userCount: users?.count || 0,
articleCount: allArticles?.count || 0,
fileCount: files?.count || 0,
success: true
};
console.log('统计测试完成:', result);
return result;
} catch (error) {
console.error('统计测试失败:', error);
return {
userCount: 0,
articleCount: 0,
fileCount: 0,
success: false,
error: error.message
};
}
}
/**
*
*/
export const ARTICLE_STATUS = {
PUBLISHED: 0, // 已发布
PENDING: 1, // 待审核
REJECTED: 2, // 已驳回
VIOLATION: 3 // 违规内容
} as const;
/**
*
*/
export function getArticleStatusText(status: number): string {
switch (status) {
case ARTICLE_STATUS.PUBLISHED:
return '已发布';
case ARTICLE_STATUS.PENDING:
return '待审核';
case ARTICLE_STATUS.REJECTED:
return '已驳回';
case ARTICLE_STATUS.VIOLATION:
return '违规内容';
default:
return '未知状态';
}
}

54
src/views/cms/cmsStatistics/index.vue

@ -20,11 +20,11 @@
<a-card :bordered="false" class="stat-card">
<a-statistic
title="文章总数"
:value="statistics.orderCount"
:value="statistics.articleCount"
:value-style="{ color: '#1890ff' }"
>
<template #prefix>
<AccountBookOutlined />
<FileTextOutlined />
</template>
</a-statistic>
</a-card>
@ -33,12 +33,12 @@
<a-col :span="6">
<a-card :bordered="false" class="stat-card">
<a-statistic
title="总营业额"
:value="statistics.totalSales"
title="素材(文件)数"
:value="statistics.fileCount"
:value-style="{ color: '#cf1322' }"
>
<template #prefix>
<MoneyCollectOutlined />
<FileOutlined />
</template>
</a-statistic>
</a-card>
@ -73,6 +73,7 @@
SettingOutlined,
AccountBookOutlined,
FileTextOutlined,
FileOutlined,
MoneyCollectOutlined
} from '@ant-design/icons-vue';
import { getSiteInfo } from '@/api/layout';
@ -81,6 +82,7 @@
import { getPageTitle } from '@/utils/common';
import { listCmsStatistics } from '@/api/cms/cmsStatistics';
import { pageCmsArticle } from '@/api/cms/cmsArticle';
import { pageFiles } from '@/api/system/file';
//
const siteInfo = ref<CmsWebsite>({});
@ -102,8 +104,8 @@
//
const statistics = ref({
userCount: 0,
orderCount: 0,
todayVisit: 0,
articleCount: 0,
fileCount: 0,
runDays: 365
});
@ -126,20 +128,30 @@
};
const loadStatistics = async () => {
// TODO: API
const users = await pageUsers({});
const articles = await pageCmsArticle({});
if (users) {
statistics.value.userCount = users.count;
}
if (articles) {
statistics.value.orderCount = articles.count;
}
//
const data = await listCmsStatistics({});
if (data) {
//
statistics.value.totalSales = data[0].totalSales;
try {
//
const [users, allArticles, files] = await Promise.all([
pageUsers({}).catch(() => null),
pageCmsArticle({}).catch(() => null),
pageFiles({}).catch(() => null) //
]);
//
if (users) {
statistics.value.userCount = users.count || 0;
}
//
if (allArticles) {
statistics.value.articleCount = allArticles.count || 0;
}
//
if (files) {
statistics.value.fileCount = files.count || 0;
}
} catch (error) {
console.error('加载统计数据失败:', error);
}
};
</script>

18
src/views/cms/dashboard/index.vue

@ -51,7 +51,7 @@
<a-col :span="6">
<a-card :bordered="false" class="stat-card">
<a-statistic
title="用户总数"
title="用户"
:value="userCount"
:value-style="{ color: '#3f8600' }"
:loading="loading"
@ -66,13 +66,13 @@
<a-col :span="6">
<a-card :bordered="false" class="stat-card">
<a-statistic
title="订单总数"
title="文章"
:value="orderCount"
:value-style="{ color: '#1890ff' }"
:loading="loading"
>
<template #prefix>
<AccountBookOutlined />
<FileTextOutlined />
</template>
</a-statistic>
</a-card>
@ -81,13 +81,13 @@
<a-col :span="6">
<a-card :bordered="false" class="stat-card">
<a-statistic
title="总营业额"
:value="totalSales"
title="素材"
:value="fileCount"
:value-style="{ color: '#cf1322' }"
:loading="loading"
>
<template #prefix>
<MoneyCollectOutlined />
<FileOutlined />
</template>
</a-statistic>
</a-card>
@ -96,7 +96,7 @@
<a-col :span="6">
<a-card :bordered="false" class="stat-card">
<a-statistic
title="系统运行天数"
title="已运行"
:value="runDays"
suffix="天"
:value-style="{ color: '#722ed1' }"
@ -191,6 +191,7 @@
SettingOutlined,
AccountBookOutlined,
FileTextOutlined,
FileOutlined,
MoneyCollectOutlined
} from '@ant-design/icons-vue';
import { openNew } from '@/utils/common';
@ -223,7 +224,8 @@
//
const runDays = computed(() => siteStore.runDays);
const userCount = computed(() => statisticsStore.userCount);
const orderCount = computed(() => statisticsStore.orderCount);
const orderCount = computed(() => statisticsStore.articleCount);
const fileCount = computed(() => statisticsStore.fileCount);
const totalSales = computed(() => statisticsStore.totalSales);
//

Loading…
Cancel
Save