# 陇耘鲜达项目 - 数据库设计规范 ## 表设计规则 ### 1. 必须字段 所有数据库表必须包含以下字段: - `id` - 主键,VARCHAR(32),全局唯一 - `is_del` - 是否删除,TINYINT,0=未删除,1=已删除 - `create_at` - 创建时间,DATETIME - `create_by` - 创建人ID,VARCHAR(32) - `create_name` - 创建人姓名,VARCHAR(100) - `update_at` - 修改时间,DATETIME - `update_by` - 修改人ID,VARCHAR(32) ### 2. 删除策略 - 所有表采用**虚拟删除**机制 - 删除操作时,将 `is_del` 字段设为 1,不执行物理删除 - 查询时默认添加 `WHERE is_del = 0` 条件 ### 3. 历史表机制 - **每个业务表**都需要创建一个对应的历史表 - 历史表命名规则:`主表名 + _his` - 触发时机:在进行 UPDATE 操作时 1. 首先将原始数据完整复制到历史表 2. 然后再更新主表数据 - 历史表结构:与主表结构相同 - 历史表特殊处理: - 不需要任何索引 - `id` 字段不需要唯一性限制(可以重复) - 不需要 `is_del` 字段(历史数据永久保留) ### 4. 其他规范 - 表名使用下划线命名法,如:`sys_user`, `ord_order` - 字段名使用下划线命名法 - 金额字段使用 DECIMAL(12, 2) 类型 - 状态字段使用 VARCHAR(20) 或 INT - 时间字段使用 DATETIME 类型 - 字符串类型根据实际长度选择 VARCHAR 或 TEXT ## 数据库命名约定 - 数据库名称:`sanqiang` - 表前缀:无特殊前缀 - 历史表后缀:`_his` --- ## UI 设计风格规范 ### 1. 整体风格 - **设计理念**:现代、专业、高效;运营 Web 管理端以 **Fresh Mint(薄荷绿)** 为品牌主色,中性色以 Slate 系为主 - **艺术风格**:简洁、清爽;强调色集中用于主按钮、导航选中、主状态标签等,避免一屏多种高饱和彩色 - **设计一致性**:**Web 管理端(`web-admin`)** 以设计源 `test/fresh-mint-green.html` 与文档 `docs/web-admin-ui-spec-fresh-mint.md` 为唯一视觉权威;**小程序各角色端** 可继续使用角色主题色(橙/绿/红),不必与 Web 管理端同色 ### 2. Web端 - Fresh Mint(`web-admin`) #### 技术栈 - Vue3 + TypeScript - Element Plus 组件库 - Tailwind CSS - Pinia 状态管理 #### 权威文档与实现方式 - **完整 Token、布局、组件、与 Element 映射**:见 **`docs/web-admin-ui-spec-fresh-mint.md`** - **设计稿 / 对照 HTML**:`test/fresh-mint-green.html` - **`web-admin` 界面改造留痕**:对运营后台页面做 Fresh Mint 对齐、布局或组件级调整时,**约定将过程性与结论性说明同步写入** **`docs/web-admin-ui-spec-fresh-mint.md`**(如增补小节、实现清单、或某页的专用布局/交互约定),便于后续统一改版时对照,避免只改代码不更新规范。 - 实现时优先:**全局 CSS 变量(与 demo `:root` 一致)→ Element 主题变量 → `el-ui.scss` / 布局组件覆盖**,与 demo 色值保持一致 - **硬提醒(壳子与区块勿漏)**:侧栏/顶栏/内容区/Tab 条 **§3**;筛选区 **§5**(**含带清除输入**);按钮与 Loading **§6**;列表工具栏、表格、分页、标签 **§7**;树形子表 **§8**;弹窗/抽屉 **§9**;表单、迷你表与上传 **§10**;图标与无障碍 **§11**(如 **`.sr-only`**);细节与 HTML 不一致时以 **`test/fresh-mint-green.html`** 及规范 **§14–§15** 为准 #### 色彩方案(运营 Web 管理端;与 demo 一致) ```scss // 主色 - 薄荷绿(Emerald) $primary-color: #10b981; $primary-dark: #059669; $primary-bg: #ecfdf5; // 中性色(Slate) $text-primary: #1e293b; $text-muted: #64748b; $border-color: #d9e8e2; // 背景 $bg-page: #fefefe; $surface: #ffffff; $table-head: #f8fafc; $row-alt: #fafafa; $row-hover: #f1f5f9; // 语义色(列表状态等;与业务表配合,慎用大红大蓝) $success-color: #059669; // 成功/正向(可与 primary-dark 协调) $warning-color: #d97706; // 警告/待处理(琥珀,见 demo .stat.warn) $danger-color: #dc2626; // 危险/异常(强提醒、二次确认场景) ``` #### 组件风格(对齐 demo) - 圆角:面板/大卡片 **10px**;按钮、输入、筛选控件多为 **8px**;行内操作按钮 **6px** - 阴影:`0 1px 3px rgba(0, 0, 0, 0.05)`(卡片/面板轻阴影) - 按钮:主按钮实心绿;次要/批量操作为 **中性描边**(demo 中批量删除非必选红色按钮) - 表格:表头 `#f8fafc`、斑马纹、hover、细边框;支持时末列操作 **sticky** 与 demo 一致 - 表单:筛选区 label **11px** 灰色;控件高度 **36px**;focus 环 `0 0 0 2px rgba(16, 185, 129, 0.2)` #### 布局规范(对齐 demo) - 左侧菜单:**220px** 宽,可折叠 - 顶部导航:**56px** 高(以 `fresh-mint-green.html` 为准),白底 + 底部分割线;面包屑 **13px** - 内容区:**24px** 内边距(`--content-padding`) - 字体:**Inter**(或项目已加载字体)+ 系统回退;正文 **14px** #### 状态标签样式(Web 管理端) ```scss .status-tag { padding: 2px 8px; border-radius: 6px; font-size: 12px; font-weight: 600; } .status-tag.primary { background: #ecfdf5; color: #059669; } // 待处理/进行中(主品牌绿) .status-tag.success { background: #d1fae5; color: #047857; } // 成功/已完成 .status-tag.warning { background: #fffbeb; color: #d97706; } // 警告/待支付(琥珀) .status-tag.danger { background: #fef2f2; color: #dc2626; } // 危险/异常 .status-tag.info { background: #f8fafc; color: #64748b; } // 信息/取消/禁用 ``` ### 3. 小程序端 - 移动端风格 #### 技术栈 - uni-app + Vue3 + TypeScript - Vant Weapp 组件库 (移动端适配版) - Pinia 状态管理 #### 权威文档与实现方式(新增,强约束) - **小程序 UI 规范权威文档**:`docs/miniprogram-ui-spec-sanqiang.md` - **配送员端 UI 改造执行文档(强约束)**:`docs/小程序-配送员端UI改造指南.md` - **小程序 UI 设计基准 Demo**: - `mobile-ui/sanqiang-client-ui-demo.html` - `mobile-ui/sanqiang-client-cart-ui-demo.html` - `mobile-ui/sanqiang-client-order-ui-demo.html` - `mobile-ui/sanqiang-client-profile-ui-demo.html` - `mobile-ui/sanqiang-supplier-ui-demo.html` - `mobile-ui/sanqiang-deliverer-ui-demo.html` - 后续小程序 UI 改造(客户端/供应商端/配送员端)必须以以上文档和 Demo 为视觉标准,**不再使用旧风格自由发挥**。 - **配送员小程序端特殊约束**:`miniprogram/src/pages/deliverer/**` 的 UI 改造必须遵循 `docs/小程序-配送员端UI改造指南.md`;其中首页 `pages/deliverer/home/home` 的布局与视觉层级必须严格对齐 `mobile-ui/sanqiang-deliverer-ui-demo.html`,功能保持现有逻辑不变。 - **配送员卡片素材替换规则**:配送员端界面卡片中的 icon 与图片素材可按设计图与统一视觉方案进行替换,**不要求复用现有素材**;但需保持语义清晰、风格一致与交互可识别性。 - **改造留痕强制规则**:配送员端每次完成 UI 改造后,必须同步回写 `docs/小程序-配送员端UI改造指南.md` 的“变更记录”小节,至少记录改造页面、视觉变更点、功能保持说明、遗留问题;禁止只改代码不更新文档。 - 改造优先顺序:**Token(颜色/圆角/间距/字号)→ 页面骨架(头部/功能区/列表区)→ 组件映射(分类、卡片、状态、按钮)→ 交互细节(滑块、翻页、点击反馈)**。 - 如遇历史页面样式冲突,以 `docs/miniprogram-ui-spec-sanqiang.md` 为准,并将差异回写该文档,避免只改代码不更新规范。 #### 色彩方案(小程序端按角色区分;不必与 Web 管理端同色) ```scss // 主色调(可按角色换肤;示例沿用原角色色) $primary-color: #1989fa; // 示例:运营/默认蓝(小程序若独立配置可改) $success-color: #07c160; $warning-color: #ff976a; $danger-color: #ee0a24; // 背景色 $bg-white: #ffffff; $bg-gray: #f5f5f5; ``` #### 组件风格 - 圆角:8px (按钮), 12px (卡片), 16px (弹窗) - 间距:20rpx (小), 30rpx (中), 40rpx (大) - 字体:28rpx (正文), 24rpx (辅助), 32rpx (标题) - 图标:简洁线条风格 #### 布局规范 - 顶部:角色名称 + 退出登录 - 中部:功能卡片网格布局 (2列) - 底部:标签导航 (可选) #### 三端统一硬规则(新增) - **客户端首页分类区**:采用“一级分类两行五列(每页10个)+ 多页左右滑动 + 分页滑块(有几页就几个,支持点击翻页)+ 二级分类侧栏联动商品区”模式。 - **客户端底部结算条**:信息结构固定为“数量 → 总价 → 去结算主按钮”,主按钮视觉优先级最高。 - **供应商端与配送员端**:保持同一配色体系、同一卡片风格、同一菜单宫格视觉节奏。 - **配送员端菜单位置**:放在任务列表上方,与供应商端布局逻辑一致。 - **状态标签语义一致**:warning=待处理,success=进行中/已完成,danger=异常;禁止同屏滥用高饱和颜色。 #### 状态标签样式 ```scss .status-tag { padding: 4px 10px; border-radius: 4px; font-size: 12px; } .status-tag.primary { background: #e6f7ff; color: #1989fa; } .status-tag.success { background: #f6ffed; color: #07c160; } .status-tag.warning { background: #fff7e6; color: #ff976a; } .status-tag.danger { background: #fff1f0; color: #ee0a24; } .status-tag.info { background: #f5f5f5; color: #999; } ``` ### 4. 角色主题色区分 | 角色 | 主色调 | 渐变配色 | 场景 | |------|--------|----------|------| | 运营端(Web 管理后台) | #10b981 (薄荷绿) | linear-gradient(135deg, #10b981 0%, #34d399 100%) | `web-admin` 顶部/主按钮(见 `docs/web-admin-ui-spec-fresh-mint.md`) | | 供应商 | #ff976a (活力橙) | linear-gradient(135deg, #ff976a 0%, #ff4444 100%) | 小程序顶部/按钮 | | 客户 | #07c160 (清新绿) | linear-gradient(135deg, #07c160 0%, #1989fa 100%) | 小程序顶部/按钮 | | 配送员 | #ee0a24 (活力红) | linear-gradient(135deg, #ee0a24 0%, #ff976a 100%) | 小程序顶部/按钮 | ```scss // 运营端 Web 管理端 - Fresh Mint(与 demo 一致) $admin-primary: #10b981; $admin-gradient: linear-gradient(135deg, #10b981 0%, #34d399 100%); // 供应商端 - 活力橙 $supplier-primary: #ff976a; $supplier-gradient: linear-gradient(135deg, #ff976a 0%, #ff4444 100%); // 客户端 - 清新绿 $client-primary: #07c160; $client-gradient: linear-gradient(135deg, #07c160 0%, #1989fa 100%); // 配送员端 - 活力红 $deliver-primary: #ee0a24; $deliver-gradient: linear-gradient(135deg, #ee0a24 0%, #ff976a 100%); ``` ### 5. 通用规范 #### 图标系统 - Web端:使用 Element Plus Icons - 小程序端:使用 Vant Icons - 图标风格:简洁线条风格 #### 间距系统 - Web端:基于 4px 网格系统 (4, 8, 12, 16, 20, 24, 32, 40, 48) - 小程序端:基于 10rpx 网格系统 (10, 20, 30, 40) #### 响应式断点 - Web端:1920px / 1440px / 1200px / 768px - 小程序端:375px / 414px (固定设计宽度) #### 字体规范 - Web端(`web-admin`):Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif(与 `fresh-mint-green.html` 一致;以项目字体加载为准) - 小程序端:-apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', Arial, sans-serif ### 6. 页面通用元素 #### 顶部导航 (Web端) - 高度:**56px**(以 `fresh-mint-green.html` / `docs/web-admin-ui-spec-fresh-mint.md` 为准) - 包含:面包屑或标题区、消息通知、个人下拉等(具体以 `web-admin` 布局组件为准) - 背景:白底 + 底部分割线(**不以**大色块渐变为主;主色用于按钮与选中态) #### 侧边菜单 (Web端) - 宽度:**220px** (可折叠) - 包含:一级分组、二级链接 - 选中状态:浅绿底 `primary-bg` + 字色 `primary-dark`(与 demo `.nav a.active` 一致) #### 原型导航 (原型图专用) - 固定在页面右上角 - 快速切换各页面 - 包含页面名称和激活状态 #### 手机框架 (小程序端) - 最大宽度:414px - 圆角:40px - 顶部状态栏模拟 ### 7. 交互规范 #### 按钮样式 - 主要按钮:实心主色(Web 管理端 **#10b981**),圆角 **8px**(小程序可为 24rpx 等) - 次要按钮:白底 + 边框(`--border`),高度与主按钮对齐 **36px** - 文字/链接按钮:如筛选区「展开更多」——透明底、主色深绿字、hover 浅绿底(见 demo `.btn-link`) #### 表单验证 - 实时校验 - 错误提示:红色文字 + 底部提示 - 必填标识:红色星号 #### 列表操作 - 查看:跳转详情 - 编辑:弹窗或新页面 - 删除:二次确认弹窗 ### 8. 订单状态流转 (前端显示) | 状态 | 显示文本 | 颜色类 | 适用角色 | |------|----------|--------|----------| | pending_payment | 待支付 | warning | 客户/运营 | | pending_review_cancel | 待审核取消 | primary | 运营 | | pending_delivery | 待分配配送 | primary | 运营 | | delivering | 配送中 | info | 配送员/客户 | | partial_delivered | 部分送达 | warning | 运营 | | pending_confirm | 待确认收货 | primary | 客户 | | completed | 已完结 | success | 所有 | | cancelled | 已取消 | info | 所有 | ### 9. 配送任务状态 (前端显示) | 状态 | 显示文本 | 颜色类 | |------|----------|--------| | pending | 待取货 | warning | | picking | 取货中 | primary | | delivering | 配送中 | info | | completed | 已完成 | success | | cancelled | 已取消 | info | --- ## 接口设计规范 ### 1. 通用约定 #### 请求格式 - 所有接口使用 **JSON** 格式进行数据交换 - 请求头必须包含 `Content-Type: application/json` - 认证接口使用 Bearer Token 方式 #### 响应格式 ```json { "code": 200, "message": "success", "data": { }, "timestamp": 1700000000000 } ``` #### 错误码规范 ```json { "code": 400, "message": "错误描述", "data": null, "timestamp": 1700000000000 } ``` | 错误码 | 含义 | |--------|------| | 200 | 成功 | | 400 | 请求参数错误 | | 401 | 未授权/Token过期 | | 403 | 无权限 | | 404 | 资源不存在 | | 500 | 服务器内部错误 | ### 2. URL 规范 #### 路由前缀 - Web端API: `/api/web/` - 小程序端API: `/api/mini/` #### 资源命名 - 复数形式:`/users`, `/orders`, `/products` - 单个资源:`/users/{id}`, `/orders/{id}` - 动作资源:`/orders/{id}/cancel`, `/orders/{id}/pay` #### 动词使用 | 方法 | 用途 | |------|------| | GET | 查询/获取资源 | | POST | 创建新资源 | | PUT | 完整更新资源 | | PATCH | 部分更新资源 | | DELETE | 删除资源 | ### 3. 分页规范 #### 请求参数 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | page | int | 否 | 页码,默认1 | | pageSize | int | 否 | 每页条数,默认10 | #### 响应格式 ```json { "code": 200, "data": { "list": [ ], "total": 100, "page": 1, "pageSize": 10, "totalPages": 10 } } ``` ### 4. 排序规范 #### 请求参数 | 参数 | 类型 | 说明 | |------|------|------| | orderBy | string | 排序字段 | | orderType | string | 排序方式:asc/desc | #### 默认排序规则 - **所有列表接口默认按创建时间倒序排列**(最新创建的记录显示在最前面) - 默认排序参数:`orderBy=create_at&orderType=desc` - 后端 CRUD 基类已统一实现此默认排序逻辑,无需前端重复指定 - 特殊情况(如树形分类的 sortOrder 排序)可在具体接口中单独定义 ### 5. 时间格式 - 请求/响应中使用 **ISO 8601** 格式:`2026-03-19T10:30:00+08:00` - 数据库存储使用 **DATETIME** 类型 - 前端展示格式:`YYYY-MM-DD HH:mm:ss` ### 6. 金额规范 - 存储单位:**分**(整数) - 展示单位:**元**(除以100,保留2位小数) - API响应示例:`"amount": 1000` 表示 `10.00元` ### 7. 角色权限标识 | 角色 | 标识 | 说明 | |------|------|------| | admin | 运营人员 | 全部权限 | | supplier | 供应商 | 本区域数据 | | client | 客户 | 本区域数据 | | deliver | 配送员 | 本区域数据 | ### 8. 区域数据隔离 - 所有查询接口默认按当前用户所属区域过滤 - 跨区域访问返回空列表或无权限错误 ### 9. 审计日志记录 以下操作必须记录审计日志: - 用户创建/修改/删除/登录 - 密码修改/重置 - 价格发布/修改 - 订单状态变更 - 退款/结算操作 - 配送任务分配 --- ## 前后端交互规范 ### 1. 命名约定 #### 字段命名规范 | 层级 | 命名风格 | 示例 | |------|----------|------| | 数据库 | 蛇形命名 | `is_required`, `sort_order`, `param_type` | | 后端 Schema | 蛇形命名 + Pydantic alias | `is_required: int = Field(..., alias="isRequired")` | | 后端 Model | 蛇形命名 | `is_required`, `sort_order` | | 前端 API 请求 | 驼峰命名 | `{ isRequired: 1, sortOrder: 10 }` | | 前端 API 响应 | 驼峰命名 | `{ isRequired: 1, sortOrder: 10, paramType: "select" }` | #### 关键字段映射对照表 | 后端蛇形 | 后端 Model | 前端驼峰 | |----------|-----------|----------| | `is_required` | `is_required` | `isRequired` | | `is_active` | `is_active` | `isActive` | | `is_del` | `is_del` | `isDel` | | `sort_order` | `sort_order` | `sortOrder` | | `param_type` | `param_type` | `paramType` | | `param_value` | `param_value` | `paramValue` | | `product_id` | `product_id` | `productId` | | `category_id` | `category_id` | `categoryId` | | `create_at` | `create_at` | `createAt` | | `update_at` | `update_at` | `updateAt` | | `create_by` | `create_by` | `createBy` | | `create_name` | `create_name` | `createName` | ### 2. HTTP 响应数据处理 #### 前端 HTTP 封装规范 前端 `utils/http/index.ts` 中的 `request` 函数已自动处理响应数据提取: ```typescript // request 函数返回的是 response.data,即 { code, message, data, timestamp } 中的 data 部分 const res = await fetchProductParameterList(params) // res 已经是 { list: [...], total: 100 } 这样的数据结构 // 不需要再访问 res.data ``` #### 前端正确的数据访问方式 ```typescript // ✅ 正确写法 const loadData = async () => { const res: any = await fetchProductParameterList(params) if (res && res.list) { tableData.value = res.list pagination.total = res.total } } // ❌ 错误写法(多了一层 .data) if (res.code === 200) { tableData.value = res.data.list // 错误! } ``` #### 删除/更新操作的简化处理 ```typescript // ✅ 正确写法 - request 函数会自动处理 200 响应 const handleDelete = async (row: any) => { await fetchDeleteProductParameter(row.id) ElMessage.success('删除成功') loadData() } // ✅ 正确写法 - 需要判断时 const handleSubmit = async () => { await fetchCreateProductParameter(data) ElMessage.success('创建成功') dialogVisible.value = false loadData() } ``` ### 3. 后端 Pydantic Schema 规范 #### 必须添加 alias 和 populate_by_name ```python from pydantic import BaseModel, Field, ConfigDict class ProductParameterBase(BaseModel): """商品参数基础字段""" model_config = ConfigDict(populate_by_name=True) # 使用 alias 指定前端字段名 name: str = Field(..., alias="name") param_type: str = Field(default="text", alias="paramType") is_required: int = Field(default=0, alias="isRequired") is_active: int = Field(default=1, alias="isActive") sort_order: int = Field(default=0, alias="sortOrder") class ProductParameterUpdate(BaseModel): """更新商品参数请求""" model_config = ConfigDict(populate_by_name=True) name: Optional[str] = Field(None, alias="name") param_type: Optional[str] = Field(None, alias="paramType") is_required: Optional[int] = Field(None, alias="isRequired") sort_order: Optional[int] = Field(None, alias="sortOrder") ``` #### 关键点 - `model_config = ConfigDict(populate_by_name=True)` - 允许使用 alias 填充 - 每个字段必须指定 `alias="驼峰命名"` - 与前端字段对应 ### 4. 后端 CRUD Base 规范 #### 字段映射工具函数 `backend/app/crud/base.py` 必须包含字段名映射逻辑: ```python import re def camel_to_snake(name: str) -> str: """驼峰命名转蛇形命名""" s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() def get_model_attr(obj, key: str): """获取模型的属性名,支持驼峰转蛇形""" # 先尝试直接匹配 if hasattr(obj, key): return key # 尝试驼峰转蛇形 snake_key = camel_to_snake(key) if hasattr(obj, snake_key): return snake_key return None ``` #### CRUD 方法中使用映射 ```python class CRUDBase: def create(self, db: Session, obj_in: dict, creator: dict = None) -> ModelType: obj = self.model() for key, value in obj_in.items(): attr_name = get_model_attr(obj, key) # 使用映射函数 if attr_name: setattr(obj, attr_name, value) # ... 其他逻辑 def update(self, db: Session, id: str, obj_in: dict, updater: dict = None): obj = self.get(db, id) if obj: for key, value in obj_in.items(): attr_name = get_model_attr(obj, key) # 使用映射函数 if attr_name and key not in ["id", "create_at", "create_by", "create_name"]: setattr(obj, attr_name, value) # ... 其他逻辑 ``` ### 5. API 响应字段映射 #### 后端返回时使用驼峰命名 ```python @router.get("", response_model=dict) def list_parameters(...): return success_response({ "list": [{ "id": p.id, "name": p.name, "code": p.code, "paramType": p.param_type, # 蛇形转驼峰 "isRequired": p.is_required, # 蛇形转驼峰 "isActive": p.is_active, # 蛇形转驼峰 "sortOrder": p.sort_order, # 蛇形转驼峰 "createAt": str(p.create_at) # 蛇形转驼峰 } for p in items], "total": total, "page": page, "pageSize": pageSize }) ``` ### 6. 新增模块 Checklist 新增一个包含增删改查的模块时,必须完成以下步骤: #### 后端 - [ ] 创建 Schema 类时,添加 `model_config = ConfigDict(populate_by_name=True)` - [ ] 所有字段添加 `alias="驼峰命名"` - [ ] API 返回数据时,将蛇形字段转为驼峰 - [ ] 确认 CRUD base 已包含字段映射逻辑(已有通用逻辑) #### 前端 - [ ] API 响应数据访问时,使用 `res.list` 而不是 `res.data.list` - [ ] 删除/更新操作后直接处理成功逻辑 ### 7. 常见错误排查 | 问题现象 | 原因 | 解决方案 | |----------|------|----------| | 前端新增的数据 `sortOrder` 为 0 | CRUD 未处理字段映射 | 确保 `get_model_attr` 函数生效 | | 前端提交的 `isRequired` 未保存 | Schema 缺少 alias | 添加 `alias="isRequired"` | | 列表数据无法展示 | 前端访问路径错误 | 使用 `res.list` 而非 `res.data.list` | | 编辑后数据未更新 | update 方法未映射字段 | 确保使用 `get_model_attr(obj, key)` | --- ## 测试执行留痕强制规则(P0) - 当代理执行任何 `P0` 回归测试(单条或批量)后,必须同步更新 `docs/P0-实际验证记录.md`。 - 更新方式必须为“追加新执行批次”,禁止覆盖历史记录。 - 每条已执行用例至少记录以下内容: - 请求流程与关键入参(敏感信息脱敏) - 接口结果(HTTP 状态码、业务 code、关键信息) - 数据库前后快照 SQL - 数据库前后结果与差异结论 - 若存在失败用例,必须额外记录: - 失败响应体或报错摘要 - 断言失败点 - 下一步处理动作(修复建议/重试计划) - 若仅进行了口头汇报而未更新文档,视为流程未完成。 --- ## Web 慢接口优化执行规范(强制) - 当识别到 `web-admin` 慢接口(建议阈值:`p95 >= 800ms`)后,后续执行必须遵循: 1. 基线采样(固定口径,记录 `avg/p95/p99/max`) 2. 慢点定位(代码 N+1 + SQL EXPLAIN) 3. 优化落地(代码优化优先,索引补强其次) 4. 同口径复测(输出前后对比) - 列表接口默认要求: - 禁止循环内逐条查库(必须批量查询 + map 回填) - 禁止无差别整行查询(必须字段投影) - `total` 统计优先 `func.count(id) + order_by(None)` - 索引策略默认要求: - 围绕 `is_del + 常用过滤列 + create_at(order by)` 设计联合索引 - 索引变更需提供 `backend/scripts/*.sql` 脚本并在测试库验证 - 文档留痕要求: - 必须同步更新 `docs/web-admin-接口性能测试报告-*.md` - 必须同步更新 `docs/后端接口全覆盖测试与数据库校验实施跟踪.md` - 未更新文档视为性能优化流程未完成。 --- ## 小程序慢接口优化执行规范(强制) - 当识别到 `mini/client/*` 慢接口(建议阈值:`p95 >= 800ms`)后,必须执行完整闭环: 1. 基线采样(固定口径:账号、参数、采样次数,记录 `avg/p95/p99/max`) 2. 慢点定位(代码 N+1、循环查库、字段冗余;必要时 SQL EXPLAIN) 3. 优化落地(批量查询 + 字段投影 + count 优化 + 必要索引/缓存) 4. 同口径复测(输出前后对比,确认收益) 5. 文档留痕(报告 + 跟踪文档同步) - 列表接口强约束: - 禁止循环内逐条查询商品/分类/单位等关联数据 - 必须优先使用批量查询与 map 回填 - 必须按需字段投影,避免无差别整行读取 - 规则适用范围: - 至少覆盖 `mini/client/products`、`mini/client/price-list/current`、`mini/client/cart*`、`mini/client/orders*` 等高频接口 - 留痕要求: - 必须同步更新 `docs/sqxp-wx-接口性能排查报告-*.md` - 必须同步更新 `docs/后端接口全覆盖测试与数据库校验实施跟踪.md` - 未同步文档视为优化流程未完成。