# 用户层级架构说明 > **文档版本**: 1.2 > **最后更新**: 2026-03-29 > **更新内容**: 根据实际代码更新表名、字段定义、数据范围类型、服务方法签名、权限点设计,删除不存在的表和服务引用 > **适用范围**: Crawlful Hub 多租户用户管理体系 --- ## 1. 多租户层级结构 Crawlful Hub 采用多层级的用户架构设计,确保数据隔离和权限控制: ``` 平台(Platform) ↓ 商户/公司(Tenant/Organization) ↓ 组织结构(Org Tree) ├── 部门A(主管) │ ├── 组A1(组长) │ │ ├── 员工1 │ │ └── 员工2 │ └── 组A2(组长) │ └── 员工3 └── 部门B(主管) └── ... ``` ### 1.1 层级关系说明 | 层级 | 英文 | 描述 | 数据隔离级别 | |------|------|------|-------------| | **平台** | Platform | 系统运营方,管理所有租户 | 全局管理 | | **租户** | Tenant | 企业/商户,拥有独立数据空间 | 完全隔离 | | **部门** | Department | 租户内的组织结构 | 层级隔离 | | **店铺** | Shop | 具体电商平台的店铺 | 业务隔离 | | **用户** | User | 系统使用者 | 权限控制 | --- ## 2. 核心层级模型 ### 2.1 层级关系详解 #### 商户 (Merchant/Tenant) - **定义**: 最高业务层级,代表一个独立的企业或组织 - **属性**: 商户ID、名称、认证状态、计费套餐、配额限制 - **管理**: 由平台管理员创建,商户管理员管理 - **数据**: 所有数据归属于特定租户,完全隔离 #### 部门 (Department) - **定义**: 商户内的组织结构单元 - **属性**: 部门ID、名称、父部门ID、层级路径(path)、深度(depth) - **管理**: 商户管理员创建和管理部门层级 - **特性**: 支持多级嵌套,形成树形结构 #### 店铺 (Shop) - **定义**: 具体的电商平台店铺(如Amazon、TikTok店铺) - **属性**: 店铺ID、平台类型、授权状态、所属部门 - **管理**: 可分配给特定部门或用户组 - **隔离**: 店铺间操作互不影响 #### 用户 (User) - **定义**: 系统的实际使用者 - **属性**: 用户ID、用户名、邮箱、角色、所属租户/部门 - **状态**: active(活跃)、inactive(未激活)、suspended(暂停)、deleted(已删除) ### 2.2 数据隔离机制 #### 租户隔离 ```sql -- 所有业务表必须包含 tenant_id 字段 SELECT * FROM cf_products WHERE tenant_id = 'tenant_xxx'; SELECT * FROM cf_orders WHERE tenant_id = 'tenant_xxx'; ``` #### 部门隔离 ```sql -- 通过部门路径实现层级数据访问 SELECT * FROM cf_user WHERE tenant_id = 'tenant_xxx' AND dept_path LIKE '/dept_a/%'; ``` #### 店铺隔离 ```sql -- 店铺级别数据过滤 SELECT * FROM cf_products WHERE tenant_id = 'tenant_xxx' AND shop_id = 'shop_xxx'; ``` --- ## 3. 权限系统(RBAC) ### 3.1 系统级角色定义 | 角色 | 英文 | 描述 | 权限范围 | |------|------|------|----------| | **ADMIN** | 系统管理员 | 平台运营方 | 所有资源的所有操作 | | **MANAGER** | 运营主管 | 租户内高级管理 | 租户内大部分资源的管理操作 | | **OPERATOR** | 运营专员 | 日常运营人员 | 基础运营操作(商品、订单) | | **FINANCE** | 财务主管 | 财务人员 | 财务相关操作(账单、结算) | | **SOURCING** | 采购专家 | 采购人员 | 采购相关操作(供应商、选品) | | **LOGISTICS** | 物流专家 | 物流人员 | 物流相关操作(发货、跟踪) | | **ANALYST** | 数据分析师 | 数据分析人员 | 数据分析相关操作(报表、洞察) | ### 3.2 店铺级角色定义 | 角色 | 描述 | 权限范围 | 适用场景 | |------|------|----------|----------| | **owner** | 拥有者 | 删除店铺、管理授权、管理成员、所有权限 | 店铺创建者 | | **admin** | 管理员 | 管理商品、管理价格、管理订单、不可删除店铺 | 店铺运营主管 | | **operator** | 运营 | 刊登、改价、查看数据 | 日常运营人员 | | **viewer** | 只读 | 查看数据、不可操作 | 仅查看报表人员 | ### 3.3 权限点设计 ```typescript // 权限对象结构 export interface Permission { id: string; // 权限ID,格式:资源:操作 name: string; // 权限名称 description: string; // 权限描述 module: string; // 所属模块 action: 'READ' | 'WRITE' | 'DELETE' | 'EXECUTE'; // 操作类型 } // 权限点定义(按模块划分) 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' }, // 库存权限 { id: 'inventory:read', name: '查看库存', description: '允许查看库存数据', module: 'INVENTORY', action: 'READ' }, { id: 'inventory:write', name: '编辑库存', description: '允许调整库存', module: 'INVENTORY', action: 'WRITE' }, { id: 'inventory:sync', name: '库存同步', description: '允许执行跨平台库存同步', module: 'INVENTORY', action: 'EXECUTE' }, { id: 'inventory:alert', name: '库存预警', description: '允许配置库存预警', module: 'INVENTORY', action: 'EXECUTE' }, // 财务权限 { id: 'finance:read', name: '查看财务', description: '允许查看财务数据', module: 'FINANCE', action: 'READ' }, { id: 'finance:recon', name: '财务对账', description: '允许执行自动化对账', module: 'FINANCE', action: 'EXECUTE' }, { id: 'finance:settlement', name: '结算管理', description: '允许处理结算', module: 'FINANCE', action: 'EXECUTE' }, { id: 'finance:report', name: '财务报表', description: '允许查看财务报表', module: 'FINANCE', action: 'READ' }, // 广告权限 { id: 'ad:read', name: '查看广告', description: '允许查看广告数据', module: 'ADVERTISING', action: 'READ' }, { id: 'ad:write', name: '编辑广告', description: '允许创建和修改广告', module: 'ADVERTISING', action: 'WRITE' }, { id: 'ad:launch', name: '投放广告', description: '允许执行广告投放', module: 'ADVERTISING', action: 'EXECUTE' }, { id: 'ad:optimize', name: '广告优化', description: '允许执行AI广告优化', module: 'ADVERTISING', action: 'EXECUTE' }, // 采购权限 { id: 'sourcing:read', name: '查看采购', description: '允许查看采购数据', module: 'SOURCING', action: 'READ' }, { id: 'sourcing:write', name: '编辑采购', description: '允许创建采购单', module: 'SOURCING', action: 'WRITE' }, { id: 'sourcing:approve', name: '采购审批', description: '允许审批采购单', module: 'SOURCING', action: 'EXECUTE' }, // 物流权限 { id: 'logistics:read', name: '查看物流', description: '允许查看物流数据', module: 'LOGISTICS', action: 'READ' }, { id: 'logistics:write', name: '编辑物流', description: '允许配置物流', module: 'LOGISTICS', action: 'WRITE' }, { id: 'logistics:track', name: '物流追踪', description: '允许追踪物流状态', module: 'LOGISTICS', action: 'EXECUTE' }, // AI权限 { id: 'ai:read', name: '查看AI分析', description: '允许查看AI分析结果', module: 'AI', action: 'READ' }, { id: 'ai:scoring', name: 'AI选品评分', description: '允许执行AI选品评分', module: 'AI', action: 'EXECUTE' }, { id: 'ai:arbitrage', name: '套利识别', description: '允许执行套利机会识别', module: 'AI', action: 'EXECUTE' }, { id: 'ai:pricing', name: '智能定价', description: '允许执行智能定价建议', module: 'AI', action: 'EXECUTE' }, { id: 'ai:monitor', name: '价格监控', description: '允许配置竞争对手价格监控', module: 'AI', action: 'EXECUTE' }, // 采集权限 { id: 'collection:read', name: '查看采集', description: '允许查看采集任务', module: 'COLLECTION', action: 'READ' }, { id: 'collection:write', name: '编辑采集', description: '允许创建采集任务', module: 'COLLECTION', action: 'WRITE' }, { id: 'collection:execute', name: '执行采集', description: '允许执行采集任务', module: 'COLLECTION', action: 'EXECUTE' }, // 用户权限 { id: 'user:read', name: '查看用户', description: '允许查看用户列表', module: 'USER', action: 'READ' }, { id: 'user:write', name: '编辑用户', description: '允许创建和修改用户', module: 'USER', action: 'WRITE' }, { id: 'user:role', name: '角色管理', description: '允许分配用户角色', module: 'USER', action: 'EXECUTE' }, // 租户权限 { id: 'tenant:read', name: '查看租户', description: '允许查看租户信息', module: 'TENANT', action: 'READ' }, { id: 'tenant:write', name: '编辑租户', description: '允许修改租户配置', module: 'TENANT', action: 'WRITE' }, { id: 'tenant:config', name: '租户配置', description: '允许配置租户设置', module: 'TENANT', action: 'EXECUTE' }, // 审计权限 { id: 'audit:read', name: '查看审计', description: '允许查看审计日志', module: 'AUDIT', action: 'READ' }, { id: 'audit:export', name: '导出审计', description: '允许导出审计日志', module: 'AUDIT', action: 'EXECUTE' }, ]; ``` --- ## 4. 数据范围控制 ### 4.1 数据范围类型 | 范围类型 | 英文 | 说明 | SQL过滤条件 | 适用角色 | |---------|------|------|------------|---------| | **OWN** | Own | 只看自己创建的数据 | `WHERE created_by = {userId}` | 普通员工 | | **SHOP** | Shop | 看自己店铺的数据 | `WHERE shop_id IN ({userShops})` | 店铺管理员 | | **DEPT** | Department | 看自己部门的数据 | `WHERE dept_id IN ({userDepts})` | 部门主管 | | **ORG** | Organization | 看整个公司的数据 | `WHERE tenant_id = {tenantId}` | 高管 | | **ALL** | All | 全平台数据(超管) | 无过滤 | 系统管理员 | ### 4.2 数据范围实现 ```typescript // 数据范围接口 export interface DataScope { type: 'ALL' | 'ORG' | 'DEPT' | 'SHOP' | 'OWN'; departmentId?: string; shopId?: string; } // 数据隔离服务 export class DataIsolationService { static async getUserDataScope(userId: string): Promise { const user = await UserService.getUserById(userId); const role = user.role; switch(role) { case 'ADMIN': return { type: 'ALL' }; case 'MANAGER': return { type: 'ORG', tenantId: user.tenantId }; case 'DEPT_MANAGER': const depts = await DepartmentService.getSubDepartments(user.deptId); return { type: 'DEPT', deptIds: depts.map(d => d.id) }; default: return { type: 'OWN', userId }; } } static applyDataScope(query: Knex.QueryBuilder, scope: DataScope): Knex.QueryBuilder { switch(scope.type) { case 'OWN': return query.where('created_by', scope.userId); case 'SHOP': return query.whereIn('shop_id', scope.shopIds); case 'DEPT': return query.whereIn('dept_id', scope.deptIds); case 'ORG': return query.where('tenant_id', scope.tenantId); case 'ALL': default: return query; } } } ``` ### 4.3 授权模型 **核心原则**: --- ## 5. 技术实现 ### 5.1 数据模型 #### 用户表 (`cf_user`) ```sql CREATE TABLE cf_user ( 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, INDEX idx_tenant (tenant_id), INDEX idx_email (email), FOREIGN KEY (tenant_id) REFERENCES cf_tenant(id) ON DELETE CASCADE ); ``` #### 租户表 (`cf_tenant`) ```sql CREATE TABLE cf_tenant ( 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, INDEX (domain), INDEX (status) ); ``` #### 部门表 (`cf_department`) ```sql CREATE TABLE cf_department ( 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 ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (tenant_id) REFERENCES cf_tenant(id), INDEX idx_tenant_path (tenant_id, path) ); ``` #### 角色权限表 (`cf_role_permission`) ```sql CREATE TABLE cf_role_permission ( 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 ); ``` ### 5.2 核心服务 #### HierarchyService - 层级服务 ```typescript export class HierarchyService { // 初始化租户层级结构 static async initializeTenantHierarchy(tenantId: string): Promise; // 创建部门 static async createDepartment( tenantId: string, name: string, parentId?: string, managerId?: string ): Promise; // 更新部门 static async updateDepartment( departmentId: string, updates: Partial ): Promise; // 删除部门 static async deleteDepartment(departmentId: string, tenantId: string): Promise; // 分配部门经理 static async assignDepartmentManager( departmentId: string, managerId: string, tenantId: string ): Promise; // 获取部门经理 static async getDepartmentManager(departmentId: string, tenantId: string): Promise; // 获取部门统计 static async getDepartmentStats(departmentId: string, tenantId: string): Promise; // 创建店铺 static async createShop( tenantId: string, departmentId: string, shopData: Partial ): Promise; // 更新店铺 static async updateShop(shopId: string, updates: Partial): Promise; // 删除店铺 static async deleteShop(shopId: string, tenantId: string): Promise; // 获取层级统计 static async getHierarchyStats(tenantId: string): Promise; // 获取部门树 static async getDepartmentTree(tenantId: string): Promise; // 获取部门下的店铺 static async getDepartmentShops(departmentId: string, tenantId: string): Promise; // 获取用户层级上下文 static async getUserHierarchyContext(userId: string): Promise<{ departmentId?: string; departmentPath?: string; shopIds: string[]; }>; // 更新用户层级 static async updateUserHierarchy( userId: string, updates: { departmentId?: string; shopIds?: string[] } ): Promise; } ``` #### RBACService - 权限服务 ```typescript export class RBACService { // 创建角色 static async createRole(roleData: RoleData): Promise; // 为角色分配权限 static async assignPermissions(roleId: string, permissions: string[]): Promise; // 检查用户权限 static async checkPermission(userId: string, permission: string): Promise; // 获取用户所有权限 static async getUserPermissions(userId: string): Promise; // 权限审计 static async auditPermissionChange(auditData: AuditData): Promise; } ``` #### AuthService - 认证服务 ```typescript export class AuthService { // 用户登录 static async login(input: LoginInput): Promise; // 用户注册 static async register(input: RegisterInput): Promise; // 请求密码重置 static async requestPasswordReset(input: PasswordResetInput): Promise; // 检查权限 static async checkPermission(input: PermissionCheckInput): Promise; // 获取用户权限列表 static async getUserPermissionsList(input: UserPermissionsInput): Promise; // 分配角色 static async assignRole(input: AssignRoleInput): Promise; // 验证会话 static async validateSession(input: SessionValidationInput): Promise; // 刷新Token static async refreshToken(input: RefreshTokenInput): Promise; // 登出 static async logout(input: LogoutInput): Promise; // 获取活跃会话 static async getActiveSessions(userId: string, tenantId: string): Promise; // 初始化表 static async initializeTables(): Promise; } ``` ### 5.3 权限检查中间件 ```typescript // Express 权限检查中间件 export function requirePermission(...permissions: string[]) { return async (req: Request, res: Response, next: NextFunction) => { const userId = req.user?.id; if (!userId) { return res.status(401).json({ error: 'Unauthorized' }); } // 获取用户所有权限 const userPermissions = await RBACService.getUserPermissions(userId); // 检查是否拥有所需权限 const hasPermission = permissions.some(p => userPermissions.includes(p)); if (!hasPermission) { return res.status(403).json({ error: 'Permission denied', required: permissions, current: userPermissions }); } next(); }; } // 数据范围中间件 export function applyDataScope(resourceType: string) { return async (req: Request, res: Response, next: NextFunction) => { const userId = req.user?.id; const scope = await DataScopeService.getUserDataScope(userId); // 将数据范围附加到请求对象 req.dataScope = scope; next(); }; } ``` --- ## 6. 安全考虑 ### 6.1 安全原则 1. **最小权限原则**: 用户只获得完成工作所必需的最小权限 2. **权限分离**: 敏感操作需要多个权限组合 3. **定期审计**: 定期审查权限配置,清理无效权限 4. **数据加密**: 敏感数据加密存储和传输 5. **访问控制**: 严格的身份验证和访问控制 ### 6.2 安全措施 | 安全措施 | 实现方式 | 状态 | |---------|---------|------| | **强密码策略** | 密码复杂度检查、定期更换 | ⚠️ 待实现 | | **双因素认证(2FA)** | TOTP/短信验证码 | ✅ 已实现 | | **登录异常检测** | 异常IP、时间、地点检测 | ⚠️ 待实现 | | **权限边界检查** | 防止水平/垂直权限提升 | ✅ 已实现 | | **敏感数据加密** | AES-256加密存储 | ✅ 已实现 | | **审计日志** | 记录所有权限变更和数据访问 | ✅ 已实现 | | **会话管理** | Token过期、单点登录限制 | ✅ 已实现 | | **API限流** | 基于用户/租户的请求限流 | ✅ 已实现 | ### 6.3 审计日志 ```typescript // 审计日志记录 export class AuditService { static async log(data: { tenantId: string; userId: string; action: string; resource: string; resourceId?: string; oldValue?: any; newValue?: any; ip?: string; userAgent?: string; }): Promise { await db('cf_audit_log').insert({ id: uuidv4(), ...data, created_at: new Date() }); } } ``` --- ## 7. 管理功能 ### 7.1 后台管理系统架构 ``` 后台管理系统 ├── 用户与权限管理 │ ├── 用户管理 │ │ ├── 用户列表 │ │ ├── 用户创建/编辑 │ │ ├── 用户禁用/启用 │ │ └── 用户登录日志 │ ├── 角色管理 │ │ ├── 角色列表 │ │ ├── 角色创建/编辑 │ │ ├── 权限分配 │ │ └── 角色成员 │ ├── 权限管理 │ │ ├── 权限列表 │ │ ├── 权限树 │ │ └── 权限分析 │ └── 部门管理 │ ├── 部门树 │ ├── 部门创建/编辑 │ ├── 部门成员 │ └── 部门统计 ├── 租户管理 │ ├── 租户列表 │ ├── 租户创建/编辑 │ ├── 租户配置 │ ├── 配额管理 │ ├── 租户隔离 │ └── 租户数据备份 ├── 店铺管理 │ ├── 我的店铺 │ │ ├── 店铺列表(卡片形式) │ │ ├── 店铺状态(已连接/已过期/错误) │ │ ├── 编辑店铺配置 │ │ ├── 刷新授权 │ │ ├── 管理成员 │ │ └── 删除店铺 │ ├── 店铺成员管理 │ │ ├── 侧边栏:我的店铺列表 │ │ ├── 主区域:当前店铺的成员列表 │ │ ├── 添加成员 │ │ ├── 修改成员角色 │ │ └── 移除成员 │ └── 用户店铺管理 │ ├── 查看用户拥有的店铺 │ ├── 添加用户到店铺 │ ├── 移除用户的店铺权限 │ └── 批量分配店铺 └── 系统监控 ├── 审计日志 ├── 登录日志 ├── 操作日志 └── 系统告警 ``` ### 7.2 前端实现 | 功能页面 | 组件路径 | 状态 | |---------|---------|------| | 用户管理 | `pages/Settings/UserManagement.tsx` | ✅ 已实现 | | 角色管理 | `pages/Settings/RoleManagement.tsx` | ✅ 已实现 | | 部门管理 | `pages/Settings/DepartmentManagement.tsx` | ✅ 已实现 | | 租户设置 | `pages/Settings/TenantSettings.tsx` | ✅ 已实现 | | 订阅管理 | `pages/Settings/SubscriptionManage.tsx` | ✅ 已实现 | | 我的店铺 | `pages/Settings/MyShops.tsx` | ✅ 已实现 | | 店铺成员管理 | `pages/Settings/ShopMemberManagement.tsx` | ✅ 已实现 | | 系统监控 | `pages/Monitoring/SystemStatus.tsx` | ✅ 已实现 | | 操作日志 | `pages/OperationLogs/index.tsx` | ✅ 已实现 | ### 7.3 店铺管理流程 #### 7.3.1 店铺视角管理(我的店铺) **页面路径**: `/dashboard/settings/my-shops` **功能说明**: - 显示用户拥有的所有店铺(卡片形式) - 每个店铺卡片显示: - 店铺名称 - 平台类型(带图标) - 授权状态(已连接/已过期/错误) - 成员数量 - 最后同步时间 - 操作按钮: - **管理成员**:跳转到店铺成员管理页面 - **编辑配置**:修改店铺名称、平台配置 - **刷新授权**:刷新过期的店铺授权 - **删除店铺**:删除店铺及其成员关系 **使用场景**: 1. 用户登录系统 2. 进入"我的店铺"页面 3. 查看自己拥有的所有店铺 4. 点击某个店铺的"管理成员"按钮 5. 进入店铺成员管理页面 #### 7.3.2 店铺成员管理 **页面路径**: `/dashboard/settings/shop-members/:shopId` **功能说明**: - **左侧边栏**:我的店铺列表 - 显示用户拥有的所有店铺 - 当前选中的店铺高亮 - 显示每个店铺的成员数量 - 点击切换店铺 - **右侧主区域**:当前店铺的成员列表 - 显示成员信息(用户名、邮箱、角色、权限) - 添加成员(选择用户,分配角色和权限) - 修改成员角色(下拉选择) - 移除成员 **使用场景**: 1. 从"我的店铺"页面点击"管理成员" 2. 进入店铺成员管理页面 3. 左侧边栏显示我的店铺列表 4. 选择要管理的店铺 5. 右侧显示该店铺的成员列表 6. 添加/修改/移除成员 #### 7.3.3 用户视角管理(用户店铺分配) **页面路径**: `/dashboard/settings/user` **功能说明**: - 在用户管理页面,每个用户有"管理店铺"按钮 - 点击后弹出店铺分配模态框 - 模态框功能: - 按平台分组显示所有店铺 - 支持平台级别全选 - 支持单个店铺选择 - 显示已分配店铺列表 - 保存分配结果 **使用场景**: 1. 管理员进入用户管理页面 2. 点击某个用户的"管理店铺"按钮 3. 在弹出的模态框中: - 查看该用户当前拥有的店铺 - 添加新的店铺权限 - 移除现有的店铺权限 4. 保存分配结果 ### 7.4 双向管理关系 #### 7.4.1 店铺 → 用户管理 **入口**: 我的店铺 → 店铺成员管理 **操作流程**: ``` 我的店铺页面 ↓ 选择店铺 → 点击"管理成员" ↓ 店铺成员管理页面 ↓ 左侧边栏:我的店铺列表 ↓ 选择要管理的店铺 ↓ 右侧主区域:当前店铺的成员列表 ↓ 添加/修改/移除成员 ``` **特点**: - 店铺拥有者可以管理自己店铺的成员 - 可以添加、修改、删除成员 - 可以分配不同的角色和权限 - 侧边栏支持快速切换店铺 #### 7.4.2 用户 → 店铺管理 **入口**: 用户管理 → 管理店铺 **操作流程**: ``` 用户管理页面 ↓ 选择用户 → 点击"管理店铺" ↓ 店铺分配模态框 ↓ 查看该用户拥有的店铺 ↓ 添加/删除店铺权限 ↓ 保存分配结果 ``` **特点**: - 管理员可以管理任何用户的店铺权限 - 可以批量分配多个店铺 - 支持按平台分组显示 - 可以查看已分配的店铺列表 #### 7.4.3 数据关系 ``` cf_shop(店铺表) ↓ cf_shop_member(店铺成员表) ↓ 记录:用户-店铺-角色关系 cf_user(用户表) ↓ 通过cf_shop_member关联店铺 ``` **关键约束**: - 一个用户可以拥有多个店铺的权限 - 一个店铺可以有多个成员 - 成员角色:owner(拥有者)、admin(管理员)、operator(运营)、viewer(只读) - 权限可以自定义,也可以使用预设权限 ### 7.5 店铺管理API #### 7.5.1 店铺相关API | API路径 | 方法 | 说明 | 权限要求 | |---------|------|------|----------| | `/api/shops/my-shops` | GET | 获取当前用户的店铺列表 | 登录用户 | | `/api/shops/:id` | GET | 获取店铺详情 | 店铺成员 | | `/api/shops` | POST | 创建店铺 | 店铺拥有者 | | `/api/shops/:id` | PUT | 更新店铺信息 | 店铺拥有者 | | `/api/shops/:id/refresh-auth` | POST | 刷新店铺授权 | 店铺拥有者 | | `/api/shops/:id` | DELETE | 删除店铺 | 店铺拥有者 | | `/api/shops/stats` | GET | 获取店铺统计信息 | 登录用户 | #### 7.5.2 店铺成员相关API | API路径 | 方法 | 说明 | 权限要求 | |---------|------|------|----------| | `/api/shops/:shopId/members` | GET | 获取店铺成员列表 | 店铺成员 | | `/api/shops/user/:userId/shops` | GET | 获取用户拥有的店铺 | 管理员或用户本人 | | `/api/shop-members` | POST | 添加店铺成员 | 店铺拥有者 | | `/api/shop-members/:shopId/:userId` | DELETE | 移除店铺成员 | 店铺拥有者 | | `/api/shop-members/:shopId/:userId` | PUT | 更新成员角色和权限 | 店铺拥有者 | #### 7.5.3 数据源实现 **文件路径**: `dashboard/src/services/shopDataSource.ts` **主要方法**: - `getMyShops()`: 获取当前用户的店铺列表 - `getById(id)`: 获取店铺详情 - `getShopMembers(shopId)`: 获取店铺成员列表 - `getUserShops(userId)`: 获取用户拥有的店铺 - `createShop(data)`: 创建店铺 - `updateShop(id, data)`: 更新店铺信息 - `refreshAuth(id)`: 刷新店铺授权 - `deleteShop(id)`: 删除店铺 - `addMember(data)`: 添加店铺成员 - `removeMember(shopId, userId)`: 移除店铺成员 - `updateMemberRole(shopId, userId, role, permissions)`: 更新成员角色和权限 - `getStats()`: 获取店铺统计信息 --- ## 8. 实现状态 ### 8.1 已实现功能 | 功能模块 | 功能点 | 状态 | 实现位置 | |---------|--------|------|---------| | **用户管理** | 用户CRUD | ✅ | UserService.ts, UserManagement.tsx | | | 用户状态管理 | ✅ | UserService.updateUserStatus | | | 用户缓存 | ✅ | UserService (Redis缓存) | | | 批量操作 | ✅ | UserService.batchCreateUsers | | **角色管理** | 角色CRUD | ✅ | RBACService.ts, RoleManagement.tsx | | | 权限分配 | ✅ | RBACService.assignPermissions | | | 权限树 | ✅ | RoleManagement.tsx | | **部门管理** | 部门CRUD | ✅ | HierarchyService.ts, DepartmentManagement.tsx | | | 层级结构 | ✅ | HierarchyService (path + depth) | | | 部门转移 | ✅ | HierarchyService.transferUser | | **租户管理** | 租户CRUD | ✅ | SaasTenantService.ts | | | 租户隔离 | ✅ | 所有表tenant_id字段 | | | 配额管理 | ✅ | QuotaGovernance | | **店铺管理** | 店铺CRUD | ✅ | ShopService.ts, MyShops.tsx | | | 店铺成员管理 | ✅ | ShopMemberService.ts, ShopMemberManagement.tsx | | | 店铺授权刷新 | ✅ | ShopService.refreshAuth | | | 用户店铺分配 | ✅ | UserManagement.tsx | | | 双向管理关系 | ✅ | 店铺视角 + 用户视角 | | **认证授权** | 登录认证 | ✅ | AuthService.ts | | | Token管理 | ✅ | JWT + Refresh Token | | | 权限检查 | ✅ | requirePermission中间件 | | **数据范围** | 范围控制 | ✅ | DataScopeService | | | 部门过滤 | ✅ | dept_path字段 | ### 8.2 待实现功能 | 功能模块 | 功能点 | 优先级 | 计划时间 | |---------|--------|--------|---------| | **安全增强** | 强密码策略 | P1 | 待定 | | | 登录异常检测 | P2 | 待定 | | **用户体验** | 拖拽排序 | P2 | 待定 | | **集成扩展** | SSO集成 | P2 | 待定 | | | LDAP/AD集成 | P3 | 待定 | | | Webhook通知 | P3 | 待定 | | **测试覆盖** | 功能测试 | P1 | 待定 | | | 安全测试 | P1 | 待定 | | | 性能测试 | P2 | 待定 | --- ## 9. 相关文档 - [User_Tenant_Improvement_Checklist.md](./User_Tenant_Improvement_Checklist.md) - 用户租户改进清单 - [RBAC_Design.md](./archive/02_Backend/07_RBAC_Design.md) - RBAC详细设计 - [Governance_Standards.md](./archive/00_Business/Governance_Standards.md) - 治理规范 - [Security_Policy.md](./rules/security.md) - 安全策略 --- ## 10. 总结 Crawlful Hub 的用户层级架构采用了**多租户 + 多层级 + RBAC** 的设计模式: 1. **多租户隔离**: 确保不同商户数据完全隔离,保障数据安全 2. **灵活的组织结构**: 支持多级部门,适应不同规模企业 3. **细粒度权限控制**: 基于角色的权限管理,支持自定义角色 4. **数据范围控制**: 从个人到全平台的多级数据访问控制 5. **完整的审计体系**: 记录所有操作,支持安全审计 该架构不仅满足了企业级应用的安全需求,也为不同规模的商户提供了灵活的组织管理能力,支持从初创企业到大型集团的业务场景。