feat(shared): A4 数据字典与系统配置契约

背景:A4 需要字典三层合并、配置版本与命名规则的共享契约。\n改动:新增 dict/config 契约、system-configs 定义与校验、命名模板解析;新增 dict_types/dict_items/system_config_versions 迁移与 13 类/96 条字典、26 项配置种子。\n影响面:shared 新增导出;prisma 新增表与迁移;客户基础字段 DTO 硬上界调整为 50(实际生效上限仍由配置动态校验)。\n回滚:回滚本提交并保留新增表(不删数据)。\n验证:shared typecheck/test 147;seed 幂等;prisma migrate dev 已应用。
This commit is contained in:
Stev_Wang committed 2026-11-04 11:48:38 +08:00
1 parent 32b44bdeec
commit cc6e84cdbc
15 files changed
+2899 -75

No files matched your search

+81
View File
@@ -226,9 +226,29 @@ model SystemConfig {
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
updatedBy String? @map("updated_by") @db.Char(26)
versions SystemConfigVersion[]
@@map("system_configs")
}
/// 系统配置版本历史(append-only):每次变更留前后值、原因、操作人(A4-BE-02)
model SystemConfigVersion {
id String @id @db.Char(26)
configKey String @map("config_key") @db.VarChar(128)
version Int
oldValue Json? @map("old_value") @db.JsonB
newValue Json @map("new_value") @db.JsonB
reason String? @db.VarChar(255)
changedBy String? @map("changed_by") @db.Char(26)
changedAt DateTime @default(now()) @map("changed_at") @db.Timestamptz(3)
config SystemConfig @relation(fields: [configKey], references: [configKey], onDelete: Cascade)
@@unique([configKey, version])
@@index([changedAt])
@@map("system_config_versions")
}
// ---------------------------------------------------------------------------
// A3 客户与行业(client 模块;ADR-002 两级行业)
// ---------------------------------------------------------------------------
@@ -254,6 +274,7 @@ model Industry {
parent Industry? @relation("IndustryTree", fields: [parentId], references: [id], onDelete: Restrict)
children Industry[] @relation("IndustryTree")
customers Customer[]
dictItems DictItem[]
@@index([parentId, sortOrder])
@@index([level, status])
@@ -361,3 +382,63 @@ model CustomerField {
@@index([customerId, status])
@@map("customer_fields")
}
// ---------------------------------------------------------------------------
// A4 数据字典(catalog 模块):一张通用枚举表同时表达二级树与词表
// ---------------------------------------------------------------------------
enum DictStatus {
ACTIVE
DISABLED
}
enum DictKind {
TREE
LIST
}
/// 字典类型:编码唯一且创建后不可改;内置类型不可删除
model DictType {
id String @id @db.Char(26)
code String @unique @db.VarChar(64)
name String @db.VarChar(64)
groupKey String @map("group_key") @db.VarChar(32)
kind DictKind @default(LIST)
description String @default("") @db.VarChar(255)
industryScoped Boolean @default(false) @map("industry_scoped")
builtin Boolean @default(false)
status DictStatus @default(ACTIVE)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
updatedBy String? @map("updated_by") @db.VarChar(64)
items DictItem[]
@@index([groupKey, sortOrder])
@@map("dict_types")
}
/// 字典条目:industry_id 为空 = 通用层;parent_code 表达二级树;
/// 同 type + code + industry 唯一由迁移中的部分唯一索引保证(NULL 也唯一)。
model DictItem {
id String @id @db.Char(26)
typeId String @map("type_id") @db.Char(26)
code String @db.VarChar(64)
name String @db.VarChar(64)
parentCode String? @map("parent_code") @db.VarChar(64)
industryId String? @map("industry_id") @db.Char(26)
sortOrder Int @default(0) @map("sort_order")
status DictStatus @default(ACTIVE)
remark String @default("") @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
updatedBy String? @map("updated_by") @db.VarChar(64)
type DictType @relation(fields: [typeId], references: [id], onDelete: Cascade)
industry Industry? @relation(fields: [industryId], references: [id], onDelete: Restrict)
@@index([typeId, industryId, sortOrder])
@@index([typeId, parentCode])
@@map("dict_items")
}