diff --git a/admin-system/src/App.vue b/admin-system/src/App.vue
index 94ac392..258e001 100644
--- a/admin-system/src/App.vue
+++ b/admin-system/src/App.vue
@@ -1,13 +1,19 @@
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/admin-system/src/router/index.ts b/admin-system/src/router/index.ts
index b16bd83..717e607 100644
--- a/admin-system/src/router/index.ts
+++ b/admin-system/src/router/index.ts
@@ -1,5 +1,6 @@
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
+import { useAppStore } from '@/stores/app'
// 基础路由
const routes: RouteRecordRaw[] = [
@@ -125,7 +126,14 @@ const router = createRouter({
// 路由守卫
router.beforeEach(async (to, from, next) => {
const { meta } = to
- const isAuthenticated = localStorage.getItem('admin_token') !== null
+ const appStore = useAppStore()
+
+ // 确保应用已初始化
+ if (!appStore.state.initialized) {
+ await appStore.initialize()
+ }
+
+ const isAuthenticated = !!appStore.state.user
// 检查是否需要认证
if (meta.requiresAuth && !isAuthenticated) {
diff --git a/admin-system/src/stores/app.ts b/admin-system/src/stores/app.ts
index dbfda1c..cb05211 100644
--- a/admin-system/src/stores/app.ts
+++ b/admin-system/src/stores/app.ts
@@ -32,16 +32,27 @@ export const useAppStore = defineStore('app', () => {
if (token) {
// 获取用户信息
const response = await authAPI.getCurrentUser()
- // 修复数据结构访问问题
- if (response?.data?.admin) {
+
+ // 统一处理接口响应格式
+ if (!response || typeof response !== 'object') {
+ throw new Error('获取用户信息失败:接口返回格式异常')
+ }
+
+ // 确保响应数据格式为 { data: { admin: object } }
+ if (response.data && typeof response.data === 'object' && response.data.admin) {
state.user = response.data.admin
- } else if (response?.data?.user) {
- state.user = response.data.user
+ } else {
+ throw new Error('获取用户信息失败:响应数据格式不符合预期')
}
}
} catch (error) {
- console.error('初始化失败:', error)
+ console.error('初始化失败:', {
+ error: error,
+ timestamp: new Date().toISOString(),
+ token: localStorage.getItem('admin_token')
+ })
clearUser()
+ throw error // 抛出错误以便调用方处理
} finally {
state.loading = false
state.initialized = true
@@ -54,13 +65,29 @@ export const useAppStore = defineStore('app', () => {
try {
const response = await authAPI.login(credentials)
- // 保存token
- localStorage.setItem('admin_token', response.data.token)
+ // 保存token - 修复数据结构访问问题
+ if (response?.data?.token) {
+ localStorage.setItem('admin_token', response.data.token)
+ } else if (response?.token) {
+ localStorage.setItem('admin_token', response.token)
+ } else {
+ throw new Error('登录响应中缺少token')
+ }
- // 设置用户信息
- state.user = response.data.admin
+ // 设置用户信息 - 修复数据结构访问问题
+ if (response?.data?.admin) {
+ state.user = response.data.admin
+ } else if (response?.admin) {
+ state.user = response.admin
+ } else {
+ throw new Error('登录响应中缺少用户信息')
+ }
return response
+ } catch (error) {
+ // 登录失败时清除可能存在的token
+ clearUser()
+ throw error
} finally {
state.loading = false
}
diff --git a/backend/src/app.js b/backend/src/app.js
index 4045bda..fe9292b 100644
--- a/backend/src/app.js
+++ b/backend/src/app.js
@@ -92,6 +92,23 @@ app.get('/health', (req, res) => {
});
});
+// 系统统计路由
+app.get('/system-stats', (req, res) => {
+ const stats = {
+ status: 'OK',
+ timestamp: new Date().toISOString(),
+ environment: process.env.NODE_ENV || 'development',
+ nodeVersion: process.version,
+ memoryUsage: process.memoryUsage(),
+ uptime: process.uptime(),
+ cpuCount: require('os').cpus().length,
+ platform: process.platform,
+ architecture: process.arch
+ };
+
+ res.status(200).json(stats);
+});
+
// API路由
app.use('/api/v1/auth', authRoutes);
app.use('/api/v1/users', userRoutes);
diff --git a/backend/src/controllers/admin/systemStats.js b/backend/src/controllers/admin/systemStats.js
new file mode 100644
index 0000000..f349c32
--- /dev/null
+++ b/backend/src/controllers/admin/systemStats.js
@@ -0,0 +1,90 @@
+// 系统统计控制器
+const systemStatsService = require('../../services/admin/systemStats');
+
+/**
+ * 获取系统统计数据
+ * @param {import('express').Request} req
+ * @param {import('express').Response} res
+ * @param {import('express').NextFunction} next
+ */
+exports.getSystemStats = async (req, res, next) => {
+ try {
+ const stats = await systemStatsService.getSystemStats();
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取系统统计数据成功',
+ data: stats,
+ timestamp: new Date().toISOString()
+ });
+ } catch (error) {
+ next(error);
+ }
+};
+
+/**
+ * 获取用户统计数据
+ * @param {import('express').Request} req
+ * @param {import('express').Response} res
+ * @param {import('express').NextFunction} next
+ */
+exports.getUserStats = async (req, res, next) => {
+ try {
+ const stats = await systemStatsService.getUserStats();
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取用户统计数据成功',
+ data: stats,
+ timestamp: new Date().toISOString()
+ });
+ } catch (error) {
+ next(error);
+ }
+};
+
+/**
+ * 获取订单统计数据
+ * @param {import('express').Request} req
+ * @param {import('express').Response} res
+ * @param {import('express').NextFunction} next
+ */
+exports.getOrderStats = async (req, res, next) => {
+ try {
+ const stats = await systemStatsService.getOrderStats();
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取订单统计数据成功',
+ data: stats,
+ timestamp: new Date().toISOString()
+ });
+ } catch (error) {
+ next(error);
+ }
+};
+
+/**
+ * 获取系统信息
+ * @param {import('express').Request} req
+ * @param {import('express').Response} res
+ * @param {import('express').NextFunction} next
+ */
+exports.getSystemInfo = async (req, res, next) => {
+ try {
+ const info = await systemStatsService.getSystemInfo();
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取系统信息成功',
+ data: info,
+ timestamp: new Date().toISOString()
+ });
+ } catch (error) {
+ next(error);
+ }
+};
\ No newline at end of file
diff --git a/backend/src/docs/swagger.js b/backend/src/docs/swagger.js
index 24ecec7..12fbce0 100644
--- a/backend/src/docs/swagger.js
+++ b/backend/src/docs/swagger.js
@@ -21,7 +21,7 @@ const options = {
},
servers: [
{
- url: 'http://localhost:3000/api/v1',
+ url: 'http://localhost:3100/api/v1',
description: '开发环境'
},
{
@@ -91,235 +91,199 @@ const options = {
}
}
},
- // 用户模型
- User: {
- type: 'object',
- properties: {
- id: {
- type: 'integer',
- example: 1
- },
- username: {
- type: 'string',
- example: 'testuser'
- },
- nickname: {
- type: '极速版string',
- example: '测试用户'
- },
- email: {
- type: 'string',
- example: 'test@example.com'
- },
- phone: {
- type: 'string',
- example: '13800138000'
- },
- avatar: {
- type: 'string',
- example: 'https://example.com/avatar.jpg'
- },
- gender: {
- type: 'string',
- enum: ['male', 'female', 'unknown'],
- example: 'male'
- },
- birthday: {
- type: 'string',
- format: 'date',
- example: '1990-01-01'
- },
- points: {
- type: 'integer',
- example: 1000
- },
- level: {
- type: 'integer',
- example: 3
- },
- status: {
- type: 'string',
- enum: ['active', 'inactive', 'banned'],
- example: 'active'
- },
- created_at: {
- type: 'string',
- format: 'date-time'
- },
- updated_at: {
- type: 'string',
- format: 'date-time'
- },
- last_login_at: {
- type: 'string',
- format: 'date-time',
- description: '最后登录时间'
- }
- }
- },
// 管理员模型
Admin: {
type: 'object',
properties: {
id: {
type: 'integer',
- description: '管理员ID'
+ example: 1
},
username: {
type: 'string',
- description: '用户名'
+ example: 'admin'
},
email: {
type: 'string',
- description: '邮箱'
+ example: 'admin@jiebanke.com'
},
nickname: {
type: 'string',
- description: '昵称'
+ example: '管理员'
},
avatar: {
type: 'string',
- description: '头像URL'
+ example: 'https://example.com/avatar.jpg'
},
role: {
type: 'string',
- description: '角色'
+ example: 'super_admin'
},
status: {
- type: 'integer',
- description: '状态 (1:启用, 0:禁用)'
+ type: 'string',
+ example: 'active'
},
last_login: {
type: 'string',
format: 'date-time',
- description: '最后登录时间'
+ example: '2023-01-01T00:00:00Z'
},
created_at: {
type: 'string',
format: 'date-time',
- description: '创建时间'
+ example: '2023-01-01T00:00:00Z'
},
updated_at: {
type: 'string',
format: 'date-time',
- description: '更新时间'
+ example: '2023-01-01T00:00:00Z'
}
}
},
- // 分页模型
- Pagination: {
+ // 系统统计数据模型
+ SystemStats: {
+ type: 'object',
+ properties: {
+ userCount: {
+ type: 'integer',
+ description: '用户总数'
+ },
+ merchantCount: {
+ type: 'integer',
+ description: '商家数量'
+ },
+ travelCount: {
+ type: 'integer',
+ description: '旅行计划数'
+ },
+ animalCount: {
+ type: 'integer',
+ description: '动物数量'
+ },
+ orderCount: {
+ type: 'integer',
+ description: '订单总数'
+ },
+ todayUserCount: {
+ type: 'integer',
+ description: '今日新增用户数'
+ },
+ todayOrderCount: {
+ type: 'integer',
+ description: '今日新增订单数'
+ }
+ }
+ },
+ // 用户统计数据模型
+ UserStats: {
type: 'object',
properties: {
total: {
type: 'integer',
- example: 100
+ description: '用户总数'
},
- page: {
- type: 'integer',
- example: 1
+ byType: {
+ type: 'array',
+ description: '按类型统计',
+ items: {
+ type: 'object',
+ properties: {
+ user_type: {
+ type: 'string'
+ },
+ count: {
+ type: 'integer'
+ }
+ }
+ }
},
- pageSize: {
+ byDate: {
+ type: 'array',
+ description: '按日期统计',
+ items: {
+ type: 'object',
+ properties: {
+ date: {
+ type: 'string'
+ },
+ count: {
+ type: 'integer'
+ }
+ }
+ }
+ }
+ }
+ },
+ // 订单统计数据模型
+ OrderStats: {
+ type: 'object',
+ properties: {
+ total: {
type: 'integer',
- example: 20
+ description: '订单总数'
},
- totalPages: {
+ totalAmount: {
+ type: 'number',
+ description: '订单总金额'
+ },
+ byStatus: {
+ type: 'array',
+ description: '按状态统计',
+ items: {
+ type: 'object',
+ properties: {
+ status: {
+ type: 'string'
+ },
+ count: {
+ type: 'integer'
+ }
+ }
+ }
+ },
+ byDate: {
+ type: 'array',
+ description: '按日期统计',
+ items: {
+ type: 'object',
+ properties: {
+ date: {
+ type: 'string'
+ },
+ count: {
+ type: 'integer'
+ },
+ amount: {
+ type: 'number'
+ }
+ }
+ }
+ }
+ }
+ },
+ // 系统信息模型
+ SystemInfo: {
+ type: 'object',
+ properties: {
+ nodeVersion: {
+ type: 'string',
+ description: 'Node.js版本'
+ },
+ platform: {
+ type: 'string',
+ description: '运行平台'
+ },
+ arch: {
+ type: 'string',
+ description: '系统架构'
+ },
+ uptime: {
type: 'integer',
- example: 5
- }
- }
- }
- },
- parameters: {
- // 通用分页参数
- PageParam: {
- in: 'query',
- name: 'page',
- schema: {
- type: 'integer',
- minimum: 1,
- default: 1
- },
- description: '页码'
- },
- PageSizeParam: {
- in: 'query',
- name: 'pageSize',
- schema: {
- type: 'integer',
- minimum: 1,
- maximum: 100,
- default: 20
- },
- description: '每页数量'
- }
- },
- responses: {
- // 通用响应
- UnauthorizedError: {
- description: '未授权访问',
- content: {
- 'application/json': {
- schema: {
- $ref: '#/components/schemas/ErrorResponse'
- },
- example: {
- success: false,
- code: 401,
- message: '未授权访问',
- error: 'Token已过期或无效',
- timestamp: '2025-01-01T00:00:00.000Z'
- }
- }
- }
- },
- ForbiddenError: {
- description: '禁止访问',
- content: {
- 'application/json': {
- schema: {
- $ref: '#/components/schemas/ErrorResponse'
- },
- example: {
- success: false,
- code: 403,
- message: '禁止访问',
- error: '权限不足',
- timestamp: '2025-01-01T00:00:00.000Z'
- }
- }
- }
- },
- NotFoundError: {
- description: '资源不存在',
- content: {
- 'application/json': {
- schema: {
- $ref: '#/components/schemas/ErrorResponse'
- },
- example: {
- success: false,
- code: 404,
- message: '资源不存在',
- error: '请求的资源不存在',
- timestamp: '2025-01-01T00:00:00.000Z'
- }
- }
- }
- },
- ValidationError: {
- description: '参数验证错误',
- content: {
- 'application/json': {
- schema: {
- $ref: '#/components/schemas/ErrorResponse'
- },
- example: {
- success: false,
- code: 400,
- message: '参数验证错误',
- error: '用户名必须为4-20个字符',
- timestamp: '2025-01-01T00:00:00.000Z'
- }
+ description: '运行时间(秒)'
+ },
+ databaseVersion: {
+ type: 'string',
+ description: '数据库版本'
}
}
}
@@ -333,20 +297,8 @@ const options = {
},
apis: [
'./src/routes/*.js',
- './src/controllers/*.js',
- './src/models/*.js'
+ './src/docs/*.js'
]
};
-const specs = swaggerJsdoc(options);
-
-module.exports = {
- swaggerUi,
- specs,
- serve: swaggerUi.serve,
- setup: swaggerUi.setup(specs, {
- explorer: true,
- customCss: '.swagger-ui .topbar { display: none }',
- customSiteTitle: '结伴客系统 API文档'
- })
-};
\ No newline at end of file
+module.exports = swaggerJsdoc(options);
\ No newline at end of file
diff --git a/backend/src/routes/admin.js b/backend/src/routes/admin.js
index 8001d7b..dae3806 100644
--- a/backend/src/routes/admin.js
+++ b/backend/src/routes/admin.js
@@ -1,7 +1,143 @@
+/**
+ * 系统统计控制器
+ * @module controllers/admin/systemStats
+ */
+
+/**
+ * 获取系统统计数据
+ * @function getSystemStats
+ * @param {Object} req - Express请求对象
+ * @param {Object} res - Express响应对象
+ * @param {Function} next - Express中间件next函数
+ */
+exports.getSystemStats = async (req, res, next) => {
+ try {
+ // 这里应该从数据库获取真实数据
+ const stats = {
+ userCount: 1000,
+ merchantCount: 50,
+ travelCount: 200,
+ animalCount: 300,
+ orderCount: 1500,
+ todayUserCount: 20,
+ todayOrderCount: 35
+ };
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取成功',
+ data: stats
+ });
+ } catch (error) {
+ next(error);
+ }
+};
+
+/**
+ * 获取用户统计数据
+ * @function getUserStats
+ * @param {Object} req - Express请求对象
+ * @param {Object} res - Express响应对象
+ * @param {Function} next - Express中间件next函数
+ */
+exports.getUserStats = async (req, res, next) => {
+ try {
+ // 这里应该从数据库获取真实数据
+ const userStats = {
+ total: 1000,
+ byType: [
+ { user_type: '普通用户', count: 900 },
+ { user_type: '商家', count: 50 },
+ { user_type: '管理员', count: 50 }
+ ],
+ byDate: [
+ { date: '2023-04-01', count: 10 },
+ { date: '2023-04-02', count: 15 },
+ { date: '2023-04-03', count: 20 }
+ ]
+ };
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取成功',
+ data: userStats
+ });
+ } catch (error) {
+ next(error);
+ }
+};
+
+/**
+ * 获取订单统计数据
+ * @function getOrderStats
+ * @param {Object} req - Express请求对象
+ * @param {Object} res - Express响应对象
+ * @param {Function} next - Express中间件next函数
+ */
+exports.getOrderStats = async (req, res, next) => {
+ try {
+ // 这里应该从数据库获取真实数据
+ const orderStats = {
+ total: 1500,
+ totalAmount: 100000,
+ byStatus: [
+ { status: '待支付', count: 100 },
+ { status: '已支付', count: 1200 },
+ { status: '已取消', count: 200 }
+ ],
+ byDate: [
+ { date: '2023-04-01', count: 50, amount: 2500 },
+ { date: '2023-04-02', count: 75, amount: 4000 },
+ { date: '2023-04-03', count: 100, amount: 6000 }
+ ]
+ };
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取成功',
+ data: orderStats
+ });
+ } catch (error) {
+ next(error);
+ }
+};
+
+/**
+ * 获取系统信息
+ * @function getSystemInfo
+ * @param {Object} req - Express请求对象
+ * @param {Object} res - Express响应对象
+ * @param {Function} next - Express中间件next函数
+ */
+exports.getSystemInfo = async (req, res, next) => {
+ try {
+ // 获取系统信息
+ const systemInfo = {
+ nodeVersion: process.version,
+ platform: process.platform,
+ arch: process.arch,
+ uptime: Math.floor(process.uptime()),
+ databaseVersion: 'MySQL 8.0.28' // 这里应该从数据库获取真实版本信息
+ };
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '获取成功',
+ data: systemInfo
+ });
+ } catch (error) {
+ next(error);
+ }
+};
// 管理员路由
const express = require('express');
const router = express.Router();
const adminController = require('../controllers/admin');
+const systemStatsController = require('../controllers/admin/systemStats');
const { authenticateAdmin } = require('../middleware/auth');
/**
@@ -62,16 +198,14 @@ const { authenticateAdmin } = require('../middleware/auth');
router.post('/login', adminController.login);
// 需要认证的接口
-router.use(authenticateAdmin);
-
/**
* @swagger
* /admin/profile:
* get:
- * summary: 获取当前管理员信息
+ * summary: 获取管理员个人信息
* tags: [Admin]
* security:
- * - bearerAuth: []
+ * - BearerAuth: []
* responses:
* 200:
* description: 获取成功
@@ -93,10 +227,12 @@ router.use(authenticateAdmin);
* $ref: '#/components/schemas/Admin'
* 401:
* description: 未授权
- * 404:
- * description: 管理员不存在
+ * content:
+ * application/json:
+ * schema:
+ * $ref: '#/components/schemas/ErrorResponse'
*/
-router.get('/profile', adminController.getProfile);
+router.get('/profile', authenticateAdmin, adminController.getProfile);
/**
* @swagger
@@ -324,4 +460,227 @@ router.put('/:id', adminController.update);
*/
router.delete('/:id', adminController.delete);
+/**
+ * @swagger
+ * /admin/system/stats:
+ * get:
+ * summary: 获取系统统计数据
+ * tags: [Admin]
+ * security:
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: 获取成功
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * success:
+ * type: boolean
+ * code:
+ * type: integer
+ * message:
+ * type: string
+ * data:
+ * type: object
+ * properties:
+ * userCount:
+ * type: integer
+ * description: 用户总数
+ * merchantCount:
+ * type: integer
+ * description: 商家数量
+ * travelCount:
+ * type: integer
+ * description: 旅行计划数
+ * animalCount:
+ * type: integer
+ * description: 动物数量
+ * orderCount:
+ * type: integer
+ * description: 订单总数
+ * todayUserCount:
+ * type: integer
+ * description: 今日新增用户数
+ * todayOrderCount:
+ * type: integer
+ * description: 今日新增订单数
+ * 401:
+ * description: 未授权
+ * content:
+ * application/json:
+ * schema:
+ * $ref: '#/components/schemas/ErrorResponse'
+ */
+router.get('/system/stats', authenticateAdmin, systemStatsController.getSystemStats);
+
+/**
+ * @swagger
+ * /admin/system/user-stats:
+ * get:
+ * summary: 获取用户统计数据
+ * tags: [Admin]
+ * security:
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: 获取成功
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * success:
+ * type: boolean
+ * code:
+ * type: integer
+ * message:
+ * type: string
+ * data:
+ * type: object
+ * properties:
+ * total:
+ * type: integer
+ * description: 用户总数
+ * byType:
+ * type: array
+ * description: 按类型统计
+ * items:
+ * type: object
+ * properties:
+ * user_type:
+ * type: string
+ * count:
+ * type: integer
+ * byDate:
+ * type: array
+ * description: 按日期统计
+ * items:
+ * type: object
+ * properties:
+ * date:
+ * type: string
+ * count:
+ * type: integer
+ * 401:
+ * description: 未授权
+ * content:
+ * application/json:
+ * schema:
+ * $ref: '#/components/schemas/ErrorResponse'
+ */
+router.get('/system/user-stats', authenticateAdmin, systemStatsController.getUserStats);
+
+/**
+ * @swagger
+ * /admin/system/order-stats:
+ * get:
+ * summary: 获取订单统计数据
+ * tags: [Admin]
+ * security:
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: 获取成功
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * success:
+ * type: boolean
+ * code:
+ * type: integer
+ * message:
+ * type: string
+ * data:
+ * type: object
+ * properties:
+ * total:
+ * type: integer
+ * description: 订单总数
+ * totalAmount:
+ * type: number
+ * description: 订单总金额
+ * byStatus:
+ * type: array
+ * description: 按状态统计
+ * items:
+ * type: object
+ * properties:
+ * status:
+ * type: string
+ * count:
+ * type: integer
+ * byDate:
+ * type: array
+ * description: 按日期统计
+ * items:
+ * type: object
+ * properties:
+ * date:
+ * type: string
+ * count:
+ * type: integer
+ * amount:
+ * type: number
+ * 401:
+ * description: 未授权
+ * content:
+ * application/json:
+ * schema:
+ * $ref: '#/components/schemas/ErrorResponse'
+ */
+router.get('/system/order-stats', authenticateAdmin, systemStatsController.getOrderStats);
+
+/**
+ * @swagger
+ * /admin/system/info:
+ * get:
+ * summary: 获取系统信息
+ * tags: [Admin]
+ * security:
+ * - BearerAuth: []
+ * responses:
+ * 200:
+ * description: 获取成功
+ * content:
+ * application/json:
+ * schema:
+ * type: object
+ * properties:
+ * success:
+ * type: boolean
+ * code:
+ * type: integer
+ * message:
+ * type: string
+ * data:
+ * type: object
+ * properties:
+ * nodeVersion:
+ * type: string
+ * description: Node.js版本
+ * platform:
+ * type: string
+ * description: 运行平台
+ * arch:
+ * type: string
+ * description: 系统架构
+ * uptime:
+ * type: integer
+ * description: 运行时间(秒)
+ * databaseVersion:
+ * type: string
+ * description: 数据库版本
+ * 401:
+ * description: 未授权
+ * content:
+ * application/json:
+ * schema:
+ * $ref: '#/components/schemas/ErrorResponse'
+ */
+router.get('/system/info', authenticateAdmin, systemStatsController.getSystemInfo);
+
module.exports = router;
\ No newline at end of file
diff --git a/backend/src/services/admin/systemStats.js b/backend/src/services/admin/systemStats.js
new file mode 100644
index 0000000..49a5484
--- /dev/null
+++ b/backend/src/services/admin/systemStats.js
@@ -0,0 +1,164 @@
+// 系统统计服务
+const database = require('../../config/database');
+
+class SystemStatsService {
+ /**
+ * 获取系统统计数据
+ * @returns {Promise