- 在 README.md 中新增数据库设计规范、代码生成配置规范和改进规划的文档链接 - 在 CacheDb 结构体中添加历史记录开关 HistorySet - 实现历史记录的写入逻辑,记录每次缓存的新增和修改 - 更新缓存的获取和设置方法,支持历史记录的管理 - 优化数据库表的初始化和迁移逻辑,确保历史表的创建与管理
21 KiB
代码生成配置规范
本文档详细说明 HoTime 框架代码生成器的配置体系,包括 config.json 中的 codeConfig、菜单权限配置和字段规则配置。
配置体系概览
config.json
└── codeConfig[] # 代码生成配置数组(支持多套)
├── config # 菜单权限配置文件路径(如 admin.json)
├── configDB # 数据库生成的完整配置
├── rule # 字段规则配置文件路径(如 rule.json)
├── table # 管理员表名
├── name # 生成代码的包名
└── mode # 生成模式
一、config.json 中的 codeConfig
配置结构
{
"codeConfig": [
{
"config": "config/admin.json",
"configDB": "config/adminDB.json",
"mode": 0,
"name": "",
"rule": "config/rule.json",
"table": "admin"
}
]
}
配置项说明
| 字段 | 类型 | 说明 |
|---|---|---|
| config | string | 菜单权限配置文件路径,用于定义菜单结构、权限控制 |
| configDB | string | 代码生成器输出的完整配置文件(自动生成) |
| rule | string | 字段规则配置文件路径,定义字段在增删改查中的行为 |
| table | string | 管理员/用户表名,用于身份验证和权限控制 |
| name | string | 生成的代码包名,为空则不生成代码文件 |
| mode | int | 生成模式:0-仅配置不生成代码,非0-生成代码文件 |
多配置支持
可以配置多个独立的代码生成实例,适用于多端场景:
{
"codeConfig": [
{
"config": "config/admin.json",
"table": "admin",
"rule": "config/rule.json"
},
{
"config": "config/user.json",
"table": "user",
"rule": "config/rule.json"
}
]
}
二、菜单权限配置(如 admin.json)
配置文件更新机制
- 首次运行:代码生成器会根据数据库表结构自动创建配置文件(如 admin.json)
- 后续运行:配置文件不会自动更新,避免覆盖手动修改的内容
- 重新生成:如需重新生成,删除配置文件后重新运行即可
- 参考更新:可参考
configDB指定的文件(如 adminDB.json)查看最新的数据库结构变化,手动调整配置
完整配置结构
{
"id": "唯一标识(自动生成)",
"name": "admin",
"label": "管理平台名称",
"labelConfig": { ... },
"menus": [ ... ],
"flow": { ... }
}
2.1 label 配置
定义系统显示名称:
{
"label": "HoTime管理平台"
}
2.2 labelConfig 配置
定义权限的显示文字:
{
"labelConfig": {
"show": "开启",
"add": "添加",
"delete": "删除",
"edit": "编辑",
"info": "查看详情",
"download": "下载清单"
}
}
| 操作 | 说明 |
|---|---|
| show | 显示/查看列表权限 |
| add | 添加数据权限 |
| delete | 删除数据权限 |
| edit | 编辑数据权限 |
| info | 查看详情权限 |
| download | 下载/导出权限 |
2.3 menus 配置
定义菜单结构,支持多级嵌套:
{
"menus": [
{
"label": "系统管理",
"name": "sys",
"icon": "Setting",
"auth": ["show"],
"menus": [
{
"label": "用户管理",
"table": "user",
"auth": ["show", "add", "delete", "edit", "info", "download"]
},
{
"label": "角色管理",
"table": "role",
"auth": ["show", "add", "delete", "edit", "info"]
}
]
},
{
"label": "文章管理",
"table": "article",
"icon": "Document",
"auth": ["show", "add", "edit", "info"]
}
]
}
menus 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| label | string | 菜单显示名称 |
| name | string | 菜单标识(用于分组,不绑定表时使用) |
| table | string | 绑定的数据表名(用于自动生成 CRUD) |
| icon | string | 菜单图标名称 |
| auth | array | 权限数组,定义该菜单/表拥有的操作权限 |
| menus | array | 子菜单数组(支持嵌套) |
name vs table
- table: 绑定数据表,拥有该表的增删查改等权限,自动生成 CRUD 接口
- name: 自定义功能标识,不绑定表,前端根据 name 和 auth 来显示和操作自定义内容(如首页 home、仪表盘 dashboard 等)
- 如果配置了
menus子菜单,则作为分组功能,前端展开显示下级菜单 - 如果没有
menus,则作为独立的自定义功能入口
- 如果配置了
注意:目前只支持两级菜单,不允许更多层级嵌套。
// 使用 table:绑定数据表,有增删查改权限
{ "label": "用户管理", "table": "user", "auth": ["show", "add", "edit", "delete"] }
// 使用 name:自定义功能(无子菜单)
{ "label": "首页", "name": "home", "icon": "House", "auth": ["show"] }
// 使用 name:分组功能(有子菜单)
{ "label": "系统管理", "name": "sys", "icon": "Setting", "auth": ["show"], "menus": [...] }
自动分组规则
代码生成器在自动生成配置时,会根据表名的 _ 分词进行自动分组:
- 表名
sys_logs、sys_menus、sys_config→ 自动归入sys分组 - 表名
article、article_tag→ 自动归入article分组
分组的显示名称(label)使用该分组下第一张表的名字,如果表有备注则使用备注名。
2.4 auth 配置
权限数组定义菜单/表拥有的操作权限:
{
"auth": ["show", "add", "delete", "edit", "info", "download"]
}
内置权限
| 权限 | 对应接口 | 说明 |
|---|---|---|
| show | /search | 列表查询 |
| add | /add | 新增数据 |
| delete | /remove | 删除数据 |
| edit | /update | 编辑数据 |
| info | /info | 查看详情 |
| download | /search?download=1 | 导出数据 |
自定义权限扩展
auth 数组可以自由增删,新增的权限项会:
- 在前端菜单/功能中显示
- 在角色管理(role)的权限设置中显示,供管理员分配
// 示例:为文章表添加自定义权限
{
"label": "文章管理",
"table": "article",
"auth": ["show", "add", "edit", "delete", "info", "publish", "audit", "top"]
}
上例中 publish(发布)、audit(审核)、top(置顶)为自定义权限,前端可根据这些权限控制对应按钮的显示和操作。
2.5 icon 配置
菜单图标,使用 Element Plus 图标名称:
{ "icon": "Setting" } // 设置图标
{ "icon": "User" } // 用户图标
{ "icon": "Document" } // 文档图标
{ "icon": "Folder" } // 文件夹图标
2.6 flow 配置
flow 是一个简易的数据权限控制机制,用于限制用户只能操作自己权限范围内的数据。
基本结构
{
"flow": {
"role": {
"table": "role",
"stop": true,
"sql": {
"id": "role_id"
}
},
"article": {
"table": "article",
"stop": false,
"sql": {
"admin_id": "id"
}
},
"org": {
"table": "org",
"stop": false,
"sql": {
"parent_ids[~]": ",org_id,"
}
}
}
}
flow 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| table | string | 表名 |
| stop | bool | 是否禁止修改自身关联的数据 |
| sql | object | 数据过滤条件,自动填充查询/操作条件 |
stop 配置详解
stop 用于防止用户修改自己当前关联的敏感数据。
场景示例:当前登录用户是 admin 表的用户,其 role_id = 1
"role": {
"table": "role",
"stop": true,
"sql": { "id": "role_id" }
}
效果:
- 用户不能修改 role 表中
id = 1的这行数据(自己的角色) - 用户可以修改其他 role 记录(如果有权限的话)
典型用途:
- 防止用户提升自己的角色权限
- 防止用户修改自己所属的组织
sql 配置详解
sql 用于自动填充数据过滤条件,实现数据隔离。
格式:{ "目标表字段": "当前用户字段" }
示例 1:精确匹配
"article": {
"sql": { "admin_id": "id" }
}
效果:查询/操作 article 表时,自动添加条件 WHERE admin_id = 当前用户.id
即:用户只能看到/操作自己创建的文章。
示例 2:角色关联
"role": {
"sql": { "id": "role_id" }
}
效果:查询/操作 role 表时,自动添加条件 WHERE id = 当前用户.role_id
即:用户只能看到自己的角色。
示例 3:树形结构(模糊匹配)
"org": {
"sql": { "parent_ids[~]": ",org_id," }
}
效果:查询/操作 org 表时,自动添加条件 WHERE parent_ids LIKE '%,用户.org_id,%'
即:用户只能看到自己组织及其下级组织。
sql 条件语法
| 格式 | 含义 | SQL 等价 |
|---|---|---|
"field": "user_field" |
精确匹配 | field = 用户.user_field |
"field[~]": ",value," |
模糊匹配 | field LIKE '%,value,%' |
完整示例
假设当前登录用户数据:
{ "id": 5, "role_id": 2, "org_id": 10 }
flow 配置:
{
"flow": {
"role": {
"table": "role",
"stop": true,
"sql": { "id": "role_id" }
},
"article": {
"table": "article",
"stop": false,
"sql": { "admin_id": "id" }
},
"org": {
"table": "org",
"stop": false,
"sql": { "parent_ids[~]": ",org_id," }
}
}
}
效果:
| 表 | 查询条件 | stop 效果 |
|---|---|---|
| role | WHERE id = 2 |
不能修改 id=2 的角色 |
| article | WHERE admin_id = 5 |
可以修改自己的文章 |
| org | WHERE parent_ids LIKE '%,10,%' |
可以修改下级组织 |
三、字段规则配置(rule.json)
定义字段在增删改查操作中的默认行为。
配置结构
[
{
"name": "id",
"add": false,
"edit": false,
"info": true,
"list": true,
"must": false,
"strict": true,
"type": ""
}
]
字段属性说明
| 属性 | 类型 | 说明 |
|---|---|---|
| name | string | 字段名或字段名包含的关键词 |
| add | bool | 新增时是否显示该字段 |
| edit | bool | 编辑时是否显示该字段 |
| info | bool | 详情页是否显示该字段 |
| list | bool | 列表页是否显示该字段 |
| must | bool | 是否必填(详见下方说明) |
| strict | bool | 是否严格匹配字段名(true=完全匹配,false=包含匹配) |
| type | string | 字段类型(影响前端控件和数据处理) |
must 必填字段规则
must 字段用于控制前端表单的必填验证:
自动识别规则:
- MySQL:如果字段设置为
NOT NULL(即IS_NULLABLE='NO'),自动设为must=true - SQLite:如果字段是主键(
pk=1),自动设为must=true
规则配置覆盖:
rule.json中的must设置会覆盖数据库的自动识别结果- 可以将数据库中 NOT NULL 的字段在规则中设为
must=false,反之亦然
前端效果:
must=true的字段在新增/编辑表单中显示必填标记(*)- 提交时前端会验证必填字段
后端验证:
- 新增操作时,如果
must=true的字段为空,返回"请求参数不足"
type 类型说明
| 类型 | 说明 | 前端控件 |
|---|---|---|
| (空) | 普通文本 | 文本输入框 |
| text | 文本 | 文本输入框 |
| number | 数字 | 数字输入框 |
| select | 选择 | 下拉选择框(根据注释自动生成选项) |
| time | 时间(datetime) | 日期时间选择器 |
| unixTime | 时间戳 | 日期时间选择器(存储为 Unix 时间戳) |
| password | 密码 | 密码输入框(自动 MD5 加密) |
| textArea | 多行文本 | 文本域 |
| image | 图片 | 图片上传 |
| file | 文件 | 文件上传 |
| money | 金额 | 金额输入框 |
| auth | 权限 | 权限树选择器 |
| form | 表单 | 动态表单 |
| index | 索引 | 隐藏字段(用于 parent_ids 等) |
| table | 动态表 | 表名选择器 |
| table_id | 动态表ID | 根据 table 字段动态关联 |
内置字段规则
以下是框架默认的字段规则,可在 rule.json 中覆盖:
主键和索引
{"name": "id", "add": false, "list": true, "edit": false, "info": true, "strict": true}
{"name": "sn", "add": false, "list": true, "edit": false, "info": true}
{"name": "parent_ids", "add": false, "list": false, "edit": false, "info": false, "type": "index", "strict": true}
{"name": "index", "add": false, "list": false, "edit": false, "info": false, "type": "index", "strict": true}
层级关系
{"name": "parent_id", "add": true, "list": true, "edit": true, "info": true}
{"name": "level", "add": false, "list": false, "edit": false, "info": true}
时间字段
{"name": "create_time", "add": false, "list": false, "edit": false, "info": true, "type": "time", "strict": true}
{"name": "modify_time", "add": false, "list": true, "edit": false, "info": true, "type": "time", "strict": true}
{"name": "time", "add": true, "list": true, "edit": true, "info": true, "type": "time"}
状态字段
{"name": "status", "add": true, "list": true, "edit": true, "info": true, "type": "select"}
{"name": "state", "add": true, "list": true, "edit": true, "info": true, "type": "select"}
{"name": "sex", "add": true, "list": true, "edit": true, "info": true, "type": "select"}
敏感字段
{"name": "password", "add": true, "list": false, "edit": true, "info": false, "type": "password"}
{"name": "pwd", "add": true, "list": false, "edit": true, "info": false, "type": "password"}
{"name": "delete", "add": false, "list": false, "edit": false, "info": false}
{"name": "version", "add": false, "list": false, "edit": false, "info": false}
媒体字段
{"name": "image", "add": true, "list": false, "edit": true, "info": true, "type": "image"}
{"name": "img", "add": true, "list": false, "edit": true, "info": true, "type": "image"}
{"name": "avatar", "add": true, "list": false, "edit": true, "info": true, "type": "image"}
{"name": "icon", "add": true, "list": false, "edit": true, "info": true, "type": "image"}
{"name": "file", "add": true, "list": false, "edit": true, "info": true, "type": "file"}
文本字段
{"name": "info", "add": true, "list": false, "edit": true, "info": true, "type": "textArea"}
{"name": "content", "add": true, "list": false, "edit": true, "info": true, "type": "textArea"}
{"name": "description", "add": true, "list": false, "edit": true, "info": true}
{"name": "note", "add": true, "list": false, "edit": true, "info": true}
{"name": "address", "add": true, "list": true, "edit": true, "info": true}
特殊字段
{"name": "amount", "add": true, "list": true, "edit": true, "info": true, "type": "money", "strict": true}
{"name": "auth", "add": true, "list": false, "edit": true, "info": true, "type": "auth", "strict": true}
{"name": "rule", "add": true, "list": true, "edit": true, "info": true, "type": "form"}
{"name": "table", "add": false, "list": true, "edit": false, "info": true, "type": "table"}
{"name": "table_id", "add": false, "list": true, "edit": false, "info": true, "type": "table_id"}
自定义字段规则
在 rule.json 中添加项目特定的字段规则:
[
// 项目特定规则
{
"name": "company_name",
"add": true,
"edit": true,
"info": true,
"list": true,
"must": true,
"strict": true,
"type": ""
},
// 表.字段 形式的精确规则
{
"name": "user.nickname",
"add": true,
"edit": true,
"info": true,
"list": true,
"strict": true,
"type": ""
}
]
四、配置示例
完整的 admin.json 示例
{
"id": "74a8a59407fa7d6c7fcdc85742dbae57",
"name": "admin",
"label": "后台管理系统",
"labelConfig": {
"show": "开启",
"add": "添加",
"delete": "删除",
"edit": "编辑",
"info": "查看详情",
"download": "下载清单"
},
"menus": [
{
"label": "系统管理",
"name": "sys",
"icon": "Setting",
"auth": ["show"],
"menus": [
{
"label": "日志管理",
"table": "logs",
"auth": ["show", "download"]
},
{
"label": "角色管理",
"table": "role",
"auth": ["show", "add", "delete", "edit", "info"]
},
{
"label": "组织管理",
"table": "org",
"auth": ["show", "add", "delete", "edit", "info"]
},
{
"label": "人员管理",
"table": "admin",
"auth": ["show", "add", "delete", "edit", "info", "download"]
}
]
}
],
"flow": {
"admin": {
"table": "admin",
"stop": false,
"sql": { "role_id": "role_id" }
},
"role": {
"table": "role",
"stop": true,
"sql": { "admin_id": "id", "id": "role_id" }
},
"org": {
"table": "org",
"stop": false,
"sql": { "admin_id": "id" }
},
"logs": {
"table": "logs",
"stop": false,
"sql": {}
}
}
}
五、SQLite 备注替代方案
SQLite 数据库不支持表备注(TABLE COMMENT)和字段备注(COLUMN COMMENT),代码生成器会使用表名/字段名作为默认显示名称。
通过配置文件设置备注
利用 HoTime 的配置覆盖机制,可以在配置文件中手动设置显示名称和提示:
步骤:
- 首次运行,生成配置文件(如 admin.json)
- 编辑配置文件中的
tables部分
设置表显示名称
在菜单配置中设置 label:
{
"menus": [
{
"label": "用户管理", // 手动设置表显示名称
"table": "user",
"auth": ["show", "add", "edit", "delete"]
}
]
}
设置字段显示名称和提示
在 configDB 文件(如 adminDB.json)中的 tables.表名.columns 部分设置:
{
"tables": {
"user": {
"label": "用户管理",
"columns": [
{
"name": "id",
"label": "ID",
"type": "number"
},
{
"name": "name",
"label": "用户名",
"ps": "请输入用户名", // 前端输入提示
"must": true
},
{
"name": "phone",
"label": "手机号",
"ps": "请输入11位手机号"
},
{
"name": "status",
"label": "状态",
"type": "select",
"options": [
{"name": "正常", "value": "0"},
{"name": "禁用", "value": "1"}
]
}
]
}
}
}
注意:直接编辑的是 configDB 指定的文件(如 adminDB.json),该文件会在每次启动时重新生成。如需持久化修改,应将自定义的 columns 配置放入 config 指定的文件(如 admin.json)中。
六、配置检查清单
codeConfig 检查
- config 文件路径正确
- rule 文件路径正确
- table 指定的管理员表存在
菜单权限配置检查
- 所有 table 指向的表在数据库中存在
- auth 数组包含需要的权限
- menus 结构正确(有子菜单用 name,无子菜单用 table)
- flow 配置的 sql 条件字段存在
字段规则配置检查
- strict=true 的规则字段名完全匹配
- type 类型与前端控件需求一致
- 敏感字段(password等)的 list 和 info 为 false