From 0579609d19f25c69123deb55fc1a4d7deeb7adf0 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Thu, 20 Aug 2026 11:29:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(skill):=20=E4=BA=A7=E7=BA=BF=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E5=B8=88=E6=95=B0=E6=8D=AE=E5=BA=93=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E8=A7=84=E8=8C=83=20database-design?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 字段语义→类型/长度/精度映射(金额double 18/2、外键str 32、日期date等) - 系统不加外键,codes段逻辑关联 - 编码字典 appcodes/appcodes_kv 初始化数据设计 - 种子数据在应用模块自身build.sh落库(非平台代码) - 运行时环境变量 init/.模块名 文件约定 --- .../agent.design/database-design/SKILL.md | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 skills_library/pipelines/sdlc_general/roles/agent.design/database-design/SKILL.md diff --git a/skills_library/pipelines/sdlc_general/roles/agent.design/database-design/SKILL.md b/skills_library/pipelines/sdlc_general/roles/agent.design/database-design/SKILL.md new file mode 100644 index 0000000..8cdece0 --- /dev/null +++ b/skills_library/pipelines/sdlc_general/roles/agent.design/database-design/SKILL.md @@ -0,0 +1,154 @@ +--- +name: database-design +description: 产线设计师数据库设计规范——字段语义到类型/长度/精度的映射规则、系统不加外键的关联方式、编码字典(appcodes/appcodes_kv)初始化数据设计、build.sh种子数据落库、运行时环境变量约定。触发:设计新模块的数据表、定义表字段、准备编码字典/初始化数据。 +capability: task_capability +--- + +# 产线设计师数据库设计规范 + +本 skill 是产线设计师(agent.design)在设计阶段产出模块数据设计时必须遵守的规范。 +表定义 JSON 的四段式格式、CRUD JSON 格式沿用 `database-table-definition-spec` / `crud-definition-spec`, +本 skill 聚焦:**字段怎么定类型**、**表间怎么关联**、**编码字典怎么准备和落库**、**环境变量怎么放**。 + +## 一、字段语义 → 类型/长度/精度 映射 + +| 字段语义 | type | length | dec | 备注 | +|---|---|---|---|---| +| 主键 id | str | 32 | - | 铁律 | +| 外键引用 xxx_id | str | 32 | - | 存目标表 id,不建 FK 约束 | +| 名称 name/title/*_name | str | 255 | - | 短名用 64/100/128 | +| 编码/编号 code/no | str | 64 | - | 合同编号、单据号 | +| 描述/备注 description/remark | text | - | - | 短备注用 str 500 | +| 内容 content | text | - | - | 富文本/大字段 | +| 金额 amount/balance/cost/total | double | 18 | 2 | 统一 18/2 | +| 单价 price | double | 18 | 4 | 保留 4 位 | +| 折扣/比例 discount/rate/ratio | double | 5 | 4 | 0.0000~1.0000 | +| 数量 count/qty | int | - | - | 整数 | +| 状态 status | str | 16 | - | 字符串码,配编码字典 | +| 开关/标志 flg/is_ | str | 1 | - | 0/1 | +| 创建/更新时间 created_at/updated_at | timestamp | - | - | | +| 业务日期 *_date | date | - | - | 只到天,不显示时分秒 | + +**规则**: +- 金额/单价/折扣必须带 `length` + `dec`,缺了 DDL 会生成不带精度的类型 +- 金额统一 `double` + `18/2`;**用 double 不用 decimal**(sqlor DDL 模板无 decimal 分支,会丢失精度) +- 业务日期用 `date`,别用 `timestamp`(否则 UI 出现时分秒控件困扰用户) +- 禁用原生类型:`varchar`、`bigint`、`boolean`、`int(11)` —— 一律用抽象类型(str/int/double/timestamp/date/text) + +## 二、系统不加外键 + +- 表之间**不建 FOREIGN KEY 约束** +- 关联方式 = 字段存目标表 id(str 32)+ `codes` 段声明逻辑关联(下拉、显示名),不产生 DDL 约束 + +```json +"codes": [ + {"field": "orgid", "table": "organization", "valuefield": "id", "textfield": "orgname"} +] +``` + +## 三、编码字典设计(appcodes / appcodes_kv) + +所有枚举/下拉选项统一进 appbase 的 **appcodes + appcodes_kv 两张表**,不写死在字段 default 里。 + +### 1. 适用字段 +状态、类型、开关、类别等取值有限且稳定的枚举字段。 + +### 2. 数据定义:模块 `init/data.json` + +```json +{ + "appcodes": [ + { + "parentid": "order_status", + "parentname": "订单状态", + "items": [ + {"k": "pending", "v": "待处理"}, + {"k": "paid", "v": "已支付"}, + {"k": "shipped", "v": "已发货"}, + {"k": "closed", "v": "已关闭"} + ] + } + ] +} +``` + +- `parentid` 下划线小写、见名知义(<31 字符) +- `k` 是存储值(写入业务表 status 字段),`v` 是显示文本 + +### 3. 表里引用(models codes 段,cond 必须 parentid=) + +```json +"codes": [ + {"field": "status", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='order_status'"} +] +``` + +**cond 必须用 `parentid=`,绝不能用 `id=`**(用 id 会查空)。 + +### 4. 两张表结构(复用 appbase,不自建) +- `appcodes`(父表):id(字典组名)、name(显示名)、hierarchy_flg('0'平铺/'1'层级) +- `appcodes_kv`(子表):id、parentid(=字典组名)、k(存储值)、v(显示文本) + +### 5. 数据落库:应用模块自身 build.sh 的「种子数据」步骤 + +在**应用模块自己的 build.sh**(不是产线平台代码)里加种子数据步骤,内联 Python 幂等导入: + +```bash +# 应用模块 build.sh 的种子数据步骤 +"${PYTHON}" - "${CDIR}" <<'PYEOF' +import sys, os, json, asyncio +CDIR = sys.argv[1] +sys.path[:0] = [os.path.join(CDIR, 'py3', 'lib', 'python3.10', 'site-packages')] +from appPublic.jsonConfig import getConfig +from sqlor.dbpools import DBPools +from appPublic.uniqueID import getID + +data = json.load(open(os.path.join(CDIR, 'pkgs', '<模块名>', 'init', 'data.json'))) + +async def seed(): + config = getConfig(CDIR) + db = DBPools(config.databases) + async with db.sqlorContext('<应用库名>') as sor: + for ac in data.get('appcodes', []): + pid = ac['parentid'] + rows = await sor.R('appcodes', {'id': pid}) + if not rows: + await sor.C('appcodes', {'id': pid, 'name': ac.get('parentname', pid), 'hierarchy_flg': '0'}) + for item in ac.get('items', []): + chk = await sor.sqlExe( + "SELECT id FROM appcodes_kv WHERE parentid=${p}$ AND k=${k}$", + {'p': pid, 'k': item['k']}) + if not chk: + await sor.C('appcodes_kv', {'id': getID(), 'parentid': pid, 'k': item['k'], 'v': item['v']}) + print(f"seeded {len(data.get('appcodes', []))} code groups") +asyncio.run(seed()) +PYEOF +``` + +**要点**: +- 种子数据步骤在**应用模块自身 build.sh**(不是平台代码),一键部署时自动落库 +- 幂等靠 `(parentid, k)` 判重,重复执行不报错、不重复插入 +- 数据源是模块 `init/data.json`,改字典只改 data.json,不碰 build.sh + +## 四、其他初始化数据(同样写法) + +模块若有其他数据需要初始化(组织、角色、默认配置等),**同样写在 `init/data.json`**,在 build.sh 的种子数据步骤里一起幂等导入,不另起一套机制。`init/data.json` 是模块初始化数据的唯一入口。 + +## 五、运行时环境变量 + +模块运行时需要的环境变量(密钥、端点等),放在模块 `init` 目录,文件命名 `.模块名`(如 `.smssend`): + +``` +init/ +├── data.json # 数据库初始化数据(appcodes 等) +└── .smssend # 运行时环境变量(export KEY=value) +``` + +```bash +# init/.smssend 内容 +export BAIDU_SMS_ACCESS_KEY=xxx +export BAIDU_SMS_HOST=yyy +``` + +- 部署时 build.sh 把 `init/.模块名` 复制到应用根目录,`start.sh` 里 `[ -f .模块名 ] && source .模块名` 加载 +- 该文件含敏感信息,**不入库**(.gitignore),部署时按实际环境填写