7090ee7d65
PRD FR-506/FR-1202 的 P0 项:V9 给 sys_operation_log 补 target_type/target_id/ before_val/after_val,OperationLogService 显式留痕并统一强制脱敏; 已接入的敏感动作:名册改证件号/改名/删名册项、任务发布/暂停/恢复/截止/归档。 F-32 的教训落地:动作名由调用方显式给,不从 (原状态, 新状态) 反推—— 「发布」与「恢复」都是 →收集中,反推必然把 resume 记成 PUBLISH_TASK。 字典:内置字典写在代码里(DictCatalog),库里只存客户自定义项与内置项停用开关, 两表分开才能「一键恢复默认」;表单下拉与字典共用同一份口径(BuiltinFields 加访问器)。 验证:e2e-m5-logs 44/44、e2e-m1-dict 53/53。
79 lines
4.5 KiB
SQL
79 lines
4.5 KiB
SQL
-- ============================================================================
|
||
-- V10:数据字典(《03-接口设计》§13.3)
|
||
--
|
||
-- 为什么内置字典**不进这张表**
|
||
-- ---------------------------------------------------------------------------
|
||
-- 契约 §13.3 把字典分成两类,而这个区分是刻意的:
|
||
--
|
||
-- · **内置字典**(`builtin: true`):EDU_LEVEL / JOB_LEVEL / CERT_TYPE /
|
||
-- RETARGET_SUBJECT / REJECT_REASON 五项。它们的选项**照抄官方表格**,
|
||
-- 不许擅改(`BuiltinFields` 的类注释里写了这条)。所以它们定义在**代码里** ——
|
||
-- 和权限码同样的思路:能改的放库里,不能改的放代码里,改它必须走一次发布。
|
||
-- 放进表里会带来一个具体风险:有人从界面上把"四级/中级工"改名成"中级",
|
||
-- 导出的汇总表就与官方模板对不上了,而那时没有任何地方会报错。
|
||
--
|
||
-- · **可维护的字典**:客户填表时遇到的内置项不够用(例如多了个"技校"学历),
|
||
-- 由管理员自己加。这类进 `sys_dict_item` —— 它们**允许**被改,
|
||
-- 因为它们是客户自己的口径,不是官方的。
|
||
--
|
||
-- OCCUPATION(职业/工种)是第三种情况:它**来自 `sys_occupation_ref`**
|
||
-- (国标职业库,有自己的层级与别名),既不进代码也不进这张表。
|
||
-- 三处来源的取舍都写在 `DictCatalog` 的注释里。
|
||
-- ============================================================================
|
||
|
||
-- 自定义字典项(含对内置字典的"追加")
|
||
CREATE TABLE IF NOT EXISTS sys_dict_item (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
tenant_id BIGINT NOT NULL,
|
||
-- 字典码,如 EDU_LEVEL / JOB_LEVEL / CERT_TYPE
|
||
dict_code VARCHAR(64) NOT NULL,
|
||
item_code VARCHAR(64) NOT NULL,
|
||
item_name VARCHAR(128) NOT NULL,
|
||
-- 层级(如职业-工种):指向同字典内另一个 item_code
|
||
parent_item_code VARCHAR(64),
|
||
sort_no INTEGER NOT NULL DEFAULT 0,
|
||
-- 0 停用 / 1 启用
|
||
status SMALLINT NOT NULL DEFAULT 1,
|
||
-- true = 这个项是对**内置字典**的追加(内置项本身仍在代码里)
|
||
builtin_extend SMALLINT NOT NULL DEFAULT 0,
|
||
create_by BIGINT,
|
||
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
update_by BIGINT,
|
||
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
deleted SMALLINT NOT NULL DEFAULT 0
|
||
);
|
||
|
||
COMMENT ON TABLE sys_dict_item IS '自定义字典项(内置字典的选项在代码里,见 DictCatalog;OCCUPATION 来自 sys_occupation_ref)';
|
||
COMMENT ON COLUMN sys_dict_item.dict_code IS '字典码:EDU_LEVEL/JOB_LEVEL/CERT_TYPE/RETARGET_SUBJECT/REJECT_REASON/OCCUPATION + 客户自定义';
|
||
COMMENT ON COLUMN sys_dict_item.item_code IS '项码。⚠️ **不许改**(改了会破坏历史数据里已经存下的值)';
|
||
COMMENT ON COLUMN sys_dict_item.parent_item_code IS '层级父项(如职业-工种);空表示顶层';
|
||
COMMENT ON COLUMN sys_dict_item.builtin_extend IS '1 = 对内置字典的追加项(内置项本身不出来在这里)';
|
||
|
||
-- 同一个字典里项码唯一(软删的不算)—— 手工建一条部分唯一索引:
|
||
-- 普通 UNIQUE 会把软删的行也算进去,于是"删过再想加回来"会失败,
|
||
-- 而用户看到的是"这个编码已存在",但他明明刚删掉它
|
||
CREATE UNIQUE INDEX IF NOT EXISTS uk_dict_item_code
|
||
ON sys_dict_item (tenant_id, dict_code, item_code)
|
||
WHERE deleted = 0;
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_dict_item_code
|
||
ON sys_dict_item (tenant_id, dict_code, status, sort_no);
|
||
|
||
-- 内置字典的"停用单项"(契约 §13.3:内置字典不可删,只可停用单项)。
|
||
-- ⚠️ 不复用 sys_dict_item.status:那张表是"客户自己加的项",
|
||
-- 而这里是"官方项被客户停用了"。混在一起之后,
|
||
-- "恢复默认"就没法做了(分不清哪些是官方项、哪些是客户加的)。
|
||
CREATE TABLE IF NOT EXISTS sys_dict_disabled (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
tenant_id BIGINT NOT NULL,
|
||
dict_code VARCHAR(64) NOT NULL,
|
||
item_code VARCHAR(64) NOT NULL,
|
||
create_by BIGINT,
|
||
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
COMMENT ON TABLE sys_dict_disabled IS '被停用的**内置**字典项(契约 §13.3:内置字典不可删、只可停用单项)';
|
||
|
||
CREATE UNIQUE INDEX IF NOT EXISTS uk_dict_disabled
|
||
ON sys_dict_disabled (tenant_id, dict_code, item_code);
|