status: reviewed_passed created: 2026-07-16 complexity: 🔴复杂
Forge 当前编码规则使用 ai_code_rule.template 保存 ${...} 模板,能够覆盖简单日期和十进制流水号,但无法用结构化方式表达固定段、变量段、系统变量、进制、分组和周期重置。配置页要求管理员直接理解模板语法,也无法可靠校验溢出、分组碰撞和段级联动。
本变更把编码规则升级为“规则主表 + 稳定分段明细 + 统一生成引擎”,并保持低代码字段自动编号及旧 /ai/code-rule 调用兼容。完成后应达到以下可验证结果:
CodeRuleService 自动生成编号,旧模板规则迁移后无需重新绑定。system:codeRule:* 权限,业务字段不能伪造租户、用户或组织系统变量。forge-admin-ui/src/views/app-center/code-rules.vue 使用 AiCrudPage 维护模板字符串、重置周期和流水长度,没有分段编辑器。forge-admin-ui/src/views/app-center/components/designer/forge-form-designer/ForgePropertyPanel.vue#loadCodeRuleOptions 调用 /ai/code-rule/list,字段生成配置保存 generation.ruleCode。forge-server/.../generator/controller/CodeRuleController.java 暴露 /ai/code-rule CRUD、预览和生成接口,所有操作共用 ai:businessObject:design。forge-server/.../generator/service/businessapp/CodeRuleService.java 解析 ${yyyyMMdd}、${seq:4}、${field:xxx} 等 Token,并调用 ISequenceService.nextId。forge-server/.../generator/service/DynamicCrudService.java#applyAutoGeneratedFields 在低代码新增前调用 CodeRuleService.generate,已是统一自动编号主链路。AiCodeRule 只包含 scene/template/resetPolicy/seqLength/status/builtin/options 等主表字段。CodeRuleMapper.xml 已显式过滤 tenant_id 和 del_flag='0',规则编码按租户唯一。SegmentSequenceGenerator 使用数据库号段和进程内缓存生成序列,默认每次分配 1000 个号。forge-server/db/backup/V1.0.86__add_code_rule_generator.sql,正式迁移目录没有结构化编码规则脚本。V1.0.35,本变更新脚本使用下一可用版本;执行前仍需重新检查版本占用。SegmentSequenceGenerator#tryPrefetch 在当前段余量低于阈值后会重复分配并覆盖 next 段,可能造成巨量跳号;结构化规则不能直接复用该行为。CodeRuleService#resolveToken 优先读取请求 context 中的 tenantId/userId/username,调用方可以覆盖系统变量。resolveTenantId 在上下文缺失时回退租户 1,不适合作为业务取号的安全边界。sequenceScope;新规则需要由规则分段明确决定分组,迁移时必须保留原规则绑定而不能改写 generation.ruleCode。segmentKey 标识计数器身份。fields 取值;SYS_VAR 只从可信 Session 读取。groupEnabled=true 分段的解析值按段顺序构建并摘要,避免分隔碰撞和数据库 key 超长。/system/code-rule 管理接口和 capability 接口,保留旧 /ai/code-rule list/preview/generate 兼容协议。ai_code_rule 全量迁移:已知模板由 SQL 回填,其它历史模板由 legacy parser 兼容物化并返回迁移提示。generation.ruleCode,生成上下文中的业务字段映射为新请求的 fields。AiCrudPage 承载查询和列表,新增/编辑进入同路由下的全屏配置工作台和分段编辑器。sys_code_rule_scene 字典;该字段保留旧调用方场景筛选语义,低代码精确范围改由业务对象绑定控制。CUSTOM 自定义变量和 LOWCODE 低代码字段两种分段来源;只有 LOWCODE 分段需要保存 source_object_id/source_object_code 并校验字段归属,CUSTOM 由业务代码通过 fields 显式传值。segmentKey,禁止通过删除、改型或替换分段重置计数器。REQUIRES_NEW + READ_COMMITTED 保证多实例重试可见性。/sequence API 默认关闭;显式开启后仅允许 POST、要求 system:sequence:use,并限制 bizKey 长度和字符集。legacy_compat_enabled=1 安全续接旧水位,新建规则显式写 0,不再为每个新分组扫描 legacy key。tenantId/ruleId/versionNo 缓存不可变分段快照,不构造预览模板、表达式、分段预览或 warning VO。ruleCode 在租户内历史永久唯一,逻辑删除后仍保留且不得复用;创建后不可修改,格式为字母开头,后续只允许字母、数字和下划线,保留历史大小写。sys_code_rule_category 字典;现有 scene 保留为兼容适用范围,不与分类混用。includeInCode=true 的分段,总声明长度不得超过 96。0,ALPHA_UPPER 为 A,ALPHA_LOWER 为 a。startValue 决定;默认 startValue=1,因此所有进制首个值均对应数值 1。radix^length;新规则序号值必须落在 [0, capacity-1],否则抛出溢出异常。历史规则因旧号段预分配水位已经超过原宽度时,为避免回退水位造成重复编号,真实生成允许按“旧安全起点”所需的最小宽度兼容扩宽;扩宽只覆盖旧水位所需位数,后续序号超过该有效宽度仍抛出溢出异常。excludeAmbiguous 只对 ALPHA_UPPER、ALPHA_LOWER、ALPHANUMERIC 生效,移除 I/O/Z 或 i/o/z。resetEnabled=false 时周期强制为 NONE;为 true 时只允许 YEAR/MONTH/DAY/HOUR。周期使用应用配置时区,本轮以注入 Clock 的服务端时区为基线。segmentOrder 解析,使用长度前缀规范化后做 SHA-256 摘要;原始分组值不进入日志和计数 key。ISequenceService,默认使用 startValue 作为示例序号。fields 取值;SYS_VAR 不读取同名业务字段。segmentOrder 和拖拽排序表达,不新增重复的“顺序段”;SEQ 对用户显示为“流水号(顺序递增)”。variableSource=CUSTOM|LOWCODE;历史协议缺省和 legacy parser 物化均按 CUSTOM 处理。fields.<variableName> 提供值。objectCode。segmentKey 且该段仍为 SEQ;允许排序和属性调整,禁止删除、改型或用新 key 替换。原本没有 SEQ 的规则允许首次增加。clamp(radix^length / 1000, 1, 1000) 计算,数据库 UPDATE 前按剩余容量裁剪;达到 capacity-1 后失败且不得推进水位。/sequence 不是默认公共能力;只有配置 forge.id.sequence.enable-api=true 后才注册,且所有取号入口要求专用权限、POST 和安全 bizKey。| 操作 | 表名 | 字段/索引 | 说明 |
|---|---|---|---|
| 修改 | ai_code_rule |
category, source_object_id, source_object_code, version_no, legacy_compat_enabled, in_code_list, del_flag, logic_delete_active |
增加分类、低代码来源对象、乐观锁、legacy 兼容标记、可选择标记和逻辑删除;存量规则默认兼容,新规则显式关闭 |
| 调整唯一索引 | ai_code_rule |
(tenant_id, rule_code) |
规则编码跨逻辑删除记录永久唯一,禁止删除后重建导致新 ruleId 重置计数器 |
| 新增 | ai_code_rule_segment |
variable_source、标准审计字段、del_flag、logic_delete_active |
保存稳定分段定义;VARIABLE 来源为 CUSTOM/LOWCODE,默认 CUSTOM |
| 调整索引 | ai_code_rule_segment |
(tenant_id, rule_id, del_flag, segment_order, id) |
先按租户、规则和活跃状态定位,再稳定按序读取 |
| 新增唯一索引 | ai_code_rule_segment |
(tenant_id, rule_id, segment_key, logic_delete_active) |
稳定分段键仅约束未删除记录 |
| 新增字典 | sys_dict_type/sys_dict_data |
sys_code_rule_category |
编码分类,tenant_id 固定 1 |
| 新增字典 | sys_dict_type/sys_dict_data |
sys_code_rule_scene |
兼容适用场景,tenant_id 固定 1 |
| 调整资源 | sys_resource/sys_role_resource |
system:codeRule:* |
迁移菜单权限并保留路由 |
| 数据回填 | ai_code_rule_segment |
现有全部规则 | SQL 回填已知内置模板,Java legacy parser 兜底其它模板 |
ai_code_rule.template/reset_policy/seq_length/options 本轮不删除。结构化规则保存时同步生成兼容摘要;没有分段的旧规则继续由 legacy parser 解释,成功后可在编辑保存时物化为分段。
| 操作 | 接口 | 方法 | 变更内容 |
|---|---|---|---|
| 新增 | /system/code-rule/page |
GET | 规则分页 |
| 新增 | /system/code-rule/list |
GET | 启用且可选择规则 |
| 新增 | /system/code-rule/getById |
POST | 主表和分段详情 |
| 新增 | /system/code-rule/add |
POST | 新增规则及分段 |
| 新增 | /system/code-rule/edit |
POST | 乐观锁更新规则及全量分段 |
| 新增 | /system/code-rule/remove/{id} |
POST | 逻辑删除自定义规则 |
| 新增 | /system/code-rule/status |
POST | 启停规则 |
| 新增 | /system/code-rule/preview |
POST | 无副作用结构化预览 |
| 新增 | /system/code-rule/generate |
POST | 生成编码,返回 code/sequence/group/period |
| 新增 | /system/code-rule/capabilities?sourceObjectId=... |
GET | 返回段类型、日期格式、系统变量、进制、业务对象及指定对象字段能力 |
| 兼容 | `/ai/code-rule/list | preview | generate` |
| 收口 | /sequence/next* |
POST | 默认不注册;显式开启后要求 system:sequence:use,限制 bizKey 且禁止 GET 取号 |
管理接口使用 POST-safe 配置协议,所有请求/响应继续使用 @ApiDecrypt/@ApiEncrypt。权限拆分为 system:codeRule:list/add/edit/remove/use。
forge-plugin-generator:编码规则实体、Mapper、DTO/VO、生成引擎、Controller、低代码自动编号。forge-starter-id:号段缓存切换、起始值、旧水位只读解析、有界缓存和 READ_COMMITTED 分配事务。forge-admin-ui:编码规则列表、全屏编辑工作台、分段编辑器、API 和低代码字段预览摘要。objectCode 过滤,通用规则与当前对象专属规则可见。forge-server/db/migration:结构、字典、菜单权限和历史规则迁移。generation.ruleCode、ai_code_rule 数据和 /ai/code-rule 兼容调用。ai:businessObject:code-rules 迁移到 system:codeRule:*;Flyway 必须同步已有角色授权,避免升级后菜单丢失。forge-starter-id 会影响其它序列调用者,必须用回归测试覆盖段耗尽和并发切换。.DS_Store 等无关差异;本变更不清理、不回滚这些文件。test-spec.md。无。用户在上一轮分析后明确回复“按照你的方案实施 按照sdd开发流程”,本 Spec 采用上一轮推荐的兼容和安全取舍。
ai_code_rule 主表,新增 ai_code_rule_segment,避免重建规则 ID 和低代码绑定。segmentKey 是计数器稳定身份,segmentOrder 只控制展示和拼接顺序。ruleCode 和既有 SEQ segmentKey 都属于计数器永久身份:逻辑删除不释放 ruleCode,规则更新不允许替换已有 SEQ 的 key。CodeRuleService 负责事务编排,避免 Service 互相注入。ISequenceService 的数据库号段能力,不在 Generator 内另建 Redis 计数器;先修复缓存跨段问题并补起始值接口。REQUIRES_NEW + READ_COMMITTED,避免 MySQL RR 快照让乐观重试持续读取旧版本。sys_code_rule_scene 字典;VARIABLE 的精确字段边界使用低代码业务对象和字段元数据,不复用自由文本场景。fields 取值协议,LOWCODE 只在配置和运行时增加元数据边界;不为两种来源分叉生成引擎。objectCode 的选择请求中不可见;精确匹配当前对象时优先于 COMMON 场景过滤,运行时仍再次校验对象编码。AiCrudPage,复杂主从编辑使用同路由查询状态切换到全屏工作台,保持通用 CRUD 与业务编辑器边界,同时避免新增权限路由。legacy_compat_enabled 保留升级安全边界。该标记由 V1.0.37 默认置 1,新建服务代码显式写 0,兼容滚动升级。biz_key 做函数改为尾部通配的参数化前缀 LIKE,并使用 ! 显式转义 _/%,让主键可参与前缀范围过滤且不受反斜杠 SQL mode 影响。| Task | 状态 | 实际改动文件 | 备注 |
|---|---|---|---|
| Task 0 | complete | spec.md, tasks.md, test-spec.md, execution-log.md |
SDD 基线与 HARD-GATE |
| Task 1 | complete | forge-starter-id 序列接口、生成器及测试 |
3/3 测试通过;跨 1000 号段连续且并发唯一 |
| Task 2 | complete | Flyway、实体、Mapper | 存量主表逻辑删除升级与结构化分段模型完成 |
| Task 3 | complete | 结构化引擎、DTO/VO、服务 | 五类分段、五种进制、分组、周期和 legacy 兼容完成 |
| Task 4 | complete | Controller 与兼容接口 | /system/code-rule、独立权限、API 资源和旧入口兼容完成 |
| Task 5 | complete | 前端 API、分段编辑器和页面 | AiCrudPage 列表、全屏编辑工作台、拖拽编辑和实时预览完成 |
| Task 6 | complete | 低代码兼容与回归 | generation.ruleCode 与业务 fields 分层完成 |
| Task 7 | complete | 测试、构建和审查 | 定向测试、Admin 编译、前端构建和两阶段自审通过 |
| Task 9 | complete | 场景字典、来源对象字段映射、低代码规则过滤与运行时校验 | Generator 15/15、前端 Vitest 9/9、Admin 42/42 和生产构建通过 |
| Task 10 | complete | VARIABLE 分段 CUSTOM/LOWCODE 双来源、按需对象映射与自定义 fields 调用 |
Generator 20/20、前端 11/11、ESLint、Admin 42/42 和生产构建通过 |
| Task 11 | complete | LOWCODE 字段映射弹窗、行内摘要和对象切换原子应用 | 前端 Vitest 13/13、ESLint、生产构建和交互静态契约通过 |
| Task 12 | complete | 旧号段水位与固定宽度组合兼容 | 归档前 Review 发现 P0 后完成 Red/Green;Starter ID 7/7、Generator 21/21、Admin 42/42 通过 |
| Task 13 | complete | 归档前两阶段复审安全与质量修复 | 规则/SEQ 身份保护、缓存上限、事务隔离、legacy/字段别名兼容;Starter ID 9/9、Generator 25/25、Admin 42/42 通过 |
| Task 14 | complete | SDD 归档与知识沉淀 | 状态统一为 done,四份 SDD 文档及需求/UI 原型归档到日期目录 |
| Task 15 | complete | 容量感知号段、CAS 热路径及测试 | 有限容量按剩余值裁剪;当前段 CAS 消费;Starter ID 15/15 通过 |
| Task 16 | complete | 原始 /sequence API 收口 |
默认关闭、POST、专用权限及 bizKey 边界完成 |
| Task 17 | complete | V1.0.37、legacy 标记与索引友好查询 |
存量/新规则兼容边界分离;转义前缀 LIKE 和活跃分段索引完成 |
| Task 18 | complete | 规则定义缓存、生成快路径与输入上限 | Caffeine 不可变快照、版本重载、32/256/96 上限完成 |
| Task 19 | complete | 预览降载、聚合验证与复审 | AbortController、预览免审计、全量增量验证和两阶段复审完成 |
review-date: 2026-07-16 conclusion: NEEDS_FIX
code-rule:{tenant}:{ruleCode}:{scope}:{period},新实现改为 cr:{tenant}:{ruleId}:{segmentHash}:{groupHash}:{period};V1.0.36 只物化分段且把 start_value 固定为 1,没有迁移或兼容读取 sys_id_sequence 旧 key。升级后的新 key 可从 1 重新取号,违反编号唯一递增和迁移连续性要求。max_id 再计算区间;另一实例可在两条语句之间完成下一次分配,使两个实例都按较新的 max_id 返回同一后段。sys_id_sequence,但 JVM 的 SegmentHolder 不会回滚,另一实例或进程重启后可再次分配同一区间。category 字段;若 DDL 后、UPDATE 前失败,修复重跑时 @category_added=0,存量分类将永久跳过回填。reviewed_with_findings,不得归档。/fix 编码规则配置优化;修复结果见下节,仍需重新执行 /review 编码规则配置优化 后才能归档。fix-date: 2026-07-16 status: fixed_pending_review
| Review 项 | 修复结果 | 实现摘要 |
|---|---|---|
| R1 旧计数器续接 | FIXED | 新结构化 key 首次初始化时按租户、规则编码和周期精确查询旧 code-rule:* 最大水位,从 max(startValue, legacyMaxId + 1) 开始;HOUR 兼容旧小时/分钟/秒周期。 |
| R2 多实例号段 | FIXED | 乐观锁 UPDATE 前保存本实例读取的 currentMaxId,成功后直接返回本次快照对应区间,不再重新查询最新水位。 |
| R3 事务回滚 | FIXED | 号段分配使用 TransactionTemplate + PROPAGATION_REQUIRES_NEW,提交成功后才写入 JVM 缓存;外层业务回滚只产生空洞,不回退数据库号段。 |
| R4 分类回填 | FIXED | Flyway 分类 UPDATE 改为按 category/scene/rule_code 当前数据状态幂等执行,移除 @category_added 会话条件。 |
| 前端复核项 | FIXED | 详情和预览采用最新请求 Guard,输入变化即作废在途预览;新增、编辑/启停、删除入口分别按权限显示。用户验收发现页面误用 Naive 组件内部颜色变量后,已复修为 Forge 全局背景、文字、边框和主色 Token。 |
--n-color、--n-action-color 当作页面背景。review-date: 2026-07-17 status: fixed_pending_review
material_code 只要使用过一次,旧数据库水位就可能为 1000;按 R1 从 1001 续接会与三位十进制容量冲突。resolveLegacyStartValue,Generator 测试编译失败。review-date: 2026-07-17 conclusion: PASS_WITH_COMMENTS
HHmmss 旧 NONE/all 语义、VARIABLE snake/camel 别名、ruleCode 历史唯一和 SEQ identity 保护。/apply。code-copilot/changes/archive/2026-07-17-编码规则配置优化/git diff --check、三个 Mapper XML 和 Flyway placeholder 静态检查通过。conclusion: NEEDS_FIX fix-authorized: true
/sequence 默认启用、使用 GET 执行取号、没有专用权限且接受任意 bizKey,登录用户可制造序列表膨胀和缓存淘汰,放大正常编码规则不可用风险。biz_key 使用函数,无法稳定利用主键前缀范围。synchronized。code-copilot/changes/编码规则配置优化/,按 /fix 增量执行。conclusion: PASS_WITH_COMMENTS status: reviewed_passed
generation.ruleCode、CUSTOM/LOWCODE 字段协议、主题和全屏工作台没有回退。biz_key 使用函数,V1.0.36/V1.0.37 无 Flyway placeholder,tracked/untracked 差异无空白错误。sys_id_sequence 增长率并另行制定可审计留存策略。