liuyun 950e13a4a8
Some checks are pending
CI / backend (push) Waiting to run
CI / frontend (push) Waiting to run
docs(spec): 归档 force-password-change + 同步首登改密主 spec
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-11 21:57:51 +08:00

98 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Data Model Specification
## Purpose
定义系统数据模型的字段字典:实体目录、公共字段、枚举、状态机与命名约定,作为前后端字段一致性的唯一锚点。
## Requirements
### Requirement: 业务实体公共字段
所有业务软删实体 SHALL 携带公共字段:id(UUID v7)、tenant_code、created_at、created_by、updated_at、deleted_at;日志/会话类实体不携带 deleted_at。
#### Scenario: 创建记录
- **WHEN** 创建任一业务实体记录
- **THEN** 系统自动填充 id、tenant_code、created_at、created_by
#### Scenario: 软删
- **WHEN** 删除业务实体
- **THEN** 系统置 deleted_at 而非物理删除
### Requirement: 实体目录
系统 SHALL 包含实体 tenant、user、role、resource、org、dict_type、dict_item、config、audit_log、login_log、refresh_token,以及关联表 user_role、role_resource、role_org。
#### Scenario: 字典拆分
- **WHEN** 维护数据字典
- **THEN** 字典分为 dict_type(类型)与 dict_item(项)两类,经 dict_type_code 关联
### Requirement: 资源类型与代码
resource 实体 SHALL 通过 type 字段区分菜单(menu)、按钮(button)、接口(api)三种类型;「目录」由菜单节点是否拥有菜单子节点推导,不设独立类型。每个 resource SHALL 拥有租户内唯一的 code,作为关联键与权限标识。
#### Scenario: 按钮鉴权点
- **WHEN** 前端需要按钮级权限
- **THEN** 该按钮登记为 type=button 的资源,并携带 code 权限标识
### Requirement: 引用键约定
所有跨实体引用 SHALL 优先使用业务键:角色、资源、组织、字典类型、租户用 code,树的父引用用 parent_code;对用户的引用 SHALL 使用用户 id。关联表 sys_user_role、sys_role_resource、sys_role_org 分别保存 user_id+role_code、role_code+resource_code、role_code+org_code;其余引用(user.org_code、dict_item.dict_type_code、resource.parent_code、org.parent_code)同理。
#### Scenario: 为角色分配资源
- **WHEN** 管理员为角色分配资源
- **THEN** 关联记录保存 role_code 与 resource_code
### Requirement: 数据权限档位
role 实体 SHALL 通过 data_scope 字段支持全部/本部门/本部门及以下/本人/自定义五档;「自定义」经 role_org 关联表声明可见部门。
#### Scenario: 本部门及以下
- **WHEN** 角色数据权限为「本部门及以下」
- **THEN** 该角色用户仅可见本部门及下级部门的数据
### Requirement: 命名与表前缀
所有脚手架表 SHALL 以 sys_ 前缀命名,数据库列名采用 snake_case。
#### Scenario: 表命名
- **WHEN** 新建脚手架表
- **THEN** 表名以 sys_ 开头,列名使用 snake_case
### Requirement: 用户状态机
user 实体 SHALL 通过 `status` 字段支持启用/停用(管理员手动启停),并通过独立的 `locked_at`(锁定时间,可空)与 `lock_reason`(锁定原因,可空)表示安全锁定;「锁定」由 `locked_at` 非空推导,`status` 仅存 enabled/disabled。停用或锁定的用户 SHALL 均无法登录。
#### Scenario: 锁定登录
- **WHEN** 锁定用户(locked_at 非空)尝试登录
- **THEN** 系统拒绝登录并提示账号已锁定
#### Scenario: 停用登录
- **WHEN** 停用用户(status=disabled)尝试登录
- **THEN** 系统拒绝登录并提示账号已停用
### Requirement: 待改密标记
user 实体 SHALL 通过 `must_change_password`(布尔,默认 false)标记待改密状态:管理员重置密码、租户初始化下发随机密码、创建用户(默认)时置 true;创建用户时管理员可显式关闭;用户自行改密成功后置 false。
#### Scenario: 临时密码置标记
- **WHEN** 管理员重置密码或初始化租户下发临时密码
- **THEN** 该用户 must_change_password 为 true
#### Scenario: 创建用户默认强制改密
- **WHEN** 管理员创建用户(未显式关闭「首登强制改密」)
- **THEN** 该用户 must_change_password 为 true;显式关闭则为 false
#### Scenario: 改密清除标记
- **WHEN** 用户修改本人密码成功
- **THEN** 该用户 must_change_password 置为 false
### Requirement: 字典实体扩展
dict_type 实体 SHALL 新增 built_in 字段(布尔,标记内置字典类型);dict_item 实体 SHALL 新增 built_in(布尔,标记内置字典项)与 color_type(字符串,取值 primary/success/warning/danger/info,可空)字段,用于前端标签渲染与内置保护。
#### Scenario: 内置类型标记
- **WHEN** 某字典类型由系统 seed 预置
- **THEN** 其 built_in 为真,后端据此保护其不被删除
#### Scenario: 内置项颜色
- **WHEN** 内置字典项需要区分展示
- **THEN** 其 color_type 指定标签色(如启用=success、锁定=danger、停用=info)
### Requirement: 内置枚举字典取值
系统 SHALL 预置 5 个内置枚举字典并锚定其取值集合:common_status={enabled,disabled}、user_status={enabled,disabled,locked}、resource_type={menu,button,api}、data_scope={all,dept,dept_and_child,self,custom}、login_status={success,fail}。
#### Scenario: 前端按字典渲染枚举
- **WHEN** 前端渲染用户/角色/资源等页面的枚举字段
- **THEN** 从对应内置字典读取 label 与 color_type,取值不脱离上述集合