# 用户层级架构文档与实际代码差异分析 > **分析日期**: 2026-03-29 > **文档版本**: 用户层级架构说明.md v1.1 > **代码版本**: server/src --- ## 1. 表名差异 | 文档中的表名 | 实际代码中的表名 | 说明 | |-------------|----------------|------| | `cf_users` | `cf_user` | 复数/单数差异 | | `cf_tenants` | `cf_tenant` | 复数/单数差异 | | `cf_departments` | `cf_department` | 复数/单数差异 | | `cf_role_permissions` | `cf_role_permission` | 复数/单数差异 | | `cf_shop_auth` | **不存在** | 文档中提到但代码中未实现 | --- ## 2. 用户表 (`cf_user`) 差异 ### 文档中的字段 ```sql id VARCHAR(36) PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, role VARCHAR(20) DEFAULT 'OPERATOR', tenant_id VARCHAR(36) NOT NULL, dept_id VARCHAR(36), status ENUM('active', 'inactive', 'suspended') DEFAULT 'active', last_login_at TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ``` ### 实际代码中的字段 ```sql id VARCHAR(36) PRIMARY KEY, tenant_id VARCHAR(36) NOT NULL, username VARCHAR(64) NOT NULL UNIQUE, email VARCHAR(128) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, full_name VARCHAR(128) NOT NULL, phone VARCHAR(32), status ENUM('ACTIVE', 'INACTIVE', 'LOCKED') DEFAULT 'ACTIVE'), role ENUM('ADMIN', 'MANAGER', 'OPERATOR', 'FINANCE', 'SOURCING', 'LOGISTICS', 'ANALYST') NOT NULL, is_superadmin BOOLEAN DEFAULT FALSE, last_login_by VARCHAR(36), last_login_at TIMESTAMP, created_by VARCHAR(36) NOT NULL, updated_by VARCHAR(36) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ``` ### 差异点 | 字段 | 文档 | 实际代码 | 差异说明 | |------|------|---------|---------| | `username` | VARCHAR(50) | VARCHAR(64) | 长度不同 | | `email` | VARCHAR(100) | VARCHAR(128) | 长度不同 | | `dept_id` | ✅ 存在 | ❌ 不存在 | 实际代码中没有部门ID字段 | | `full_name` | ❌ 不存在 | ✅ 存在 | 实际代码中有全名字段 | | `phone` | ❌ 不存在 | ✅ 存在 | 实际代码中有电话字段 | | `is_superadmin` | ❌ 不存在 | ✅ 存在 | 实际代码中有超级管理员标识 | | `created_by` | ❌ 不存在 | ✅ 存在 | 实际代码中有创建人字段 | | `updated_by` | ❌ 不存在 | ✅ 存在 | 实际代码中有更新人字段 | | `status` | 小写枚举 | 大写枚举 | 命名风格不同 | | `role` | 字符串 | 枚举类型 | 类型定义不同 | --- ## 3. 租户表 (`cf_tenant`) 差异 ### 文档中的字段 ```sql id VARCHAR(36) PRIMARY KEY, name VARCHAR(100) NOT NULL, type ENUM('SAAS', 'ENTERPRISE', 'TRIAL') DEFAULT 'SAAS', status ENUM('ACTIVE', 'SUSPENDED', 'CANCELLED') DEFAULT 'ACTIVE', plan_id VARCHAR(36), quota_config JSON, settings JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ``` ### 实际代码中的字段 ```sql id VARCHAR(36) PRIMARY KEY, name VARCHAR(128) NOT NULL UNIQUE, domain VARCHAR(128) NOT NULL UNIQUE, contact_name VARCHAR(64) NOT NULL, contact_email VARCHAR(128) NOT NULL UNIQUE, contact_phone VARCHAR(32) NOT NULL, address VARCHAR(255) NOT NULL, status ENUM('ACTIVE', 'INACTIVE', 'SUSPENDED') DEFAULT 'ACTIVE'), quota_limit DECIMAL(10, 2) DEFAULT 10000, quota_used DECIMAL(10, 2) DEFAULT 0, created_by VARCHAR(36) NOT NULL, updated_by VARCHAR(36) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ``` ### 差异点 | 字段 | 文档 | 实际代码 | 差异说明 | |------|------|---------|---------| | `name` | VARCHAR(100) | VARCHAR(128) | 长度不同 | | `type` | ✅ 存在 | ❌ 不存在 | 实际代码中没有租户类型字段 | | `plan_id` | ✅ 存在 | ❌ 不存在 | 实际代码中没有套餐ID字段 | | `quota_config` | ✅ 存在 | ❌ 不存在 | 实际代码中没有JSON配置字段 | | `settings` | ✅ 存在 | ❌ 不存在 | 实际代码中没有JSON设置字段 | | `domain` | ❌ 不存在 | ✅ 存在 | 实际代码中有域名字段 | | `contact_name` | ❌ 不存在 | ✅ 存在 | 实际代码中有联系人姓名字段 | | `contact_email` | ❌ 不存在 | ✅ 存在 | 实际代码中有联系人邮箱字段 | | `contact_phone` | ❌ 不存在 | ✅ 存在 | 实际代码中有联系人电话字段 | | `address` | ❌ 不存在 | ✅ 存在 | 实际代码中有地址字段 | | `quota_limit` | ❌ 不存在 | ✅ 存在 | 实际代码中有配额限制字段 | | `quota_used` | ❌ 不存在 | ✅ 存在 | 实际代码中有已用配额字段 | | `created_by` | ❌ 不存在 | ✅ 存在 | 实际代码中有创建人字段 | | `updated_by` | ❌ 不存在 | ✅ 存在 | 实际代码中有更新人字段 | --- ## 4. 部门表 (`cf_department`) 差异 ### 文档中的字段 ```sql id VARCHAR(36) PRIMARY KEY, tenant_id VARCHAR(36) NOT NULL, parent_id VARCHAR(36), name VARCHAR(100) NOT NULL, manager_id VARCHAR(36), path VARCHAR(500), depth INT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (tenant_id) REFERENCES cf_tenants(id), INDEX idx_tenant_path (tenant_id, path) ``` ### 实际代码中的字段(HierarchyService.ts中定义) ```sql id VARCHAR(36) PRIMARY KEY, tenant_id VARCHAR(36) NOT NULL, name VARCHAR(128) NOT NULL, parent_id VARCHAR(36), path VARCHAR(500), depth INT DEFAULT 0, manager_id VARCHAR(36), status ENUM('ACTIVE', 'INACTIVE') DEFAULT 'ACTIVE', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ``` ### 差异点 | 字段 | 文档 | 实际代码 | 差异说明 | |------|------|---------|---------| | `name` | VARCHAR(100) | VARCHAR(128) | 长度不同 | | `status` | ❌ 不存在 | ✅ 存在 | 实际代码中有状态字段 | | `updated_at` | ❌ 不存在 | ✅ 存在 | 实际代码中有更新时间字段 | --- ## 5. 角色权限表 (`cf_role_permission`) 差异 ### 文档中的字段 ```sql id VARCHAR(36) PRIMARY KEY, role_key VARCHAR(50) NOT NULL, permission_key VARCHAR(100) NOT NULL, tenant_id VARCHAR(36), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_role_perm (role_key, permission_key, tenant_id) ``` ### 实际代码中的字段 ```sql id VARCHAR(36) PRIMARY KEY, role_id VARCHAR(36) NOT NULL, permission_id VARCHAR(36) NOT NULL, created_by VARCHAR(36) NOT NULL, updated_by VARCHAR(36) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_role_perm (role_id, permission_id), FOREIGN KEY (role_id) REFERENCES cf_role(id) ON DELETE CASCADE, FOREIGN KEY (permission_id) REFERENCES cf_permission(id) ON DELETE CASCADE ``` ### 差异点 | 字段 | 文档 | 实际代码 | 差异说明 | |------|------|---------|---------| | `role_key` | ✅ 存在 | ❌ 不存在 | 实际代码中是`role_id` | | `permission_key` | ✅ 存在 | ❌ 不存在 | 实际代码中是`permission_id` | | `tenant_id` | ✅ 存在 | ❌ 不存在 | 实际代码中没有租户ID字段 | | `created_by` | ❌ 不存在 | ✅ 存在 | 实际代码中有创建人字段 | | `updated_by` | ❌ 不存在 | ✅ 存在 | 实际代码中有更新人字段 | | `updated_at` | ❌ 不存在 | ✅ 存在 | 实际代码中有更新时间字段 | --- ## 6. 数据范围类型差异 ### 文档中的数据范围类型 | 类型 | 说明 | SQL过滤条件 | 适用角色 | |------|------|------------|---------| | **SELF** | 只看自己创建的数据 | `WHERE created_by = {userId}` | 普通员工 | | **TEAM** | 看自己组的数据 | `WHERE team_id IN ({userTeams})` | 组长 | | **DEPT** | 看自己部门的数据 | `WHERE dept_id IN ({userDepts})` | 部门主管 | | **ORG** | 看整个公司的数据 | `WHERE tenant_id = {tenantId}` | 高管 | | **ALL** | 全平台数据(超管) | 无过滤 | 系统管理员 | ### 实际代码中的数据范围类型(RBACEngine.ts) ```typescript export interface DataScope { type: 'ALL' | 'ORG' | 'DEPT' | 'SHOP' | 'OWN'; departmentId?: string; shopId?: string; } ``` ### 差异点 | 文档类型 | 实际代码类型 | 差异说明 | |----------|-------------|---------| | **SELF** | **OWN** | 实际代码中是`OWN`而不是`SELF` | | **TEAM** | **SHOP** | 实际代码中是`SHOP`而不是`TEAM` | | **DEPT** | **DEPT** | 一致 | | **ORG** | **ORG** | 一致 | | **ALL** | **ALL** | 一致 | --- ## 7. 服务实现差异 ### DataScopeService - **文档中**: 提到`DataScopeService`类,包含`getUserDataScope`和`applyDataScope`方法 - **实际代码**: 不存在`DataScopeService`类 - **实际实现**: 数据隔离功能通过`DataIsolationService`实现 ### HierarchyService - **文档中的方法签名**: ```typescript static async getUserHierarchyPath(userId: string): Promise; static async getSubDepartments(deptId: string): Promise; static async getDepartmentUsers(deptId: string): Promise; static async transferUser(userId: string, targetDeptId: string): Promise; static async getDepartmentStats(deptId: string): Promise; ``` - **实际代码中的方法**: ```typescript static async initializeTenantHierarchy(tenantId: string): Promise; static async createDepartment(tenantId: string, name: string, parentId?: string): Promise; static async updateDepartment(deptId: string, updates: Partial): Promise; static async deleteDepartment(deptId: string): Promise; static async getDepartmentTree(tenantId: string): Promise; static async getDepartmentStats(deptId: string): Promise; static async transferUser(userId: string, targetDeptId: string): Promise; static async createShop(tenantId: string, deptId: string, shopData: Partial): Promise; static async updateShop(shopId: string, updates: Partial): Promise; static async deleteShop(shopId: string): Promise; static async getShopTree(tenantId: string): Promise; static async assignUserToShop(userId: string, shopId: string): Promise; static async removeUserFromShop(userId: string): Promise; ``` ### AuthService - **文档中的方法签名**: ```typescript static async login(credentials: LoginCredentials): Promise; static async verifyToken(token: string): Promise; static async refreshToken(refreshToken: string): Promise; static async logout(userId: string): Promise; ``` - **实际代码中的方法**: ```typescript static async login(input: LoginInput): Promise; static async register(input: RegisterInput): Promise; static async passwordReset(input: PasswordResetInput): Promise; static async checkPermission(input: PermissionCheckInput): Promise; static async getUserPermissions(input: UserPermissionsInput): Promise; static async assignRole(input: AssignRoleInput): Promise; static async removeRole(input: RemoveRoleInput): Promise; ``` --- ## 8. 权限点设计差异 ### 文档中的权限点命名规范 ```typescript const PERMISSIONS = { 'product:read': '查看商品', 'product:create': '创建商品', 'product:update': '更新商品', 'product:delete': '删除商品', 'product:export': '导出商品', 'product:import': '导入商品', // ... 其他权限 }; ``` ### 实际代码中的权限点(RBACEngine.ts) ```typescript const PERMISSIONS: Permission[] = [ { id: 'admin:all', name: '超级管理员', description: '拥有所有系统权限', module: 'SYSTEM', action: 'EXECUTE' }, { id: 'product:read', name: '查看商品', description: '允许查看商品列表与详情', module: 'PRODUCT', action: 'READ' }, { id: 'product:write', name: '编辑商品', description: '允许创建和修改商品信息', module: 'PRODUCT', action: 'WRITE' }, { id: 'product:delete', name: '删除商品', description: '允许删除商品', module: 'PRODUCT', action: 'DELETE' }, { id: 'product:publish', name: '发布商品', description: '允许执行商品刊登任务', module: 'PRODUCT', action: 'EXECUTE' }, { id: 'product:score', name: '商品评分', description: '允许查看AI选品评分', module: 'PRODUCT', action: 'READ' }, { id: 'order:read', name: '查看订单', description: '允许查看销售订单', module: 'ORDER', action: 'READ' }, { id: 'order:write', name: '创建订单', description: '允许创建订单', module: 'ORDER', action: 'WRITE' }, { id: 'order:cancel', name: '取消订单', description: '允许取消订单', module: 'ORDER', action: 'EXECUTE' }, { id: 'order:refund', name: '退款处理', description: '允许处理退款', module: 'ORDER', action: 'EXECUTE' }, // ... 更多权限 ]; ``` ### 差异点 | 差异 | 说明 | |------|------| | **权限结构** | 实际代码使用`Permission`对象数组,包含id、name、description、module、action字段 | | **模块划分** | 实际代码按模块划分(PRODUCT、ORDER、INVENTORY、FINANCE、ADVERTISING、SOURCING、LOGISTICS、AI、COLLECTION、USER、TENANT、AUDIT) | | **操作类型** | 实际代码使用READ、WRITE、DELETE、EXECUTE四种操作类型 | | **权限数量** | 实际代码中定义了50+个权限点,比文档中更详细 | --- ## 9. 建议修正 ### 9.1 表名统一 建议将文档中的表名统一为实际代码中的单数形式: - `cf_users` → `cf_user` - `cf_tenants` → `cf_tenant` - `cf_departments` → `cf_department` - `cf_role_permissions` → `cf_role_permission` ### 9.2 字段定义更新 建议更新文档中的字段定义,与实际代码保持一致: - 添加缺失的字段(如`full_name`、`phone`、`is_superadmin`等) - 删除不存在的字段(如`dept_id`、`type`、`plan_id`等) - 更新字段类型和长度(如`username`从VARCHAR(50)改为VARCHAR(64)) ### 9.3 数据范围类型更新 建议将文档中的数据范围类型更新为实际代码中的定义: - `SELF` → `OWN` - `TEAM` → `SHOP` - 保持`DEPT`、`ORG`、`ALL`不变 ### 9.4 服务方法签名更新 建议更新文档中的服务方法签名,与实际代码保持一致: - `HierarchyService`方法签名更新 - `AuthService`方法签名更新 - 删除不存在的`DataScopeService`引用 ### 9.5 权限点设计更新 建议更新文档中的权限点设计,与实际代码中的RBACEngine保持一致: - 使用`Permission`对象结构 - 按模块划分权限 - 使用READ、WRITE、DELETE、EXECUTE操作类型 ### 9.6 店铺授权表 建议删除文档中关于`cf_shop_auth`表的描述,因为实际代码中不存在此表。 --- ## 10. 总结 | 差异类型 | 数量 | 严重程度 | |----------|------|---------| | 表名不一致 | 5 | 🟡 中等 | | 字段缺失 | 15+ | 🔴 严重 | | 字段类型不一致 | 8 | 🟡 中等 | | 数据范围类型不一致 | 2 | 🟡 中等 | | 服务方法签名不一致 | 3 | 🟡 中等 | | 权限点设计不一致 | 1 | 🟡 中等 | **总体评估**: 文档与实际代码存在较多差异,建议尽快更新文档以保持一致性。