build / build-push (push) Successful in 2m22s
定义与答卷物理分离的第一步:把"契约"落进可执行代码,让后续答卷域只需消费不必再解释。
- form/form_version 头表+版本行:已发布行零写路径(改版=v+1 新行,老行逐字节冻结),
升版期间头表指针不动,使契约 §5 的钉版与 §3.2 的两层缓存声明天然成立;uuid 建草稿即生成
- FormSchemaValidator:19 项属性白名单、14/11 控件、options 只认 {label,value} 数组或
dict:{code} 引用(字符串数组被拒)、searchable 只出显式声明字段、跨版本同 key 不得换 type
(否则 answer_index 分类型落值的语义与"删字段后历史仍可筛"当场失效)
- 选项字典两级:管理面同层精确匹配(校级改不到平台级)、解析面 {会话校,0} 且本校遮蔽不回落;
value 物理不可变而 label 可改;软删条目仍进提交放行集;引用是活引用、只在读路径内联展开
- 表单级配置(audience/fill_limit/deadline 补 23:59:59/报名号/状态定义)留在头表,不随版本快照
- 另存为副本:新 code+新 uuid+version 1、schema 深拷贝且字典引用随行,源表只读
- 出入参不出现库内 id;手写 DDL 落 sql/t2_definition_domain.sql 并按 MySQL 5.7 复核(无 native SQL)
自验:mvn -B -o clean package 绿(67 测试,含 27 条打真实 MySQL 的 IT),逐 V 证据与 9 条
实现期问题单见 docs/T2-report.md
92 lines
6.6 KiB
SQL
92 lines
6.6 KiB
SQL
-- ============================================================
|
||
-- 表单中心 T2 · 定义域 DDL(MySQL 5.7 兼容复核版)
|
||
-- 范围:契约 §10 九表中的定义域四表 = form / form_version / form_dict / form_dict_item
|
||
-- (answer / answer_index / status_log / answer_op_log / fill_quota 属 T3)
|
||
-- 用途:本文件是**评审与生产脚本底稿**,不是应用启动依赖。
|
||
-- 开发期由 spring.jpa.hibernate.ddl-auto=update 自动建表(application.yml);
|
||
-- 生产建议 ddl-auto=none + 按本脚本升级(P10:160 生产 MySQL 版本待核,按 5.7 保守写)。
|
||
-- 5.7 复核要点:①无 CTE/WITH;②无函数索引/生成列;③utf8mb4(5.7 默认 utf8mb3 会截断 emoji/生僻字);
|
||
-- ④复合唯一键字节长 (8+64*4+64*4)=520 < 767,两个 uk 均不需要前缀长度;
|
||
-- ⑤TEXT/LONGTEXT 列不写 DEFAULT(5.7 不允许);⑥无物理外键(方案 §7.7 逻辑外键约定)。
|
||
-- P5 裁决:实体继承 BaseEntity,实际表=契约 §10 草案 + create_by/update_by 两列(不改 §10 文本)。
|
||
-- 审计两列在 BaseEntity 未标 nullable=false,故本脚本按建表实态写 DEFAULT NULL
|
||
-- (FormCenterAuditListener 恒写 now(),业务上不会为空)——差异记问题单 P15。
|
||
-- 本机取证:MySQL 8.0.45 / 库 bsch_formcenter 由 ddl-auto=update 建表后 SHOW CREATE TABLE 逐列比对一致。
|
||
-- ============================================================
|
||
|
||
CREATE TABLE `form` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||
`uuid` VARCHAR(32) NOT NULL COMMENT '数据面运行时身份:建草稿即生成、跨版本不变(契约 §1)',
|
||
`sch_id` BIGINT NOT NULL COMMENT '租户键;0=平台级表单(U5/U6,超管上下文建)',
|
||
`app_code` VARCHAR(64) NOT NULL DEFAULT 'form-center' COMMENT '归属应用:中心/平台级挂 form-center,快应用挂其 app_code',
|
||
`code` VARCHAR(64) NOT NULL COMMENT '入口寻址+配置期引用;同校同 app_code 内唯一;发布后不可改',
|
||
`name` VARCHAR(128) NOT NULL,
|
||
`current_version` INT DEFAULT NULL COMMENT '当前发布版本指针,NULL=从未发布(resolve 只认它)',
|
||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '0 草稿 / 1 已发布 / 2 停用(停用只断填报入口,数据可读可导)',
|
||
`status_defs` TEXT COMMENT '状态定义 JSON [{code,label,is_deleted}];NULL=默认待处理/已处理(V12)',
|
||
`audience` TINYINT NOT NULL DEFAULT 1 COMMENT '1 面向学生 / 2 面向教师(数据范围默认矩阵输入)',
|
||
`fill_limit` TINYINT NOT NULL DEFAULT 0 COMMENT '0 不限 / 1 限一次(去重维度按 subject→submitter 推导)',
|
||
`deadline` DATETIME DEFAULT NULL COMMENT '收集截止,datetime 粒度(只选日期时补当日 23:59:59)',
|
||
`answer_no_enabled` TINYINT NOT NULL DEFAULT 0 COMMENT '报名号开关,默认关',
|
||
`group_tag` VARCHAR(64) DEFAULT NULL COMMENT '多表单快应用的菜单分组标签',
|
||
`is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删=唯一删除形态(有答卷的表单禁物理删除)',
|
||
`create_by` VARCHAR(255) DEFAULT NULL,
|
||
`create_time` DATETIME DEFAULT NULL,
|
||
`update_by` VARCHAR(255) DEFAULT NULL,
|
||
`update_time` DATETIME DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_form_uuid` (`uuid`),
|
||
UNIQUE KEY `uk_form` (`sch_id`, `app_code`, `code`),
|
||
KEY `idx_form_app` (`sch_id`, `app_code`, `status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='表单头表(方案 §5.1)';
|
||
|
||
CREATE TABLE `form_version` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||
`form_id` BIGINT NOT NULL COMMENT '逻辑外键 → form.id(无物理 FK)',
|
||
`sch_id` BIGINT NOT NULL,
|
||
`app_code` VARCHAR(64) NOT NULL,
|
||
`code` VARCHAR(64) NOT NULL,
|
||
`version` INT NOT NULL COMMENT '只增不改(契约 §1)',
|
||
`schema_json` LONGTEXT NOT NULL COMMENT '结构快照:{"groups":[{key,label,fields:[…]}]},数组序即展示序、无 orderNum',
|
||
`change_log` VARCHAR(500) DEFAULT NULL COMMENT '升版改动说明',
|
||
`publish_time` DATETIME DEFAULT NULL COMMENT 'NULL=未发布草稿行;发布动作只补这一列,内容列从此冻结(V7)',
|
||
`create_by` VARCHAR(255) DEFAULT NULL,
|
||
`create_time` DATETIME DEFAULT NULL,
|
||
`update_by` VARCHAR(255) DEFAULT NULL,
|
||
`update_time` DATETIME DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_form_ver` (`sch_id`, `app_code`, `code`, `version`),
|
||
KEY `idx_ver_form` (`form_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
|
||
COMMENT='版本行:行不可变(方案 §3.2)——已发布行禁止就地修改,改版=新增行';
|
||
|
||
CREATE TABLE `form_dict` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||
`sch_id` BIGINT NOT NULL DEFAULT 0 COMMENT '0=平台级(学校可见可用不可改);其余=校级(仅本校表单可引用)',
|
||
`code` VARCHAR(64) NOT NULL COMMENT 'schema 里 options.source="dict:{code}" 的引用键,建后不可改',
|
||
`name` VARCHAR(128) NOT NULL,
|
||
`is_deleted` TINYINT NOT NULL DEFAULT 0,
|
||
`create_by` VARCHAR(255) DEFAULT NULL,
|
||
`create_time` DATETIME DEFAULT NULL,
|
||
`update_by` VARCHAR(255) DEFAULT NULL,
|
||
`update_time` DATETIME DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_dict` (`sch_id`, `code`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='选项字典(契约 §2.1)';
|
||
|
||
CREATE TABLE `form_dict_item` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||
`dict_id` BIGINT NOT NULL COMMENT '逻辑外键 → form_dict.id',
|
||
`value` VARCHAR(64) NOT NULL COMMENT '答案存储值:建一次即不可变(实体 updatable=false + 本 uk)',
|
||
`label` VARCHAR(128) NOT NULL COMMENT '展示名,可随便改(改名不打穿历史答卷)',
|
||
`sort` INT NOT NULL DEFAULT 0 COMMENT '展示顺序(同值按 id 稳定排)',
|
||
`is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删:设计器不可新选,但 value 仍通过提交校验(V38)',
|
||
`create_by` VARCHAR(255) DEFAULT NULL,
|
||
`create_time` DATETIME DEFAULT NULL,
|
||
`update_by` VARCHAR(255) DEFAULT NULL,
|
||
`update_time` DATETIME DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_dict_item` (`dict_id`, `value`),
|
||
KEY `idx_dict_item_sort` (`dict_id`, `sort`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='字典条目(契约 §2.1)';
|