| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- # 叁强鲜配项目 - 数据库设计规范
- ## 表设计规则
- ### 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)` |
|