# 03-数据库设计文档 - **Schema**: `xlyweberp_vibe_erp_test` - **Migration 清单**: `sql/migrations/V*.sql`(由 Flyway 顺序 apply) - **生成方式**: 由 A3 `db-design-gen` 基于 `docs/01-需求清单//REQ-*.md` REQ 卡片正向设计生成(schema SSoT)。 ## 项目标准列约定 下文每张业务表的字段清单都自动包含以下 5 个标准列(匈牙利前缀 `i` int / `s` varchar / `t` datetime)。渲染时由 `docs-03-table-template.md` 模板内置原样输出。 | 列名 | 类型 | 可空 | 主键 | 说明 | |---|---|---|---|---| | `iIncrement` | int | 否 | 是 | 整数主键 ID(自增方式由实现决定:DB `AUTO_INCREMENT` 或应用 / 触发器分配) | | `sId` | varchar(100) | 是 | — | 业务 ID(对外暴露的字符串标识,如 UUID / 人类可读编号) | | `sBrandsId` | varchar(100) | 是 | — | 母公司 ID(多租户隔离) | | `sSubsidiaryId` | varchar(100) | 是 | — | 子公司 ID(组织层级隔离) | | `tCreateDate` | datetime | 否 | — | 记录创建时间 | 字典 / 辅助表如有豁免,在该表业务注记里注明豁免原因。 ## ER 关系概览 ``` sys_department ◄──┐ sys_company(独立,登录页"版本"下拉) │ │ N:1 sys_employee ─────┘ ▲ │ N:1 (可选, ON DELETE SET NULL) │ sys_user ────────► sys_user_permission_category ◄──── sys_permission_category (用户 × 权限分类多对多, ON DELETE CASCADE) ``` - `sys_company`:登录页"版本"下拉来源;目前独立存在,不与 user 直接 FK,登录上下文记录公司选择即可。 - `sys_department`:部门字典;被 `sys_employee` 引用。 - `sys_employee`:职员档案;被 `sys_user` 通过 `iEmployeeId` 可选引用(员工先存在,用户后绑定)。 - `sys_user`:用户账号(登录、权限、状态、登录追踪一体)。 - `sys_permission_category`:权限分类字典(USR-002/003 表 2 "权限组"的来源)。 - `sys_user_permission_category`:用户 × 权限分类多对多授权表,记录每个用户被授予哪些权限分类。 ## 表清单 - `sys_company` — 公司 / 版本字典,登录页下拉选择来源 - `sys_department` — 部门字典,职员归属 - `sys_employee` — 职员档案,员工基础信息 - `sys_user` — 用户账号(登录认证 + 类型 + 语言 + 状态 + 登录追踪) - `sys_permission_category` — 权限分类字典 - `sys_user_permission_category` — 用户 × 权限分类授权关系 --- ## `sys_company` — 公司 / 版本字典,登录页下拉选择来源 ### 字段 | 字段 | 类型 | Nullable | 默认 | 业务含义 | |---|---|---|---|---| | `iIncrement` | int | 否 | 自增函数 | 整数主键 ID(标准列) | | `sId` | varchar(100) | 是 | uuid 函数 | 业务 ID(标准列) | | `sBrandsId` | varchar(100) | 是 | `1111111111` | 品牌 ID(多租户隔离,标准列) | | `sSubsidiaryId` | varchar(100) | 是 | `1111111111` | 子公司 ID(组织层级隔离,标准列) | | `tCreateDate` | datetime | 否 | 当前时间 | 创建时间(标准列) | | `sCompanyName` | varchar(100) | 否 | — | 公司 / 版本名称(登录页下拉显示文本) | | `sCompanyCode` | varchar(50) | 否 | — | 公司编码(前端唯一识别) | | `iSortOrder` | int | 否 | 0 | 下拉列表排序权重,升序 | | `iIsDeleted` | tinyint(1) | 否 | 0 | 软删除标记,0=正常 1=已删 | ### 索引 - `pk_sys_company` (PRIMARY): `iIncrement` - `uk_sys_company_code` (UNIQUE): `sCompanyCode` - `idx_sys_company_is_deleted` (BTREE): `iIsDeleted, iSortOrder` ### 外键 (无) ### 业务注记 REQ-USR-001 登录页 "版本" 字段下拉来源。当前与 `sys_user` 不直接 FK,登录会话记录用户选择的公司即可(避免单用户跨公司绑定的复杂度)。新增公司由后续运营模块管理;本模块阶段只读使用。 --- ## `sys_department` — 部门字典,职员归属 ### 字段 | 字段 | 类型 | Nullable | 默认 | 业务含义 | |---|---|---|---|---| | `iIncrement` | int | 否 | 自增函数 | 整数主键 ID(标准列) | | `sId` | varchar(100) | 是 | uuid 函数 | 业务 ID(标准列) | | `sBrandsId` | varchar(100) | 是 | `1111111111` | 品牌 ID(多租户隔离,标准列) | | `sSubsidiaryId` | varchar(100) | 是 | `1111111111` | 子公司 ID(组织层级隔离,标准列) | | `tCreateDate` | datetime | 否 | 当前时间 | 创建时间(标准列) | | `sDepartmentName` | varchar(100) | 否 | — | 部门名称 | | `sDepartmentCode` | varchar(50) | 否 | — | 部门编码 | | `iIsDeleted` | tinyint(1) | 否 | 0 | 软删除标记 | ### 索引 - `pk_sys_department` (PRIMARY): `iIncrement` - `uk_sys_department_code` (UNIQUE): `sDepartmentCode` ### 外键 (无) ### 业务注记 REQ-USR-004 查询输出 "部门" 字段来源(经 `sys_employee` 关联)。本阶段是扁平字典,未来 HR 模块扩展时可加 `iParentId` 形成树状结构。 --- ## `sys_employee` — 职员档案,员工基础信息 ### 字段 | 字段 | 类型 | Nullable | 默认 | 业务含义 | |---|---|---|---|---| | `iIncrement` | int | 否 | 自增函数 | 整数主键 ID(标准列) | | `sId` | varchar(100) | 是 | uuid 函数 | 业务 ID(标准列) | | `sBrandsId` | varchar(100) | 是 | `1111111111` | 品牌 ID(多租户隔离,标准列) | | `sSubsidiaryId` | varchar(100) | 是 | `1111111111` | 子公司 ID(组织层级隔离,标准列) | | `tCreateDate` | datetime | 否 | 当前时间 | 创建时间(标准列) | | `sEmployeeName` | varchar(50) | 否 | — | 员工姓名(2-50 字符) | | `sEmployeeCode` | varchar(50) | 否 | — | 员工工号(系统内唯一) | | `iDepartmentId` | int | 否 | — | 所属部门 ID(FK → sys_department.iIncrement) | | `sPhone` | varchar(20) | 是 | NULL | 手机号 | | `sEmail` | varchar(100) | 是 | NULL | 邮箱 | | `iIsDeleted` | tinyint(1) | 否 | 0 | 软删除标记 | ### 索引 - `pk_sys_employee` (PRIMARY): `iIncrement` - `uk_sys_employee_code` (UNIQUE): `sEmployeeCode` - `idx_sys_employee_department` (BTREE): `iDepartmentId` - `idx_sys_employee_name` (BTREE): `sEmployeeName` ### 外键 - `fk_sys_employee_department`: `iDepartmentId` → `sys_department.iIncrement` (ON DELETE RESTRICT, ON UPDATE CASCADE) ### 业务注记 REQ-USR-002 / 003 "员工名" 下拉来源;REQ-USR-004 "员工名" / "部门" 输出来源。`iDepartmentId` 用 RESTRICT 防止删除还有员工的部门。员工先于用户存在;同一员工可对应 0 或 1 个用户账号。 --- ## `sys_user` — 用户账号(登录认证 + 类型 + 语言 + 状态 + 登录追踪) ### 字段 | 字段 | 类型 | Nullable | 默认 | 业务含义 | |---|---|---|---|---| | `iIncrement` | int | 否 | 自增函数 | 整数主键 ID(标准列) | | `sId` | varchar(100) | 是 | uuid 函数 | 业务 ID(标准列) | | `sBrandsId` | varchar(100) | 是 | `1111111111` | 品牌 ID(多租户隔离,标准列) | | `sSubsidiaryId` | varchar(100) | 是 | `1111111111` | 子公司 ID(组织层级隔离,标准列) | | `tCreateDate` | datetime | 否 | 当前时间 | 创建时间(标准列) | | `sUsername` | varchar(50) | 否 | — | 用户名(登录凭据,系统内全局唯一,3-20 位字母数字下划线) | | `sUserCode` | varchar(50) | 否 | — | 用户号(业务展示用编码,系统内唯一) | | `sPasswordHash` | varchar(255) | 否 | — | 密码哈希(BCrypt / Argon2,禁明文) | | `iEmployeeId` | int | 是 | NULL | 关联职员 ID(可选;FK → sys_employee.iIncrement) | | `sUserType` | varchar(20) | 否 | `NORMAL` | 用户类型枚举:`NORMAL`=普通用户 / `SUPER_ADMIN`=超级管理员 | | `sLanguage` | varchar(10) | 否 | `zh-CN` | 语言:`zh-CN`=中文 / `en-US`=英文 / `zh-TW`=繁体 | | `iCanEditDocument` | tinyint(1) | 否 | 0 | 单据修改权限:0=否 1=是 | | `iIsDeleted` | tinyint(1) | 否 | 0 | 是否作废:0=启用 1=作废(停用) | | `iFailedLoginCount` | int | 否 | 0 | 累计登录失败次数,达阈值锁定,登录成功清零 | | `tLockUntil` | datetime | 是 | NULL | 锁定截止时间,NULL=未锁定,过期自动解锁 | | `tLastLoginDate` | datetime | 是 | NULL | 最后一次成功登录时间,REQ-USR-004 "登录日期" 来源 | | `sCreatedBy` | varchar(50) | 是 | NULL | 制单人(创建该用户的用户名),REQ-USR-002 "制单人" | | `sUpdatedBy` | varchar(50) | 是 | NULL | 最后修改人用户名 | | `tUpdatedDate` | datetime | 是 | NULL | 最后修改时间 | ### 索引 - `pk_sys_user` (PRIMARY): `iIncrement` - `uk_sys_user_username` (UNIQUE): `sUsername` - `uk_sys_user_code` (UNIQUE): `sUserCode` - `idx_sys_user_employee` (BTREE): `iEmployeeId` - `idx_sys_user_type` (BTREE): `sUserType` - `idx_sys_user_is_deleted` (BTREE): `iIsDeleted` - `idx_sys_user_created_by` (BTREE): `sCreatedBy` ### 外键 - `fk_sys_user_employee`: `iEmployeeId` → `sys_employee.iIncrement` (ON DELETE SET NULL, ON UPDATE CASCADE) ### 业务注记 USR 模块核心表。 - **登录认证**(REQ-USR-001):`sUsername` + `sPasswordHash` 验证;连续失败累加 `iFailedLoginCount`,达 5 次写 `tLockUntil = now() + 30 分钟`;登录成功清零 + 更新 `tLastLoginDate`。 - **作废**(`iIsDeleted = 1`):等价业务"停用",登录直接拒绝。删除用户不物理删,避免 FK 联动;`uk_sys_user_username` 与作废态共存的可能由应用层处理(作废后用户名释放或保留按运营决定,本阶段保留唯一)。 - **职员关联**(`iEmployeeId`):可选;删除职员时此字段置 NULL(`ON DELETE SET NULL`),用户记录不丢。 - **密码不在本接口修改**(REQ-USR-003 边界):修改用户走非密码字段;密码重置走独立流程(后续 REQ 扩展)。 --- ## `sys_permission_category` — 权限分类字典 ### 字段 | 字段 | 类型 | Nullable | 默认 | 业务含义 | |---|---|---|---|---| | `iIncrement` | int | 否 | 自增函数 | 整数主键 ID(标准列) | | `sId` | varchar(100) | 是 | uuid 函数 | 业务 ID(标准列) | | `sBrandsId` | varchar(100) | 是 | `1111111111` | 品牌 ID(多租户隔离,标准列) | | `sSubsidiaryId` | varchar(100) | 是 | `1111111111` | 子公司 ID(组织层级隔离,标准列) | | `tCreateDate` | datetime | 否 | 当前时间 | 创建时间(标准列) | | `sCategoryName` | varchar(100) | 否 | — | 权限分类名称(如 "采购管理" / "销售管理") | | `sCategoryCode` | varchar(50) | 否 | — | 权限分类编码(系统内唯一,代码层引用) | | `sCategoryDesc` | varchar(255) | 是 | NULL | 分类说明 | | `iSortOrder` | int | 否 | 0 | 列表展示顺序 | | `iIsDeleted` | tinyint(1) | 否 | 0 | 软删除标记 | ### 索引 - `pk_sys_permission_category` (PRIMARY): `iIncrement` - `uk_sys_permission_category_code` (UNIQUE): `sCategoryCode` - `idx_sys_permission_category_sort` (BTREE): `iIsDeleted, iSortOrder` ### 外键 (无) ### 业务注记 REQ-USR-002 / 003 表 2 "权限组" 的"权限分类"来源。本表是字典,分类条目由系统初始化或运营维护,**用户管理模块只读使用**。 --- ## `sys_user_permission_category` — 用户 × 权限分类授权关系 ### 字段 | 字段 | 类型 | Nullable | 默认 | 业务含义 | |---|---|---|---|---| | `iIncrement` | int | 否 | 自增函数 | 整数主键 ID(标准列) | | `sId` | varchar(100) | 是 | uuid 函数 | 业务 ID(标准列) | | `sBrandsId` | varchar(100) | 是 | `1111111111` | 品牌 ID(多租户隔离,标准列) | | `sSubsidiaryId` | varchar(100) | 是 | `1111111111` | 子公司 ID(组织层级隔离,标准列) | | `tCreateDate` | datetime | 否 | 当前时间 | 创建时间(标准列) | | `iUserId` | int | 否 | — | 用户 ID(FK → sys_user.iIncrement) | | `iPermissionCategoryId` | int | 否 | — | 权限分类 ID(FK → sys_permission_category.iIncrement) | | `sGrantedBy` | varchar(50) | 是 | NULL | 授予人用户名 | ### 索引 - `pk_sys_user_permission_category` (PRIMARY): `iIncrement` - `uk_sys_user_permission_category` (UNIQUE): `iUserId, iPermissionCategoryId` - `idx_sys_user_permission_category_category` (BTREE): `iPermissionCategoryId` ### 外键 - `fk_sys_upc_user`: `iUserId` → `sys_user.iIncrement` (ON DELETE CASCADE, ON UPDATE CASCADE) - `fk_sys_upc_permission_category`: `iPermissionCategoryId` → `sys_permission_category.iIncrement` (ON DELETE CASCADE, ON UPDATE CASCADE) ### 业务注记 记录每个用户被授予的权限分类清单。 - REQ-USR-002 新增用户时,根据表 2 勾选生成本表对应行。 - REQ-USR-003 修改用户时,重新计算差集做增量增删。 - `ON DELETE CASCADE`:用户被物理删除时联动清理(注意:业务上用户作废不会物理删除,所以联动主要面向极端场景);权限分类被物理删除时联动清理用户授权关系,避免悬挂。 - 复合唯一键 `(iUserId, iPermissionCategoryId)` 保证同一用户同一分类只授权一次。