From cfec4a16c05696e2d752ee703fe7d582087ff99c Mon Sep 17 00:00:00 2001 From: comlibmb <1844410276@qq.com> Date: Fri, 30 Jan 2026 16:11:23 +0800 Subject: [PATCH] =?UTF-8?q?mall=E6=95=B0=E6=8D=AE=E5=BA=93=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CRMEB | 1 - components/supadb/aksupa.uts | 50 + components/supadb/docs/CHANGELOG.md | 22 + .../supadb/{ => docs}/SIMPLIFIED_API_GUIDE.md | 0 .../supadb/{ => docs}/TYPED_QUERIES_README.md | 0 .../{ => docs}/TYPE_CONVERSION_FIX_SUMMARY.md | 0 components/supadb/{ => docs}/aksupareal.md | 0 mall_sql/README.md | 354 ++++ mall_sql/deploy.bat | 201 +++ mall_sql/deploy.sh | 247 +++ mall_sql/docs/FRONTEND_BACKEND_DEBUGGING.md | 875 ++++++++++ mall_sql/docs/MALL_README.md | 216 +++ mall_sql/docs/MIGRATION_CHECKLIST.md | 254 +++ mall_sql/docs/MIGRATION_GUIDE.md | 542 +++++++ mall_sql/docs/MIGRATION_SUMMARY.md | 180 +++ mall_sql/docs/MODULE_ANALYSIS.md | 710 ++++++++ mall_sql/docs/QUICK_START_MIGRATION.md | 111 ++ mall_sql/docs/README.md | 108 ++ mall_sql/docs/README_subscription_consumer.md | 16 + mall_sql/docs/ROLE_FIELD_FIX_REPORT.md | 151 ++ mall_sql/docs/ROLE_FIELD_SUMMARY.md | 172 ++ mall_sql/docs/TECHNICAL_IMPLEMENTATION.md | 1431 +++++++++++++++++ mall_sql/docs/UNI_APP_X_MIGRATION.md | 198 +++ mall_sql/docs/UPGRADE_GUIDE.md | 402 +++++ mall_sql/docs/VARIABLE_CONFLICT_FIX_REPORT.md | 224 +++ .../analysis/user_compatibility_analysis.md | 195 +++ mall_sql/docs/complete_deployment_guide.md | 231 +++ mall_sql/docs/database_creation_report.md | 186 +++ mall_sql/docs/database_syntax_fix_report.md | 153 ++ mall_sql/docs/deployment_guide.md | 223 +++ mall_sql/docs/migration_complete_report.md | 105 ++ mall_sql/docs/mock_data_documentation.md | 194 +++ mall_sql/docs/reports/detail_pages_report.md | 253 +++ mall_sql/docs/reports/profile_pages_report.md | 209 +++ .../docs/reports/system_generation_report.md | 204 +++ mall_sql/docs/seo_optimization_guide.md | 333 ++++ mall_sql/docs/seo_optimization_report.md | 247 +++ mall_sql/docs/type_error_fix_report.md | 153 ++ mall_sql/docs/user_reuse_summary.md | 138 ++ mall_sql/docs/裂变红包.md | 236 +++ mall_sql/scripts/migrate.ps1 | 190 +++ mall_sql/scripts/migrate.sh | 178 ++ pages/mall/analytics/coupon-analysis.uvue | 113 +- pages/mall/analytics/custom-report.uvue | 349 +++- pages/mall/analytics/data-detail.uvue | 264 +-- pages/mall/analytics/delivery-analysis.uvue | 129 +- pages/mall/analytics/index.uvue | 322 +--- pages/mall/analytics/insight-detail.uvue | 45 +- pages/mall/analytics/market-trends.uvue | 106 +- pages/mall/analytics/product-insights.uvue | 106 +- pages/mall/analytics/report-detail.uvue | 102 +- pages/mall/analytics/sales-report.uvue | 91 +- pages/mall/analytics/user-analysis.uvue | 3 +- pages/user/login.uvue | 16 + services/analytics/auth.uts | 21 + services/analytics/couponAnalysisService.uts | 41 + services/analytics/customReportService.uts | 87 + services/analytics/dashboardService.uts | 151 ++ services/analytics/dataDetailService.uts | 70 + services/analytics/dateRange.uts | 15 + .../analytics/deliveryAnalysisService.uts | 132 ++ services/analytics/errorMapper.uts | 53 + services/analytics/insightDetailService.uts | 67 + services/analytics/marketTrendsService.uts | 53 + services/analytics/productInsightsService.uts | 113 ++ services/analytics/reportDetailService.uts | 146 ++ services/analytics/rpc.uts | 42 + services/analytics/salesReportService.uts | 127 ++ services/analytics/userAnalysisService.uts | 121 ++ uni_modules/ak-req/ak-req.uts | 3 +- utils/utils.uts | 14 + 71 files changed, 11786 insertions(+), 1009 deletions(-) delete mode 160000 CRMEB create mode 100644 components/supadb/docs/CHANGELOG.md rename components/supadb/{ => docs}/SIMPLIFIED_API_GUIDE.md (100%) rename components/supadb/{ => docs}/TYPED_QUERIES_README.md (100%) rename components/supadb/{ => docs}/TYPE_CONVERSION_FIX_SUMMARY.md (100%) rename components/supadb/{ => docs}/aksupareal.md (100%) create mode 100644 mall_sql/README.md create mode 100644 mall_sql/deploy.bat create mode 100644 mall_sql/deploy.sh create mode 100644 mall_sql/docs/FRONTEND_BACKEND_DEBUGGING.md create mode 100644 mall_sql/docs/MALL_README.md create mode 100644 mall_sql/docs/MIGRATION_CHECKLIST.md create mode 100644 mall_sql/docs/MIGRATION_GUIDE.md create mode 100644 mall_sql/docs/MIGRATION_SUMMARY.md create mode 100644 mall_sql/docs/MODULE_ANALYSIS.md create mode 100644 mall_sql/docs/QUICK_START_MIGRATION.md create mode 100644 mall_sql/docs/README.md create mode 100644 mall_sql/docs/README_subscription_consumer.md create mode 100644 mall_sql/docs/ROLE_FIELD_FIX_REPORT.md create mode 100644 mall_sql/docs/ROLE_FIELD_SUMMARY.md create mode 100644 mall_sql/docs/TECHNICAL_IMPLEMENTATION.md create mode 100644 mall_sql/docs/UNI_APP_X_MIGRATION.md create mode 100644 mall_sql/docs/UPGRADE_GUIDE.md create mode 100644 mall_sql/docs/VARIABLE_CONFLICT_FIX_REPORT.md create mode 100644 mall_sql/docs/analysis/user_compatibility_analysis.md create mode 100644 mall_sql/docs/complete_deployment_guide.md create mode 100644 mall_sql/docs/database_creation_report.md create mode 100644 mall_sql/docs/database_syntax_fix_report.md create mode 100644 mall_sql/docs/deployment_guide.md create mode 100644 mall_sql/docs/migration_complete_report.md create mode 100644 mall_sql/docs/mock_data_documentation.md create mode 100644 mall_sql/docs/reports/detail_pages_report.md create mode 100644 mall_sql/docs/reports/profile_pages_report.md create mode 100644 mall_sql/docs/reports/system_generation_report.md create mode 100644 mall_sql/docs/seo_optimization_guide.md create mode 100644 mall_sql/docs/seo_optimization_report.md create mode 100644 mall_sql/docs/type_error_fix_report.md create mode 100644 mall_sql/docs/user_reuse_summary.md create mode 100644 mall_sql/docs/裂变红包.md create mode 100644 mall_sql/scripts/migrate.ps1 create mode 100644 mall_sql/scripts/migrate.sh create mode 100644 services/analytics/auth.uts create mode 100644 services/analytics/couponAnalysisService.uts create mode 100644 services/analytics/customReportService.uts create mode 100644 services/analytics/dashboardService.uts create mode 100644 services/analytics/dataDetailService.uts create mode 100644 services/analytics/dateRange.uts create mode 100644 services/analytics/deliveryAnalysisService.uts create mode 100644 services/analytics/errorMapper.uts create mode 100644 services/analytics/insightDetailService.uts create mode 100644 services/analytics/marketTrendsService.uts create mode 100644 services/analytics/productInsightsService.uts create mode 100644 services/analytics/reportDetailService.uts create mode 100644 services/analytics/rpc.uts create mode 100644 services/analytics/salesReportService.uts create mode 100644 services/analytics/userAnalysisService.uts diff --git a/CRMEB b/CRMEB deleted file mode 160000 index d3dba751..00000000 --- a/CRMEB +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d3dba751cabc8becc01843916c8e4a947379391b diff --git a/components/supadb/aksupa.uts b/components/supadb/aksupa.uts index c47057f4..c88778d4 100644 --- a/components/supadb/aksupa.uts +++ b/components/supadb/aksupa.uts @@ -624,6 +624,56 @@ export class AkSupa { this.baseUrl = baseUrl; this.apikey = apikey; this.storage = new AkSupaStorageApi(this); + // [CHANGE][2026-01-30] hydrate user/session from persisted token (see docs: components/supadb/docs/CHANGELOG.md) + try { + this.hydrateSessionFromStorage(); + } catch (e) { + // ignore + } + } + + // [CHANGE][2026-01-30] hydrate user from /auth/v1/user when token exists in storage + async hydrateSessionFromStorage() : Promise { + try { + const token = AkReq.getToken(); + if (token == null || token == '') return false; + const res = await AkReq.request({ + url: this.baseUrl + '/auth/v1/user', + method: 'GET', + headers: { + apikey: this.apikey, + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json' + } as UTSJSONObject + }, false); + const status = res.status ?? 0; + if (!(status >= 200 && status < 400)) { + return false; + } + let user: UTSJSONObject | null = null; + try { + user = new UTSJSONObject(res.data); + } catch (e) { + user = null; + } + if (user == null) return false; + this.user = user; + // 仅补齐最小 session 结构,供 getSession / UI 判断登录态使用 + if (this.session == null) { + this.session = { + access_token: token, + refresh_token: AkReq.getRefreshToken() ?? '', + expires_at: AkReq.getExpiresAt() ?? 0, + user: user, + token_type: 'bearer', + expires_in: 0, + raw: user + } as any; + } + return true; + } catch (e) { + return false; + } } async resetPassword(email : string) : Promise { diff --git a/components/supadb/docs/CHANGELOG.md b/components/supadb/docs/CHANGELOG.md new file mode 100644 index 00000000..9c6fef1e --- /dev/null +++ b/components/supadb/docs/CHANGELOG.md @@ -0,0 +1,22 @@ +# SupaDB 文档更新记录 + +## 2026-01-30 + +### AkSupa:从本地持久化 token 恢复 user/session + +- **文件**:`components/supadb/aksupa.uts` +- **位置**:`export class AkSupa` -> `constructor(baseUrl: string, apikey: string)`,以及新增方法 `hydrateSessionFromStorage()` +- **定位标记**:在代码中搜索 `// [CHANGE][2026-01-30]` + +#### 修改了什么 + +- 在 `AkSupa` 构造时,会尝试基于本地已持久化的 token(由 `AkReq.setToken` 写入 storage)恢复登录态。 +- 新增 `hydrateSessionFromStorage()`: + - 通过 `AkReq.getToken()` 读取本地 access token + - 若 token 存在,则请求 `GET {baseUrl}/auth/v1/user` + - 将返回的 user 写入 `this.user` + - 若 `this.session` 为空,则补齐一个最小 session 对象,使 `getSession()` 在「重启 App / 刷新页面」后仍能正确反映登录状态 + +#### 为什么要改 + +此前 `AkReq` 会把 token 持久化到本地,但 `AkSupa` 启动时不会自动恢复 `this.user` / `this.session`,导致即使 token 仍有效,`getSession()` 也可能返回 `{ session: null, user: null }`,从而使依赖登录态的页面判断失败。 diff --git a/components/supadb/SIMPLIFIED_API_GUIDE.md b/components/supadb/docs/SIMPLIFIED_API_GUIDE.md similarity index 100% rename from components/supadb/SIMPLIFIED_API_GUIDE.md rename to components/supadb/docs/SIMPLIFIED_API_GUIDE.md diff --git a/components/supadb/TYPED_QUERIES_README.md b/components/supadb/docs/TYPED_QUERIES_README.md similarity index 100% rename from components/supadb/TYPED_QUERIES_README.md rename to components/supadb/docs/TYPED_QUERIES_README.md diff --git a/components/supadb/TYPE_CONVERSION_FIX_SUMMARY.md b/components/supadb/docs/TYPE_CONVERSION_FIX_SUMMARY.md similarity index 100% rename from components/supadb/TYPE_CONVERSION_FIX_SUMMARY.md rename to components/supadb/docs/TYPE_CONVERSION_FIX_SUMMARY.md diff --git a/components/supadb/aksupareal.md b/components/supadb/docs/aksupareal.md similarity index 100% rename from components/supadb/aksupareal.md rename to components/supadb/docs/aksupareal.md diff --git a/mall_sql/README.md b/mall_sql/README.md new file mode 100644 index 00000000..08007f3d --- /dev/null +++ b/mall_sql/README.md @@ -0,0 +1,354 @@ +# Mall SQL 数据库脚本集合 + +> **电商商城系统** - PostgreSQL + Supabase 数据库脚本总目录 + +--- + +## 📁 目录结构 + +``` +mall_sql/ +├── schemas/ # 数据库表结构定义 +├── migrations/ # 数据库迁移/升级脚本 +├── tests/ # 测试和验证脚本 +├── subscription/ # 订阅系统专用脚本 +├── scripts/ # 迁移脚本 (migrate.sh/ps1) +├── docs/ # 数据库文档 +├── deploy.sh # Linux/Mac 自动部署脚本 +├── deploy.bat # Windows 自动部署脚本 +└── README.md # 本文件 +``` + +--- + +## 🚀 快速开始 + +### 首次部署(全新数据库) + +```bash +# 1. 执行完整数据库创建 +psql -h db.example.com -U postgres -d akmon -f schemas/complete_mall_database.sql + +# 2. 创建测试用户和模拟数据 +psql -h db.example.com -U postgres -d akmon -f tests/mock_data_insert.sql +``` + +### 增量升级(已有数据库) + +```bash +# 1. 先检查数据库状态 +psql -h db.example.com -U postgres -d akmon -f tests/mall_database_check.sql + +# 2. 执行增量升级 +psql -h db.example.com -U postgres -d akmon -f migrations/mall_alter_upgrade.sql +``` + +--- + +## 📦 schemas/ - 数据库表结构 + +| 文件 | 说明 | 执行顺序 | +|------|------|----------| +| `complete_mall_database.sql` | 完整商城数据库(21个表)**推荐** | 1 | +| `ak_contents_product_extension.sql` | **备选方案**: 基于ak_contents扩展商品 | - | +| `product_database.sql` | 商品相关表补充 | 2 | +| `mall_seo_security.sql` | SEO优化和安全策略 | 3 | + +### 两种实现方案 + +**方案一: 独立商城表(推荐)** +- 使用 `ml_products` 等独立表 +- 执行: `complete_mall_database.sql` +- 优点: 职责清晰,不影响资讯系统 + +**方案二: 扩展ak_contents表(备选)** +- 复用 `ak_contents` 表,添加商品字段 +- 执行: `ak_contents_product_extension.sql` +- 优点: 统一内容管理,但混合了资讯和商品 + +### complete_mall_database.sql + +完整的商城系统数据库定义,包含: + +**用户模块**: +- `ml_user_profiles` - 用户扩展信息 +- `ml_user_addresses` - 用户地址 + +**商品模块**: +- `ml_categories` - 商品分类 +- `ml_brands` - 品牌 +- `ml_products` - 商品主表 +- `ml_product_skus` - SKU规格 +- `ml_product_images` - 商品图片 + +**订单模块**: +- `ml_orders` - 订单主表 +- `ml_order_items` - 订单明细 +- `ml_order_status_log` - 订单状态日志 + +**配送模块**: +- `ml_delivery_tasks` - 配送任务 +- `ml_delivery_tracking` - 配送跟踪 + +**支付模块**: +- `ml_payments` - 支付记录 + +**营销模块**: +- `ml_coupons` - 优惠券 +- `ml_user_coupons` - 用户优惠券 + +**订阅模块**: +- `ml_subscriptions` - 订阅计划 +- `ml_user_subscriptions` - 用户订阅 + +--- + +## 🔄 migrations/ - 数据库迁移 + +| 文件 | 说明 | 使用场景 | +|------|------|----------| +| `mall_alter_upgrade.sql` | 完整增量升级 | 生产环境升级 | +| `mall_fields_only_upgrade.sql` | 仅字段升级 | 最小化修改 | +| `quick_role_migration.sql` | 角色字段快速迁移 | user_type→role | +| `mall_migration.sql` | 通用迁移脚本 | 兼容性处理 | +| `role_field_unification.sql` | 角色字段统一 | 数据一致性 | +| `role_field_cleanup.sql` | 角色字段清理 | 清理冗余字段 | +| `user_compatibility_implementation.sql` | 用户兼容性实现 | 跨模块兼容 | + +### 重要迁移说明 + +**角色字段统一**: +- 旧字段: `user_type` (INTEGER) +- 新字段: `role` (TEXT) +- 迁移脚本: `quick_role_migration.sql` + +**角色值映射**: +| user_type | role | +|-----------|------| +| 1 | 'admin' | +| 2 | 'merchant' | +| 3 | 'customer' | +| 4 | 'delivery' | +| 5 | 'service' | + +--- + +## 🧪 tests/ - 测试和验证 + +| 文件 | 说明 | +|------|------| +| `mall_database_check.sql` | 数据库状态检查 | +| `validation_test.sql` | 数据完整性验证 | +| `verify_mock_data_fix.sql` | 模拟数据修复验证 | +| `mock_data_insert.sql` | 创建测试数据 | +| `create_supabase_auth_users.sql` | 创建Supabase Auth用户 | + +### 测试数据说明 + +`mock_data_insert.sql` 创建以下测试数据: +- 1个管理员 +- 2个商家 +- 10个商品 +- 3个客户 +- 20个订单 +- 2个配送员 +- 5个配送任务 + +--- + +## 📬 subscription/ - 订阅系统 + +| 文件 | 说明 | +|------|------| +| `create_mall_subscription_tables.sql` | 订阅表创建 | +| `subscription_guard_trigger.sql` | 订阅守护触发器 | +| `subscription_rls_policies.sql` | 订阅RLS安全策略 | + +### 订阅系统表 + +- `ml_subscriptions` - 订阅计划定义 +- `ml_user_subscriptions` - 用户订阅记录 +- `ml_subscription_payments` - 订阅支付记录 + +--- + +## 📚 docs/ - 文档 + +### 核心文档 +| 文件 | 说明 | +|------|------| +| `MALL_README.md` | 商城系统主文档 | +| `TECHNICAL_IMPLEMENTATION.md` | 技术实现详解 | +| `MODULE_ANALYSIS.md` | 模块分析 | + +### 部署与升级 +| 文件 | 说明 | +|------|------| +| `UPGRADE_GUIDE.md` | 数据库升级指南 | +| `MIGRATION_GUIDE.md` | 迁移指南 | +| `QUICK_START_MIGRATION.md` | 快速迁移指南 | +| `MIGRATION_CHECKLIST.md` | 迁移检查清单 | +| `MIGRATION_SUMMARY.md` | 迁移总结 | +| `complete_deployment_guide.md` | 完整部署指南 | +| `deployment_guide.md` | 部署指南 | +| `migration_complete_report.md` | 迁移完成报告 | + +### 角色与权限 +| 文件 | 说明 | +|------|------| +| `ROLE_FIELD_SUMMARY.md` | 角色字段变更总结 | +| `ROLE_FIELD_FIX_REPORT.md` | 角色字段修复报告 | +| `user_reuse_summary.md` | 用户复用总结 | + +### 问题修复报告 +| 文件 | 说明 | +|------|------| +| `VARIABLE_CONFLICT_FIX_REPORT.md` | 变量冲突修复 | +| `database_syntax_fix_report.md` | 数据库语法修复 | +| `type_error_fix_report.md` | 类型错误修复 | + +### 测试与数据 +| 文件 | 说明 | +|------|------| +| `mock_data_documentation.md` | 测试数据文档 | +| `database_creation_report.md` | 数据库创建报告 | +| `FRONTEND_BACKEND_DEBUGGING.md` | 前后端调试指南 | + +### SEO与优化 +| 文件 | 说明 | +|------|------| +| `seo_optimization_guide.md` | SEO优化指南 | +| `seo_optimization_report.md` | SEO优化报告 | + +### 订阅系统 +| 文件 | 说明 | +|------|------| +| `README_subscription_consumer.md` | 订阅系统说明 | +| `裂变红包.md` | 裂变红包功能 | + +### 页面报告 +| 目录 | 说明 | +|------|------| +| `docs/reports/` | 页面生成报告 | +| `docs/analysis/` | 兼容性分析 | + +--- + +## 🗄️ 数据库表总览 + +``` +akmon (PostgreSQL Database) +│ +├── public.ak_users # 用户主表(共享) +│ +└── public.ml_* (商城系统表,21张) + ├── ml_user_profiles # 用户扩展信息 + ├── ml_user_addresses # 用户地址 + ├── ml_categories # 商品分类 + ├── ml_brands # 品牌 + ├── ml_products # 商品 + ├── ml_product_skus # SKU + ├── ml_product_images # 商品图片 + ├── ml_orders # 订单 + ├── ml_order_items # 订单明细 + ├── ml_order_status_log # 订单日志 + ├── ml_delivery_tasks # 配送任务 + ├── ml_delivery_tracking # 配送跟踪 + ├── ml_payments # 支付 + ├── ml_coupons # 优惠券 + ├── ml_user_coupons # 用户优惠券 + ├── ml_subscriptions # 订阅计划 + ├── ml_user_subscriptions # 用户订阅 + ├── ml_subscription_payments # 订阅支付 + ├── ml_merchant_profiles # 商家资料 + ├── ml_delivery_staff # 配送员 + └── ml_notifications # 通知 +``` + +--- + +## 🔧 常用SQL操作 + +### 检查表是否存在 +```sql +SELECT table_name, table_type +FROM information_schema.tables +WHERE table_schema = 'public' + AND table_name LIKE 'ml_%' +ORDER BY table_name; +``` + +### 查看表结构 +```sql +\d+ public.ml_products +-- 或 +SELECT column_name, data_type, is_nullable, column_default +FROM information_schema.columns +WHERE table_schema = 'public' + AND table_name = 'ml_products' +ORDER BY ordinal_position; +``` + +### 检查索引 +```sql +SELECT indexname, indexdef +FROM pg_indexes +WHERE schemaname = 'public' + AND tablename LIKE 'ml_%' +ORDER BY tablename, indexname; +``` + +### 检查RLS策略 +```sql +SELECT schemaname, tablename, policyname, permissive, roles, cmd, qual +FROM pg_policies +WHERE schemaname = 'public' + AND tablename LIKE 'ml_%' +ORDER BY tablename, policyname; +``` + +--- + +## ⚠️ 注意事项 + +### 执行顺序 + +1. **全新部署**: 按以下顺序执行 + - `schemas/complete_mall_database.sql` + - `schemas/product_database.sql` + - `schemas/mall_seo_security.sql` + - `subscription/create_mall_subscription_tables.sql` + - `tests/mock_data_insert.sql` + +2. **增量升级**: 先检查后升级 + - `tests/mall_database_check.sql` + - 根据检查结果选择合适的迁移脚本 + - `tests/validation_test.sql` + +### Supabase Auth 用户 + +在执行任何脚本之前,**必须先创建 Supabase Auth 用户**: +```bash +psql -f tests/create_supabase_auth_users.sql +``` + +### 角色字段兼容性 + +如果你的数据库使用旧的 `user_type` 字段,请先执行角色迁移: +```bash +psql -f migrations/quick_role_migration.sql +``` + +--- + +## 📞 支持 + +如有问题,请查阅: +1. `docs/complete_deployment_guide.md` - 完整部署指南 +2. `docs/UPGRADE_GUIDE.md` - 升级指南 +3. `docs/ROLE_FIELD_SUMMARY.md` - 角色字段说明 + +--- + +**最后更新**: 2026-01-30 +**维护者**: AKMON开发团队 diff --git a/mall_sql/deploy.bat b/mall_sql/deploy.bat new file mode 100644 index 00000000..8a2184cd --- /dev/null +++ b/mall_sql/deploy.bat @@ -0,0 +1,201 @@ +@echo off +REM ================================================================================ +REM Mall SQL 自动部署脚本 (Windows) +REM ================================================================================ +REM 用途:自动执行商城数据库脚本 +REM 使用:deploy.bat [选项] +REM +REM 选项: +REM --full 完整部署(删除重建) +REM --upgrade 增量升级 +REM --check 仅检查数据库状态 +REM --test 创建测试数据 +REM --help 显示帮助 +REM ================================================================================ + +setlocal enabledelayedexpansion + +REM 默认配置 +if "%DB_HOST%"=="" set DB_HOST=localhost +if "%DB_PORT%"=="" set DB_PORT=5432 +if "%DB_NAME%"=="" set DB_NAME=akmon +if "%DB_USER%"=="" set DB_USER=postgres + +set SCHEMA_DIR=schemas +set MIGRATION_DIR=migrations +set TEST_DIR=tests +set SUBSCRIPTION_DIR=subscription + +REM 显示帮助 +if "%1"=="--help" goto :show_help +if "%1"=="-h" goto :show_help + +echo ========================================== +echo Mall SQL 自动部署脚本 +echo ========================================== +echo 数据库: %DB_USER%@%DB_HOST%:%DB_PORT%/%DB_NAME% +echo ========================================== +echo. + +REM 检查连接 +echo [INFO] 检查数据库连接... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -c "\q" >nul 2>&1 +if errorlevel 1 ( + echo [ERROR] 无法连接到数据库 + echo 请检查环境变量或连接信息 + goto :end +) +echo [SUCCESS] 数据库连接成功 +echo. + +REM 解析参数 +if "%1"=="--full" goto :deploy_full +if "%1"=="--upgrade" goto :deploy_upgrade +if "%1"=="--check" goto :check_database +if "%1"=="--test" goto :create_test_data +if "%1"=="--subscription" goto :deploy_subscription + +echo [ERROR] 未知选项: %1% +echo. +goto :show_help + +:deploy_full +echo ========================================== +echo [WARNING] 完整部署将重建所有商城表! +echo ========================================== +set /p confirm="确认继续? (yes/no): " +if /i not "%confirm%"=="yes" ( + echo [INFO] 已取消 + goto :end +) + +echo [INFO] 开始完整部署... + +echo [INFO] 执行: 创建商城核心表... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SCHEMA_DIR%\complete_mall_database.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 创建商品补充表... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SCHEMA_DIR%\product_database.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 配置SEO和安全策略... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SCHEMA_DIR%\mall_seo_security.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 创建订阅表... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SUBSCRIPTION_DIR%\create_mall_subscription_tables.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 创建订阅触发器... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SUBSCRIPTION_DIR%\subscription_guard_trigger.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 创建订阅RLS策略... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SUBSCRIPTION_DIR%\subscription_rls_policies.sql +if errorlevel 1 goto :error + +echo. +echo [SUCCESS] 完整部署完成! +echo [INFO] 接下来可以运行: deploy.bat --test +goto :end + +:deploy_upgrade +echo [INFO] 开始增量升级... + +echo [INFO] 执行: 数据库状态检查... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %TEST_DIR%\mall_database_check.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 增量升级... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %MIGRATION_DIR%\mall_alter_upgrade.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 数据完整性验证... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %TEST_DIR%\validation_test.sql +if errorlevel 1 goto :error + +echo. +echo [SUCCESS] 增量升级完成! +goto :end + +:check_database +echo [INFO] 检查数据库状态... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %TEST_DIR%\mall_database_check.sql +if errorlevel 1 goto :error +echo [SUCCESS] 检查完成 +goto :end + +:create_test_data +echo [INFO] 创建测试数据... + +echo [INFO] 执行: 创建测试用户... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %TEST_DIR%\create_supabase_auth_users.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 创建模拟数据... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %TEST_DIR%\mock_data_insert.sql +if errorlevel 1 goto :error + +echo [INFO] 执行: 验证测试数据... +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %TEST_DIR%\verify_mock_data_fix.sql +if errorlevel 1 goto :error + +echo. +echo [SUCCESS] 测试数据创建完成! +goto :end + +:deploy_subscription +echo [INFO] 部署订阅系统... + +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SUBSCRIPTION_DIR%\create_mall_subscription_tables.sql +if errorlevel 1 goto :error + +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SUBSCRIPTION_DIR%\subscription_guard_trigger.sql +if errorlevel 1 goto :error + +psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -f %SUBSCRIPTION_DIR%\subscription_rls_policies.sql +if errorlevel 1 goto :error + +echo [SUCCESS] 订阅系统部署完成! +goto :end + +:show_help +echo Mall SQL 自动部署脚本 (Windows) +echo. +echo 用法: deploy.bat [选项] +echo. +echo 选项: +echo --full 完整部署(删除重建) +echo --upgrade 增量升级(保留现有数据) +echo --check 检查数据库状态 +echo --test 创建测试数据 +echo --subscription 部署订阅系统 +echo --help 显示此帮助信息 +echo. +echo 环境变量: +echo DB_HOST 数据库主机 (默认: localhost) +echo DB_PORT 数据库端口 (默认: 5432) +echo DB_NAME 数据库名称 (默认: akmon) +echo DB_USER 数据库用户 (默认: postgres) +echo. +echo 示例: +echo 完整部署 +echo deploy.bat --full +echo. +echo 增量升级 +echo deploy.bat --upgrade +echo. +echo 使用自定义数据库 +echo set DB_HOST=prod.example.com +echo set DB_NAME=akmon_prod +echo deploy.bat --upgrade +goto :end + +:error +echo. +echo [ERROR] 部署失败!请检查错误信息。 +exit /b 1 + +:end +endlocal diff --git a/mall_sql/deploy.sh b/mall_sql/deploy.sh new file mode 100644 index 00000000..420127e0 --- /dev/null +++ b/mall_sql/deploy.sh @@ -0,0 +1,247 @@ +#!/bin/bash +# ================================================================================ +# Mall SQL 自动部署脚本 +# ================================================================================ +# 用途:自动执行商城数据库脚本 +# 使用:./deploy.sh [选项] +# +# 选项: +# --full 完整部署(删除重建) +# --upgrade 增量升级 +# --check 仅检查数据库状态 +# --test 创建测试数据 +# --help 显示帮助 +# ================================================================================ + +set -e # 遇到错误立即退出 + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 默认配置 +DB_HOST="${DB_HOST:-localhost}" +DB_PORT="${DB_PORT:-5432}" +DB_NAME="${DB_NAME:-akmon}" +DB_USER="${DB_USER:-postgres}" +SCHEMA_DIR="schemas" +MIGRATION_DIR="migrations" +TEST_DIR="tests" +SUBSCRIPTION_DIR="subscription" + +# 日志函数 +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 显示帮助 +show_help() { + cat << EOF +Mall SQL 自动部署脚本 + +用法: $0 [选项] + +选项: + --full 完整部署(删除重建数据库) + --upgrade 增量升级(保留现有数据) + --check 检查数据库状态 + --test 创建测试数据 + --subscription 部署订阅系统 + --help 显示此帮助信息 + +环境变量: + DB_HOST 数据库主机 (默认: localhost) + DB_PORT 数据库端口 (默认: 5432) + DB_NAME 数据库名称 (默认: akmon) + DB_USER 数据库用户 (默认: postgres) + +示例: + # 完整部署 + $0 --full + + # 增量升级 + $0 --upgrade + + # 检查状态 + $0 --check + + # 使用自定义数据库 + DB_HOST=prod.example.com DB_NAME=akmon_prod $0 --upgrade +EOF +} + +# 检查数据库连接 +check_connection() { + log_info "检查数据库连接..." + + if psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c '\q' 2>/dev/null; then + log_success "数据库连接成功" + return 0 + else + log_error "无法连接到数据库: $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME" + return 1 + fi +} + +# 执行SQL文件 +execute_sql() { + local sql_file=$1 + local description=$2 + + log_info "执行: $description" + + if [ ! -f "$sql_file" ]; then + log_error "文件不存在: $sql_file" + return 1 + fi + + if psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$sql_file"; then + log_success "完成: $description" + return 0 + else + log_error "失败: $description" + return 1 + fi +} + +# 检查数据库状态 +check_database() { + log_info "检查数据库状态..." + execute_sql "$TEST_DIR/mall_database_check.sql" "数据库状态检查" +} + +# 完整部署 +deploy_full() { + log_warning "==========================================" + log_warning "完整部署将重建所有商城表!" + log_warning "==========================================" + read -p "确认继续? (yes/no): " confirm + + if [ "$confirm" != "yes" ]; then + log_info "已取消" + return 0 + fi + + log_info "开始完整部署..." + + # 1. 完整数据库 + execute_sql "$SCHEMA_DIR/complete_mall_database.sql" "创建商城核心表" + + # 2. 商品表补充 + execute_sql "$SCHEMA_DIR/product_database.sql" "创建商品补充表" + + # 3. SEO和安全 + execute_sql "$SCHEMA_DIR/mall_seo_security.sql" "配置SEO和安全策略" + + # 4. 订阅系统 + execute_sql "$SUBSCRIPTION_DIR/create_mall_subscription_tables.sql" "创建订阅表" + execute_sql "$SUBSCRIPTION_DIR/subscription_guard_trigger.sql" "创建订阅触发器" + execute_sql "$SUBSCRIPTION_DIR/subscription_rls_policies.sql" "创建订阅RLS策略" + + log_success "完整部署完成!" + log_info "接下来可以运行: $0 --test" +} + +# 增量升级 +deploy_upgrade() { + log_info "开始增量升级..." + + # 1. 先检查 + check_database + + # 2. 执行升级 + execute_sql "$MIGRATION_DIR/mall_alter_upgrade.sql" "增量升级" + + # 3. 验证 + execute_sql "$TEST_DIR/validation_test.sql" "数据完整性验证" + + log_success "增量升级完成!" +} + +# 创建测试数据 +create_test_data() { + log_info "创建测试数据..." + + # 1. 先创建Auth用户 + execute_sql "$TEST_DIR/create_supabase_auth_users.sql" "创建测试用户" + + # 2. 创建模拟数据 + execute_sql "$TEST_DIR/mock_data_insert.sql" "创建模拟数据" + + # 3. 验证 + execute_sql "$TEST_DIR/verify_mock_data_fix.sql" "验证测试数据" + + log_success "测试数据创建完成!" +} + +# 部署订阅系统 +deploy_subscription() { + log_info "部署订阅系统..." + + execute_sql "$SUBSCRIPTION_DIR/create_mall_subscription_tables.sql" "创建订阅表" + execute_sql "$SUBSCRIPTION_DIR/subscription_guard_trigger.sql" "创建订阅触发器" + execute_sql "$SUBSCRIPTION_DIR/subscription_rls_policies.sql" "创建订阅RLS策略" + + log_success "订阅系统部署完成!" +} + +# 主函数 +main() { + echo "==========================================" + echo " Mall SQL 自动部署脚本" + echo "==========================================" + echo "数据库: $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME" + echo "==========================================" + echo "" + + # 检查连接 + if ! check_connection; then + exit 1 + fi + + # 解析参数 + case "${1:-}" in + --full) + deploy_full + ;; + --upgrade) + deploy_upgrade + ;; + --check) + check_database + ;; + --test) + create_test_data + ;; + --subscription) + deploy_subscription + ;; + --help|-h) + show_help + ;; + *) + log_error "未知选项: ${1:-}" + echo "" + show_help + exit 1 + ;; + esac +} + +# 运行主函数 +main "$@" diff --git a/mall_sql/docs/FRONTEND_BACKEND_DEBUGGING.md b/mall_sql/docs/FRONTEND_BACKEND_DEBUGGING.md new file mode 100644 index 00000000..e08d77c7 --- /dev/null +++ b/mall_sql/docs/FRONTEND_BACKEND_DEBUGGING.md @@ -0,0 +1,875 @@ +# 🔧 前端与后端联调指南 + +## 📋 目录 +1. [联调环境配置](#联调环境配置) +2. [本地开发环境搭建](#本地开发环境搭建) +3. [前端连接后端](#前端连接后端) +4. [调试工具和方法](#调试工具和方法) +5. [常见联调场景](#常见联调场景) +6. [问题排查](#问题排查) + +--- + +## 一、联调环境配置 + +### 1.1 环境类型 + +#### 开发环境 (Development) +- **Supabase 本地实例**: Docker Compose 运行在 `192.168.0.150:8080` +- **Supabase 云服务**: 使用开发项目 +- **前端**: uni-app-x 开发模式 + +#### 生产环境 (Production) +- **Supabase 云服务**: 生产项目 +- **前端**: 编译后的应用 + +### 1.2 配置文件位置 + +#### 前端配置 +**文件**: `ak/config.uts` + +```typescript +// 开发环境 - 本地 Supabase +export const SUPA_URL: string = 'http://192.168.0.150:8080' +export const SUPA_KEY: string = 'your-anon-key' + +// 生产环境 - Supabase 云服务 +export const SUPA_URL: string = 'https://ak3.oulog.com' +export const SUPA_KEY: string = 'your-anon-key' + +// WebSocket 实时连接 +export const WS_URL: string = 'wss://ak3.oulog.com/realtime/v1/websocket' +``` + +#### 后端配置 (Docker) +**文件**: `doc_chat/supa.env` + +```env +# Supabase 本地配置 +POSTGRES_HOST=db +POSTGRES_DB=postgres +POSTGRES_PORT=5432 +POSTGRES_PASSWORD=your-password + +# API 配置 +KONG_HTTP_PORT=8000 +KONG_HTTPS_PORT=8443 + +# Auth 配置 +API_EXTERNAL_URL=http://localhost:8000 +SITE_URL=http://localhost:3000 +``` + +--- + +## 二、本地开发环境搭建 + +### 2.1 Supabase 本地实例启动 + +#### 方式一: Docker Compose (推荐) + +```bash +# 1. 进入 Supabase 目录 +cd doc_chat + +# 2. 启动 Supabase 服务 +docker-compose -f supa-docker-compose.yml up -d + +# 3. 检查服务状态 +docker-compose -f supa-docker-compose.yml ps + +# 4. 查看日志 +docker-compose -f supa-docker-compose.yml logs -f +``` + +**服务端口**: +- **API**: `http://localhost:8000` 或 `http://192.168.0.150:8080` +- **PostgreSQL**: `localhost:5432` +- **Dashboard**: `http://localhost:3000` + +#### 方式二: Supabase CLI + +```bash +# 1. 安装 Supabase CLI +npm install -g supabase + +# 2. 初始化项目 +supabase init + +# 3. 启动本地实例 +supabase start + +# 4. 查看服务信息 +supabase status +``` + +### 2.2 数据库初始化 + +```bash +# 1. 执行商城数据库脚本 +psql -h localhost -U postgres -d postgres -f doc_mall/database/complete_mall_database.sql + +# 或使用 Supabase Dashboard SQL Editor +# 1. 打开 http://localhost:3000 +# 2. 进入 SQL Editor +# 3. 复制粘贴 complete_mall_database.sql 内容 +# 4. 执行脚本 + +# 2. 插入模拟数据 (可选) +psql -h localhost -U postgres -d postgres -f doc_mall/database/mock_data_insert.sql + +# 3. 验证数据库 +psql -h localhost -U postgres -d postgres -f doc_mall/database/validation_test.sql +``` + +### 2.3 前端开发环境 + +```bash +# 1. 安装依赖 (如果使用 npm) +npm install + +# 2. 启动 uni-app-x 开发服务器 +# 在 HBuilderX 中: +# - 运行 -> 运行到浏览器/手机模拟器 +# - 或使用命令行工具 + +# 3. 配置开发环境 +# 修改 ak/config.uts 中的 SUPA_URL 和 SUPA_KEY +``` + +--- + +## 三、前端连接后端 + +### 3.1 Supabase 客户端初始化 + +#### 全局单例模式 +**文件**: `components/supadb/aksupainstance.uts` + +```typescript +import AkSupa from './aksupa.uts' +import { SUPA_URL, SUPA_KEY } from '@/ak/config.uts' + +// 创建全局 Supabase 客户端实例 +const supa = new AkSupa(SUPA_URL, SUPA_KEY) + +// 自动登录 (开发环境) +const supaReady: Promise = (async () => { + try { + await supa.signIn('test@example.com', 'password') + return true + } catch (err) { + console.error('Supabase auto sign-in failed', err) + return false + } +})() + +export { supaReady } +export default supa +``` + +#### 在页面中使用 + +```typescript +// pages/mall/consumer/index.uvue + +``` + +### 3.2 API 调用方式 + +#### 3.2.1 查询数据 (SELECT) + +```typescript +// 简单查询 +const res = await supa.select('ml_products', null, { + limit: 10, + order: 'created_at.desc' +}) + +// 带过滤条件 +const res = await supa.select('ml_products', { + status: 1, + category_id: categoryId +}, { + limit: 20, + order: 'sale_count.desc' +}) + +// 复杂过滤 (PostgREST 操作符) +const res = await supa.select('ml_products', { + base_price: { gte: 100, lte: 500 }, + name: { ilike: '%商品%' }, + category_id: { in: [id1, id2, id3] } +}, { + limit: 20 +}) + +// 单条记录 +const res = await supa.select('ml_products', { id: productId }, { + single: true +}) + +// 选择特定字段 +const res = await supa.select('ml_products', null, { + columns: 'id,name,base_price,main_image_url', + limit: 20 +}) +``` + +#### 3.2.2 插入数据 (INSERT) + +```typescript +// 插入订单 +const orderRes = await supa.insert('ml_orders', { + user_id: userId, + merchant_id: merchantId, + total_amount: 100.00, + order_status: 1, + payment_status: 1, + shipping_status: 1, + shipping_address: { + receiver_name: '张三', + receiver_phone: '13800138000', + address_detail: '北京市朝阳区xxx' + } +}) + +// 批量插入 +const items = [ + { order_id: orderId, product_id: productId1, quantity: 2 }, + { order_id: orderId, product_id: productId2, quantity: 1 } +] +const itemsRes = await supa.insert('ml_order_items', items) +``` + +#### 3.2.3 更新数据 (UPDATE) + +```typescript +// 更新商品状态 +await supa.update('ml_products', + { id: productId }, // 过滤条件 + { + status: 2, // 下架 + updated_at: new Date().toISOString() + } +) + +// 更新订单状态 +await supa.update('ml_orders', + { id: orderId }, + { + order_status: 2, // 待发货 + updated_at: new Date().toISOString() + } +) +``` + +#### 3.2.4 删除数据 (DELETE) + +```typescript +// 删除收藏 +await supa.delete('ml_user_favorites', { id: favoriteId }) + +// 删除购物车商品 +await supa.delete('ml_shopping_cart', { + user_id: userId, + product_id: productId +}) +``` + +#### 3.2.5 调用数据库函数 (RPC) + +```typescript +// 计算购物车总金额 +const totalRes = await supa.rpc('calculate_cart_total', { + p_user_id: userId +}) + +// 生成订单号 +const orderNoRes = await supa.rpc('generate_order_no') + +// 获取用户默认地址 +const addressRes = await supa.rpc('get_user_default_address', { + p_user_id: userId +}) +``` + +### 3.3 链式查询构建器 + +```typescript +// 使用链式 API +const res = await supa + .from('ml_products') + .eq('status', 1) + .gte('base_price', 100) + .lte('base_price', 500) + .like('name', '%商品%') + .order('created_at', { ascending: false }) + .limit(20) + .select() +``` + +--- + +## 四、调试工具和方法 + +### 4.1 浏览器开发者工具 + +#### 网络请求调试 +1. **打开 Chrome DevTools** (F12) +2. **Network 标签页** + - 查看所有 HTTP 请求 + - 检查请求 URL、Headers、Body + - 查看响应状态码、数据 + +3. **Console 标签页** + - 查看 `console.log()` 输出 + - 查看错误信息 + - 执行调试代码 + +#### 示例: 检查 API 请求 + +```typescript +// 在代码中添加日志 +console.log('请求商品列表:', { + table: 'ml_products', + filter: { status: 1 }, + options: { limit: 20 } +}) + +const res = await supa.select('ml_products', { status: 1 }, { limit: 20 }) + +console.log('API 响应:', { + success: res.success, + data: res.data, + error: res.error, + status: res.status +}) +``` + +### 4.2 Supabase Dashboard + +#### 实时查看数据 +1. **Table Editor** + - 查看表数据 + - 手动编辑数据 + - 验证数据是否正确 + +2. **SQL Editor** + - 执行 SQL 查询 + - 测试数据库函数 + - 验证 RLS 策略 + +3. **API Logs** + - 查看 API 请求日志 + - 检查错误信息 + - 分析性能问题 + +#### 示例: 测试查询 + +```sql +-- 在 Supabase Dashboard SQL Editor 中执行 +SELECT * FROM ml_products +WHERE status = 1 +ORDER BY created_at DESC +LIMIT 20; + +-- 测试 RLS 策略 +SET ROLE authenticated; +SET request.jwt.claim.sub = 'user-uuid-here'; +SELECT * FROM ml_user_profiles; +``` + +### 4.3 Postman / Insomnia + +#### 直接测试 Supabase API + +```http +# 获取商品列表 +GET https://your-project.supabase.co/rest/v1/ml_products?status=eq.1&limit=20 +Headers: + apikey: your-anon-key + Authorization: Bearer your-jwt-token + Content-Type: application/json + +# 创建订单 +POST https://your-project.supabase.co/rest/v1/ml_orders +Headers: + apikey: your-anon-key + Authorization: Bearer your-jwt-token + Content-Type: application/json + Prefer: return=representation +Body: +{ + "user_id": "user-uuid", + "merchant_id": "merchant-uuid", + "total_amount": 100.00, + "order_status": 1 +} + +# 调用 RPC 函数 +POST https://your-project.supabase.co/rest/v1/rpc/calculate_cart_total +Headers: + apikey: your-anon-key + Authorization: Bearer your-jwt-token + Content-Type: application/json +Body: +{ + "p_user_id": "user-uuid" +} +``` + +### 4.4 数据库客户端工具 + +#### pgAdmin / DBeaver / DataGrip + +```sql +-- 直接连接 PostgreSQL 数据库 +-- Host: localhost (或 192.168.0.150) +-- Port: 5432 +-- Database: postgres +-- User: postgres +-- Password: (从 supa.env 获取) + +-- 查看表结构 +SELECT * FROM information_schema.tables +WHERE table_schema = 'public' AND table_name LIKE 'ml_%'; + +-- 查看数据 +SELECT * FROM ml_products LIMIT 10; + +-- 查看 RLS 策略 +SELECT * FROM pg_policies WHERE tablename = 'ml_products'; +``` + +### 4.5 uni-app-x 调试 + +#### HBuilderX 调试工具 +1. **控制台输出** + - 查看 `console.log()` 输出 + - 查看错误堆栈 + +2. **网络请求监控** + - 查看所有网络请求 + - 检查请求参数和响应 + +3. **断点调试** + - 在代码中设置断点 + - 单步执行 + - 查看变量值 + +--- + +## 五、常见联调场景 + +### 5.1 场景一: 查询商品列表失败 + +#### 问题现象 +```typescript +// 前端代码 +const res = await supa.select('ml_products', null, { limit: 20 }) +// res.success = false +// res.error = "relation 'ml_products' does not exist" +``` + +#### 排查步骤 +1. **检查数据库表是否存在** + ```sql + SELECT table_name FROM information_schema.tables + WHERE table_schema = 'public' AND table_name = 'ml_products'; + ``` + +2. **检查表是否已创建** + - 执行 `complete_mall_database.sql` 脚本 + - 验证脚本执行成功 + +3. **检查连接配置** + ```typescript + console.log('Supabase URL:', SUPA_URL) + console.log('Supabase Key:', SUPA_KEY) + ``` + +#### 解决方案 +```bash +# 重新执行数据库脚本 +psql -h localhost -U postgres -d postgres -f doc_mall/database/complete_mall_database.sql +``` + +### 5.2 场景二: RLS 策略阻止数据访问 + +#### 问题现象 +```typescript +// 查询用户数据返回空 +const res = await supa.select('ml_user_profiles', { user_id: userId }) +// res.data = [] 或 null +``` + +#### 排查步骤 +1. **检查用户是否已登录** + ```typescript + const session = await supa.getSession() + console.log('当前用户:', session.user) + ``` + +2. **检查 RLS 策略** + ```sql + -- 查看表的 RLS 策略 + SELECT * FROM pg_policies WHERE tablename = 'ml_user_profiles'; + + -- 测试 RLS 策略 + SET ROLE authenticated; + SET request.jwt.claim.sub = 'auth-user-id'; + SELECT * FROM ml_user_profiles; + ``` + +3. **检查 auth_id 关联** + ```sql + -- 验证 ak_users.auth_id 是否正确 + SELECT id, auth_id FROM ak_users WHERE id = 'user-uuid'; + ``` + +#### 解决方案 +```typescript +// 确保用户已登录 +await supa.signIn('user@example.com', 'password') + +// 或检查 Token +const token = AkReq.getToken() +console.log('JWT Token:', token) +``` + +### 5.3 场景三: 插入数据失败 + +#### 问题现象 +```typescript +// 插入订单失败 +const res = await supa.insert('ml_orders', orderData) +// res.success = false +// res.error = "new row violates row-level security policy" +``` + +#### 排查步骤 +1. **检查必填字段** + ```typescript + console.log('订单数据:', JSON.stringify(orderData, null, 2)) + ``` + +2. **检查外键约束** + ```sql + -- 验证 user_id 和 merchant_id 是否存在 + SELECT id FROM ak_users WHERE id IN ('user-id', 'merchant-id'); + ``` + +3. **检查 RLS INSERT 策略** + ```sql + SELECT * FROM pg_policies + WHERE tablename = 'ml_orders' AND cmd = 'INSERT'; + ``` + +#### 解决方案 +```typescript +// 确保数据完整 +const orderData = { + user_id: userId, // 必须存在 + merchant_id: merchantId, // 必须存在 + total_amount: 100.00, + order_status: 1, + payment_status: 1, + shipping_status: 1, + shipping_address: addressData // 必须提供 +} + +// 确保用户有权限 +await supa.signIn('user@example.com', 'password') +``` + +### 5.4 场景四: 实时数据同步不工作 + +#### 问题现象 +```typescript +// 订阅订单状态更新,但没有收到推送 +supa.realtime.subscribe('ml_orders', { + filter: `id=eq.${orderId}`, + event: 'UPDATE', + callback: (payload) => { + console.log('订单更新:', payload) // 没有触发 + } +}) +``` + +#### 排查步骤 +1. **检查 WebSocket 连接** + ```typescript + console.log('WebSocket URL:', WS_URL) + ``` + +2. **检查表是否启用 Realtime** + ```sql + -- 在 Supabase Dashboard 中检查 + -- Database -> Replication -> 确保 ml_orders 表已启用 + ``` + +3. **检查网络连接** + - 确保 WebSocket 连接没有被防火墙阻止 + - 检查浏览器控制台是否有 WebSocket 错误 + +#### 解决方案 +```typescript +// 确保 WebSocket URL 正确 +export const WS_URL: string = 'wss://your-project.supabase.co/realtime/v1/websocket' + +// 在 Supabase Dashboard 中启用表的 Realtime +// Database -> Replication -> 找到 ml_orders -> 启用 +``` + +### 5.5 场景五: 数据库函数调用失败 + +#### 问题现象 +```typescript +// 调用 RPC 函数失败 +const res = await supa.rpc('calculate_cart_total', { p_user_id: userId }) +// res.success = false +// res.error = "function calculate_cart_total does not exist" +``` + +#### 排查步骤 +1. **检查函数是否存在** + ```sql + SELECT routine_name FROM information_schema.routines + WHERE routine_schema = 'public' AND routine_name = 'calculate_cart_total'; + ``` + +2. **检查函数参数** + ```sql + -- 查看函数定义 + \df calculate_cart_total + ``` + +3. **测试函数** + ```sql + SELECT calculate_cart_total('user-uuid-here'); + ``` + +#### 解决方案 +```bash +# 重新执行数据库脚本,确保函数已创建 +psql -h localhost -U postgres -d postgres -f doc_mall/database/complete_mall_database.sql +``` + +--- + +## 六、问题排查 + +### 6.1 排查清单 + +#### 连接问题 +- [ ] Supabase URL 是否正确 +- [ ] API Key 是否正确 +- [ ] 网络连接是否正常 +- [ ] 防火墙是否阻止连接 + +#### 认证问题 +- [ ] 用户是否已登录 +- [ ] JWT Token 是否有效 +- [ ] Token 是否过期 +- [ ] auth_id 是否正确关联 + +#### 数据问题 +- [ ] 表是否存在 +- [ ] 字段名是否正确 +- [ ] 数据类型是否匹配 +- [ ] 外键约束是否满足 + +#### 权限问题 +- [ ] RLS 策略是否正确 +- [ ] 用户是否有权限 +- [ ] 策略条件是否满足 + +### 6.2 常用调试命令 + +#### 前端调试 +```typescript +// 打印完整请求信息 +console.log('请求详情:', { + url: `${SUPA_URL}/rest/v1/ml_products`, + headers: { + apikey: SUPA_KEY, + Authorization: `Bearer ${token}` + }, + filter: filter, + options: options +}) + +// 打印完整响应 +console.log('响应详情:', { + success: res.success, + status: res.status, + data: res.data, + error: res.error, + raw: res +}) +``` + +#### 数据库调试 +```sql +-- 查看表结构 +\d ml_products + +-- 查看索引 +\di ml_products* + +-- 查看触发器 +\d+ ml_products + +-- 查看 RLS 策略 +SELECT * FROM pg_policies WHERE tablename = 'ml_products'; + +-- 测试查询性能 +EXPLAIN ANALYZE SELECT * FROM ml_products WHERE status = 1; +``` + +### 6.3 错误码参考 + +| HTTP 状态码 | 含义 | 常见原因 | +| ----------- | ---------- | ---------------------- | +| 200 | 成功 | - | +| 400 | 请求错误 | 参数错误、数据格式错误 | +| 401 | 未授权 | Token 无效、未登录 | +| 403 | 禁止访问 | RLS 策略阻止 | +| 404 | 未找到 | 表不存在、记录不存在 | +| 500 | 服务器错误 | 数据库错误、函数错误 | + +### 6.4 日志收集 + +#### 前端日志 +```typescript +// 创建日志工具 +class DebugLogger { + static log(module: string, action: string, data: any) { + console.log(`[${module}] ${action}:`, data) + // 可以发送到日志服务器 + } +} + +// 使用 +DebugLogger.log('MallAPI', '查询商品', { filter, options }) +``` + +#### 后端日志 +```sql +-- 启用 PostgreSQL 日志 +-- 在 postgresql.conf 中设置 +log_statement = 'all' +log_duration = on +log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' +``` + +--- + +## 七、最佳实践 + +### 7.1 开发环境配置 + +1. **使用环境变量** + ```typescript + // 开发环境 + const isDev = process.env.NODE_ENV === 'development' + export const SUPA_URL = isDev + ? 'http://192.168.0.150:8080' + : 'https://ak3.oulog.com' + ``` + +2. **统一错误处理** + ```typescript + async function safeApiCall(apiCall: () => Promise>) { + try { + const res = await apiCall() + if (!res.success) { + console.error('API 调用失败:', res.error) + uni.showToast({ title: '操作失败', icon: 'error' }) + } + return res + } catch (error) { + console.error('API 调用异常:', error) + uni.showToast({ title: '网络错误', icon: 'error' }) + throw error + } + } + ``` + +3. **请求重试机制** + ```typescript + async function retryApiCall( + apiCall: () => Promise>, + maxRetries = 3 + ) { + for (let i = 0; i < maxRetries; i++) { + try { + const res = await apiCall() + if (res.success) return res + } catch (error) { + if (i === maxRetries - 1) throw error + await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) + } + } + } + ``` + +### 7.2 联调流程 + +1. **数据库准备** + - 执行数据库脚本 + - 插入测试数据 + - 验证表结构 + +2. **前端配置** + - 配置 Supabase URL 和 Key + - 测试连接 + - 验证认证 + +3. **功能测试** + - 测试 CRUD 操作 + - 测试 RLS 策略 + - 测试实时同步 + +4. **问题排查** + - 查看日志 + - 检查网络请求 + - 验证数据库数据 + +--- + +## 📚 相关文档 + +- [模块分析报告](./MODULE_ANALYSIS.md) +- [数据库创建报告](./database/database_creation_report.md) +- [完整部署指南](./database/complete_deployment_guide.md) +- [Supabase 官方文档](https://supabase.com/docs) + +--- + +**生成时间**: 2025年1月 +**版本**: v1.0 +**状态**: ✅ 完整联调指南 diff --git a/mall_sql/docs/MALL_README.md b/mall_sql/docs/MALL_README.md new file mode 100644 index 00000000..568aa3f4 --- /dev/null +++ b/mall_sql/docs/MALL_README.md @@ -0,0 +1,216 @@ +# 商城系统文档目录 + +## 📁 目录结构 + +``` +doc_mall/ +├── README.md # 本文件 - 文档目录索引 +├── user_reuse_summary.md # 用户表复用方案总结 +├── analysis/ # 分析文档 +│ └── user_compatibility_analysis.md # 用户表兼容性详细分析 +├── database/ # 数据库相关 +│ ├── complete_mall_database.sql # 🎯 完整商城数据库(推荐使用) +│ ├── database_creation_report.md # 📊 数据库创建完成报告 +│ ├── database_syntax_fix_report.md # 数据库语法修正报告 +│ ├── user_compatibility_implementation.sql # 用户兼容性实施脚本 +│ ├── product_database.sql # 商品数据库设计脚本 +│ ├── mock_data_insert.sql # 模拟数据插入脚本 +│ ├── mock_data_documentation.md # 模拟数据说明文档 +│ ├── deployment_guide.md # 快速部署指南 +│ ├── validation_test.sql # 数据库验证测试脚本 +│ └── complete_deployment_guide.md # 完整部署与测试指南 +└── reports/ # 生成报告 + ├── system_generation_report.md # 系统生成报告 + ├── detail_pages_report.md # 详情页生成报告 + └── profile_pages_report.md # 个人中心页面报告 +``` + +## 📋 文档说明 + +### 核心文档 + +#### 📊 [模块深度分析报告](./MODULE_ANALYSIS.md) ⭐ **新增** +- **内容**: 完整的模块分析,包括数据库存储、交互方式、开发模式、开发流程 +- **适用**: 了解模块整体架构和设计理念 + +#### 🔧 [技术实现拆解](./TECHNICAL_IMPLEMENTATION.md) ⭐ **新增** +- **内容**: 详细的技术实现拆解,包括数据库层、API层、前端实现、数据流机制 +- **适用**: 深入了解具体实现细节和开发方式 + +#### 🔗 [前后端联调指南](./FRONTEND_BACKEND_DEBUGGING.md) ⭐ **新增** +- **内容**: 完整的前后端联调指南,包括环境配置、调试工具、常见问题 +- **适用**: 开发调试和问题排查 + +#### 🎯 [用户表复用方案总结](./user_reuse_summary.md) +- **问题**: 商城系统是否可以复用运动训练平台的 `ak_users` 用户表? +- **结论**: ✅ 可以复用,采用混合扩展方案 +- **方案**: 保持 `ak_users` 主表不变,增加商城扩展表 +- **优势**: 单点登录、数据一致性、业务隔离 + +#### 🔍 [用户兼容性详细分析](./analysis/user_compatibility_analysis.md) +- 字段级兼容性对比分析 +- 三种方案对比(共用/独立/混合) +- 风险评估和解决方案 +- 具体实施步骤和建议 + +### 数据库脚本 + +#### 🎯 [完整商城数据库](./database/complete_mall_database.sql) **← 推荐使用** +- **全新设计**: 使用 `ml_` 前缀的独立商城数据库 +- **复用优化**: 仅复用 `ak_users` 用户主表 +- **功能完整**: 21张表覆盖所有商城功能 +- **Supabase优化**: 包含RLS策略、触发器、函数、视图 +- **性能优化**: 完整索引设计和查询优化 + +#### 📊 [数据库创建报告](./database/database_creation_report.md) +- 详细的数据库架构说明 +- 21张表的功能分析和设计理念 +- 索引、触发器、函数、视图的完整清单 +- 部署步骤和性能优化建议 + +#### 🛠️ [数据库语法修正报告](./database/database_syntax_fix_report.md) +- 修正了RLS策略的语法错误 +- 提供了修正前后的对比 +- 包含常见问题解答和修正建议 + +#### 🔧 [类型错误修正报告](./database/type_error_fix_report.md) +- **问题分析**: auth_id 字段 UUID 类型错误的详细分析 +- **修正措施**: 完整的问题解决方案和预防措施 +- **验证工具**: 新增的验证脚本和部署指南 +- **流程优化**: 改进的部署流程和错误监控建议 + +#### 🎯 [SEO 优化实施报告](./database/seo_optimization_report.md) +- **优化成果**: CID 自增字段的完整实施效果 +- **性能提升**: URL 结构、查询性能、存储空间的全面优化 +- **技术细节**: 索引、视图、函数的具体实现 +- **收益分析**: SEO 表现、用户体验、开发效率的预期提升 + +#### 💾 [用户兼容性实施脚本](./database/user_compatibility_implementation.sql) +- 商城用户扩展表 `mall_user_profiles` +- 用户地址表 `ak_user_addresses` +- 用户收藏、搜索、浏览历史表 +- 触发器、索引、RLS策略 +- 数据迁移和权限设置 + +#### 🛍️ [商品数据库设计脚本](./database/product_database.sql) +- 完整的商品管理数据库设计 +- 商品、SKU、分类、品牌、规格等表 +- 支持多规格、库存管理、营销活动 +- 推荐使用独立商品表,不复用 `ak_contents` + +#### 🔍 [数据库验证测试脚本](./database/validation_test.sql) +- **环境检查**: 验证 PostgreSQL 扩展和依赖项 +- **表结构验证**: 检查 `ak_users` 表和商城表的完整性 +- **语法测试**: 验证 RLS 策略和 UUID 类型的正确性 +- **数据统计**: 检查模拟数据的插入情况 + +#### 📚 [完整部署与测试指南](./database/complete_deployment_guide.md) +- **部署前检查**: 详细的环境要求和准备工作 +- **分步骤部署**: PostgreSQL 和 Supabase 的完整部署流程 +- **验证测试**: 部署后的功能验证和性能检查 +- **问题解决**: 常见错误的详细解决方案和预防措施 +- **维护建议**: 数据维护、备份和性能优化指导 + +#### 🧪 [模拟数据插入脚本](./database/mock_data_insert.sql) +- **测试专用**: 为开发和测试生成完整的模拟数据 +- **数据丰富**: 包含8个测试用户、6个商品、多个订单等 +- **场景完整**: 涵盖购物车、优惠券、评价、配送等业务场景 +- **依赖**: 需要先执行 `complete_mall_database.sql` + +#### 📋 [模拟数据说明文档](./database/mock_data_documentation.md) +- **详细说明**: 所有测试数据的详细说明和使用指南 +- **用户角色**: 8个测试用户的账号信息和权限说明 +- **测试场景**: 完整的业务流程测试建议 +- **数据维护**: 数据更新和维护的最佳实践 + +#### 🚀 [快速部署指南](./database/deployment_guide.md) +- **部署步骤**: PostgreSQL 和 Supabase 的详细部署指南 +- **执行顺序**: 脚本执行的正确顺序和注意事项 +- **测试验证**: 部署后的功能验证和性能测试 +- **问题排查**: 常见问题的解决方案和检查清单 + +#### 🔍 [SEO 优化指南](./database/seo_optimization_guide.md) +- **CID 自增字段**: 为主要表添加 SEO 友好的自增 ID +- **URL 结构优化**: 提供简洁、语义化的 URL 路径 +- **函数工具**: 完整的 SEO 相关查询和工具函数 +- **前端集成**: Vue Router 配置和 API 调用示例 +- **性能监控**: 索引优化和查询性能监控指导 + +### 生成报告 + +#### 📊 [系统生成报告](./reports/system_generation_report.md) +- 6个角色端首页代码生成完成 +- 类型定义和UTS Android兼容性说明 +- 页面功能模块和技术特点总结 + +#### 📄 [详情页生成报告](./reports/detail_pages_report.md) +- 商品详情、订单详情、店铺详情等页面 +- 具体功能实现和代码结构 +- UTS Android语法规范遵循情况 + +#### 👤 [个人中心页面报告](./reports/profile_pages_report.md) +- 6个角色端个人中心页面生成 +- 用户信息管理、设置、统计等功能 +- 响应式设计和现代UI实现 + +## 🔗 相关文件 + +### 类型定义 +- `../types/mall-types.uts` - 商城系统完整类型定义 + +### 页面代码 +- `../pages/mall/` - 所有角色端页面代码 +- `../pages/mall/pages-config.json` - 页面路由配置 + +### 订阅功能(本次实现) +- 数据库脚本:`./create_mall_subscription_tables.sql` +- RLS/权限:`./subscription_rls_policies.sql` +- 消费端页面: + - `../pages/mall/consumer/subscription/plan-list.uvue` + - `../pages/mall/consumer/subscription/plan-detail.uvue` + - `../pages/mall/consumer/subscription/subscribe-checkout.uvue` + - `../pages/mall/consumer/subscription/my-subscriptions.uvue` +- 管理端页面: + - `../pages/mall/admin/subscription/plan-management.uvue` + - `../pages/mall/admin/subscription/user-subscriptions.uvue` + +### 业务需求 +- `../mall.md` - 原始业务需求文档 + +## 🎯 核心结论 + +### 🆕 最新推荐方案 +✅ **使用完整商城数据库设计**: +- 使用 `complete_mall_database.sql` 创建独立商城系统 +- 仅复用 `ak_users` 用户主表,其他表全部独立 +- 包含 20+ 张表,覆盖用户、商品、订单、营销、配送等全部功能 +- 优化的 Supabase 兼容设计(RLS、触发器、函数、视图) + +### 用户表复用方案 +✅ **推荐采用混合扩展方案**: +- 保持 `ak_users` 表作为用户主表 +- 创建 `ml_user_profiles` 商城扩展表 +- 新建 `ml_user_addresses` 地址管理表 +- 实现业务数据隔离的同时保持账号统一 + +### 商品表设计方案 +❌ **不推荐复用 `ak_contents` 表**: +- 语义不匹配、字段冲突、业务逻辑差异 +- 强烈建议使用独立的商品数据库设计 + +### 技术实现标准 +✅ **严格遵循UTS Android兼容性**: +- 全部使用 `type` 声明,避免 `interface` +- 数组类型使用 `Array` 格式 +- 无 `undefined` 类型,变量类型明确 +- JSON对象使用 `UTSJSONObject` + +## 📞 支持 + +本文档集涵盖了商城系统与运动训练平台用户表复用的完整分析和实施方案。如需了解更多技术细节,请查看相应的具体文档文件。 + +--- + +**生成时间**: 2025年7月11日 +**版本**: v1.0 +**状态**: ✅ 已完成分析和实施方案 diff --git a/mall_sql/docs/MIGRATION_CHECKLIST.md b/mall_sql/docs/MIGRATION_CHECKLIST.md new file mode 100644 index 00000000..a3fa6a22 --- /dev/null +++ b/mall_sql/docs/MIGRATION_CHECKLIST.md @@ -0,0 +1,254 @@ +# ✅ doc_mall 项目迁移检查清单 + +## 📋 文件迁移清单 + +### 1. 文档和数据库脚本 (`doc_mall/`) + +#### 核心文档 +- [ ] `README.md` - 文档索引 +- [ ] `TECHNICAL_IMPLEMENTATION.md` - 技术实现拆解 +- [ ] `MODULE_ANALYSIS.md` - 模块深度分析 +- [ ] `FRONTEND_BACKEND_DEBUGGING.md` - 前后端联调指南 +- [ ] `user_reuse_summary.md` - 用户表复用方案 +- [ ] `migration_complete_report.md` - 迁移完成报告 +- [ ] `README_subscription_consumer.md` - 订阅功能说明 +- [ ] `裂变红包.md` - 红包功能文档 +- [ ] `MIGRATION_GUIDE.md` - 迁移指南(本文档) +- [ ] `MIGRATION_CHECKLIST.md` - 迁移清单(本文件) + +#### SQL 脚本 +- [ ] `create_mall_subscription_tables.sql` - 订阅表创建脚本 +- [ ] `subscription_guard_trigger.sql` - 订阅触发器 +- [ ] `subscription_rls_policies.sql` - 订阅RLS策略 + +#### 分析文档目录 (`analysis/`) +- [ ] `analysis/user_compatibility_analysis.md` - 用户兼容性分析 + +#### 数据库目录 (`database/`) +- [ ] `database/complete_mall_database.sql` - 完整数据库(推荐) +- [ ] `database/database_creation_report.md` - 数据库创建报告 +- [ ] `database/database_syntax_fix_report.md` - 语法修正报告 +- [ ] `database/type_error_fix_report.md` - 类型错误修正报告 +- [ ] `database/seo_optimization_report.md` - SEO优化报告 +- [ ] `database/seo_optimization_guide.md` - SEO优化指南 +- [ ] `database/user_compatibility_implementation.sql` - 用户兼容性实施脚本 +- [ ] `database/product_database.sql` - 商品数据库设计 +- [ ] `database/mock_data_insert.sql` - 模拟数据插入脚本 +- [ ] `database/mock_data_documentation.md` - 模拟数据说明 +- [ ] `database/deployment_guide.md` - 快速部署指南 +- [ ] `database/validation_test.sql` - 数据库验证测试脚本 +- [ ] `database/complete_deployment_guide.md` - 完整部署与测试指南 +- [ ] `database/database_creation_report.md` - 数据库创建报告 +- [ ] `database/[其他SQL文件]` - 其他数据库脚本 + +#### 报告目录 (`reports/`) +- [ ] `reports/system_generation_report.md` - 系统生成报告 +- [ ] `reports/detail_pages_report.md` - 详情页生成报告 +- [ ] `reports/profile_pages_report.md` - 个人中心页面报告 + +--- + +### 2. 前端页面代码 (`pages/mall/`) + +#### 管理端页面 (`admin/`) +- [ ] `admin/index.uvue` - 管理端首页 +- [ ] `admin/profile.uvue` - 管理端个人中心 +- [ ] `admin/user-detail.uvue` - 用户详情 +- [ ] `admin/subscription/plan-management.uvue` - 订阅方案管理 +- [ ] `admin/subscription/user-subscriptions.uvue` - 用户订阅管理 + +#### 数据分析端页面 (`analytics/`) +- [ ] `analytics/index.uvue` - 数据分析首页 +- [ ] `analytics/profile.uvue` - 数据分析个人中心 +- [ ] `analytics/report-detail.uvue` - 报表详情 + +#### 消费者端页面 (`consumer/`) +- [ ] `consumer/index.uvue` - 消费者首页 +- [ ] `consumer/product-detail.uvue` - 商品详情 +- [ ] `consumer/order-detail.uvue` - 订单详情 +- [ ] `consumer/profile.uvue` - 消费者个人中心 +- [ ] `consumer/subscription/plan-list.uvue` - 订阅方案列表 +- [ ] `consumer/subscription/plan-detail.uvue` - 订阅方案详情 +- [ ] `consumer/subscription/subscribe-checkout.uvue` - 订阅确认 +- [ ] `consumer/subscription/my-subscriptions.uvue` - 我的订阅 +- [ ] `consumer/subscription/README.md` - 订阅功能说明 + +#### 配送端页面 (`delivery/`) +- [ ] `delivery/index.uvue` - 配送端首页 +- [ ] `delivery/order-detail.uvue` - 配送订单详情 +- [ ] `delivery/profile.uvue` - 配送员个人中心 + +#### 商家端页面 (`merchant/`) +- [ ] `merchant/index.uvue` - 商家端首页 +- [ ] `merchant/product-detail.uvue` - 商品管理详情 +- [ ] `merchant/profile.uvue` - 商家个人中心 + +#### 客服端页面 (`service/`) +- [ ] `service/index.uvue` - 客服工作台首页 +- [ ] `service/profile.uvue` - 客服个人中心 +- [ ] `service/ticket-detail.uvue` - 工单详情 + +#### NFC 功能页面 (`nfc/`) - 可选 +- [ ] `nfc/admin/index.uvue` +- [ ] `nfc/librarian/index.uvue` +- [ ] `nfc/merchant/pos-cashier.uvue` +- [ ] `nfc/parent/index.uvue` +- [ ] `nfc/security/index.uvue` +- [ ] `nfc/student/index.uvue` +- [ ] `nfc/student/nfc-pay.uvue` +- [ ] `nfc/teacher/index.uvue` + +#### 配置文件 +- [ ] `mall.md` - 业务需求文档 +- [ ] `nfc.md` - NFC功能文档 +- [ ] `nfc-modules-guide.md` - NFC模块指南 +- [ ] `pages-config.json` - 主要页面路由配置 +- [ ] `pages-admin.json` - 管理端路由配置 +- [ ] `pages-librarian.json` - 图书管理员路由配置 +- [ ] `pages-merchant.json` - 商家路由配置 +- [ ] `pages-parent.json` - 家长路由配置 +- [ ] `pages-security.json` - 安全员路由配置 +- [ ] `pages-student.json` - 学生路由配置 +- [ ] `pages-teacher.json` - 教师路由配置 + +--- + +### 3. 类型定义文件 + +- [ ] `types/mall-types.uts` - 商城系统完整类型定义(**必须迁移**) + +--- + +### 4. 依赖文件(可选,根据实际情况) + +#### Supabase 客户端封装 +- [ ] `components/supadb/aksupainstance.uts` - Supabase实例 +- [ ] `components/supadb/aksupa.uts` - Supabase客户端封装 +- [ ] `components/supadb/aksuparealtime.uts` - 实时订阅封装 +- [ ] `components/supadb/[其他相关文件]` - 其他Supabase相关文件 + +#### 工具函数(根据实际引用) +- [ ] 检查 `pages/mall/` 中所有 `@/utils/` 的引用 +- [ ] 迁移需要的工具函数文件 + +--- + +## 🔗 依赖关系检查 + +### 数据库依赖 +- [ ] 确定用户表处理方案(独立表/复用表/API服务) +- [ ] 更新相关外键引用(如需要) +- [ ] 配置 Supabase 项目连接信息 + +### 代码依赖 +- [ ] 检查所有 `@/types/mall-types.uts` 引用(应已迁移) +- [ ] 检查所有 `@/components/supadb` 引用 +- [ ] 检查所有 `@/utils/` 引用 +- [ ] 更新导入路径(如需要) + +### 配置文件依赖 +- [ ] Supabase 项目 URL 和 API Key +- [ ] 环境变量配置 +- [ ] 路由配置(pages-config.json 等) + +--- + +## 🗄️ 数据库迁移步骤 + +### 环境准备 +- [ ] 创建新的 Supabase 项目(或确定使用现有项目) +- [ ] 获取 Supabase 项目 URL 和 API Key +- [ ] 准备 PostgreSQL 客户端工具(如需要) + +### 数据库脚本执行 +- [ ] 执行 `database/complete_mall_database.sql` - 创建完整数据库结构 +- [ ] 执行 `subscription_rls_policies.sql` - 订阅RLS策略 +- [ ] 执行 `subscription_guard_trigger.sql` - 订阅触发器 +- [ ] 执行 `database/mock_data_insert.sql` - 插入测试数据(可选) +- [ ] 执行 `database/validation_test.sql` - 验证数据库状态 + +### 数据库验证 +- [ ] 验证所有表已创建 +- [ ] 验证 RLS 策略已生效 +- [ ] 验证触发器已创建 +- [ ] 验证索引已创建 +- [ ] 测试数据查询功能 + +--- + +## 🔧 代码适配检查 + +### 路径更新 +- [ ] 检查所有文件中的 `@/types/mall-types` 导入路径 +- [ ] 检查所有文件中的 `@/components/supadb` 导入路径 +- [ ] 检查所有文件中的 `@/utils/` 导入路径 +- [ ] 更新为正确的相对路径或配置别名 + +### 配置更新 +- [ ] 更新 Supabase 客户端初始化配置 +- [ ] 更新环境变量配置 +- [ ] 更新路由配置文件(如需要) + +### 文档更新 +- [ ] 更新文档中的路径引用 +- [ ] 更新文档中的配置说明 + +--- + +## 🧪 测试验证 + +### 编译测试 +- [ ] 项目可以正常编译 +- [ ] 无类型错误 +- [ ] 无导入路径错误 + +### 运行时测试 +- [ ] 应用可以正常启动 +- [ ] Supabase 连接正常 +- [ ] 页面可以正常加载 + +### 功能测试 +- [ ] 用户认证功能正常 +- [ ] 商品浏览功能正常 +- [ ] 订单创建功能正常 +- [ ] 权限控制正常(RLS) + +### 数据库测试 +- [ ] CRUD 操作正常 +- [ ] RLS 策略生效 +- [ ] 触发器正常工作 + +--- + +## 📝 迁移记录 + +### 迁移信息 +- **迁移日期**: ___________ +- **源项目路径**: ___________ +- **目标项目路径**: ___________ +- **迁移人员**: ___________ + +### 迁移问题记录 +| 问题描述 | 解决方案 | 状态 | +| -------- | -------- | ---- | +| | | | +| | | | + +### 待处理事项 +- [ ] +- [ ] +- [ ] + +--- + +## ✅ 迁移完成确认 + +- [ ] 所有文件已迁移 +- [ ] 所有依赖已处理 +- [ ] 数据库已配置 +- [ ] 代码已适配 +- [ ] 测试已通过 +- [ ] 文档已更新 + +**迁移完成签名**: ___________ +**完成日期**: ___________ diff --git a/mall_sql/docs/MIGRATION_GUIDE.md b/mall_sql/docs/MIGRATION_GUIDE.md new file mode 100644 index 00000000..30a77be6 --- /dev/null +++ b/mall_sql/docs/MIGRATION_GUIDE.md @@ -0,0 +1,542 @@ +# 🚀 doc_mall 项目迁移指南 + +## 📋 迁移概述 + +本指南将帮助你将 `doc_mall` 商城系统模块从当前项目迁移到一个独立的仓库中,确保所有相关模块和依赖项都能正确复用。 + +--- + +## 📁 需要迁移的文件和目录清单 + +### 1. 核心文档和数据库脚本 (`doc_mall/`) + +**完整目录结构**: +``` +doc_mall/ +├── README.md # 文档索引 +├── TECHNICAL_IMPLEMENTATION.md # 技术实现拆解 +├── MODULE_ANALYSIS.md # 模块深度分析 +├── FRONTEND_BACKEND_DEBUGGING.md # 前后端联调指南 +├── user_reuse_summary.md # 用户表复用方案 +├── migration_complete_report.md # 迁移完成报告 +├── README_subscription_consumer.md # 订阅功能说明 +├── 裂变红包.md # 红包功能文档 +├── create_mall_subscription_tables.sql # 订阅表创建脚本 +├── subscription_guard_trigger.sql # 订阅触发器 +├── subscription_rls_policies.sql # 订阅RLS策略 +├── analysis/ # 分析文档目录 +│ └── user_compatibility_analysis.md +├── database/ # 数据库脚本目录 +│ ├── complete_mall_database.sql # 完整数据库(推荐) +│ ├── database_creation_report.md +│ ├── database_syntax_fix_report.md +│ ├── user_compatibility_implementation.sql +│ ├── product_database.sql +│ ├── mock_data_insert.sql +│ ├── mock_data_documentation.md +│ ├── deployment_guide.md +│ ├── validation_test.sql +│ ├── complete_deployment_guide.md +│ └── [其他SQL和文档文件] +└── reports/ # 生成报告目录 + ├── system_generation_report.md + ├── detail_pages_report.md + └── profile_pages_report.md +``` + +**迁移操作**: +```bash +# 直接复制整个 doc_mall 目录 +cp -r doc_mall/ /path/to/new-repo/doc_mall/ +``` + +--- + +### 2. 前端页面代码 (`pages/mall/`) + +**完整目录结构**: +``` +pages/mall/ +├── admin/ # 管理端页面 +│ ├── index.uvue +│ ├── profile.uvue +│ ├── user-detail.uvue +│ └── subscription/ +│ ├── plan-management.uvue +│ └── user-subscriptions.uvue +├── analytics/ # 数据分析端页面 +│ ├── index.uvue +│ ├── profile.uvue +│ └── report-detail.uvue +├── consumer/ # 消费者端页面 +│ ├── index.uvue +│ ├── product-detail.uvue +│ ├── order-detail.uvue +│ ├── profile.uvue +│ └── subscription/ +│ ├── plan-list.uvue +│ ├── plan-detail.uvue +│ ├── subscribe-checkout.uvue +│ ├── my-subscriptions.uvue +│ └── README.md +├── delivery/ # 配送端页面 +│ ├── index.uvue +│ ├── order-detail.uvue +│ └── profile.uvue +├── merchant/ # 商家端页面 +│ ├── index.uvue +│ ├── product-detail.uvue +│ └── profile.uvue +├── service/ # 客服端页面 +│ ├── index.uvue +│ ├── profile.uvue +│ └── ticket-detail.uvue +├── nfc/ # NFC支付相关(可选) +│ ├── admin/index.uvue +│ ├── librarian/index.uvue +│ ├── merchant/pos-cashier.uvue +│ ├── parent/index.uvue +│ ├── security/index.uvue +│ ├── student/index.uvue +│ ├── teacher/index.uvue +│ └── [其他NFC相关文件] +├── mall.md # 业务需求文档 +├── nfc.md # NFC功能文档 +├── nfc-modules-guide.md # NFC模块指南 +├── pages-config.json # 页面路由配置(主要) +├── pages-admin.json # 管理端路由配置 +├── pages-librarian.json # 图书管理员路由配置 +├── pages-merchant.json # 商家路由配置 +├── pages-parent.json # 家长路由配置 +├── pages-security.json # 安全员路由配置 +├── pages-student.json # 学生路由配置 +└── pages-teacher.json # 教师路由配置 +``` + +**迁移操作**: +```bash +# 复制整个 pages/mall 目录 +cp -r pages/mall/ /path/to/new-repo/pages/mall/ +``` + +--- + +### 3. 类型定义文件 (`types/mall-types.uts`) + +**文件路径**: +``` +types/mall-types.uts +``` + +**说明**: +- 包含所有商城系统相关的 TypeScript/UTS 类型定义 +- 所有 `pages/mall/` 下的页面都依赖此文件 +- 必须迁移,否则前端代码无法编译 + +**迁移操作**: +```bash +# 复制类型定义文件 +mkdir -p /path/to/new-repo/types +cp types/mall-types.uts /path/to/new-repo/types/ +``` + +--- + +## 🔗 依赖关系分析 + +### 3.1 内部依赖(必须迁移) + +#### Supabase 客户端封装 +- **依赖文件**:`components/supadb/aksupainstance.uts` +- **使用情况**:所有商城页面都通过 Supabase 客户端访问数据库 +- **迁移建议**: + - 如果新仓库也需要使用 Supabase,需要迁移此文件 + - 或者创建新的 Supabase 客户端封装 + +#### 工具函数 +- **检查项目**:是否需要 `utils/` 下的工具函数 +- **常见使用**:日期格式化、数据验证等 +- **迁移建议**: + - 检查商城页面中 `@/utils/` 的引用 + - 根据需要迁移相应的工具函数 + +### 3.2 外部依赖(需要配置) + +#### 数据库依赖 +- **依赖表**:`ak_users` (用户主表) +- **说明**:商城系统复用现有用户表实现单点登录 +- **迁移策略**: + - **方案A**:在新仓库中创建独立的用户表 + - **方案B**:保持与现有用户表的关联(需要跨数据库访问) + - **方案C**:通过 API 服务访问用户数据 + +#### Supabase 配置 +- **需要配置**:Supabase 项目 URL 和 API Key +- **配置文件**:通常保存在环境变量或配置文件中 +- **迁移步骤**: + 1. 在新仓库创建 Supabase 项目(或使用现有项目) + 2. 执行数据库脚本创建表结构 + 3. 配置 RLS 策略和权限 + 4. 更新前端配置中的 Supabase 连接信息 + +--- + +## 📝 迁移步骤详解 + +### 步骤 1: 创建新仓库 + +```bash +# 1. 创建新仓库目录 +mkdir mall-system +cd mall-system + +# 2. 初始化 Git 仓库 +git init + +# 3. 创建基础目录结构 +mkdir -p doc_mall/{analysis,database,reports} +mkdir -p pages/mall +mkdir -p types +mkdir -p components/supadb # 如果需要 +mkdir -p utils # 如果需要 +``` + +### 步骤 2: 迁移文档和数据库脚本 + +```bash +# 从原项目复制 doc_mall 目录 +cp -r /path/to/akmon/doc_mall/* ./doc_mall/ + +# 验证文件完整性 +ls -la doc_mall/ +``` + +### 步骤 3: 迁移前端代码 + +```bash +# 复制页面代码 +cp -r /path/to/akmon/pages/mall/* ./pages/mall/ + +# 复制类型定义 +cp /path/to/akmon/types/mall-types.uts ./types/ + +# 验证关键文件 +ls -la pages/mall/ +ls -la types/mall-types.uts +``` + +### 步骤 4: 迁移依赖文件(可选) + +```bash +# 如果需要 Supabase 客户端 +cp -r /path/to/akmon/components/supadb/* ./components/supadb/ + +# 检查并迁移需要的工具函数 +# 查看 pages/mall/ 下文件中的 import 语句 +grep -r "from '@/utils" pages/mall/ +``` + +### 步骤 5: 更新导入路径 + +在新仓库中,需要检查并更新以下内容: + +#### 5.1 检查类型导入 +```bash +# 查找所有 mall-types 的引用 +grep -r "from '@/types/mall-types" pages/mall/ +``` + +确保导入路径正确: +```typescript +// 应该是相对路径或配置的别名 +import type { ProductType } from '@/types/mall-types.uts' +``` + +#### 5.2 检查 Supabase 导入 +```bash +# 查找 Supabase 引用 +grep -r "from '@/components/supadb" pages/mall/ +``` + +#### 5.3 检查工具函数导入 +```bash +# 查找工具函数引用 +grep -r "from '@/utils" pages/mall/ +``` + +### 步骤 6: 配置数据库 + +#### 6.1 创建 Supabase 项目 +1. 访问 Supabase 控制台 +2. 创建新项目或使用现有项目 +3. 记录项目 URL 和 API Key + +#### 6.2 执行数据库脚本 +```bash +# 方式1: 通过 Supabase Dashboard SQL Editor +# 打开 doc_mall/database/complete_mall_database.sql +# 复制内容到 Supabase SQL Editor 执行 + +# 方式2: 通过 psql 命令行(如果使用自建 PostgreSQL) +psql -h localhost -U postgres -d your_database -f doc_mall/database/complete_mall_database.sql +``` + +#### 6.3 配置 RLS 策略 +确保执行以下脚本: +- `doc_mall/subscription_rls_policies.sql` +- `doc_mall/subscription_guard_trigger.sql` +- 数据库脚本中已包含的 RLS 策略 + +#### 6.4 插入测试数据(可选) +```bash +psql -h localhost -U postgres -d your_database -f doc_mall/database/mock_data_insert.sql +``` + +### 步骤 7: 配置前端环境 + +#### 7.1 创建配置文件 +在新仓库根目录创建配置文件(根据你的项目结构): + +**示例:`config/supabase.config.ts`** +```typescript +export const supabaseConfig = { + url: 'https://your-project.supabase.co', + anonKey: 'your-anon-key', + // 其他配置 +} +``` + +#### 7.2 更新 Supabase 客户端初始化 +如果迁移了 `components/supadb/aksupainstance.uts`,确保它使用新的配置。 + +#### 7.3 配置路由 +检查并更新以下路由配置文件: +- `pages/mall/pages-config.json` (主要路由配置) +- 其他角色端路由配置 JSON 文件 + +### 步骤 8: 处理用户表依赖 + +商城系统依赖 `ak_users` 表,有几种处理方案: + +#### 方案 A: 创建独立的用户表(推荐用于完全独立部署) +```sql +-- 创建独立的用户表(简化版) +CREATE TABLE public.mall_users ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + phone VARCHAR(20) UNIQUE NOT NULL, + email VARCHAR(255), + nickname VARCHAR(100), + -- 其他必要字段 + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); +``` + +然后更新所有 `ml_user_profiles` 等表的外键引用: +```sql +-- 修改外键引用 +ALTER TABLE public.ml_user_profiles +DROP CONSTRAINT ml_user_profiles_user_id_fkey; + +ALTER TABLE public.ml_user_profiles +ADD CONSTRAINT ml_user_profiles_user_id_fkey +FOREIGN KEY (user_id) REFERENCES public.mall_users(id) ON DELETE CASCADE; +``` + +#### 方案 B: 通过 API 服务访问用户数据 +- 保持数据库结构不变 +- 通过 API 服务层访问用户数据 +- 前端不直接访问 `ak_users` 表 + +#### 方案 C: 跨数据库访问(复杂,不推荐) +- 保持现有的数据库引用 +- 配置跨数据库访问权限 + +### 步骤 9: 测试和验证 + +#### 9.1 编译测试 +```bash +# 尝试编译项目(根据你的构建工具) +npm run build +# 或 +uni-app-x build +``` + +#### 9.2 数据库连接测试 +- 测试 Supabase 连接 +- 验证 RLS 策略是否生效 +- 测试 CRUD 操作 + +#### 9.3 功能测试 +- 测试各个角色端页面是否能正常加载 +- 测试核心业务流程(商品浏览、下单等) +- 测试权限控制 + +--- + +## 🔧 迁移后需要修改的内容 + +### 1. 更新导入路径 + +检查并更新所有文件中的导入路径,确保它们指向正确的位置: + +```typescript +// 原项目中的导入 +import type { ProductType } from '@/types/mall-types.uts' +import { supabase } from '@/components/supadb/aksupainstance.uts' + +// 新仓库中可能需要调整为 +import type { ProductType } from '@/types/mall-types.uts' +import { supabase } from '@/lib/supabase/client.uts' // 如果路径改变了 +``` + +### 2. 更新数据库表引用 + +如果用户表方案改变,需要更新所有相关的外键和查询: + +```sql +-- 原项目中引用 ak_users +user_id UUID NOT NULL REFERENCES public.ak_users(id) + +-- 如果改为独立用户表 +user_id UUID NOT NULL REFERENCES public.mall_users(id) +``` + +### 3. 更新环境变量和配置 + +- Supabase 项目 URL 和 API Key +- 数据库连接字符串 +- 其他环境相关配置 + +### 4. 更新文档中的路径引用 + +检查 `doc_mall/` 下的文档,更新其中的文件路径引用: + +```markdown +# 原文档中的路径 +- `../types/mall-types.uts` + +# 新仓库中应该为 +- `types/mall-types.uts` +``` + +--- + +## ✅ 迁移检查清单 + +使用以下清单确保迁移完整: + +- [ ] **文档迁移** + - [ ] `doc_mall/` 目录完整复制 + - [ ] 所有子目录(analysis, database, reports)已迁移 + - [ ] 文档中的路径引用已更新 + +- [ ] **前端代码迁移** + - [ ] `pages/mall/` 所有页面文件已迁移 + - [ ] `types/mall-types.uts` 已迁移 + - [ ] 所有路由配置文件(pages-*.json)已迁移 + - [ ] 业务需求文档(mall.md)已迁移 + +- [ ] **依赖文件迁移** + - [ ] Supabase 客户端封装已迁移或重新创建 + - [ ] 必要的工具函数已迁移 + - [ ] 组件依赖已处理 + +- [ ] **数据库配置** + - [ ] Supabase 项目已创建并配置 + - [ ] 数据库脚本已执行 + - [ ] RLS 策略已配置 + - [ ] 测试数据已插入(可选) + - [ ] 用户表依赖已处理 + +- [ ] **代码适配** + - [ ] 所有导入路径已更新 + - [ ] 数据库表引用已更新(如需要) + - [ ] 配置文件已更新 + - [ ] 环境变量已配置 + +- [ ] **测试验证** + - [ ] 项目可以正常编译 + - [ ] 数据库连接正常 + - [ ] 页面可以正常加载 + - [ ] 核心功能测试通过 + +--- + +## 🚨 常见问题和解决方案 + +### 问题 1: 编译错误 - 找不到类型定义 + +**错误信息**: +``` +Cannot find module '@/types/mall-types.uts' +``` + +**解决方案**: +1. 确认 `types/mall-types.uts` 文件已迁移 +2. 检查 TypeScript/UTS 配置中的路径别名设置 +3. 确保 `@/types` 正确映射到 `types/` 目录 + +### 问题 2: Supabase 连接失败 + +**错误信息**: +``` +Failed to connect to Supabase +``` + +**解决方案**: +1. 检查 Supabase 项目 URL 和 API Key 配置 +2. 验证网络连接 +3. 检查 Supabase 项目的状态 + +### 问题 3: RLS 策略导致权限错误 + +**错误信息**: +``` +new row violates row-level security policy +``` + +**解决方案**: +1. 确认已执行所有 RLS 策略脚本 +2. 检查用户认证状态 +3. 验证 RLS 策略的 SELECT/INSERT/UPDATE 权限设置 + +### 问题 4: 外键约束错误 + +**错误信息**: +``` +foreign key constraint "ml_user_profiles_user_id_fkey" fails +``` + +**解决方案**: +1. 如果使用独立用户表,需要更新外键引用 +2. 确保引用的用户记录存在 +3. 检查外键约束的 CASCADE 设置 + +--- + +## 📚 参考资料 + +- [Supabase 官方文档](https://supabase.com/docs) +- [uni-app-x 官方文档](https://uniapp.dcloud.net.cn/uni-app-x/) +- [PostgreSQL 官方文档](https://www.postgresql.org/docs/) +- 项目内部文档: + - `doc_mall/TECHNICAL_IMPLEMENTATION.md` - 技术实现详情 + - `doc_mall/FRONTEND_BACKEND_DEBUGGING.md` - 调试指南 + - `doc_mall/database/complete_deployment_guide.md` - 数据库部署指南 + +--- + +## 📞 迁移支持 + +如果在迁移过程中遇到问题: + +1. **查看文档**:先查看 `doc_mall/` 下的相关文档 +2. **检查日志**:查看编译日志和运行时日志 +3. **数据库验证**:使用 `doc_mall/database/validation_test.sql` 验证数据库状态 +4. **联系开发团队**:提供详细的错误信息和迁移步骤 + +--- + +**最后更新**: 2025年1月 +**版本**: v1.0 +**状态**: ✅ 完整迁移指南 diff --git a/mall_sql/docs/MIGRATION_SUMMARY.md b/mall_sql/docs/MIGRATION_SUMMARY.md new file mode 100644 index 00000000..175941ff --- /dev/null +++ b/mall_sql/docs/MIGRATION_SUMMARY.md @@ -0,0 +1,180 @@ +# 📦 doc_mall 迁移工作总览 + +## ✅ 已完成的准备工作 + +### 📄 迁移文档 +- ✅ **MIGRATION_GUIDE.md** - 完整的迁移指南(543行) +- ✅ **MIGRATION_CHECKLIST.md** - 详细的迁移检查清单(255行) +- ✅ **QUICK_START_MIGRATION.md** - 快速开始指南 +- ✅ **MIGRATION_SUMMARY.md** - 本文件,迁移工作总览 + +### 🔧 迁移工具 +- ✅ **migrate.ps1** - Windows PowerShell 迁移脚本(191行) +- ✅ **migrate.sh** - Linux/Mac Bash 迁移脚本(179行) + +### 📊 迁移统计 + +#### 文档和数据库脚本 (`doc_mall/`) +- **文件数量**: 约 48 个文件 +- **主要目录**: + - `analysis/` - 分析文档 + - `database/` - 数据库脚本(15+ SQL文件,12+ MD文档) + - `reports/` - 生成报告 + +#### 前端页面代码 (`pages/mall/`) +- **文件数量**: 约 45 个文件 +- **主要目录**: + - `admin/` - 管理端页面(5个文件) + - `analytics/` - 数据分析端(3个文件) + - `consumer/` - 消费者端(9个文件,含订阅功能) + - `delivery/` - 配送端(3个文件) + - `merchant/` - 商家端(3个文件) + - `service/` - 客服端(3个文件) + - `nfc/` - NFC支付相关(8个文件,可选) + +#### 类型定义文件 +- ✅ `types/mall-types.uts` - 商城系统完整类型定义(必须) + +--- + +## 🚀 执行迁移 + +### 方式 1: 使用自动化脚本(推荐) + +#### Windows 系统 +```powershell +# 1. 切换到项目目录 +cd D:\datas\hfkj\akmon + +# 2. 预览迁移(推荐先执行) +.\doc_mall\migrate.ps1 -TargetPath "D:\path\to\new-repo" -DryRun + +# 3. 执行实际迁移 +.\doc_mall\migrate.ps1 -TargetPath "D:\path\to\new-repo" + +# 4. 如果需要包含 Supabase 组件 +.\doc_mall\migrate.ps1 -TargetPath "D:\path\to\new-repo" -CopySupabaseComponents + +# 5. 如果需要包含工具函数 +.\doc_mall\migrate.ps1 -TargetPath "D:\path\to\new-repo" -CopyUtils +``` + +#### Linux/Mac 系统 +```bash +# 1. 切换到项目目录 +cd /path/to/akmon + +# 2. 添加执行权限 +chmod +x doc_mall/migrate.sh + +# 3. 预览迁移 +./doc_mall/migrate.sh /path/to/new-repo --dry-run + +# 4. 执行实际迁移 +./doc_mall/migrate.sh /path/to/new-repo + +# 5. 包含可选组件 +./doc_mall/migrate.sh /path/to/new-repo --copy-supabase --copy-utils +``` + +### 方式 2: 手动迁移 + +如果不想使用脚本,可以手动执行以下步骤: + +```powershell +# 1. 创建目标目录结构 +New-Item -ItemType Directory -Path "D:\path\to\new-repo\doc_mall\analysis" -Force +New-Item -ItemType Directory -Path "D:\path\to\new-repo\doc_mall\database" -Force +New-Item -ItemType Directory -Path "D:\path\to\new-repo\doc_mall\reports" -Force +New-Item -ItemType Directory -Path "D:\path\to\new-repo\pages\mall" -Force +New-Item -ItemType Directory -Path "D:\path\to\new-repo\types" -Force + +# 2. 复制文件 +Copy-Item -Path "doc_mall\*" -Destination "D:\path\to\new-repo\doc_mall\" -Recurse -Force +Copy-Item -Path "pages\mall\*" -Destination "D:\path\to\new-repo\pages\mall\" -Recurse -Force +Copy-Item -Path "types\mall-types.uts" -Destination "D:\path\to\new-repo\types\mall-types.uts" -Force +``` + +--- + +## 📋 迁移后必做事项 + +### 1. 验证文件完整性 + +使用检查清单验证所有文件已迁移: +- 打开 `MIGRATION_CHECKLIST.md` +- 逐项检查文件是否存在 +- 确认文件数量和大小 + +### 2. 配置 Supabase + +```typescript +// 创建 config/supabase.config.ts +export const supabaseConfig = { + url: 'https://your-project.supabase.co', + anonKey: 'your-anon-key', +} +``` + +### 3. 执行数据库脚本 + +按照 `database/complete_deployment_guide.md` 执行: +1. 执行 `complete_mall_database.sql` - 创建数据库结构 +2. 执行 `subscription_rls_policies.sql` - RLS策略 +3. 执行 `subscription_guard_trigger.sql` - 触发器 +4. 执行 `validation_test.sql` - 验证数据库 + +### 4. 更新代码路径 + +检查并更新以下导入路径: +- `@/types/mall-types.uts` +- `@/components/supadb/*` +- `@/utils/*`(如需要) + +### 5. 测试验证 + +- [ ] 项目可以编译 +- [ ] 页面可以加载 +- [ ] 数据库连接正常 +- [ ] 核心功能测试通过 + +--- + +## 📚 文档结构 + +``` +doc_mall/ +├── MIGRATION_GUIDE.md # 详细迁移指南 ⭐ +├── MIGRATION_CHECKLIST.md # 迁移检查清单 ⭐ +├── QUICK_START_MIGRATION.md # 快速开始 ⭐ +├── MIGRATION_SUMMARY.md # 本文档 +├── migrate.ps1 # PowerShell 脚本 ⭐ +├── migrate.sh # Bash 脚本 ⭐ +└── [其他原有文档和脚本] +``` + +--- + +## 🎯 下一步 + +1. **确定目标路径**:决定新仓库的位置 +2. **执行预览**:使用 `-DryRun` 参数预览迁移 +3. **执行迁移**:运行迁移脚本 +4. **验证文件**:使用检查清单验证 +5. **配置环境**:设置 Supabase 和数据库 +6. **测试验证**:确保一切正常工作 + +--- + +## 💡 提示 + +- **预览模式**:强烈建议先使用 `-DryRun` 预览,确认无误后再执行 +- **备份重要数据**:迁移前备份重要文件 +- **分批迁移**:如果文件很多,可以分批测试迁移 +- **记录问题**:在 `MIGRATION_CHECKLIST.md` 中记录遇到的问题 + +--- + +**创建时间**: 2025年1月 +**版本**: v1.0 +**状态**: ✅ 迁移工具已准备就绪,可以开始迁移 diff --git a/mall_sql/docs/MODULE_ANALYSIS.md b/mall_sql/docs/MODULE_ANALYSIS.md new file mode 100644 index 00000000..92d01596 --- /dev/null +++ b/mall_sql/docs/MODULE_ANALYSIS.md @@ -0,0 +1,710 @@ +# 📊 doc_mall 模块深度分析报告 + +## 📋 目录 +1. [模块概述](#模块概述) +2. [数据库存储方式](#数据库存储方式) +3. [数据库交互方式](#数据库交互方式) +4. [开发模式](#开发模式) +5. [开发流程](#开发流程) +6. [技术架构总结](#技术架构总结) + +--- + +## 一、模块概述 + +### 1.1 模块定位 +`doc_mall` 是一个**电商商城系统模块**,属于"梅州市智慧医养数字赋能平台"中的医养商城子系统。该模块提供医疗用品、保健产品、医养结合服务的在线销售平台。 + +### 1.2 核心功能 +- 🛒 **商品管理**: 商品展示、分类、品牌、多规格SKU +- 🏪 **店铺管理**: 商家店铺信息、认证、营业管理 +- 📦 **订单系统**: 订单创建、支付、发货、收货、评价全流程 +- 🛍️ **购物车**: 商品选择、数量管理 +- 🎫 **营销系统**: 优惠券、收藏、浏览历史、搜索记录 +- 🚚 **配送管理**: 配送员管理、配送任务、实时位置跟踪 +- ⭐ **评价系统**: 商品评价、商家回复、匿名评价 + +### 1.3 技术栈 +- **数据库**: PostgreSQL 13+ / Supabase +- **前端框架**: uni-app-x (UTS Android 兼容) +- **认证系统**: Supabase Auth +- **API方式**: Supabase REST API + PostgREST + +--- + +## 二、数据库存储方式 + +### 2.1 数据库类型 +**PostgreSQL + Supabase 兼容架构** + +- **主数据库**: PostgreSQL 13+ +- **云服务**: Supabase (PostgreSQL 托管 + 扩展服务) +- **兼容性**: 同时支持标准 PostgreSQL 和 Supabase 环境 + +### 2.2 存储架构设计 + +#### 2.2.1 表命名规范 +- **前缀策略**: 所有商城表使用 `ml_` 前缀 (mall) +- **复用策略**: 仅复用 `ak_users` 用户主表,其他表全部独立 +- **命名示例**: + - `ml_products` - 商品表 + - `ml_orders` - 订单表 + - `ml_user_profiles` - 用户扩展表 + +#### 2.2.2 数据表结构 (21张表) + +| 功能模块 | 表数量 | 主要表名 | 说明 | +| ------------ | ------ | ---------------------------------------------------------------------------------- | --------------------------- | +| **用户管理** | 2张 | `ml_user_profiles`, `ml_user_addresses` | 用户扩展信息、地址管理 | +| **商品管理** | 5张 | `ml_products`, `ml_product_skus`, `ml_categories`, `ml_brands`, `ml_product_specs` | 商品、SKU、分类、品牌、规格 | +| **店铺管理** | 1张 | `ml_shops` | 商家店铺信息 | +| **订单管理** | 2张 | `ml_orders`, `ml_order_items` | 订单主表、订单商品明细 | +| **购物车** | 1张 | `ml_shopping_cart` | 购物车商品 | +| **营销系统** | 2张 | `ml_coupon_templates`, `ml_user_coupons` | 优惠券模板、用户优惠券 | +| **配送管理** | 2张 | `ml_delivery_drivers`, `ml_delivery_tasks` | 配送员、配送任务 | +| **评价系统** | 1张 | `ml_product_reviews` | 商品评价 | +| **用户行为** | 3张 | `ml_user_favorites`, `ml_browse_history`, `ml_search_history` | 收藏、浏览历史、搜索记录 | +| **系统配置** | 2张 | `ml_system_configs`, `ml_regions` | 系统配置、地区数据 | + +#### 2.2.3 核心设计特性 + +**1. UUID 主键设计** +```sql +id UUID PRIMARY KEY DEFAULT uuid_generate_v4() +``` +- 所有表使用 UUID 作为主键 +- 支持分布式系统,避免ID冲突 +- 使用 `uuid-ossp` 扩展生成 + +**2. SEO 友好的自增ID (cid)** +```sql +cid SERIAL UNIQUE NOT NULL -- SEO友好的自增ID +``` +- 为主要表添加 `cid` 字段用于URL生成 +- 提供简洁、语义化的URL路径 +- 例如: `/product/123` 而不是 `/product/uuid-string` + +**3. JSONB 灵活数据存储** +```sql +image_urls JSONB DEFAULT '[]' +preferences JSONB DEFAULT '{}' +specifications JSONB DEFAULT '{}' +``` +- 使用 JSONB 存储灵活的JSON数据 +- 支持高效查询和索引 (GIN索引) +- 适合存储数组、对象等非结构化数据 + +**4. 时间戳字段** +```sql +created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +``` +- 标准的时间戳字段 +- 自动记录创建和更新时间 +- 通过触发器自动更新 `updated_at` + +**5. 外键约束** +```sql +user_id UUID NOT NULL REFERENCES public.ak_users(id) ON DELETE CASCADE +``` +- 完整的引用完整性约束 +- 级联删除保证数据一致性 +- 复用 `ak_users` 表实现单点登录 + +### 2.3 索引优化策略 + +#### 2.3.1 索引类型 +- **主键索引**: 自动创建 (UUID) +- **唯一索引**: 防止数据重复 (`product_code`, `order_no` 等) +- **外键索引**: 30+ 个优化查询索引 +- **复合索引**: 针对常用查询组合 +- **GIN 索引**: JSON 和数组字段的高效查询 + +#### 2.3.2 索引示例 +```sql +-- 商品表索引 +CREATE INDEX idx_ml_products_merchant ON public.ml_products(merchant_id); +CREATE INDEX idx_ml_products_category ON public.ml_products(category_id); +CREATE INDEX idx_ml_products_status ON public.ml_products(status); +CREATE INDEX idx_ml_products_cid ON public.ml_products(cid); -- SEO查询 + +-- 订单表索引 +CREATE INDEX idx_ml_orders_user ON public.ml_orders(user_id); +CREATE INDEX idx_ml_orders_merchant ON public.ml_orders(merchant_id); +CREATE INDEX idx_ml_orders_status ON public.ml_orders(order_status); +CREATE INDEX idx_ml_orders_created ON public.ml_orders(created_at DESC); + +-- JSONB GIN索引 +CREATE INDEX idx_ml_products_images_gin ON public.ml_products USING GIN(image_urls); +``` + +### 2.4 数据安全策略 (RLS) + +#### 2.4.1 Row Level Security (行级安全) +- **启用方式**: 所有表启用 RLS 策略 +- **认证方式**: 使用 Supabase `auth.uid()` 进行身份验证 +- **权限模型**: 基于用户角色的细粒度权限控制 + +#### 2.4.2 RLS 策略示例 +```sql +-- 用户只能访问自己的数据 +CREATE POLICY ml_user_profiles_select_policy ON public.ml_user_profiles + FOR SELECT USING ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id) + ); + +-- 商品公开查看,商家管理 +CREATE POLICY ml_products_select_policy ON public.ml_products + FOR SELECT USING (status = 1); -- 所有人可查看已上架商品 + +CREATE POLICY ml_products_update_policy ON public.ml_products + FOR UPDATE USING ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id) + ); -- 商家只能管理自己的商品 + +-- 订单权限:用户和商家都可查看 +CREATE POLICY ml_orders_select_policy ON public.ml_orders + FOR SELECT USING ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id) + OR + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id) + ); +``` + +### 2.5 触发器自动化 + +#### 2.5.1 触发器功能 +| 触发器名称 | 功能 | 应用表 | +| ------------------------------- | ---------------- | ------------------- | +| `update_updated_at_column` | 自动更新时间戳 | 8张主要表 | +| `ensure_single_default_address` | 确保唯一默认地址 | `ml_user_addresses` | +| `update_product_stock` | 自动更新商品库存 | `ml_product_skus` | +| `handle_order_status_change` | 订单状态变更处理 | `ml_orders` | + +#### 2.5.2 触发器示例 +```sql +-- 自动更新 updated_at +CREATE TRIGGER trigger_ml_user_profiles_updated_at + BEFORE UPDATE ON public.ml_user_profiles + FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); + +-- 确保唯一默认地址 +CREATE TRIGGER trigger_ensure_single_default_address + BEFORE INSERT OR UPDATE ON public.ml_user_addresses + FOR EACH ROW EXECUTE FUNCTION public.ensure_single_default_address(); +``` + +### 2.6 数据库函数 + +#### 2.6.1 业务函数 +| 函数名称 | 功能描述 | 返回类型 | +| ------------------------------- | ---------------- | -------- | +| `generate_order_no()` | 生成唯一订单号 | TEXT | +| `generate_coupon_code()` | 生成优惠券码 | TEXT | +| `get_user_default_address()` | 获取用户默认地址 | TABLE | +| `is_verified_merchant()` | 检查是否认证商家 | BOOLEAN | +| `calculate_cart_total()` | 计算购物车总金额 | DECIMAL | +| `get_product_available_stock()` | 获取商品可用库存 | INTEGER | + +#### 2.6.2 函数示例 +```sql +-- 生成订单号 +CREATE OR REPLACE FUNCTION public.generate_order_no() +RETURNS TEXT AS $$ +BEGIN + RETURN 'ORD' || TO_CHAR(NOW(), 'YYYYMMDD') || LPAD(NEXTVAL('order_no_seq')::TEXT, 6, '0'); +END; +$$ LANGUAGE plpgsql; + +-- 计算购物车总金额 +CREATE OR REPLACE FUNCTION public.calculate_cart_total(p_user_id UUID) +RETURNS DECIMAL AS $$ +DECLARE + total DECIMAL(12,2); +BEGIN + SELECT COALESCE(SUM(c.quantity * p.base_price), 0) + INTO total + FROM ml_shopping_cart c + JOIN ml_products p ON c.product_id = p.id + WHERE c.user_id = p_user_id AND c.selected = TRUE; + RETURN total; +END; +$$ LANGUAGE plpgsql; +``` + +### 2.7 视图设计 + +#### 2.7.1 业务视图 +| 视图名称 | 功能描述 | +| ------------------------- | -------------------------------------- | +| `ml_users_view` | 商城用户完整信息视图 | +| `ml_products_detail_view` | 商品详情视图(含分类、品牌、店铺信息) | +| `ml_orders_detail_view` | 订单详情视图(含客户、商家、状态信息) | + +#### 2.7.2 视图示例 +```sql +-- 商品详情视图 +CREATE VIEW ml_products_detail_view AS +SELECT + p.*, + c.name as category_name, + b.name as brand_name, + s.shop_name, + s.shop_logo +FROM ml_products p +LEFT JOIN ml_categories c ON p.category_id = c.id +LEFT JOIN ml_brands b ON p.brand_id = b.id +LEFT JOIN ml_shops s ON p.merchant_id = s.merchant_id; +``` + +--- + +## 三、数据库交互方式 + +### 3.1 API 架构 + +#### 3.1.1 Supabase REST API +- **基础URL**: `https://your-project.supabase.co/rest/v1/` +- **认证方式**: JWT Token (Bearer Token) +- **API Key**: `apikey` Header +- **协议**: HTTP/HTTPS RESTful API + +#### 3.1.2 PostgREST 自动生成 +- Supabase 基于 PostgREST 自动生成 REST API +- 每个表自动获得 CRUD 接口 +- 支持复杂查询、过滤、排序、分页 + +### 3.2 前端交互方式 + +#### 3.2.1 Supabase 客户端封装 +项目使用自定义的 Supabase 客户端封装 (`components/supadb/aksupa.uts`): + +```typescript +// 客户端初始化 +const supaClient = new AkSupa({ + baseUrl: 'https://your-project.supabase.co', + apikey: 'your-anon-key' +}); + +// 查询数据 +const response = await supaClient.select('ml_products', null, { + columns: 'id,name,base_price,main_image_url', + limit: 20, + order: 'created_at.desc' +}); + +// 插入数据 +const result = await supaClient.insert('ml_orders', { + user_id: userId, + merchant_id: merchantId, + total_amount: 100.00, + order_status: 1 +}); + +// 更新数据 +await supaClient.update('ml_products', { id: productId }, { + status: 2, + updated_at: new Date().toISOString() +}); + +// 删除数据 +await supaClient.delete('ml_user_favorites', { id: favoriteId }); +``` + +#### 3.2.2 查询选项支持 +```typescript +type AkSupaSelectOptions = { + columns?: string; // 选择字段: 'id,name,price' + limit?: number; // 限制数量 + order?: string; // 排序: 'created_at.desc' + rangeFrom?: number; // 分页起始 + rangeTo?: number; // 分页结束 + count?: string; // 计数方式: 'exact'|'planned'|'estimated' + single?: boolean; // 单条记录 + head?: boolean; // 仅返回元数据 +} +``` + +#### 3.2.3 过滤条件支持 +```typescript +// 简单过滤 +const filter = { + status: 1, + merchant_id: userId +}; + +// 复杂过滤 (PostgREST 操作符) +const filter = { + base_price: { gte: 100, lte: 500 }, // 范围查询 + name: { ilike: '%商品%' }, // 模糊查询 + category_id: { in: [id1, id2, id3] }, // IN 查询 + created_at: { gte: '2024-01-01' } // 时间范围 +}; +``` + +### 3.3 实时数据同步 + +#### 3.3.1 Supabase Realtime +- 支持 WebSocket 实时数据同步 +- 表变更自动推送到客户端 +- 适用于订单状态更新、库存变化等场景 + +```typescript +// 实时订阅订单状态 +supaClient.realtime.subscribe('ml_orders', { + filter: `id=eq.${orderId}`, + event: 'UPDATE', + callback: (payload) => { + console.log('订单状态更新:', payload); + } +}); +``` + +### 3.4 存储过程调用 (RPC) + +#### 3.4.1 数据库函数调用 +```typescript +// 调用数据库函数 +const result = await supaClient.rpc('calculate_cart_total', { + p_user_id: userId +}); + +// 调用生成订单号函数 +const orderNo = await supaClient.rpc('generate_order_no'); +``` + +### 3.5 认证与权限 + +#### 3.5.1 Supabase Auth 集成 +```typescript +// 用户登录 +const { data, error } = await supaClient.auth.signInWithPassword({ + email: 'user@example.com', + password: 'password' +}); + +// 获取当前用户 +const user = await supaClient.auth.getUser(); + +// Token 自动附加到请求头 +// Authorization: Bearer +``` + +#### 3.5.2 RLS 自动生效 +- 前端请求自动携带 JWT Token +- RLS 策略根据 `auth.uid()` 自动过滤数据 +- 用户只能访问被授权的数据 + +### 3.6 数据迁移与初始化 + +#### 3.6.1 数据库脚本执行 +```bash +# PostgreSQL 直接执行 +psql -h localhost -U postgres -d your_database -f complete_mall_database.sql + +# Supabase Dashboard 执行 +# 1. 登录 Supabase Dashboard +# 2. 进入 SQL Editor +# 3. 复制粘贴 SQL 脚本 +# 4. 执行脚本 +``` + +#### 3.6.2 模拟数据插入 +```bash +# 先执行主数据库脚本 +psql -f complete_mall_database.sql + +# 再执行模拟数据 +psql -f mock_data_insert.sql +``` + +--- + +## 四、开发模式 + +### 4.1 架构模式 + +#### 4.1.1 BaaS (Backend as a Service) 模式 +- **特点**: 使用 Supabase 作为后端服务 +- **优势**: + - 无需自建后端服务器 + - 自动生成 REST API + - 内置认证、权限、实时同步 + - 减少后端开发工作量 + +#### 4.1.2 数据库优先 (Database-First) 模式 +- **流程**: 先设计数据库 → 自动生成 API → 前端调用 +- **优势**: + - 数据结构清晰 + - API 自动生成,减少手写代码 + - 类型安全 (通过 TypeScript/UTS 类型定义) + +### 4.2 前端开发模式 + +#### 4.2.1 uni-app-x 框架 +- **平台**: uni-app-x (跨平台框架) +- **语言**: UTS (UniApp TypeScript) +- **兼容性**: 严格遵循 UTS Android 语法规范 + +#### 4.2.2 类型定义驱动 +```typescript +// types/mall-types.uts +export type ProductType = { + id: string + merchant_id: string + category_id: string + name: string + description: string | null + images: Array + price: number + stock: number + status: number + created_at: string +} +``` + +#### 4.2.3 组件化开发 +- 页面组件: `pages/mall/` +- 业务组件: `components/` +- 工具类: `utils/` +- 类型定义: `types/` + +### 4.3 数据访问模式 + +#### 4.3.1 服务层封装 +```typescript +// 商品服务 +class ProductService { + async getProducts(filters: any) { + return await supaClient.select('ml_products', filters, { + limit: 20, + order: 'created_at.desc' + }); + } + + async getProductById(id: string) { + return await supaClient.select('ml_products', { id }, { + single: true + }); + } +} +``` + +#### 4.3.2 响应式数据绑定 +- 使用 uni-app-x 的数据绑定机制 +- 结合 Supabase Realtime 实现实时更新 +- 状态管理通过组件状态或全局状态 + +### 4.4 安全模式 + +#### 4.4.1 多层安全防护 +1. **网络层**: HTTPS 加密传输 +2. **认证层**: Supabase Auth JWT Token +3. **权限层**: RLS 行级安全策略 +4. **应用层**: 前端数据验证 + +#### 4.4.2 最小权限原则 +- 用户只能访问自己的数据 +- 商家只能管理自己的商品和订单 +- 公开数据 (商品列表) 所有人可查看 + +--- + +## 五、开发流程 + +### 5.1 数据库设计流程 + +#### 5.1.1 需求分析 +1. **业务需求梳理** + - 商品管理需求 + - 订单流程需求 + - 用户角色需求 + - 营销功能需求 + +2. **数据模型设计** + - 实体识别 (商品、订单、用户等) + - 关系设计 (一对多、多对多) + - 字段设计 (类型、约束、索引) + +#### 5.1.2 数据库脚本编写 +```sql +-- 1. 创建表结构 +CREATE TABLE ml_products (...); + +-- 2. 创建索引 +CREATE INDEX idx_ml_products_merchant ON ml_products(merchant_id); + +-- 3. 创建触发器 +CREATE TRIGGER trigger_update_updated_at ...; + +-- 4. 创建 RLS 策略 +CREATE POLICY ml_products_select_policy ...; + +-- 5. 创建函数 +CREATE FUNCTION generate_order_no() ...; + +-- 6. 创建视图 +CREATE VIEW ml_products_detail_view AS ...; +``` + +#### 5.1.3 数据库部署 +1. **环境准备** + - PostgreSQL 13+ 或 Supabase 项目 + - 数据库用户权限配置 + +2. **脚本执行** + ```bash + # 执行主数据库脚本 + psql -f complete_mall_database.sql + + # 执行模拟数据 (可选) + psql -f mock_data_insert.sql + ``` + +3. **验证测试** + ```bash + # 执行验证脚本 + psql -f validation_test.sql + ``` + +### 5.2 前端开发流程 + +#### 5.2.1 类型定义 +```typescript +// 1. 定义 TypeScript/UTS 类型 +export type ProductType = { + id: string + name: string + price: number + // ... +} +``` + +#### 5.2.2 API 服务封装 +```typescript +// 2. 封装 API 调用 +class MallAPI { + async getProducts() { + return await supaClient.select('ml_products', ...); + } +} +``` + +#### 5.2.3 页面开发 +```vue + + + + +``` + +#### 5.2.4 测试验证 +- 功能测试: 验证业务流程 +- 权限测试: 验证 RLS 策略 +- 性能测试: 验证查询性能 + +### 5.3 迭代开发流程 + +#### 5.3.1 功能迭代 +1. **需求变更** → 数据库迁移脚本 +2. **表结构更新** → `mall_alter_upgrade.sql` +3. **数据迁移** → 迁移脚本执行 +4. **前端适配** → 类型定义更新 → 页面更新 + +#### 5.3.2 版本管理 +- **数据库版本**: 通过迁移脚本管理 +- **代码版本**: Git 版本控制 +- **文档版本**: Markdown 文档同步更新 + +### 5.4 部署流程 + +#### 5.4.1 开发环境 +1. 本地 PostgreSQL 或 Supabase 本地实例 +2. 执行数据库脚本 +3. 配置环境变量 +4. 启动前端开发服务器 + +#### 5.4.2 生产环境 +1. **Supabase 云服务部署** + - 创建 Supabase 项目 + - 执行数据库脚本 + - 配置环境变量 + - 部署前端应用 + +2. **自建 PostgreSQL 部署** + - 搭建 PostgreSQL 服务器 + - 执行数据库脚本 + - 配置 Nginx 反向代理 (如需要) + - 部署前端应用 + +--- + +## 六、技术架构总结 + +### 6.1 技术栈总结 + +| 层级 | 技术 | 说明 | +| ------------ | -------------- | ----------------- | +| **数据库** | PostgreSQL 13+ | 关系型数据库 | +| **BaaS平台** | Supabase | 后端即服务 | +| **API层** | PostgREST | 自动生成 REST API | +| **认证** | Supabase Auth | JWT Token 认证 | +| **前端框架** | uni-app-x | 跨平台框架 | +| **开发语言** | UTS | UniApp TypeScript | +| **类型系统** | TypeScript/UTS | 类型安全 | + +### 6.2 架构特点 + +#### ✅ 优势 +1. **开发效率高**: BaaS 模式减少后端开发 +2. **类型安全**: 完整的类型定义系统 +3. **自动API**: PostgREST 自动生成 REST API +4. **权限完善**: RLS 行级安全策略 +5. **实时同步**: Supabase Realtime 支持 +6. **扩展性强**: 数据库函数、触发器、视图支持 + +#### ⚠️ 注意事项 +1. **Supabase 依赖**: 深度依赖 Supabase 生态 +2. **学习曲线**: 需要熟悉 PostgreSQL 和 Supabase +3. **成本考虑**: Supabase 云服务有使用限制 +4. **迁移成本**: 如需迁移到其他平台,成本较高 + +### 6.3 最佳实践 + +1. **数据库设计优先**: 先设计好数据库结构 +2. **类型定义同步**: 保持数据库和类型定义同步 +3. **RLS 策略完善**: 确保数据安全 +4. **索引优化**: 针对查询场景优化索引 +5. **文档完善**: 保持文档与代码同步 + +--- + +## 📚 相关文档 + +- [数据库创建报告](./database/database_creation_report.md) +- [数据库语法修正报告](./database/database_syntax_fix_report.md) +- [完整部署指南](./database/complete_deployment_guide.md) +- [用户表复用方案](./user_reuse_summary.md) +- [前后端联调指南](./FRONTEND_BACKEND_DEBUGGING.md) ⭐ **新增** +- [模块README](./README.md) + +--- + +**生成时间**: 2025年1月 +**版本**: v1.0 +**状态**: ✅ 完整分析报告 diff --git a/mall_sql/docs/QUICK_START_MIGRATION.md b/mall_sql/docs/QUICK_START_MIGRATION.md new file mode 100644 index 00000000..e26d3078 --- /dev/null +++ b/mall_sql/docs/QUICK_START_MIGRATION.md @@ -0,0 +1,111 @@ +# ⚡ 快速开始迁移 + +## 🚀 快速执行迁移 + +### Windows (PowerShell) + +#### 1. 预览模式(推荐先执行) +```powershell +cd doc_mall +.\migrate.ps1 -TargetPath "D:\path\to\new-repo" -DryRun +``` + +#### 2. 执行迁移 +```powershell +cd doc_mall +.\migrate.ps1 -TargetPath "D:\path\to\new-repo" +``` + +#### 3. 包含 Supabase 组件 +```powershell +.\migrate.ps1 -TargetPath "D:\path\to\new-repo" -CopySupabaseComponents +``` + +#### 4. 包含工具函数 +```powershell +.\migrate.ps1 -TargetPath "D:\path\to\new-repo" -CopyUtils +``` + +### Linux/Mac (Bash) + +#### 1. 预览模式 +```bash +cd doc_mall +chmod +x migrate.sh +./migrate.sh /path/to/new-repo --dry-run +``` + +#### 2. 执行迁移 +```bash +./migrate.sh /path/to/new-repo +``` + +#### 3. 包含可选组件 +```bash +./migrate.sh /path/to/new-repo --copy-supabase --copy-utils +``` + +--- + +## 📋 迁移后的必要步骤 + +### 1. 检查迁移结果 +```powershell +# 检查目标目录 +ls D:\path\to\new-repo\doc_mall +ls D:\path\to\new-repo\pages\mall +ls D:\path\to\new-repo\types +``` + +### 2. 配置 Supabase + +创建配置文件 `config/supabase.config.ts`: +```typescript +export const supabaseConfig = { + url: 'https://your-project.supabase.co', + anonKey: 'your-anon-key', +} +``` + +### 3. 执行数据库脚本 + +#### 方式 1: Supabase Dashboard +1. 登录 Supabase Dashboard +2. 进入 SQL Editor +3. 复制 `doc_mall/database/complete_mall_database.sql` 内容 +4. 执行脚本 + +#### 方式 2: psql 命令行 +```bash +psql -h your-host -U postgres -d your_database -f doc_mall/database/complete_mall_database.sql +``` + +### 4. 验证数据库 +```bash +psql -h your-host -U postgres -d your_database -f doc_mall/database/validation_test.sql +``` + +### 5. 插入测试数据(可选) +```bash +psql -h your-host -U postgres -d your_database -f doc_mall/database/mock_data_insert.sql +``` + +--- + +## ✅ 验证清单 + +- [ ] 文件已复制到目标目录 +- [ ] 目录结构正确 +- [ ] Supabase 配置已更新 +- [ ] 数据库脚本已执行 +- [ ] 数据库验证通过 +- [ ] 项目可以编译 +- [ ] 页面可以正常加载 + +--- + +## 📚 更多信息 + +- 详细迁移指南: [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md) +- 完整检查清单: [MIGRATION_CHECKLIST.md](./MIGRATION_CHECKLIST.md) +- 技术实现文档: [TECHNICAL_IMPLEMENTATION.md](./TECHNICAL_IMPLEMENTATION.md) diff --git a/mall_sql/docs/README.md b/mall_sql/docs/README.md new file mode 100644 index 00000000..d3b85b94 --- /dev/null +++ b/mall_sql/docs/README.md @@ -0,0 +1,108 @@ +# 🛍️ 商城系统模块 (Mall System Module) + +本目录包含完整的商城系统模块,已从主项目中独立出来,可作为独立仓库使用。 + +## 📁 目录结构 + +``` +mall/ +├── doc_mall/ # 文档和数据库脚本 +│ ├── database/ # 数据库脚本目录 +│ ├── analysis/ # 分析文档目录 +│ ├── reports/ # 生成报告目录 +│ └── *.md # 各类文档和迁移指南 +├── pages/ # 前端页面代码 +│ └── mall/ # 商城页面 +│ ├── admin/ # 管理端页面 +│ ├── analytics/ # 数据分析端页面 +│ ├── consumer/ # 消费者端页面 +│ ├── delivery/ # 配送端页面 +│ ├── merchant/ # 商家端页面 +│ ├── service/ # 客服端页面 +│ └── nfc/ # NFC支付页面 +└── types/ # 类型定义 + └── mall-types.uts # 商城系统类型定义 +``` + +## 📊 迁移统计 + +- **文档和数据库脚本**: 48+ 个文件 (`doc_mall/`) +- **前端页面代码**: 45+ 个文件 (`pages/mall/`) +- **类型定义**: 1 个文件 (`types/mall-types.uts`) + +## 🚀 快速开始 + +### 1. 查看迁移指南 + +- **完整迁移指南**: [doc_mall/MIGRATION_GUIDE.md](./doc_mall/MIGRATION_GUIDE.md) +- **迁移检查清单**: [doc_mall/MIGRATION_CHECKLIST.md](./doc_mall/MIGRATION_CHECKLIST.md) +- **快速开始**: [doc_mall/QUICK_START_MIGRATION.md](./doc_mall/QUICK_START_MIGRATION.md) + +### 2. 配置数据库 + +执行数据库脚本创建表结构: + +```bash +# 方式1: 通过 Supabase Dashboard SQL Editor +# 打开 doc_mall/database/complete_mall_database.sql 并执行 + +# 方式2: 通过 psql 命令行 +psql -h localhost -U postgres -d your_database -f doc_mall/database/complete_mall_database.sql +``` + +### 3. 配置 Supabase 连接 + +创建配置文件,设置 Supabase 项目 URL 和 API Key。 + +### 4. 更新导入路径 + +检查并更新代码中的导入路径,确保指向正确的位置。 + +## 📚 核心文档 + +### 技术文档 +- [技术实现拆解](./doc_mall/TECHNICAL_IMPLEMENTATION.md) - 详细的技术实现说明 +- [模块深度分析](./doc_mall/MODULE_ANALYSIS.md) - 模块架构和设计理念 +- [前后端联调指南](./doc_mall/FRONTEND_BACKEND_DEBUGGING.md) - 开发调试指南 + +### 数据库文档 +- [完整部署指南](./doc_mall/database/complete_deployment_guide.md) - 数据库部署步骤 +- [快速部署指南](./doc_mall/database/deployment_guide.md) - 快速部署方法 +- [数据库创建报告](./doc_mall/database/database_creation_report.md) - 数据库结构说明 + +## 🔧 迁移到新仓库 + +如果你需要将本模块迁移到一个完全独立的 Git 仓库,可以使用提供的迁移脚本: + +### Windows (PowerShell) +```powershell +cd doc_mall +.\migrate.ps1 -TargetPath "D:\path\to\new-repo" +``` + +### Linux/Mac (Bash) +```bash +cd doc_mall +chmod +x migrate.sh +./migrate.sh /path/to/new-repo +``` + +详细步骤请参考 [MIGRATION_GUIDE.md](./doc_mall/MIGRATION_GUIDE.md)。 + +## 📝 注意事项 + +1. **用户表依赖**: 商城系统依赖 `ak_users` 用户表,迁移时需要确定处理方案(独立表/复用表/API服务) +2. **Supabase 配置**: 需要配置 Supabase 项目连接信息 +3. **路径更新**: 迁移后需要更新代码中的导入路径 +4. **数据库脚本**: 需要按顺序执行数据库脚本 + +## 📞 支持 + +- 查看文档: 参考 `doc_mall/` 目录下的相关文档 +- 迁移问题: 参考 [MIGRATION_GUIDE.md](./doc_mall/MIGRATION_GUIDE.md) 中的常见问题部分 + +--- + +**迁移日期**: 2025年1月 +**版本**: v1.0 +**状态**: ✅ 已独立迁移到 mall/ 目录 diff --git a/mall_sql/docs/README_subscription_consumer.md b/mall_sql/docs/README_subscription_consumer.md new file mode 100644 index 00000000..f7728a8e --- /dev/null +++ b/mall_sql/docs/README_subscription_consumer.md @@ -0,0 +1,16 @@ +# 软件订阅(consumer) + +入口: +- 用户中心 -> 软件订阅 + +页面: +- plan-list.uvue:展示可用订阅方案(ml_subscription_plans) +- plan-detail.uvue:展示某个订阅方案详情 +- subscribe-checkout.uvue:确认支付并创建订阅(写入 ml_user_subscriptions) + +依赖表(示例名称,可按实际后端调整): +- ml_subscription_plans(id, plan_code, name, description, features jsonb, price numeric, currency text, billing_period text, trial_days int, is_active bool, sort_order int, created_at, updated_at) +- ml_user_subscriptions(id, user_id, plan_id, status text, start_date timestamptz, end_date timestamptz, next_billing_date timestamptz, auto_renew bool, cancel_at_period_end bool, metadata jsonb, created_at, updated_at) + +注意: +- 本实现使用 uni-app-x 兼容组件与 supaClient。实际支付请替换为你们的支付网关,并在后端完成对账与签名校验。 diff --git a/mall_sql/docs/ROLE_FIELD_FIX_REPORT.md b/mall_sql/docs/ROLE_FIELD_FIX_REPORT.md new file mode 100644 index 00000000..1faa1687 --- /dev/null +++ b/mall_sql/docs/ROLE_FIELD_FIX_REPORT.md @@ -0,0 +1,151 @@ +# 角色字段统一修复完成报告 + +## 🔧 问题修复 + +### 问题1:重复的角色字段 +**原问题**:`ml_user_profiles` 表中存在重复的 `role` 字段,与 `ak_users.role` 重复。 +**解决方案**:删除 `ml_user_profiles.role` 字段,统一使用 `ak_users.role`。 + +### 问题2:变量类型错误 +**原问题**:订单生成代码中 `merchant_rec` 变量类型错误,导致数据类型不匹配。 +**解决方案**:将 `merchant_rec RECORD` 改为 `merchant_id UUID`。 + +## ✅ 已修复的文件 + +### 1. complete_mall_database.sql +- ❌ 删除:`ml_user_profiles.role` 字段定义 +- ❌ 删除:相关约束 `chk_ml_user_role` +- ❌ 删除:相关索引 `idx_ml_user_profiles_role` +- ❌ 删除:相关注释 +- ✅ 更新:`is_verified_merchant()` 函数,从 `ak_users` 表获取角色 +- ✅ 更新:`ml_users_view` 视图,使用 `u.role` 替代 `p.role` +- ✅ 更新:插入语句,移除 `role` 字段 + +### 2. mock_data_insert.sql +- ✅ 更新:用户档案插入语句,移除 `role` 字段 +- ✅ 更新:冲突处理语句,移除 `role` 字段 +- ✅ 修复:订单生成代码中的变量类型错误 + +### 3. role_field_cleanup.sql (新增) +- ✅ 创建:专门的角色字段清理脚本 +- ✅ 功能:检查并清理重复的角色字段 +- ✅ 功能:数据迁移和一致性检查 +- ✅ 功能:更新相关函数和视图 + +## 📊 当前角色字段设计 + +### 唯一的角色存储位置 +```sql +-- ak_users 表 - 唯一的角色字段存储位置 +CREATE TABLE public.ak_users ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + role TEXT DEFAULT 'customer' NOT NULL, + -- 其他字段... + + CONSTRAINT chk_ak_users_role + CHECK (role IN ('customer', 'merchant', 'delivery', 'service', 'admin')) +); +``` + +### 相关表关联 +```sql +-- ml_user_profiles 表 - 不再包含 role 字段 +CREATE TABLE public.ml_user_profiles ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id UUID UNIQUE NOT NULL REFERENCES public.ak_users(id), + status INTEGER DEFAULT 1 NOT NULL, + -- 其他扩展信息字段... +); +``` + +### 获取用户角色 +```sql +-- 通过关联查询获取角色信息 +SELECT u.role, p.real_name, p.credit_score +FROM ak_users u +LEFT JOIN ml_user_profiles p ON u.id = p.user_id +WHERE u.id = 'user-uuid'; +``` + +## 🔍 验证步骤 + +### 1. 字段检查 +```sql +-- 检查是否还有重复的 role 字段 +SELECT + table_name, + column_name, + data_type +FROM information_schema.columns +WHERE column_name = 'role' +AND table_name IN ('ak_users', 'ml_user_profiles'); + +-- 预期结果:只有 ak_users.role +``` + +### 2. 约束检查 +```sql +-- 检查角色约束 +SELECT constraint_name, table_name +FROM information_schema.check_constraints +WHERE constraint_name LIKE '%role%'; + +-- 预期结果:只有 chk_ak_users_role +``` + +### 3. 功能检查 +```sql +-- 测试角色相关函数 +SELECT get_user_role('test-user-id'); +SELECT check_user_permission('test-user-id', ARRAY['admin']); +SELECT * FROM vw_role_statistics; +``` + +## 🎯 优势总结 + +### 1. 数据一致性 +- ✅ 单一数据源:角色信息只存储在一个地方 +- ✅ 避免同步问题:不会出现两个表角色不一致的情况 +- ✅ 数据完整性:通过外键约束保证关联关系 + +### 2. 代码简洁性 +- ✅ 查询简化:直接从 `ak_users` 获取角色信息 +- ✅ 维护容易:只需要维护一个角色字段 +- ✅ 扩展性好:新增角色类型只需要修改一个约束 + +### 3. 性能优化 +- ✅ 减少JOIN:在只需要角色信息时无需关联 `ml_user_profiles` +- ✅ 索引优化:`ak_users.role` 上的索引直接支持角色查询 +- ✅ 存储节约:减少了重复数据的存储 + +## 📋 迁移指南 + +### 对于新项目 +直接使用修复后的 `complete_mall_database.sql` 脚本。 + +### 对于现有项目 +1. 执行 `role_field_cleanup.sql` 脚本 +2. 验证数据迁移结果 +3. 测试相关功能是否正常 + +### 脚本执行顺序 +```bash +# 1. 主数据库结构 +psql -f complete_mall_database.sql + +# 2. 角色字段清理(如果是从旧版本升级) +psql -f role_field_cleanup.sql + +# 3. 插入测试数据 +psql -f mock_data_insert.sql +``` + +## ✨ 结论 + +角色字段统一修复已经完成,系统现在具有: +- 🎯 **清晰的数据结构**:角色信息统一存储在 `ak_users.role` +- 🔒 **数据一致性保证**:消除了数据重复和不一致的风险 +- 🚀 **更好的性能**:简化了查询逻辑,提高了查询效率 +- 🛠️ **易于维护**:减少了代码复杂度,便于后续维护和扩展 + +所有相关文件已更新完毕,可以安全使用! diff --git a/mall_sql/docs/ROLE_FIELD_SUMMARY.md b/mall_sql/docs/ROLE_FIELD_SUMMARY.md new file mode 100644 index 00000000..e584ae50 --- /dev/null +++ b/mall_sql/docs/ROLE_FIELD_SUMMARY.md @@ -0,0 +1,172 @@ +# 角色字段统一方案总结 + +## 📋 概述 + +为了提高代码可读性和语义清晰度,我们将商城系统中的用户角色字段从 `user_type` (INTEGER) 统一为 `role` (TEXT)。 + +## 🔄 修改内容 + +### 1. 字段类型变更 + +#### 原始设计 (已废弃) +```sql +-- ml_user_profiles 表 +user_type INTEGER DEFAULT 1 NOT NULL +-- 约束:CHECK (user_type IN (1,2,3,4,5)) +-- 1:消费者 2:商家 3:配送员 4:客服 5:管理员 +``` + +#### 新设计 (当前版本) +```sql +-- ml_user_profiles 表 + ak_users 表 +role TEXT DEFAULT 'customer' NOT NULL +-- 约束:CHECK (role IN ('customer', 'merchant', 'delivery', 'service', 'admin')) +-- customer:消费者, merchant:商家, delivery:配送员, service:客服, admin:管理员 +``` + +### 2. 数据映射关系 + +| 旧 user_type (INTEGER) | 新 role (TEXT) | 中文含义 | +|------------------------|----------------|----------| +| 1 | customer | 消费者 | +| 2 | merchant | 商家 | +| 3 | delivery | 配送员 | +| 4 | service | 客服 | +| 5 | admin | 管理员 | + +### 3. 统一后的优势 + +1. **语义清晰**:`role` 比 `user_type` 更符合业务语义 +2. **代码可读**:字符串值比数字更易理解 +3. **扩展性好**:便于添加新角色类型 +4. **国际化友好**:角色名称可直接用于多语言映射 +5. **API友好**:前端可直接使用角色字符串 + +## 📁 相关文件 + +### 核心数据库文件 +- ✅ `complete_mall_database.sql` - 主数据库结构(已更新) +- ✅ `mock_data_insert.sql` - 测试数据插入(已更新) + +### 迁移脚本 +- 🆕 `quick_role_migration.sql` - 快速迁移脚本(推荐) +- 🆕 `role_field_unification.sql` - 完整统一方案 + +### 其他升级脚本(自动兼容) +- ✅ `mall_alter_upgrade.sql` - 增量升级脚本 +- ✅ `mall_fields_only_upgrade.sql` - 字段升级脚本 +- ✅ `mall_migration.sql` - 完整迁移脚本 +- ✅ `mall_seo_security.sql` - SEO和安全脚本 + +### 文档 +- ✅ `UPGRADE_GUIDE.md` - 升级指南(已更新) + +## 🚀 执行步骤 + +### 对于新项目 +直接使用最新的 `complete_mall_database.sql`,已包含 `role` 字段设计。 + +### 对于现有项目 +如果您的数据库中存在 `user_type` 字段,请按以下步骤升级: + +#### 步骤 1:数据备份 +```bash +pg_dump your_database > backup_before_role_migration.sql +``` + +#### 步骤 2:执行快速迁移 +```bash +psql -d your_database -f quick_role_migration.sql +``` + +#### 步骤 3:验证迁移结果 +```sql +-- 检查角色分布 +SELECT role, COUNT(*) as count +FROM ml_user_profiles +GROUP BY role; + +-- 检查数据一致性 +SELECT COUNT(*) as inconsistent_records +FROM ak_users u +JOIN ml_user_profiles p ON u.id = p.user_id +WHERE u.role != p.role; +``` + +#### 步骤 4:(可选)清理旧字段 +迁移成功并确认无误后,可删除旧的 `user_type` 字段: +```sql +ALTER TABLE ml_user_profiles DROP COLUMN user_type; +``` + +## 🔧 技术细节 + +### 更新的数据库对象 + +1. **表结构** + - `ml_user_profiles.role` - 新增字段 + - `ak_users.role` - 与之保持同步 + +2. **约束** + - `chk_ml_user_role` - 角色值约束 + - 移除:`chk_ml_user_type` + +3. **索引** + - `idx_ml_user_profiles_role` - 角色字段索引 + - 移除:`idx_ml_user_profiles_type` + +4. **函数** + - `is_verified_merchant()` - 商家验证函数 + - `get_user_role()` - 获取用户角色 + - `check_user_permission()` - 权限检查 + - `upgrade_user_role()` - 角色升级 + +5. **视图** + - `ml_users_view` - 用户信息视图 + - `vw_user_info` - 用户完整信息视图 + - `vw_role_statistics` - 角色统计视图 + +6. **RLS策略** + - 所有涉及角色检查的策略已更新 + +### 兼容性说明 + +- ✅ **向前兼容**:新脚本可在空数据库上运行 +- ✅ **向后兼容**:提供完整回滚方案 +- ✅ **增量升级**:支持现有数据的平滑迁移 +- ✅ **Supabase兼容**:完全支持Supabase环境 + +## 🔍 测试验证 + +### 测试用例 +```sql +-- 1. 测试角色约束 +INSERT INTO ml_user_profiles (user_id, role) +VALUES (uuid_generate_v4(), 'invalid_role'); -- 应该失败 + +-- 2. 测试函数 +SELECT get_user_role('user-uuid-here'); +SELECT check_user_permission('user-uuid-here', ARRAY['admin', 'merchant']); + +-- 3. 测试视图 +SELECT * FROM vw_role_statistics; +SELECT * FROM ml_users_view WHERE role = 'merchant'; +``` + +### 性能影响 +- 角色查询性能:通过 `idx_ml_user_profiles_role` 索引优化 +- 存储开销:TEXT字段比INTEGER稍大,但差异微小 +- 查询兼容:所有现有查询逻辑已更新 + +## 📞 支持 + +如果在角色字段迁移过程中遇到问题,请: + +1. 检查错误日志 +2. 确认数据备份完整 +3. 运行 `mall_database_check.sql` 诊断问题 +4. 如需回滚,使用 `quick_role_migration.sql` 中的回滚脚本 + +--- + +**总结**:角色字段统一方案提供了更清晰、更语义化的用户角色管理,同时保持了完整的向后兼容性和迁移安全性。 diff --git a/mall_sql/docs/TECHNICAL_IMPLEMENTATION.md b/mall_sql/docs/TECHNICAL_IMPLEMENTATION.md new file mode 100644 index 00000000..17b2546d --- /dev/null +++ b/mall_sql/docs/TECHNICAL_IMPLEMENTATION.md @@ -0,0 +1,1431 @@ +# 🔨 doc_mall 模块技术实现拆解 + +## 📋 目录 +1. [整体架构](#整体架构) +2. [数据库层实现](#数据库层实现) +3. [后端/API层实现](#后端api层实现) +4. [前端实现](#前端实现) +5. [数据流机制](#数据流机制) +6. [业务逻辑实现](#业务逻辑实现) +7. [安全机制](#安全机制) +8. [性能优化](#性能优化) + +--- + +## 一、整体架构 + +### 1.1 技术栈架构图 + +``` +┌─────────────────────────────────────────────────────────┐ +│ 前端层 (uni-app-x) │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ +│ │ 消费者端 │ │ 商家端 │ │ 配送端 │ │ 管理端 │ │ +│ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ +│ │ │ │ │ │ +│ └──────────────┴──────────────┴────────────┘ │ +│ │ │ +│ ┌───────────▼───────────┐ │ +│ │ Supabase 客户端封装 │ │ +│ │ (AkSupa.uts) │ │ +│ └───────────┬───────────┘ │ +└──────────────────────────┼──────────────────────────────┘ + │ HTTPS REST API +┌───────────────────────────▼──────────────────────────────┐ +│ API 层 (PostgREST) │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ 自动生成 REST API │ │ +│ │ - GET /rest/v1/ml_products │ │ +│ │ - POST /rest/v1/ml_orders │ │ +│ │ - RPC /rest/v1/rpc/calculate_cart_total │ │ +│ └──────────────────────────────────────────────────┘ │ +└───────────────────────────┬──────────────────────────────┘ + │ +┌───────────────────────────▼──────────────────────────────┐ +│ 认证层 (Supabase Auth) │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ JWT Token 认证 │ │ +│ │ - 用户登录/注册 │ │ +│ │ - Token 刷新 │ │ +│ │ - 权限验证 │ │ +│ └──────────────────────────────────────────────────┘ │ +└───────────────────────────┬──────────────────────────────┘ + │ +┌───────────────────────────▼──────────────────────────────┐ +│ 权限层 (RLS - Row Level Security) │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ 行级安全策略 │ │ +│ │ - 用户数据隔离 │ │ +│ │ - 商家权限控制 │ │ +│ │ - 公开数据访问 │ │ +│ └──────────────────────────────────────────────────┘ │ +└───────────────────────────┬──────────────────────────────┘ + │ +┌───────────────────────────▼──────────────────────────────┐ +│ 数据库层 (PostgreSQL) │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ +│ │ 表结构 │ │ 触发器 │ │ 函数 │ │ 视图 │ │ +│ │ 索引 │ │ RLS策略 │ │ 序列 │ │ 扩展 │ │ +│ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ +└─────────────────────────────────────────────────────────┘ +``` + +### 1.2 核心设计模式 + +#### BaaS (Backend as a Service) 模式 +- **特点**: 使用 Supabase 作为后端服务,无需自建后端服务器 +- **优势**: + - 自动生成 REST API + - 内置认证和权限系统 + - 实时数据同步 + - 减少后端开发工作量 + +#### 数据库优先 (Database-First) 模式 +- **流程**: 数据库设计 → 自动生成 API → 前端调用 +- **实现**: + 1. 设计数据库表结构 + 2. PostgREST 自动生成 REST API + 3. 前端通过 Supabase 客户端调用 + +#### 类型驱动开发 (Type-Driven Development) +- **实现**: TypeScript/UTS 类型定义 +- **文件**: `types/mall-types.uts` +- **优势**: 类型安全、代码提示、减少错误 + +--- + +## 二、数据库层实现 + +### 2.1 表结构设计 + +#### 2.1.1 核心表结构 + +**用户扩展表** (`ml_user_profiles`) +```sql +CREATE TABLE public.ml_user_profiles ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id UUID UNIQUE NOT NULL REFERENCES public.ak_users(id) ON DELETE CASCADE, + status INTEGER DEFAULT 1, -- 1:正常 2:冻结 3:注销 4:待审核 + real_name VARCHAR(100), -- 真实姓名 + id_card VARCHAR(32), -- 身份证号 + credit_score INTEGER DEFAULT 100, -- 信用分数 0-1000 + verification_status INTEGER DEFAULT 0, -- 认证状态 + verification_data JSONB DEFAULT '{}', -- 认证相关数据 + preferences JSONB DEFAULT '{}', -- 用户偏好设置 + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); +``` + +**商品表** (`ml_products`) +```sql +CREATE TABLE public.ml_products ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + cid SERIAL UNIQUE NOT NULL, -- SEO友好的自增ID + merchant_id UUID NOT NULL REFERENCES public.ak_users(id), + category_id UUID NOT NULL REFERENCES public.ml_categories(id), + brand_id UUID REFERENCES public.ml_brands(id), + product_code VARCHAR(100) UNIQUE NOT NULL, + name VARCHAR(500) NOT NULL, + description TEXT, + main_image_url TEXT, + image_urls JSONB DEFAULT '[]', -- 商品图片数组 + base_price DECIMAL(12,2) NOT NULL, + total_stock INTEGER DEFAULT 0, + available_stock INTEGER DEFAULT 0, + status INTEGER DEFAULT 1, -- 1:上架 2:下架 3:草稿 4:删除 + view_count INTEGER DEFAULT 0, + sale_count INTEGER DEFAULT 0, + rating_avg DECIMAL(3,2) DEFAULT 0.00, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); +``` + +**订单表** (`ml_orders`) +```sql +CREATE TABLE public.ml_orders ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + cid SERIAL UNIQUE NOT NULL, + order_no VARCHAR(50) UNIQUE NOT NULL, + user_id UUID NOT NULL REFERENCES public.ak_users(id), + merchant_id UUID NOT NULL REFERENCES public.ak_users(id), + product_amount DECIMAL(12,2) NOT NULL DEFAULT 0, + discount_amount DECIMAL(12,2) DEFAULT 0, + shipping_fee DECIMAL(12,2) DEFAULT 0, + total_amount DECIMAL(12,2) NOT NULL, + shipping_address JSONB NOT NULL, -- 收货地址JSON + order_status INTEGER DEFAULT 1, -- 1:待支付 2:待发货 3:待收货 4:已完成 + payment_status INTEGER DEFAULT 1, -- 1:未支付 2:已支付 3:部分退款 4:全额退款 + shipping_status INTEGER DEFAULT 1, -- 1:未发货 2:已发货 3:运输中 4:已送达 + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); +``` + +### 2.2 索引设计 + +#### 2.2.1 性能优化索引 + +```sql +-- 商品表索引 +CREATE INDEX idx_ml_products_merchant ON public.ml_products(merchant_id); +CREATE INDEX idx_ml_products_category ON public.ml_products(category_id); +CREATE INDEX idx_ml_products_status ON public.ml_products(status); +CREATE INDEX idx_ml_products_cid ON public.ml_products(cid); -- SEO查询 +CREATE INDEX idx_ml_products_created ON public.ml_products(created_at DESC); + +-- 订单表索引 +CREATE INDEX idx_ml_orders_user ON public.ml_orders(user_id); +CREATE INDEX idx_ml_orders_merchant ON public.ml_orders(merchant_id); +CREATE INDEX idx_ml_orders_status ON public.ml_orders(order_status); +CREATE INDEX idx_ml_orders_created ON public.ml_orders(created_at DESC); + +-- JSONB GIN索引(用于JSON字段查询) +CREATE INDEX idx_ml_products_images_gin ON public.ml_products USING GIN(image_urls); +CREATE INDEX idx_ml_orders_address_gin ON public.ml_orders USING GIN(shipping_address); +``` + +### 2.3 触发器实现 + +#### 2.3.1 自动更新时间戳 + +```sql +-- 触发器函数 +CREATE OR REPLACE FUNCTION public.update_updated_at_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- 应用到表 +CREATE TRIGGER trigger_ml_user_profiles_updated_at + BEFORE UPDATE ON public.ml_user_profiles + FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column(); +``` + +#### 2.3.2 确保唯一默认地址 + +```sql +CREATE OR REPLACE FUNCTION public.ensure_single_default_address() +RETURNS TRIGGER AS $$ +BEGIN + IF NEW.is_default = TRUE THEN + UPDATE public.ml_user_addresses + SET is_default = FALSE + WHERE user_id = NEW.user_id AND id != NEW.id; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER trigger_ensure_single_default_address + BEFORE INSERT OR UPDATE ON public.ml_user_addresses + FOR EACH ROW EXECUTE FUNCTION public.ensure_single_default_address(); +``` + +#### 2.3.3 自动更新商品库存 + +```sql +CREATE OR REPLACE FUNCTION public.update_product_stock() +RETURNS TRIGGER AS $$ +BEGIN + IF TG_OP = 'INSERT' THEN + -- 插入订单商品时,减少库存 + UPDATE public.ml_products + SET available_stock = available_stock - NEW.quantity + WHERE id = NEW.product_id; + ELSIF TG_OP = 'DELETE' THEN + -- 删除订单商品时,恢复库存 + UPDATE public.ml_products + SET available_stock = available_stock + OLD.quantity + WHERE id = OLD.product_id; + END IF; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER trigger_update_product_stock + AFTER INSERT OR DELETE ON public.ml_order_items + FOR EACH ROW EXECUTE FUNCTION public.update_product_stock(); +``` + +### 2.4 数据库函数实现 + +#### 2.4.1 业务函数 + +**生成订单号** +```sql +CREATE OR REPLACE FUNCTION public.generate_order_no() +RETURNS TEXT AS $$ +DECLARE + order_no TEXT; +BEGIN + order_no := 'ML' || TO_CHAR(NOW(), 'YYYYMMDD') || + LPAD(NEXTVAL('ml_order_seq')::TEXT, 6, '0'); + RETURN order_no; +END; +$$ LANGUAGE plpgsql; +``` + +**计算购物车总金额** +```sql +CREATE OR REPLACE FUNCTION public.calculate_cart_total(p_user_id UUID) +RETURNS DECIMAL AS $$ +DECLARE + total_amount DECIMAL(12,2) := 0; +BEGIN + SELECT COALESCE(SUM( + CASE + WHEN c.sku_id IS NOT NULL THEN s.price * c.quantity + ELSE p.base_price * c.quantity + END + ), 0) INTO total_amount + FROM public.ml_shopping_cart c + LEFT JOIN public.ml_product_skus s ON c.sku_id = s.id + LEFT JOIN public.ml_products p ON c.product_id = p.id + WHERE c.user_id = p_user_id + AND c.selected = TRUE + AND p.status = 1 + AND (s.id IS NULL OR s.status = 1); + + RETURN total_amount; +END; +$$ LANGUAGE plpgsql; +``` + +**获取用户默认地址** +```sql +CREATE OR REPLACE FUNCTION public.get_user_default_address(p_user_id UUID) +RETURNS TABLE ( + id UUID, + receiver_name VARCHAR, + receiver_phone VARCHAR, + address_detail TEXT +) AS $$ +BEGIN + RETURN QUERY + SELECT + a.id, + a.receiver_name, + a.receiver_phone, + a.address_detail + FROM public.ml_user_addresses a + WHERE a.user_id = p_user_id + AND a.is_default = TRUE + AND a.status = 1 + LIMIT 1; +END; +$$ LANGUAGE plpgsql; +``` + +### 2.5 RLS 行级安全策略 + +#### 2.5.1 用户数据隔离 + +```sql +-- 用户只能访问自己的数据 +CREATE POLICY ml_user_profiles_select_policy ON public.ml_user_profiles + FOR SELECT USING ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id) + ); + +CREATE POLICY ml_user_profiles_update_policy ON public.ml_user_profiles + FOR UPDATE USING ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id) + ); +``` + +#### 2.5.2 商品权限控制 + +```sql +-- 所有人可查看已上架商品 +CREATE POLICY ml_products_select_policy ON public.ml_products + FOR SELECT USING (status = 1); + +-- 商家只能管理自己的商品 +CREATE POLICY ml_products_insert_policy ON public.ml_products + FOR INSERT WITH CHECK ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id) + ); + +CREATE POLICY ml_products_update_policy ON public.ml_products + FOR UPDATE USING ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id) + ); +``` + +#### 2.5.3 订单权限控制 + +```sql +-- 用户和商家都可查看相关订单 +CREATE POLICY ml_orders_select_policy ON public.ml_orders + FOR SELECT USING ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id) + OR + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = merchant_id) + ); + +-- 只有用户能创建订单 +CREATE POLICY ml_orders_insert_policy ON public.ml_orders + FOR INSERT WITH CHECK ( + auth.uid()::text = (SELECT auth_id::text FROM public.ak_users WHERE id = user_id) + ); +``` + +--- + +## 三、后端/API层实现 + +### 3.1 PostgREST 自动生成 API + +#### 3.1.1 REST API 自动生成机制 + +Supabase 基于 PostgREST 自动为每个表生成 REST API: + +**查询 API** +``` +GET /rest/v1/ml_products +GET /rest/v1/ml_products?id=eq.{uuid} +GET /rest/v1/ml_products?status=eq.1&limit=20 +GET /rest/v1/ml_products?base_price=gte.100&base_price=lte.500 +``` + +**插入 API** +``` +POST /rest/v1/ml_orders +Content-Type: application/json +{ + "user_id": "uuid", + "merchant_id": "uuid", + "total_amount": 100.00 +} +``` + +**更新 API** +``` +PATCH /rest/v1/ml_products?id=eq.{uuid} +Content-Type: application/json +{ + "status": 2 +} +``` + +**删除 API** +``` +DELETE /rest/v1/ml_user_favorites?id=eq.{uuid} +``` + +**RPC 函数调用** +``` +POST /rest/v1/rpc/calculate_cart_total +Content-Type: application/json +{ + "p_user_id": "uuid" +} +``` + +### 3.2 查询操作符支持 + +PostgREST 支持丰富的查询操作符: + +```typescript +// 等于 +?status=eq.1 + +// 不等于 +?status=neq.2 + +// 大于/小于 +?base_price=gte.100&base_price=lte.500 + +// 模糊查询 +?name=ilike.%商品% + +// IN 查询 +?category_id=in.(id1,id2,id3) + +// IS NULL +?deleted_at=is.null + +// JSONB 查询 +?preferences->theme=eq.dark +``` + +### 3.3 分页和排序 + +```typescript +// 分页 +?limit=20&offset=0 +// 或使用 Range 头 +Range: 0-19 + +// 排序 +?order=created_at.desc +?order=base_price.asc,created_at.desc + +// 计数 +Prefer: count=exact +``` + +--- + +## 四、前端实现 + +### 4.1 项目结构 + +``` +pages/mall/ +├── consumer/ # 消费者端 +│ ├── index.uvue # 首页 +│ ├── product-detail.uvue # 商品详情 +│ ├── cart.uvue # 购物车 +│ ├── checkout.uvue # 结算页 +│ ├── orders.uvue # 订单列表 +│ └── subscription/ # 订阅相关 +├── merchant/ # 商家端 +│ ├── index.uvue # 商家首页 +│ └── product-detail.uvue +├── delivery/ # 配送端 +├── admin/ # 管理端 +└── service/ # 客服端 + +components/supadb/ +├── aksupa.uts # Supabase 客户端封装 +├── aksupainstance.uts # 全局单例 +└── aksuparealtime.uts # 实时订阅 + +types/ +└── mall-types.uts # 类型定义 +``` + +### 4.2 Supabase 客户端封装 + +#### 4.2.1 客户端初始化 + +**文件**: `components/supadb/aksupainstance.uts` + +```typescript +import AkSupa from './aksupa.uts' +import { SUPA_URL, SUPA_KEY } from '@/ak/config.uts' + +// 创建全局 Supabase 客户端实例 +const supa = new AkSupa(SUPA_URL, SUPA_KEY) + +// 自动登录 (开发环境) +const supaReady: Promise = (async () => { + try { + await supa.signIn('test@example.com', 'password') + return true + } catch (err) { + console.error('Supabase auto sign-in failed', err) + return false + } +})() + +export { supaReady } +export default supa +``` + +#### 4.2.2 API 调用封装 + +**文件**: `components/supadb/aksupa.uts` + +```typescript +export class AkSupa { + baseUrl: string + apikey: string + + constructor(baseUrl: string, apikey: string) { + this.baseUrl = baseUrl + this.apikey = apikey + } + + // 查询数据 + async select( + table: string, + filter?: string | null, + options?: AkSupaSelectOptions + ): Promise> { + let url = this.baseUrl + '/rest/v1/' + table + let headers = { + apikey: this.apikey, + 'Content-Type': 'application/json', + Authorization: `Bearer ${AkReq.getToken() ?? ''}` + } as UTSJSONObject + + // 构建查询参数 + let params: string[] = [] + if (options?.limit) params.push(`limit=${options.limit}`) + if (options?.order) params.push(`order=${encodeURIComponent(options.order)}`) + if (filter) params.push(filter) + + if (params.length > 0) { + url += '?' + params.join('&') + } + + return await this.requestWithAutoRefresh({ + url, + method: 'GET', + headers + }) + } + + // 插入数据 + async insert( + table: string, + row: UTSJSONObject | Array + ): Promise> { + const url = this.baseUrl + '/rest/v1/' + table + const headers = { + apikey: this.apikey, + 'Content-Type': 'application/json', + Authorization: `Bearer ${AkReq.getToken() ?? ''}`, + Prefer: 'return=representation' + } as UTSJSONObject + + return await this.requestWithAutoRefresh({ + url, + method: 'POST', + headers, + data: row + }) + } + + // 更新数据 + async update( + table: string, + filter: UTSJSONObject, + data: UTSJSONObject + ): Promise> { + const filterStr = buildSupabaseFilterQuery(filter) + const url = this.baseUrl + '/rest/v1/' + table + '?' + filterStr + const headers = { + apikey: this.apikey, + 'Content-Type': 'application/json', + Authorization: `Bearer ${AkReq.getToken() ?? ''}`, + Prefer: 'return=representation' + } as UTSJSONObject + + return await this.requestWithAutoRefresh({ + url, + method: 'PATCH', + headers, + data + }) + } + + // 调用 RPC 函数 + async rpc( + functionName: string, + params: UTSJSONObject + ): Promise> { + const url = `${this.baseUrl}/rest/v1/rpc/${functionName}` + const headers = { + apikey: this.apikey, + 'Content-Type': 'application/json', + Authorization: `Bearer ${AkReq.getToken() ?? ''}` + } as UTSJSONObject + + return await this.requestWithAutoRefresh({ + url, + method: 'POST', + headers, + data: params + }) + } +} +``` + +### 4.3 页面实现示例 + +#### 4.3.1 商品列表页面 + +**文件**: `pages/mall/consumer/index.uvue` + +```typescript + +``` + +#### 4.3.2 商品详情页面 + +```typescript +// 加载商品详情 +const loadProductDetail = async (productId: string) => { + try { + // 查询商品信息 + const productRes = await supa.select('ml_products', + `id=eq.${productId}`, + { single: true } + ) + + if (productRes.success && productRes.data) { + product.value = productRes.data as ProductType + } + + // 查询商品SKU + const skuRes = await supa.select('ml_product_skus', { + product_id: productId + }) + + if (skuRes.success && skuRes.data) { + productSkus.value = skuRes.data as Array + } + + // 查询商家信息 + const merchantRes = await supa.select('ml_shops', { + merchant_id: product.value.merchant_id + }, { single: true }) + + if (merchantRes.success && merchantRes.data) { + merchant.value = merchantRes.data as MerchantType + } + } catch (err) { + console.error('加载商品详情失败:', err) + } +} +``` + +#### 4.3.3 购物车操作 + +```typescript +// 添加到购物车 +const addToCart = async (product: ProductType, skuId?: string, quantity: number = 1) => { + try { + const userId = getCurrentUserId() + if (!userId) { + uni.showToast({ title: '请先登录', icon: 'error' }) + return + } + + // 检查购物车中是否已存在 + const existingRes = await supa.select('ml_shopping_cart', { + user_id: userId, + product_id: product.id, + sku_id: skuId || null + }, { single: true }) + + if (existingRes.success && existingRes.data) { + // 更新数量 + await supa.update('ml_shopping_cart', + { id: existingRes.data.id }, + { quantity: existingRes.data.quantity + quantity } + ) + } else { + // 新增购物车项 + await supa.insert('ml_shopping_cart', { + user_id: userId, + product_id: product.id, + sku_id: skuId || null, + quantity: quantity, + selected: true + }) + } + + uni.showToast({ title: '已添加到购物车', icon: 'success' }) + loadCartCount() + } catch (err) { + console.error('添加到购物车失败:', err) + uni.showToast({ title: '操作失败', icon: 'error' }) + } +} +``` + +#### 4.3.4 创建订单 + +```typescript +// 创建订单 +const createOrder = async (cartItems: Array, address: UserAddressType) => { + try { + // 1. 计算订单总金额(使用数据库函数) + const totalRes = await supa.rpc('calculate_cart_total', { + p_user_id: getCurrentUserId() + }) + + if (!totalRes.success) { + throw new Error('计算订单金额失败') + } + + const totalAmount = totalRes.data as number + + // 2. 生成订单号 + const orderNoRes = await supa.rpc('generate_order_no') + if (!orderNoRes.success) { + throw new Error('生成订单号失败') + } + const orderNo = orderNoRes.data as string + + // 3. 创建订单 + const orderRes = await supa.insert('ml_orders', { + order_no: orderNo, + user_id: getCurrentUserId(), + merchant_id: cartItems[0].product.merchant_id, + product_amount: totalAmount, + discount_amount: 0, + shipping_fee: 0, + total_amount: totalAmount, + shipping_address: { + receiver_name: address.receiver_name, + receiver_phone: address.receiver_phone, + province: address.province, + city: address.city, + district: address.district, + address_detail: address.address_detail + }, + order_status: 1, // 待支付 + payment_status: 1, + shipping_status: 1 + }) + + if (!orderRes.success) { + throw new Error('创建订单失败') + } + + const orderId = orderRes.data.id + + // 4. 创建订单商品项 + const orderItems = cartItems.map(item => ({ + order_id: orderId, + product_id: item.product_id, + sku_id: item.sku_id || null, + product_name: item.product.name, + price: item.sku?.price || item.product.price, + quantity: item.quantity, + total_amount: (item.sku?.price || item.product.price) * item.quantity + })) + + await supa.insert('ml_order_items', orderItems) + + // 5. 清空购物车 + for (const item of cartItems) { + await supa.delete('ml_shopping_cart', { id: item.id }) + } + + uni.showToast({ title: '订单创建成功', icon: 'success' }) + + // 跳转到订单详情 + uni.navigateTo({ + url: `/pages/mall/consumer/order-detail?orderId=${orderId}` + }) + } catch (err) { + console.error('创建订单失败:', err) + uni.showToast({ title: '创建订单失败', icon: 'error' }) + } +} +``` + +### 4.4 实时数据同步 + +#### 4.4.1 订阅订单状态更新 + +```typescript +import { AkSupaRealtime } from '@/components/supadb/aksuparealtime.uts' + +// 订阅订单状态更新 +const subscribeOrderStatus = (orderId: string, callback: (payload: any) => void) => { + const realtime = new AkSupaRealtime(WS_URL, SUPA_KEY) + + realtime.subscribe('ml_orders', { + filter: `id=eq.${orderId}`, + event: 'UPDATE', + callback: (payload) => { + console.log('订单状态更新:', payload) + callback(payload) + } + }) +} + +// 使用 +onMounted(() => { + subscribeOrderStatus(orderId, (payload) => { + // 更新订单状态 + order.value.order_status = payload.new.order_status + }) +}) +``` + +--- + +## 五、数据流机制 + +### 5.1 数据流向图 + +``` +用户操作 + │ + ▼ +前端页面 (uni-app-x) + │ + ▼ +Supabase 客户端 (AkSupa) + │ + ▼ HTTP Request + │ + ├─ Headers: apikey, Authorization (JWT Token) + │ + ▼ +PostgREST API + │ + ├─ 解析请求 + ├─ 验证 JWT Token + ├─ 应用 RLS 策略 + │ + ▼ +PostgreSQL 数据库 + │ + ├─ 执行 SQL 查询 + ├─ 触发触发器 + ├─ 执行函数 + │ + ▼ +返回数据 + │ + ▼ +PostgREST 格式化响应 + │ + ▼ HTTP Response + │ + ├─ JSON 数据 + ├─ 状态码 + │ + ▼ +Supabase 客户端处理 + │ + ├─ 解析响应 + ├─ 错误处理 + │ + ▼ +前端页面更新 UI +``` + +### 5.2 认证流程 + +``` +1. 用户登录 + │ + ▼ +2. Supabase Auth 验证 + │ + ├─ 验证邮箱/密码 + ├─ 生成 JWT Token + │ + ▼ +3. 存储 Token + │ + ├─ 本地存储 (uni.setStorageSync) + │ + ▼ +4. 后续请求自动携带 Token + │ + ├─ Authorization: Bearer + │ + ▼ +5. PostgREST 验证 Token + │ + ├─ 解析 JWT + ├─ 获取 auth.uid() + │ + ▼ +6. RLS 策略应用 + │ + ├─ 根据 auth.uid() 过滤数据 +``` + +### 5.3 权限控制流程 + +``` +请求到达 PostgREST + │ + ▼ +解析 JWT Token + │ + ├─ 获取 auth.uid() + │ + ▼ +查找 RLS 策略 + │ + ├─ SELECT 策略 → USING 子句 + ├─ INSERT 策略 → WITH CHECK 子句 + ├─ UPDATE 策略 → USING + WITH CHECK + ├─ DELETE 策略 → USING 子句 + │ + ▼ +应用策略条件 + │ + ├─ 用户只能访问自己的数据 + ├─ 商家只能管理自己的商品 + ├─ 公开数据所有人可查看 + │ + ▼ +执行 SQL 查询 + │ + ├─ 自动添加 WHERE 条件 + │ + ▼ +返回过滤后的数据 +``` + +--- + +## 六、业务逻辑实现 + +### 6.1 商品管理流程 + +#### 6.1.1 商品上架流程 + +```typescript +// 商家上架商品 +const publishProduct = async (productData: any) => { + // 1. 验证商家权限 + const merchantRes = await supa.select('ml_user_profiles', { + user_id: getCurrentUserId(), + user_type: 2, // 商家 + verification_status: 1 // 已认证 + }, { single: true }) + + if (!merchantRes.success || !merchantRes.data) { + throw new Error('您还不是认证商家') + } + + // 2. 创建商品 + const productRes = await supa.insert('ml_products', { + merchant_id: getCurrentUserId(), + category_id: productData.category_id, + name: productData.name, + description: productData.description, + base_price: productData.price, + total_stock: productData.stock, + available_stock: productData.stock, + status: 1, // 上架 + ...productData + }) + + // 3. 创建商品SKU + if (productData.skus && productData.skus.length > 0) { + const skus = productData.skus.map((sku: any) => ({ + product_id: productRes.data.id, + sku_code: sku.sku_code, + specifications: sku.specifications, + price: sku.price, + stock: sku.stock + })) + + await supa.insert('ml_product_skus', skus) + } + + return productRes.data +} +``` + +### 6.2 订单处理流程 + +#### 6.2.1 订单状态流转 + +```typescript +// 订单状态枚举 +const ORDER_STATUS = { + PENDING_PAYMENT: 1, // 待支付 + PAID: 2, // 已支付 + SHIPPED: 3, // 已发货 + DELIVERED: 4, // 已送达 + COMPLETED: 5, // 已完成 + CANCELLED: 6, // 已取消 + REFUNDING: 7, // 退款中 + REFUNDED: 8 // 已退款 +} + +// 更新订单状态 +const updateOrderStatus = async (orderId: string, newStatus: number) => { + const updateData: any = { + order_status: newStatus, + updated_at: new Date().toISOString() + } + + // 根据状态设置相应时间戳 + switch (newStatus) { + case ORDER_STATUS.PAID: + updateData.paid_at = new Date().toISOString() + updateData.payment_status = 2 // 已支付 + break + case ORDER_STATUS.SHIPPED: + updateData.shipped_at = new Date().toISOString() + updateData.shipping_status = 2 // 已发货 + break + case ORDER_STATUS.DELIVERED: + updateData.delivered_at = new Date().toISOString() + updateData.shipping_status = 4 // 已送达 + break + case ORDER_STATUS.COMPLETED: + updateData.completed_at = new Date().toISOString() + break + } + + await supa.update('ml_orders', { id: orderId }, updateData) +} +``` + +### 6.3 库存管理机制 + +#### 6.3.1 库存扣减流程 + +```typescript +// 下单时扣减库存 +const deductStock = async (orderItems: Array) => { + for (const item of orderItems) { + if (item.sku_id) { + // 扣减 SKU 库存 + const skuRes = await supa.select('ml_product_skus', { + id: item.sku_id + }, { single: true }) + + if (skuRes.data.stock < item.quantity) { + throw new Error(`商品 ${item.product_name} 库存不足`) + } + + await supa.update('ml_product_skus', + { id: item.sku_id }, + { stock: skuRes.data.stock - item.quantity } + ) + } else { + // 扣减商品总库存 + const productRes = await supa.select('ml_products', { + id: item.product_id + }, { single: true }) + + if (productRes.data.available_stock < item.quantity) { + throw new Error(`商品 ${item.product_name} 库存不足`) + } + + await supa.update('ml_products', + { id: item.product_id }, + { + available_stock: productRes.data.available_stock - item.quantity, + sale_count: productRes.data.sale_count + item.quantity + } + ) + } + } +} +``` + +--- + +## 七、安全机制 + +### 7.1 多层安全防护 + +``` +┌─────────────────────────────────────┐ +│ 1. 网络层安全 │ +│ - HTTPS 加密传输 │ +│ - SSL/TLS 证书 │ +└─────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────┐ +│ 2. 认证层安全 │ +│ - JWT Token 验证 │ +│ - Token 过期机制 │ +│ - 自动刷新 Token │ +└─────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────┐ +│ 3. 权限层安全 (RLS) │ +│ - 行级安全策略 │ +│ - 基于用户角色的权限控制 │ +│ - 数据隔离 │ +└─────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────┐ +│ 4. 应用层安全 │ +│ - 前端数据验证 │ +│ - 输入过滤和转义 │ +│ - 防止 SQL 注入 │ +└─────────────────────────────────────┘ +``` + +### 7.2 数据验证机制 + +#### 7.2.1 数据库约束 + +```sql +-- CHECK 约束 +CONSTRAINT chk_ml_product_status CHECK (status IN (1,2,3,4)) +CONSTRAINT chk_ml_order_status CHECK (order_status IN (1,2,3,4,5,6,7)) +CONSTRAINT chk_ml_credit_score CHECK (credit_score >= 0 AND credit_score <= 1000) + +-- 外键约束 +REFERENCES public.ak_users(id) ON DELETE CASCADE +REFERENCES public.ml_products(id) ON DELETE CASCADE + +-- 唯一约束 +UNIQUE(product_code) +UNIQUE(order_no) +UNIQUE(user_id, product_id, sku_id) -- 购物车唯一性 +``` + +#### 7.2.2 前端验证 + +```typescript +// 表单验证 +const validateOrderData = (orderData: any): boolean => { + if (!orderData.user_id) { + uni.showToast({ title: '用户ID不能为空', icon: 'error' }) + return false + } + + if (!orderData.total_amount || orderData.total_amount <= 0) { + uni.showToast({ title: '订单金额无效', icon: 'error' }) + return false + } + + if (!orderData.shipping_address) { + uni.showToast({ title: '请选择收货地址', icon: 'error' }) + return false + } + + return true +} +``` + +--- + +## 八、性能优化 + +### 8.1 数据库优化 + +#### 8.1.1 索引优化 + +```sql +-- 复合索引(针对常用查询组合) +CREATE INDEX idx_ml_products_status_created +ON ml_products(status, created_at DESC); + +CREATE INDEX idx_ml_orders_user_status +ON ml_orders(user_id, order_status); + +-- 部分索引(只索引活跃数据) +CREATE INDEX idx_ml_products_active +ON ml_products(merchant_id, category_id) +WHERE status = 1; +``` + +#### 8.1.2 查询优化 + +```typescript +// 只查询需要的字段 +const res = await supa.select('ml_products', null, { + columns: 'id,name,base_price,main_image_url', // 只查询必要字段 + limit: 20 +}) + +// 使用视图简化复杂查询 +const res = await supa.select('ml_products_detail_view', { + status: 1 +}, { + limit: 20 +}) +``` + +### 8.2 前端优化 + +#### 8.2.1 分页加载 + +```typescript +// 分页加载商品列表 +const loadProducts = async (loadMore: boolean = false) => { + const currentPage = loadMore ? page.value + 1 : 1 + + const res = await supa + .from('ml_products') + .select('*') + .eq('status', 1) + .order('created_at', { ascending: false }) + .range((currentPage - 1) * pageSize.value, currentPage * pageSize.value - 1) + + // 追加或替换数据 + if (loadMore) { + productList.value.push(...res.data) + } else { + productList.value = res.data + } +} +``` + +#### 8.2.2 数据缓存 + +```typescript +// 使用本地缓存减少请求 +const getCachedProducts = async (categoryId: string) => { + const cacheKey = `products_${categoryId}` + const cached = uni.getStorageSync(cacheKey) + + if (cached && Date.now() - cached.timestamp < 5 * 60 * 1000) { + // 5分钟内使用缓存 + return cached.data + } + + // 从服务器获取 + const res = await supa.select('ml_products', { + category_id: categoryId, + status: 1 + }) + + // 更新缓存 + uni.setStorageSync(cacheKey, { + data: res.data, + timestamp: Date.now() + }) + + return res.data +} +``` + +### 8.3 实时同步优化 + +```typescript +// 只订阅必要的数据变更 +const subscribeOrderUpdates = (orderId: string) => { + realtime.subscribe('ml_orders', { + filter: `id=eq.${orderId}`, // 只订阅特定订单 + event: 'UPDATE', // 只监听更新事件 + callback: handleOrderUpdate + }) +} + +// 及时取消订阅 +onUnmounted(() => { + realtime.unsubscribe('ml_orders') +}) +``` + +--- + +## 九、开发工作流 + +### 9.1 开发流程 + +``` +1. 数据库设计 + │ + ├─ 设计表结构 + ├─ 设计索引 + ├─ 设计 RLS 策略 + ├─ 设计触发器 + └─ 设计函数 + │ + ▼ +2. 执行数据库脚本 + │ + ├─ complete_mall_database.sql + │ + ▼ +3. 定义类型 + │ + ├─ types/mall-types.uts + │ + ▼ +4. 开发前端页面 + │ + ├─ 页面组件 + ├─ API 调用 + └─ 业务逻辑 + │ + ▼ +5. 测试验证 + │ + ├─ 功能测试 + ├─ 权限测试 + └─ 性能测试 +``` + +### 9.2 调试技巧 + +```typescript +// 1. 启用详细日志 +console.log('请求参数:', { + table: 'ml_products', + filter: filter, + options: options +}) + +// 2. 检查响应 +console.log('API 响应:', { + success: res.success, + status: res.status, + data: res.data, + error: res.error +}) + +// 3. 验证权限 +const session = await supa.getSession() +console.log('当前用户:', session.user) +console.log('JWT Token:', AkReq.getToken()) +``` + +--- + +## 📚 相关文档 + +- [模块分析报告](./MODULE_ANALYSIS.md) +- [前后端联调指南](./FRONTEND_BACKEND_DEBUGGING.md) +- [数据库创建报告](./database/database_creation_report.md) +- [完整部署指南](./database/complete_deployment_guide.md) + +--- + +**生成时间**: 2025年1月 +**版本**: v1.0 +**状态**: ✅ 完整技术实现拆解 diff --git a/mall_sql/docs/UNI_APP_X_MIGRATION.md b/mall_sql/docs/UNI_APP_X_MIGRATION.md new file mode 100644 index 00000000..7b847032 --- /dev/null +++ b/mall_sql/docs/UNI_APP_X_MIGRATION.md @@ -0,0 +1,198 @@ +# uni-app X 迁移操作总结 + +## 操作日期 +2024年(具体日期根据实际情况填写) + +## 操作背景 +项目需要从传统的 uni-app 迁移到 **uni-app X**,以支持 `.uvue` 文件在 H5 浏览器中正确渲染。 + +## 问题分析 +对比根项目(`akmon`)和 `mall` 项目,发现以下关键差异: + +1. **缺少 uni-app X 配置**:`mall/manifest.json` 中缺少 `"uni-app-x": {}` 配置项 +2. **存在 .vue 文件**:项目中有 23 个 `.vue` 文件,这些文件在 uni-app X 中无法被正确编译到 H5 +3. **编译器配置**:需要确保 HBuilderX 使用 uni-app X 编译器 + +## 执行的操作 + +### 1. 添加 uni-app X 配置 + +在 `manifest.json` 中添加了 `"uni-app-x": {}` 配置项: + +```json +{ + "vueVersion": "3", + "uni-app-x": {}, + "h5": { + "title": "mall", + "router": { + "mode": "hash", + "base": "./" + } + } +} +``` + +**位置**:`manifest.json` 第 66 行 + +**作用**: +- 告诉 HBuilderX 这是一个 uni-app X 项目 +- 启用 uni-app X 编译链,支持 `.uvue` 文件编译到 H5 +- 确保 `.uvue` 文件能够被正确编译和渲染 + +### 2. 删除所有 .vue 文件 + +删除了项目中所有 `.vue` 文件,共 23 个文件: + +**删除的文件列表**: +- `pages/user/boot.vue` +- `pages/user/login.vue` +- `pages/user/register.vue` +- `pages/user/forgot-password.vue` +- `pages/user/profile.vue` +- `pages/user/center.vue` +- `pages/user/terms.vue` +- `pages/mall/consumer/index.vue` +- `pages/mall/consumer/product-detail.vue` +- `pages/mall/consumer/order-detail.vue` +- `pages/mall/consumer/profile.vue` +- `pages/mall/consumer/subscription/plan-list.vue` +- `pages/mall/consumer/subscription/plan-detail.vue` +- `pages/mall/consumer/subscription/subscribe-checkout.vue` +- `pages/mall/consumer/subscription/my-subscriptions.vue` +- `pages/mall/merchant/index.vue` +- `pages/mall/delivery/index.vue` +- `pages/mall/admin/index.vue` +- `pages/mall/admin/subscription/plan-management.vue` +- `pages/mall/admin/subscription/user-subscriptions.vue` +- `pages/mall/service/index.vue` +- `pages/mall/analytics/index.vue` +- `pages/mall/nfc/security/index.vue` + +**删除命令**: +```powershell +Set-Location -Path 'd:\datas\hfkj\akmon\mall' +Get-ChildItem -Recurse -Filter *.vue | Remove-Item -Force +``` + +**原因**: +- `.vue` 文件在 uni-app X 中无法被正确编译到 H5 浏览器 +- 所有页面和组件应使用 `.uvue` 格式 +- 导入语句会自动识别 `.uvue` 扩展名(导入时无需显式指定扩展名) + +## 技术说明 + +### uni-app X vs 传统 uni-app + +| 特性 | 传统 uni-app | uni-app X | +| ------------- | --------------------- | ---------------------- | +| 文件格式 | `.vue` | `.uvue` | +| 脚本语言 | JavaScript/TypeScript | UTS (TypeScript 扩展) | +| 编译器 | uni-app 编译器 | uni-app X 编译器 | +| H5 渲染 | 需要编译 | 需要编译(但支持更好) | +| manifest.json | 不需要 `uni-app-x` | 需要 `"uni-app-x": {}` | + +### 导入语句说明 + +删除 `.vue` 文件后,所有导入语句会自动使用对应的 `.uvue` 文件: + +```typescript +// 之前(.vue) +import LoginPage from './pages/user/login.vue' + +// 现在(.uvue,扩展名可省略) +import LoginPage from './pages/user/login.uvue' +// 或者 +import LoginPage from './pages/user/login' // 自动识别 .uvue +``` + +## 后续操作 + +### 1. 验证配置 + +1. 打开 HBuilderX +2. 打开 `mall` 项目 +3. 检查编译器:**工具** → **切换编译器** → 确认选择 **uni-app X** +4. 如果未选择,请切换到 uni-app X 编译器 + +### 2. 运行到 H5 + +1. 在 HBuilderX 中,点击菜单:**运行** → **运行到浏览器** → **Chrome**(或内置浏览器) +2. 等待编译完成 +3. 浏览器会自动打开并显示应用 + +### 3. 发行 H5 + +如果需要打包发布: + +1. 点击菜单:**发行** → **网站-H5** +2. 等待编译完成 +3. 编译产物在 `unpackage/dist/build/h5` 目录 +4. 将整个 `h5` 目录部署到 Web 服务器 + +### 4. 检查页面 + +确保所有页面都有对应的 `.uvue` 文件: + +- 检查 `pages.json` 中配置的所有页面路径 +- 确认每个页面都有对应的 `.uvue` 文件 +- 如果缺少,需要从备份或版本控制中恢复并转换为 `.uvue` 格式 + +## 注意事项 + +1. **编译器版本**:必须使用支持 uni-app X 的 HBuilderX 版本 +2. **文件格式**:所有页面和组件必须使用 `.uvue` 格式,不能混用 `.vue` +3. **UTS 语法**:`.uvue` 文件中的 `