From 7fb22198c7d0208698eeff8a045ec3d3ee694d5b Mon Sep 17 00:00:00 2001 From: 18631081161 <2088094923@qq.com> Date: Fri, 3 Apr 2026 16:35:38 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=90=8E=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/components.d.ts | 4 + admin/package-lock.json | 26 ++ admin/package.json | 1 + admin/src/api/auth.ts | 6 + admin/src/api/dashboard.ts | 14 + admin/src/api/index.ts | 2 + admin/src/layout/AdminLayout.vue | 193 ++++++-- admin/src/views/dashboard/index.vue | 219 +++++++-- admin/src/views/login/index.vue | 23 +- .../Controllers/AdminAuthController.cs | 79 ++++ .../Controllers/AdminDashboardController.cs | 86 ++++ backend/src/VendingMachine.Api/Program.cs | 16 + .../src/VendingMachine.Api/appsettings.json | 4 +- .../Entities/AdminUser.cs | 10 + .../Data/AppDbContext.cs | 9 + .../20260403081502_AddAdminUser.Designer.cs | 432 ++++++++++++++++++ .../Migrations/20260403081502_AddAdminUser.cs | 43 ++ .../Migrations/AppDbContextModelSnapshot.cs | 29 ++ mobile/src/pages.json | 4 +- mobile/src/pages/about/index.vue | 2 +- .../{home => index}/CouponGuidePopup.vue | 0 .../src/pages/{home => index}/QrcodePopup.vue | 0 .../{home => index}/RedeemConfirmPopup.vue | 0 .../__tests__/home-properties.test.ts | 0 .../src/pages/{home => index}/home-logic.ts | 0 mobile/src/pages/{home => index}/index.vue | 0 mobile/src/pages/login/index.vue | 2 +- 27 files changed, 1135 insertions(+), 69 deletions(-) create mode 100644 admin/src/api/auth.ts create mode 100644 admin/src/api/dashboard.ts create mode 100644 backend/src/VendingMachine.Api/Controllers/AdminAuthController.cs create mode 100644 backend/src/VendingMachine.Api/Controllers/AdminDashboardController.cs create mode 100644 backend/src/VendingMachine.Domain/Entities/AdminUser.cs create mode 100644 backend/src/VendingMachine.Infrastructure/Data/Migrations/20260403081502_AddAdminUser.Designer.cs create mode 100644 backend/src/VendingMachine.Infrastructure/Data/Migrations/20260403081502_AddAdminUser.cs rename mobile/src/pages/{home => index}/CouponGuidePopup.vue (100%) rename mobile/src/pages/{home => index}/QrcodePopup.vue (100%) rename mobile/src/pages/{home => index}/RedeemConfirmPopup.vue (100%) rename mobile/src/pages/{home => index}/__tests__/home-properties.test.ts (100%) rename mobile/src/pages/{home => index}/home-logic.ts (100%) rename mobile/src/pages/{home => index}/index.vue (100%) diff --git a/admin/components.d.ts b/admin/components.d.ts index b854108d..8c427bbd 100644 --- a/admin/components.d.ts +++ b/admin/components.d.ts @@ -10,6 +10,9 @@ declare module 'vue' { export interface GlobalComponents { ElAlert: typeof import('element-plus/es')['ElAlert'] ElAside: typeof import('element-plus/es')['ElAside'] + ElAvatar: typeof import('element-plus/es')['ElAvatar'] + ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] + ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] ElButton: typeof import('element-plus/es')['ElButton'] ElCard: typeof import('element-plus/es')['ElCard'] ElCol: typeof import('element-plus/es')['ElCol'] @@ -36,6 +39,7 @@ declare module 'vue' { ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm'] ElRow: typeof import('element-plus/es')['ElRow'] + ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElSelect: typeof import('element-plus/es')['ElSelect'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] diff --git a/admin/package-lock.json b/admin/package-lock.json index 3e77d85a..b252bf93 100644 --- a/admin/package-lock.json +++ b/admin/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "axios": "^1.9.0", + "echarts": "^6.0.0", "element-plus": "^2.9.8", "pinia": "^3.0.2", "sortablejs": "^1.15.7", @@ -1829,6 +1830,16 @@ "node": ">= 0.4" } }, + "node_modules/echarts": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz", + "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "6.0.0" + } + }, "node_modules/element-plus": { "version": "2.13.6", "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.13.6.tgz", @@ -2757,6 +2768,12 @@ "node": ">=8.0" } }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -3130,6 +3147,15 @@ "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", "dev": true, "license": "MIT" + }, + "node_modules/zrender": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz", + "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } } } } diff --git a/admin/package.json b/admin/package.json index 29349745..8dbbbfdf 100644 --- a/admin/package.json +++ b/admin/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "axios": "^1.9.0", + "echarts": "^6.0.0", "element-plus": "^2.9.8", "pinia": "^3.0.2", "sortablejs": "^1.15.7", diff --git a/admin/src/api/auth.ts b/admin/src/api/auth.ts new file mode 100644 index 00000000..35de28c8 --- /dev/null +++ b/admin/src/api/auth.ts @@ -0,0 +1,6 @@ +import request from '@/utils/request' + +// 管理员认证 API +export function login(data: { username: string; password: string }) { + return request.post('/auth/login', data) +} diff --git a/admin/src/api/dashboard.ts b/admin/src/api/dashboard.ts new file mode 100644 index 00000000..1ba29da4 --- /dev/null +++ b/admin/src/api/dashboard.ts @@ -0,0 +1,14 @@ +import request from '@/utils/request' + +// 仪表盘 API +export function getDashboardStats() { + return request.get('/dashboard/stats') +} + +export function getUserTrend() { + return request.get('/dashboard/user-trend') +} + +export function getCouponDistribution() { + return request.get('/dashboard/coupon-distribution') +} diff --git a/admin/src/api/index.ts b/admin/src/api/index.ts index fc57b589..b49cfb57 100644 --- a/admin/src/api/index.ts +++ b/admin/src/api/index.ts @@ -1,7 +1,9 @@ // 管理后台 API 模块统一导出 +export * from './auth' export * from './banner' export * from './coupon' export * from './content' +export * from './dashboard' export * from './entry' export * from './membership' export * from './points' diff --git a/admin/src/layout/AdminLayout.vue b/admin/src/layout/AdminLayout.vue index 6f9bf38b..a514041b 100644 --- a/admin/src/layout/AdminLayout.vue +++ b/admin/src/layout/AdminLayout.vue @@ -1,43 +1,59 @@