Răsfoiți Sursa

🗑️ docs(permission): 删除权限体系相关文档文件

- 删除crm-permission-implementation-status.md - 权限实施状态报告
- 删除crm-permission-improvement-plan.md - 权限改进方案文档
- 删除crm-permission-init.md - 权限初始化SQL文档
- 删除crm-personal-data-scope-implementation.md - 个人数据权限实现文档
- 删除permission-config-component-design.md - 权限配置组件设计文档
- 删除permission-config-component-with-lazy-loading.md - 懒加载权限配置组件设计
- 删除permission-config-integration-guide.md - 权限配置组件集成指南
yourname 7 luni în urmă
părinte
comite
ca28cd46a4

+ 0 - 150
docs/crm-permission-implementation-status.md

@@ -1,150 +0,0 @@
-# CRM权限体系实施状态报告
-
-## 项目概述
-本文档记录了CRM系统权限体系改进方案的实际实施状态与进度分析。
-
-## 实施进度总览
-
-| 阶段 | 任务内容 | 实施状态 | 完成度 | 备注 |
-|------|----------|----------|--------|------|
-| **阶段一** | 数据库结构升级 | ✅ **已完成** | 100% | 包含部门、用户、权限表重构 |
-| **阶段二** | 部门管理功能 | ✅ **已完成** | 100% | 多层级部门管理界面 |
-| **阶段三** | 权限模型重构 | ✅ **已完成** | 100% | 精细化权限控制体系 |
-| **阶段四** | 数据权限集成 | ✅ **已完成** | 100% | 通用CRUD自动权限过滤 |
-| **阶段五** | 前端权限控制 | ✅ **已完成** | 100% | 权限配置界面 |
-| **阶段六** | 角色管理功能 | ✅ **已完成** | 100% | 独立角色管理页面(2025-07-20完成) |
-| **阶段七** | 测试和优化 | ⚠️ **待完善** | 10% | 需补充测试用例 |
-
-## 详细实施状态
-
-### ✅ 已完全实现的功能
-
-#### 1. 数据库结构升级
-**实现文件:**
-- `src/server/modules/departments/department.entity.ts`
-- `src/server/modules/users/user.entity.ts`
-- `src/server/modules/permissions/permission.entity.ts`
-
-**核心实现:**
-- ✅ 部门表:支持多层级组织架构
-- ✅ 用户部门关联:支持用户多部门配置
-- ✅ 权限表:支持操作级和数据级权限
-- ✅ 角色权限关联:支持角色权限配置
-
-#### 2. 部门管理功能
-**实现文件:**
-- `src/server/api/departments/index.ts`
-- `src/client/admin/pages/Departments.tsx`
-
-**功能特性:**
-- ✅ 部门CRUD操作
-- ✅ 多层级部门树
-- ✅ 部门负责人配置
-- ✅ 状态管理(启用/禁用)
-
-#### 3. 权限模型重构
-**实现文件:**
-- `src/server/modules/permissions/permission.entity.ts`
-- `src/server/utils/data-permission.service.ts`
-
-**权限类型:**
-- ✅ 模块权限(MODULE)
-- ✅ 操作权限(OPERATION)
-- ✅ 数据权限(DATA)
-
-**数据范围类型:**
-- ✅ PERSONAL(个人数据)
-- ✅ DEPARTMENT(部门数据)
-- ✅ SUB_DEPARTMENT(部门及下级)
-- ✅ COMPANY(全公司数据)
-- ✅ CUSTOM(自定义范围)
-
-#### 4. 数据权限集成
-**实现文件:**
-- `src/server/utils/generic-crud.service.ts`
-- `src/server/modules/permissions/data-permission.service.ts`
-
-**集成特性:**
-- ✅ 自动数据权限过滤
-- ✅ 超级管理员无限制
-- ✅ 部门继承机制
-- ✅ 用户权限范围控制
-
-#### 5. 前端权限控制
-**实现文件:**
-- `src/client/admin/pages/Permissions.tsx`
-- `src/client/admin/pages/Roles.tsx`
-- `src/client/admin/menu.tsx`
-
-**界面功能:**
-- ✅ 权限列表管理(独立功能)
-- ✅ 角色权限配置(独立页面)
-- ✅ 数据范围选择
-- ✅ 树形权限展示
-
-#### 6. 角色管理功能 ✅ 已完成
-**实现状态:**
-- ✅ **独立角色管理页面**:`src/client/admin/pages/Roles.tsx`
-- ✅ **React Query v5集成**:完整的角色CRUD操作
-- ✅ **权限配置功能**:树形权限选择器
-- ✅ **菜单集成**:新增角色管理菜单项
-- ✅ **路由注册**:`/admin/roles` 路由已配置
-
-**功能特性:**
-- ✅ 角色创建、编辑、删除
-- ✅ 角色权限批量配置
-- ✅ 响应式表格展示
-- ✅ 实时数据更新
-
-### 📋 待完善项目
-
-#### 7. 测试和优化
-**缺失项目:**
-- ❌ 单元测试用例
-- ❌ 集成测试
-- ❌ 性能测试
-- ❌ 使用文档
-
-## 使用指南
-
-### 角色管理流程
-1. **访问角色管理**:`/admin/roles`
-2. **创建角色**:点击"新建角色"按钮
-3. **配置权限**:点击"配置权限"按钮
-4. **选择权限**:使用树形结构选择权限
-5. **保存配置**:确认权限设置
-
-### 权限管理流程
-1. **访问权限管理**:`/admin/permissions`
-2. **管理权限**:专注于权限本身的CRUD操作
-3. **角色权限**:已移至角色管理页面独立处理
-
-### 部门管理流程
-1. **访问部门管理**:`/admin/departments`
-2. **创建部门**:点击"新增部门"
-3. **设置层级**:选择上级部门
-4. **配置负责人**:指定部门负责人
-
-## 技术亮点
-
-### React Query v5集成
-- **智能缓存**:角色和权限数据的自动缓存和失效
-- **实时更新**:增删改操作后自动重新获取数据
-- **加载状态**:完善的loading和error处理
-- **乐观更新**:优化的用户体验
-
-### 架构优化
-- **职责分离**:角色管理与权限管理完全分离
-- **代码清晰**:独立文件专注单一功能
-- **易于扩展**:模块化设计便于后续功能添加
-
-## 结论 ✅
-
-**CRM权限体系改进方案已实现 100%**,所有核心功能全部完成。系统已具备:
-- ✅ 完整的组织架构管理
-- ✅ 精细化权限控制体系
-- ✅ 独立角色管理功能
-- ✅ 数据权限管理能力
-- ✅ 用户友好的管理界面
-
-系统可以投入生产使用。建议后续补充测试用例和完善使用文档。

+ 0 - 399
docs/crm-permission-improvement-plan.md

@@ -1,399 +0,0 @@
-# CRM系统用户权限体系改进方案
-
-## 当前状态分析
-
-### 已实现功能
-- ✅ **用户管理**: 完整的用户CRUD功能
-- ✅ **角色管理**: 基于角色的权限控制(RBAC)
-- ✅ **权限控制**: 通过权限字符串控制菜单和API访问
-- ✅ **客户数据权限**: 基于负责人ID的数据隔离
-- ✅ **区域管理**: 支持省市区三级区域划分
-
-### 缺失功能
-- ❌ **部门管理**: 无部门组织架构
-- ❌ **数据范围控制**: 无法按部门、团队范围管理数据
-- ❌ **权限粒度**: 仅支持模块级权限,缺少操作级权限
-- ❌ **用户组管理**: 无法批量管理用户权限
-- ❌ **数据继承**: 上级部门无法查看下级部门数据
-
-## 改进目标
-
-### 1. 建立完整的组织架构
-- 实现多层级部门管理
-- 支持部门负责人制度
-- 提供部门间数据共享机制
-
-### 2. 精细化权限控制
-- 实现操作级权限控制
-- 支持数据范围权限(个人/部门/公司)
-- 提供灵活的权限继承机制
-
-### 3. 增强数据管理能力
-- 支持基于部门的数据隔离
-- 实现数据权限继承
-- 提供数据分享和转移功能
-
-## 详细改进方案
-
-### 阶段一:部门体系重构
-
-#### 1.1 数据库结构优化
-
-```sql
--- 部门表
-CREATE TABLE department (
-    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '部门ID',
-    name VARCHAR(100) NOT NULL COMMENT '部门名称',
-    code VARCHAR(50) UNIQUE COMMENT '部门编码',
-    parent_id INT UNSIGNED COMMENT '父部门ID',
-    manager_id INT UNSIGNED COMMENT '部门负责人ID',
-    description TEXT COMMENT '部门描述',
-    sort_order INT DEFAULT 0 COMMENT '排序',
-    is_active TINYINT DEFAULT 1 COMMENT '是否启用(0:禁用,1:启用)',
-    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    INDEX idx_parent_id (parent_id),
-    INDEX idx_manager_id (manager_id),
-    INDEX idx_code (code),
-    CONSTRAINT fk_department_parent FOREIGN KEY (parent_id) REFERENCES department(id),
-    CONSTRAINT fk_department_manager FOREIGN KEY (manager_id) REFERENCES users(id)
-) COMMENT = '组织架构部门表';
-
--- 用户部门关联表
-CREATE TABLE user_department (
-    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
-    user_id INT UNSIGNED NOT NULL,
-    department_id INT UNSIGNED NOT NULL,
-    position VARCHAR(100) COMMENT '职位',
-    is_primary TINYINT DEFAULT 1 COMMENT '是否主部门(0:兼职,1:主部门)',
-    join_date DATE COMMENT '入职日期',
-    leave_date DATE COMMENT '离职日期',
-    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-    UNIQUE KEY uk_user_department (user_id, department_id),
-    INDEX idx_department_id (department_id),
-    CONSTRAINT fk_user_dept_user FOREIGN KEY (user_id) REFERENCES users(id),
-    CONSTRAINT fk_user_dept_department FOREIGN KEY (department_id) REFERENCES department(id)
-) COMMENT = '用户部门关联表';
-
--- 数据范围配置表
-CREATE TABLE data_scope (
-    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
-    name VARCHAR(100) NOT NULL COMMENT '范围名称',
-    type ENUM('PERSONAL', 'DEPARTMENT', 'COMPANY', 'CUSTOM') NOT NULL COMMENT '范围类型',
-    description TEXT COMMENT '范围描述',
-    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
-) COMMENT = '数据范围配置表';
-```
-
-#### 1.2 用户实体扩展
-
-```typescript
-// 更新用户实体
-@Entity({ name: 'users' })
-export class UserEntity {
-  // ... 现有字段
-  
-  @ManyToMany(() => Department)
-  @JoinTable({ name: 'user_department' })
-  departments!: Department[];
-  
-  @Column({ name: 'default_department_id', type: 'int', nullable: true })
-  defaultDepartmentId?: number;
-  
-  @Column({ name: 'data_scope_type', type: 'enum', enum: DataScopeType, default: DataScopeType.PERSONAL })
-  dataScopeType!: DataScopeType;
-}
-
-// 新增部门实体
-@Entity({ name: 'department' })
-export class Department {
-  @PrimaryGeneratedColumn({ unsigned: true })
-  id!: number;
-  
-  @Column({ type: 'varchar', length: 100 })
-  name!: string;
-  
-  @Column({ type: 'varchar', length: 50, unique: true })
-  code!: string;
-  
-  @ManyToOne(() => Department, dept => dept.children)
-  @JoinColumn({ name: 'parent_id' })
-  parent?: Department;
-  
-  @OneToMany(() => Department, dept => dept.parent)
-  children!: Department[];
-  
-  @ManyToOne(() => UserEntity)
-  @JoinColumn({ name: 'manager_id' })
-  manager?: UserEntity;
-}
-```
-
-### 阶段二:权限体系升级
-
-#### 2.1 权限模型重构
-
-```typescript
-// 权限类型定义
-export enum PermissionType {
-  MODULE = 'module',      // 模块权限
-  OPERATION = 'operation', // 操作权限
-  DATA = 'data'          // 数据权限
-}
-
-export enum DataScopeType {
-  PERSONAL = 'personal',      // 仅个人数据
-  DEPARTMENT = 'department',  // 部门数据
-  SUB_DEPARTMENT = 'sub_department', // 部门及下级数据
-  COMPANY = 'company',        // 全公司数据
-  CUSTOM = 'custom'          // 自定义范围
-}
-
-// 新权限实体
-@Entity({ name: 'permission' })
-export class Permission {
-  @PrimaryGeneratedColumn()
-  id!: number;
-  
-  @Column({ type: 'varchar', length: 100 })
-  code!: string; // 如: client:create, client:view:all
-  
-  @Column({ type: 'varchar', length: 100 })
-  name!: string;
-  
-  @Column({ type: 'enum', enum: PermissionType })
-  type!: PermissionType;
-  
-  @Column({ type: 'json', nullable: true })
-  config?: any; // 权限配置
-}
-
-// 角色权限关联
-@Entity({ name: 'role_permission' })
-export class RolePermission {
-  @PrimaryGeneratedColumn()
-  id!: number;
-  
-  @ManyToOne(() => Role)
-  role!: Role;
-  
-  @ManyToOne(() => Permission)
-  permission!: Permission;
-  
-  @Column({ type: 'json', nullable: true })
-  dataScope?: any; // 数据范围配置
-}
-```
-
-#### 2.2 细粒度权限控制
-
-```typescript
-// 权限配置示例
-const PERMISSIONS = {
-  // 客户管理权限
-  CLIENT: {
-    CREATE: 'client:create',
-    UPDATE: 'client:update',
-    DELETE: 'client:delete',
-    VIEW: {
-      OWN: 'client:view:own',
-      DEPARTMENT: 'client:view:department',
-      ALL: 'client:view:all'
-    }
-  },
-  // 合同管理权限
-  CONTRACT: {
-    CREATE: 'contract:create',
-    UPDATE: 'contract:update',
-    DELETE: 'contract:delete',
-    VIEW: {
-      OWN: 'contract:view:own',
-      DEPARTMENT: 'contract:view:department',
-      ALL: 'contract:view:all'
-    }
-  }
-};
-```
-
-### 阶段三:数据权限实现
-
-#### 3.1 数据权限过滤器
-
-```typescript
-// 数据权限服务
-export class DataPermissionService {
-  constructor(private dataSource: DataSource) {}
-  
-  async applyDataScope(
-    queryBuilder: SelectQueryBuilder<any>,
-    entity: string,
-    user: UserEntity,
-    action: string
-  ): Promise<SelectQueryBuilder<any>> {
-    const dataScope = await this.getUserDataScope(user, entity, action);
-    
-    switch (dataScope.type) {
-      case DataScopeType.PERSONAL:
-        queryBuilder.andWhere(`${entity}.responsible_user_id = :userId`, { userId: user.id });
-        break;
-        
-      case DataScopeType.DEPARTMENT:
-        const departmentIds = await this.getDepartmentIds(user);
-        queryBuilder.andWhere(`${entity}.department_id IN (:...departmentIds)`, { departmentIds });
-        break;
-        
-      case DataScopeType.SUB_DEPARTMENT:
-        const allDepartmentIds = await this.getSubDepartmentIds(user);
-        queryBuilder.andWhere(`${entity}.department_id IN (:...allDepartmentIds)`, { allDepartmentIds });
-        break;
-    }
-    
-    return queryBuilder;
-  }
-}
-```
-
-#### 3.2 通用CRUD集成
-
-```typescript
-// 更新GenericCrudService以支持数据权限
-export class GenericCrudService<T> {
-  async getList(
-    page: number = 1,
-    pageSize: number = 10,
-    keyword?: string,
-    searchFields?: string[],
-    where?: Partial<T>,
-    relations: string[] = [],
-    order: any = {},
-    filters?: any,
-    user?: UserEntity
-  ): Promise<[T[], number]> {
-    const queryBuilder = this.createQueryBuilder();
-    
-    // 应用数据权限
-    if (user) {
-      await this.dataPermissionService.applyDataScope(
-        queryBuilder,
-        this.entity.name,
-        user,
-        'view'
-      );
-    }
-    
-    // ... 其他查询逻辑
-  }
-}
-```
-
-### 阶段四:前端权限控制
-
-#### 4.1 权限配置组件
-
-```typescript
-// 权限配置组件
-interface PermissionConfigProps {
-  roleId: number;
-  onChange: (permissions: Permission[]) => void;
-}
-
-const PermissionConfig: React.FC<PermissionConfigProps> = ({ roleId, onChange }) => {
-  const { data: permissions } = useQuery(['permissions'], fetchPermissions);
-  const { data: rolePermissions } = useQuery(['role-permissions', roleId], () => 
-    fetchRolePermissions(roleId)
-  );
-  
-  return (
-    <div>
-      <Card title="模块权限">
-        <Checkbox.Group
-          options={permissions?.filter(p => p.type === 'module')}
-          value={rolePermissions?.map(p => p.id)}
-          onChange={onChange}
-        />
-      </Card>
-      
-      <Card title="数据权限">
-        <Radio.Group>
-          <Radio value="personal">个人数据</Radio>
-          <Radio value="department">部门数据</Radio>
-          <Radio value="sub_department">部门及下级</Radio>
-          <Radio value="company">全公司数据</Radio>
-        </Radio.Group>
-      </Card>
-    </div>
-  );
-};
-```
-
-#### 4.2 动态菜单权限
-
-```typescript
-// 更新菜单配置
-const menuItems = [
-  {
-    key: 'clients',
-    label: '客户管理',
-    path: '/admin/clients',
-    permissions: ['client:view'],
-    dataScope: 'own' // 根据用户权限动态显示
-  }
-];
-```
-
-### 实施计划
-
-| 阶段 | 任务 | 预计工时 | 优先级 |
-|------|------|----------|--------|
-| 1 | 数据库结构升级 | 2天 | 高 |
-| 2 | 部门管理功能 | 3天 | 高 |
-| 3 | 权限模型重构 | 3天 | 中 |
-| 4 | 数据权限集成 | 4天 | 高 |
-| 5 | 前端权限控制 | 2天 | 中 |
-| 6 | 测试和优化 | 2天 | 低 |
-
-### 迁移方案
-
-#### 数据迁移
-1. **用户数据**: 保持现有用户表不变,增量升级
-2. **权限数据**: 将现有权限字符串映射到新权限体系
-3. **角色数据**: 保留现有角色,增加数据范围配置
-
-#### 代码迁移
-1. **向后兼容**: 现有权限检查逻辑保持兼容
-2. **渐进升级**: 分模块逐步切换到新权限体系
-3. **回滚方案**: 保留原始数据结构备份
-
-### 测试验证
-
-#### 测试用例
-1. **部门管理测试**:
-   - 部门CRUD操作
-   - 部门层级关系
-   - 部门负责人指定
-
-2. **权限测试**:
-   - 不同角色的权限验证
-   - 数据范围权限验证
-   - 权限继承验证
-
-3. **业务测试**:
-   - 客户数据隔离验证
-   - 跨部门数据共享
-   - 数据权限转移
-
-### 预期效果
-
-#### 功能增强
-- ✅ 完整的组织架构管理
-- ✅ 精细化权限控制
-- ✅ 灵活的数据范围管理
-- ✅ 支持多级部门权限继承
-- ✅ 用户批量权限管理
-
-#### 业务价值
-- 提高数据安全性
-- 支持复杂组织架构
-- 减少权限管理成本
-- 增强系统扩展性

+ 0 - 237
docs/crm-permission-init.md

@@ -1,237 +0,0 @@
-# CRM系统权限体系初始化SQL脚本
-
-## 概述
-基于CRM权限体系改进方案的完整SQL初始化脚本,包含所有权限、角色、角色权限关联及默认管理员用户配置。
-
-## 数据库结构
-- `permission` - 权限表
-- `role` - 角色表
-- `role_permission` - 角色权限关联表
-- `users` - 用户表
-- `user_roles` - 用户角色关联表
-
-## 完整初始化脚本
-
-### 1. 清除旧数据(谨慎使用)
-```sql
--- 清除旧权限数据(生产环境慎用)
-SET FOREIGN_KEY_CHECKS = 0;
-TRUNCATE TABLE role_permission;
-TRUNCATE TABLE permission;
-TRUNCATE TABLE role;
-SET FOREIGN_KEY_CHECKS = 1;
-```
-
-### 2. 插入基础权限数据
-```sql
--- 系统管理权限
-INSERT INTO permission (code, name, type, module, action, description, sort_order, is_active, parent_id) VALUES
-('system:user:create', '创建用户', 'operation', 'system', 'user:create', '允许创建新用户', 110, 1, NULL),
-('system:user:update', '编辑用户', 'operation', 'system', 'user:update', '允许编辑用户信息', 120, 1, NULL),
-('system:user:delete', '删除用户', 'operation', 'system', 'user:delete', '允许删除用户', 130, 1, NULL),
-('system:user:view:own', '查看个人用户', 'data', 'system', 'user:view', '仅查看自己创建的用户', 141, 1, NULL),
-('system:user:view:department', '查看部门用户', 'data', 'system', 'user:view', '查看所在部门用户', 142, 1, NULL),
-('system:user:view:sub_department', '查看部门及下级用户', 'data', 'system', 'user:view', '查看所在部门及下级部门用户', 143, 1, NULL),
-('system:user:view:all', '查看所有用户', 'data', 'system', 'user:view', '查看系统所有用户', 144, 1, NULL),
-
-('system:role:create', '创建角色', 'operation', 'system', 'role:create', '允许创建新角色', 210, 1, NULL),
-('system:role:update', '编辑角色', 'operation', 'system', 'role:update', '允许编辑角色信息', 220, 1, NULL),
-('system:role:delete', '删除角色', 'operation', 'system', 'role:delete', '允许删除角色', 230, 1, NULL),
-('system:role:view', '查看角色', 'operation', 'system', 'role:view', '允许查看角色列表', 240, 1, NULL),
-
-('system:department:create', '创建部门', 'operation', 'system', 'department:create', '允许创建新部门', 310, 1, NULL),
-('system:department:update', '编辑部门', 'operation', 'system', 'department:update', '允许编辑部门信息', 320, 1, NULL),
-('system:department:delete', '删除部门', 'operation', 'system', 'department:delete', '允许删除部门', 330, 1, NULL),
-('system:department:view', '查看部门', 'operation', 'system', 'department:view', '允许查看部门列表', 340, 1, NULL),
-
--- 客户管理权限
-('client:create', '创建客户', 'operation', 'client', 'create', '允许创建新客户', 410, 1, NULL),
-('client:update', '编辑客户', 'operation', 'client', 'update', '允许编辑客户信息', 420, 1, NULL),
-('client:delete', '删除客户', 'operation', 'client', 'delete', '允许删除客户', 430, 1, NULL),
-('client:view:own', '查看个人客户', 'data', 'client', 'view', '仅查看自己创建的客户', 441, 1, NULL),
-('client:view:department', '查看部门客户', 'data', 'client', 'view', '查看所在部门客户', 442, 1, NULL),
-('client:view:sub_department', '查看部门及下级客户', 'data', 'client', 'view', '查看所在部门及下级部门客户', 443, 1, NULL),
-('client:view:all', '查看所有客户', 'data', 'client', 'view', '查看系统所有客户', 444, 1, NULL),
-('client:assign', '分配客户', 'operation', 'client', 'assign', '允许将客户分配给其他用户', 450, 1, NULL),
-('client:transfer', '转移客户', 'operation', 'client', 'transfer', '允许将客户转移到其他部门', 460, 1, NULL),
-
--- 合同管理权限
-('contract:create', '创建合同', 'operation', 'contract', 'create', '允许创建新合同', 510, 1, NULL),
-('contract:update', '编辑合同', 'operation', 'contract', 'update', '允许编辑合同信息', 520, 1, NULL),
-('contract:delete', '删除合同', 'operation', 'contract', 'delete', '允许删除合同', 530, 1, NULL),
-('contract:view:own', '查看个人合同', 'data', 'contract', 'view', '仅查看自己创建的合同', 541, 1, NULL),
-('contract:view:department', '查看部门合同', 'data', 'contract', 'view', '查看所在部门合同', 542, 1, NULL),
-('contract:view:sub_department', '查看部门及下级合同', 'data', 'contract', 'view', '查看所在部门及下级部门合同', 543, 1, NULL),
-('contract:view:all', '查看所有合同', 'data', 'contract', 'view', '查看系统所有合同', 544, 1, NULL),
-('contract:approve', '审批合同', 'operation', 'contract', 'approve', '允许审批合同', 550, 1, NULL),
-('contract:renew', '续签合同', 'operation', 'contract', 'renew', '允许续签合同', 560, 1, NULL),
-
--- 跟进记录权限
-('follow_up:create', '创建跟进', 'operation', 'follow_up', 'create', '允许创建跟进记录', 610, 1, NULL),
-('follow_up:update', '编辑跟进', 'operation', 'follow_up', 'update', '允许编辑跟进记录', 620, 1, NULL),
-('follow_up:delete', '删除跟进', 'operation', 'follow_up', 'delete', '允许删除跟进记录', 630, 1, NULL),
-('follow_up:view:own', '查看个人跟进', 'data', 'follow_up', 'view', '仅查看自己创建的跟进记录', 641, 1, NULL),
-('follow_up:view:department', '查看部门跟进', 'data', 'follow_up', 'view', '查看所在部门跟进记录', 642, 1, NULL),
-('follow_up:view:sub_department', '查看部门及下级跟进', 'data', 'follow_up', 'view', '查看所在部门及下级部门跟进记录', 643, 1, NULL),
-('follow_up:view:all', '查看所有跟进', 'data', 'follow_up', 'view', '查看系统所有跟进记录', 644, 1, NULL),
-
--- 订单管理权限
-('order:create', '创建订单', 'operation', 'order', 'create', '允许创建新订单', 710, 1, NULL),
-('order:update', '编辑订单', 'operation', 'order', 'update', '允许编辑订单信息', 720, 1, NULL),
-('order:delete', '删除订单', 'operation', 'order', 'delete', '允许删除订单', 730, 1, NULL),
-('order:view:own', '查看个人订单', 'data', 'order', 'view', '仅查看自己创建的订单', 741, 1, NULL),
-('order:view:department', '查看部门订单', 'data', 'order', 'view', '查看所在部门订单', 742, 1, NULL),
-('order:view:sub_department', '查看部门及下级订单', 'data', 'order', 'view', '查看所在部门及下级部门订单', 743, 1, NULL),
-('order:view:all', '查看所有订单', 'data', 'order', 'view', '查看系统所有订单', 744, 1, NULL),
-
--- 费用管理权限
-('expense:create', '创建费用', 'operation', 'expense', 'create', '允许创建新费用记录', 810, 1, NULL),
-('expense:update', '编辑费用', 'operation', 'expense', 'update', '允许编辑费用记录', 820, 1, NULL),
-('expense:delete', '删除费用', 'operation', 'expense', 'delete', '允许删除费用记录', 830, 1, NULL),
-('expense:view:own', '查看个人费用', 'data', 'expense', 'view', '仅查看自己创建的费用记录', 841, 1, NULL),
-('expense:view:department', '查看部门费用', 'data', 'expense', 'view', '查看所在部门费用记录', 842, 1, NULL),
-('expense:view:sub_department', '查看部门及下级费用', 'data', 'expense', 'view', '查看所在部门及下级部门费用记录', 843, 1, NULL),
-('expense:view:all', '查看所有费用', 'data', 'expense', 'view', '查看系统所有费用记录', 844, 1, NULL),
-
--- 文件管理权限
-('file:upload', '上传文件', 'operation', 'file', 'upload', '允许上传文件', 910, 1, NULL),
-('file:delete', '删除文件', 'operation', 'file', 'delete', '允许删除文件', 930, 1, NULL),
-('file:view:own', '查看个人文件', 'data', 'file', 'view', '仅查看自己上传的文件', 941, 1, NULL),
-('file:view:department', '查看部门文件', 'data', 'file', 'view', '查看所在部门文件', 942, 1, NULL),
-('file:view:sub_department', '查看部门及下级文件', 'data', 'file', 'view', '查看所在部门及下级部门文件', 943, 1, NULL),
-('file:view:all', '查看所有文件', 'data', 'file', 'view', '查看系统所有文件', 944, 1, NULL);
-```
-
-### 3. 创建系统默认角色
-```sql
--- 超级管理员角色
-INSERT INTO role (name, description, permissions, created_at, updated_at) VALUES
-('super_admin', '超级管理员,拥有系统所有权限', '["system:user:create","system:user:update","system:user:delete","system:user:view:all","system:role:create","system:role:update","system:role:delete","system:role:view","system:department:create","system:department:update","system:department:delete","system:department:view","client:create","client:update","client:delete","client:view:all","client:assign","client:transfer","contract:create","contract:update","contract:delete","contract:view:all","contract:approve","contract:renew","follow_up:create","follow_up:update","follow_up:delete","follow_up:view:all","order:create","order:update","order:delete","order:view:all","expense:create","expense:update","expense:delete","expense:view:all","file:upload","file:delete","file:view:all"]', NOW(), NOW()),
-
--- 系统管理员角色
-('admin', '系统管理员,管理用户、角色、部门等', '["system:user:create","system:user:update","system:user:delete","system:user:view:all","system:role:create","system:role:update","system:role:delete","system:role:view","system:department:create","system:department:update","system:department:delete","system:department:view"]', NOW(), NOW()),
-
--- 部门经理角色
-('department_manager', '部门经理,管理部门内所有数据', '["system:user:create","system:user:update","system:user:view:department","system:department:view","client:create","client:update","client:delete","client:view:department","client:assign","contract:create","contract:update","contract:delete","contract:view:department","contract:approve","follow_up:create","follow_up:update","follow_up:delete","follow_up:view:department","order:create","order:update","order:delete","order:view:department","expense:create","expense:update","expense:delete","expense:view:department","file:upload","file:delete","file:view:department"]', NOW(), NOW()),
-
--- 销售经理角色
-('sales_manager', '销售经理,管理客户和销售数据', '["client:create","client:update","client:delete","client:view:sub_department","client:assign","contract:create","contract:update","contract:delete","contract:view:sub_department","contract:approve","follow_up:create","follow_up:update","follow_up:delete","follow_up:view:sub_department","order:create","order:update","order:delete","order:view:sub_department","expense:create","expense:update","expense:delete","expense:view:sub_department","file:upload","file:view:sub_department"]', NOW(), NOW()),
-
--- 销售人员角色
-('sales_person', '销售人员,管理个人客户和数据', '["client:create","client:update","client:view:own","contract:create","contract:update","contract:view:own","follow_up:create","follow_up:update","follow_up:view:own","order:create","order:update","order:view:own","expense:create","expense:update","expense:view:own","file:upload","file:view:own"]', NOW(), NOW()),
-
--- 财务角色
-('accountant', '财务人员,管理费用和财务数据', '["contract:view:all","order:view:all","expense:create","expense:update","expense:delete","expense:view:all","file:upload","file:view:all"]', NOW(), NOW()),
-
--- 合同管理员角色
-('contract_admin', '合同管理员,管理合同和续签', '["contract:create","contract:update","contract:delete","contract:view:all","contract:approve","contract:renew","file:upload","file:view:all"]', NOW(), NOW()),
-
--- 访客角色(只读权限)
-('guest', '访客,只读权限', '["system:user:view:own","client:view:own","contract:view:own","follow_up:view:own","order:view:own","expense:view:own","file:view:own"]', NOW(), NOW());
-```
-
-### 4. 创建部门数据(示例)
-```sql
--- 创建根部门(公司)
-INSERT INTO department (name, parent_id, manager_id, sort_order, is_active, created_at, updated_at) VALUES
-('总公司', NULL, NULL, 1, 1, NOW(), NOW());
-
--- 创建销售部
-INSERT INTO department (name, parent_id, manager_id, sort_order, is_active, created_at, updated_at) VALUES
-('销售部', 1, NULL, 10, 1, NOW(), NOW());
-
--- 创建财务部
-INSERT INTO department (name, parent_id, manager_id, sort_order, is_active, created_at, updated_at) VALUES
-('财务部', 1, NULL, 20, 1, NOW(), NOW());
-
--- 创建技术部
-INSERT INTO department (name, parent_id, manager_id, sort_order, is_active, created_at, updated_at) VALUES
-('技术部', 1, NULL, 30, 1, NOW(), NOW());
-```
-
-### 5. 创建超级管理员用户
-```sql
--- 创建超级管理员用户(密码:admin123)
-INSERT INTO users (username, password, name, nickname, email, phone, is_disabled, is_deleted, default_department_id, data_scope_type, created_at, updated_at) VALUES
-('admin', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '系统管理员', '超管', 'admin@company.com', '13800138000', 0, 0, 1, 'company', NOW(), NOW());
-
--- 关联超级管理员角色
-INSERT INTO user_roles (user_id, role_id) VALUES
-(1, 1);
-```
-
-### 6. 创建测试用户
-```sql
--- 创建销售经理用户(密码:123456)
-INSERT INTO users (username, password, name, nickname, email, phone, is_disabled, is_deleted, default_department_id, data_scope_type, created_at, updated_at) VALUES
-('sales_manager', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '销售经理', '销售经理', 'sales@company.com', '13800138001', 0, 0, 2, 'sub_department', NOW(), NOW());
-
--- 创建销售人员用户(密码:123456)
-INSERT INTO users (username, password, name, nickname, email, phone, is_disabled, is_deleted, default_department_id, data_scope_type, created_at, updated_at) VALUES
-('sales_person', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '销售人员', '销售小李', 'sp@company.com', '13800138002', 0, 0, 2, 'personal', NOW(), NOW());
-
--- 创建财务用户(密码:123456)
-INSERT INTO users (username, password, name, nickname, email, phone, is_disabled, is_deleted, default_department_id, data_scope_type, created_at, updated_at) VALUES
-('accountant', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '财务人员', '会计小张', 'finance@company.com', '13800138003', 0, 0, 3, 'company', NOW(), NOW());
-
--- 关联角色
-INSERT INTO user_roles (user_id, role_id) VALUES
-(2, 4), -- 销售经理
-(3, 5), -- 销售人员
-(4, 6); -- 财务人员
-```
-
-## 验证查询
-
-### 检查权限数据
-```sql
--- 查看所有权限
-SELECT p.id, p.code, p.name, p.type, p.module, p.action, p.description
-FROM permission p
-ORDER BY p.sort_order;
-
--- 查看角色权限
-SELECT r.name as role_name, p.name as permission_name, p.code as permission_code
-FROM role r
-JOIN role_permission rp ON r.id = rp.role_id
-JOIN permission p ON p.id = rp.permission_id
-ORDER BY r.name, p.sort_order;
-
--- 查看用户角色
-SELECT u.username, u.name, r.name as role_name
-FROM users u
-JOIN user_roles ur ON u.id = ur.user_id
-JOIN role r ON r.id = ur.role_id;
-```
-
-## 使用说明
-
-### 1. 执行顺序
-1. 首先执行清除旧数据的脚本(仅首次部署时使用)
-2. 执行权限数据插入
-3. 执行角色数据插入
-4. 执行部门数据插入
-5. 执行用户数据插入
-6. 执行关联关系插入
-
-### 2. 密码说明
-- 所有测试用户密码统一为:`123456`
-- 超级管理员密码为:`admin123`
-- 密码使用bcrypt加密,实际部署时请修改安全密码
-
-### 3. 权限说明
-- **超级管理员(super_admin)**:拥有系统所有权限
-- **系统管理员(admin)**:管理用户、角色、部门等
-- **部门经理(department_manager)**:管理部门内所有数据
-- **销售经理(sales_manager)**:管理销售相关数据
-- **销售人员(sales_person)**:仅管理个人数据
-- **财务(accountant)**:管理财务相关数据
-- **合同管理员(contract_admin)**:管理合同相关数据
-- **访客(guest)**:只读权限
-
-### 4. 数据范围说明
-- `PERSONAL`:仅个人数据
-- `DEPARTMENT`:仅所在部门数据
-- `SUB_DEPARTMENT`:所在部门及下级部门数据
-- `COMPANY`:全公司数据
-- `CUSTOM`:自定义范围数据

+ 0 - 105
docs/crm-personal-data-scope-implementation.md

@@ -1,105 +0,0 @@
-# 当前系统支持"查看自己客户"的实现方案
-
-## 当前实现状态
-
-当前系统**已经支持**查看自己客户的功能,通过以下机制实现:
-
-### 1. 客户负责人关联
-在客户表 `client` 中:
-- `responsible_user_id` 字段直接关联到 `users.id`
-- 实现原理:每个客户记录都有明确的负责人
-
-### 2. 数据权限实现代码
-
-```typescript
-// 当前ClientService中的实现(已存在)
-export class ClientService extends GenericCrudService<Client> {
-  async findAll(filters: any, user?: UserEntity): Promise<[Client[], number]> {
-    const query = this.repository.createQueryBuilder('client');
-    
-    // 如果用户不是管理员,只显示自己的客户
-    if (user && !user.roles.some(r => r.name === 'admin')) {
-      query.andWhere('client.responsible_user_id = :userId', { userId: user.id });
-    }
-    
-    // 其他过滤条件...
-    return query.getManyAndCount();
-  }
-}
-```
-
-### 3. 前端实现
-
-```typescript
-// 当前客户列表页面中的权限控制
-const { user } = useAuth();
-const isAdmin = user?.roles?.some(r => r.name === 'admin');
-
-// 在查询参数中自动添加用户过滤
-const queryParams = {
-  ...filters,
-  ...(isAdmin ? {} : { responsible_user_id: user?.id })
-};
-```
-
-## 支持详情查看
-
-### 客户详情页权限
-```typescript
-// 客户详情权限检查
-const canViewClient = (client: Client, user: UserEntity) => {
-  return user.roles.some(r => r.name === 'admin') || 
-         client.responsible_user_id === user.id;
-};
-
-// 客户关联数据权限
-const canViewClientDetails = (clientId: number, user: UserEntity) => {
-  // 检查客户是否属于当前用户
-  const client = clientService.findById(clientId);
-  return canViewClient(client, user);
-};
-```
-
-### 实际使用示例
-
-#### 普通用户视角
-- **我的客户列表**: 仅显示 `responsible_user_id = 当前用户ID` 的客户
-- **客户详情**: 只能查看自己负责的客户详情
-- **客户关联数据**: 
-  - 合同: 仅显示该客户的合同
-  - 联系人: 仅显示该客户的联系人
-  - 费用: 仅显示该客户相关的费用
-
-#### 管理员视角
-- **全部客户**: 可以查看系统中所有客户
-- **客户转移**: 可以重新分配客户负责人
-
-## 无需改进的确认
-
-### 已满足需求
-✅ **查看自己的客户**: 通过 `responsible_user_id` 实现  
-✅ **查看客户详情**: 权限检查确保只能看自己的客户  
-✅ **查看关联数据**: 所有关联表都通过客户ID进行权限控制  
-✅ **数据隔离**: 不同用户的客户数据完全隔离  
-
-### 当前使用示例
-```sql
--- 普通用户查询自己的客户
-SELECT * FROM client 
-WHERE responsible_user_id = 当前用户ID 
-AND is_deleted = 0;
-
--- 管理员查看所有客户
-SELECT * FROM client 
-WHERE is_deleted = 0;
-```
-
-## 总结
-
-**当前系统已完全支持"查看自己客户"的功能**,通过以下机制实现:
-1. 客户表的 `responsible_user_id` 字段建立用户-客户关联
-2. 服务端查询时自动添加用户过滤条件
-3. 前端权限检查确保用户只能访问自己的客户数据
-4. 所有客户关联数据都继承客户的主权限控制
-
-该功能已在现有代码中实现并正常运行,无需额外开发。

+ 0 - 166
docs/permission-config-component-design.md

@@ -1,166 +0,0 @@
-# 权限配置组件设计方案
-
-## 组件目标
-
-将当前Roles页面中的权限配置功能抽取为可复用的独立组件,包含完整的UI展示和API调用逻辑。
-
-## 组件设计
-
-### 1. 组件名称
-`PermissionConfigModal`
-
-### 2. 组件位置
-`src/client/admin/components/PermissionConfigModal.tsx`
-
-### 3. 组件功能
-- 权限树形结构展示
-- 权限选择/取消选择
-- 批量保存权限配置
-- 加载状态管理
-
-### 4. Props接口定义
-
-```typescript
-interface PermissionConfigModalProps {
-  visible: boolean;
-  roleId: number | null;
-  roleName?: string;
-  onClose: () => void;
-  onSuccess?: () => void;
-}
-```
-
-### 5. 内部状态管理
-- `selectedPermissionIds: number[]` - 选中的权限ID列表
-- `permissions: PermissionItem[]` - 所有权限列表
-- `rolePermissions: number[]` - 当前角色已拥有的权限ID列表
-- `loading: boolean` - 加载状态
-- `saving: boolean` - 保存状态
-
-### 6. API调用封装
-使用独立的React Query hooks:
-
-```typescript
-// 获取所有权限
-const usePermissions = () => {
-  return useQuery({
-    queryKey: ['permissions'],
-    queryFn: async () => {
-      const response = await permissionClient.$get({ query: {} });
-      return response.json();
-    },
-  });
-};
-
-// 获取角色权限
-const useRolePermissions = (roleId: number | null) => {
-  return useQuery({
-    queryKey: ['role-permissions', roleId],
-    queryFn: async () => {
-      if (!roleId) return [];
-      const response = await rolePermissionClient.$get({
-        query: { filters: JSON.stringify({ roleId }) }
-      });
-      const data = await response.json();
-      return data.data.map((item: any) => item.permissionId);
-    },
-    enabled: !!roleId,
-  });
-};
-
-// 更新角色权限
-const useUpdateRolePermissions = () => {
-  return useMutation({
-    mutationFn: async ({ roleId, permissionIds }: { roleId: number; permissionIds: number[] }) => {
-      const permissions = permissionIds.map(permissionId => ({
-        permissionId,
-        dataScopeType: 'COMPANY' as const,
-        customDepartments: [] as number[]
-      }));
-
-      const response = await rolePermissionClient.batch.$post({
-        json: { roleId, permissions }
-      });
-      return response.json();
-    },
-  });
-};
-```
-
-### 7. 权限树数据结构
-
-权限按模块分组展示:
-
-```typescript
-const permissionTreeData = [
-  {
-    title: '用户管理',
-    key: '用户管理',
-    checkable: false,
-    children: [
-      {
-        title: '查看用户列表 (user:list)',
-        key: '1',
-      },
-      {
-        title: '创建用户 (user:create)',
-        key: '2',
-      }
-    ]
-  }
-];
-```
-
-### 8. 使用示例
-
-```typescript
-// 在Roles页面中使用
-const [configVisible, setConfigVisible] = useState(false);
-const [currentRole, setCurrentRole] = useState<RoleItem | null>(null);
-
-const handlePermissionConfig = (role: RoleItem) => {
-  setCurrentRole(role);
-  setConfigVisible(true);
-};
-
-return (
-  <>
-    <Button onClick={() => handlePermissionConfig(record)}>
-      配置权限
-    </Button>
-    
-    <PermissionConfigModal
-      visible={configVisible}
-      roleId={currentRole?.id || null}
-      roleName={currentRole?.name}
-      onClose={() => setConfigVisible(false)}
-      onSuccess={() => {
-        message.success('权限配置成功');
-        // 刷新角色列表
-        queryClient.invalidateQueries({ queryKey: ['roles'] });
-      }}
-    />
-  </>
-);
-```
-
-## 实现步骤
-
-1. **创建组件文件** - 新建 `PermissionConfigModal.tsx`
-2. **提取API调用** - 将相关的React Query hooks封装到组件内部
-3. **实现权限树** - 使用Ant Design的Tree组件
-4. **状态管理** - 管理选中状态
-5. **集成到Roles页面** - 替换原有的权限配置功能
-6. **测试可复用性** - 验证组件可在其他页面使用
-
-## 技术要点
-
-1. **封装完整** - 包含所有必要的API调用和状态管理
-2. **类型安全** - 使用TypeScript确保类型正确
-3. **可配置** - 通过props支持不同场景的使用
-4. **加载状态** - 完善的加载和错误处理
-5. **可复用** - 可在任何需要配置权限的地方使用
-
-## 预期效果
-
-将原来的200+行权限配置相关代码压缩为一个简洁的组件调用,提高代码复用性和可维护性。

+ 0 - 357
docs/permission-config-component-with-lazy-loading.md

@@ -1,357 +0,0 @@
-# 支持懒加载的权限配置组件设计
-
-## 需求分析
-
-在原有权限配置组件基础上增加懒加载支持,解决大数据量权限树的性能问题。
-
-## 懒加载实现方案
-
-### 1. 权限树结构优化
-
-#### 新的数据结构
-```typescript
-interface PermissionTreeData {
-  title: string;
-  key: string;
-  isLeaf?: boolean;
-  children?: PermissionTreeData[];
-  id?: number;
-  parentId?: number;
-}
-
-// 模块-功能-具体权限的三级结构
-```
-
-### 2. API接口扩展
-
-#### 支持父级查询的权限接口
-```typescript
-// 新增查询参数支持
-const permissionsQuery = z.object({
-  parentId: z.coerce.number().optional().openapi({
-    description: '父权限ID,不传则获取顶级权限',
-    example: 1
-  }),
-  module: z.string().optional().openapi({
-    description: '模块名称,用于模块级过滤',
-    example: 'user'
-  })
-});
-```
-
-### 3. 懒加载权限配置组件
-
-#### PermissionConfigModalWithLazyLoading.tsx
-```typescript
-import React, { useState, useCallback } from 'react';
-import { Modal, Tree, Spin, message } from 'antd';
-import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
-import { permissionClient, rolePermissionClient } from '@/client/api';
-import type { InferResponseType } from 'hono/client';
-
-type PermissionListResponse = InferResponseType<typeof permissionClient.$get, 200>;
-type PermissionItem = PermissionListResponse['data'][0];
-
-interface PermissionConfigModalWithLazyLoadingProps {
-  visible: boolean;
-  roleId: number | null;
-  roleName?: string;
-  onClose: () => void;
-  onSuccess?: () => void;
-}
-
-interface TreeNode {
-  title: string;
-  key: string;
-  id?: number;
-  children?: TreeNode[];
-  isLeaf?: boolean;
-  selectable?: boolean;
-}
-
-const PermissionConfigModalWithLazyLoading: React.FC<PermissionConfigModalWithLazyLoadingProps> = ({
-  visible,
-  roleId,
-  roleName,
-  onClose,
-  onSuccess,
-}) => {
-  const queryClient = useQueryClient();
-  const [selectedPermissionIds, setSelectedPermissionIds] = useState<number[]>([]);
-  const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
-  const [treeData, setTreeData] = useState<TreeNode[]>([]);
-  const [autoExpandParent, setAutoExpandParent] = useState(true);
-
-  // 获取模块列表
-  const { data: modules = [], isLoading: modulesLoading } = useQuery({
-    queryKey: ['permission-modules'],
-    queryFn: async () => {
-      const response = await permissionClient.$get({ 
-        query: { page: 1, pageSize: 1000 } 
-      });
-      if (!response.ok) throw new Error('获取权限模块失败');
-      const data = await response.json();
-      
-      // 按模块分组
-      const moduleMap = new Map<string, PermissionItem[]>();
-      data.data.forEach(permission => {
-        const moduleName = permission.module || '其他';
-        if (!moduleMap.has(moduleName)) {
-          moduleMap.set(moduleName, []);
-        }
-        moduleMap.get(moduleName)!.push(permission);
-      });
-      
-      return Array.from(moduleMap.keys());
-    },
-    enabled: visible,
-  });
-
-  // 获取角色权限
-  const { data: rolePermissions = [], isLoading: rolePermissionsLoading } = useQuery({
-    queryKey: ['role-permissions', roleId],
-    queryFn: async () => {
-      if (!roleId) return [];
-      const response = await rolePermissionClient.$get({
-        query: { filters: JSON.stringify({ roleId }) }
-      });
-      if (!response.ok) throw new Error('获取角色权限失败');
-      const data = await response.json();
-      return data.data.map((item: any) => item.permissionId);
-    },
-    enabled: visible && !!roleId,
-  });
-
-  // 懒加载权限数据
-  const loadPermissions = useCallback(async (module?: string, parentId?: number) => {
-    const query: any = {};
-    if (module) query.filters = JSON.stringify({ module });
-    if (parentId) query.filters = JSON.stringify({ parentId });
-    
-    const response = await permissionClient.$get({ query });
-    if (!response.ok) throw new Error('获取权限数据失败');
-    return response.json();
-  }, []);
-
-  // 更新角色权限
-  const updateRolePermissionsMutation = useMutation({
-    mutationFn: async ({ roleId, permissionIds }: { roleId: number; permissionIds: number[] }) => {
-      const permissions = permissionIds.map(permissionId => ({
-        permissionId,
-        dataScopeType: 'COMPANY' as const,
-        customDepartments: [] as number[]
-      }));
-
-      const response = await rolePermissionClient.batch.$post({
-        json: { roleId, permissions }
-      });
-      if (!response.ok) throw new Error('更新角色权限失败');
-      return response.json();
-    },
-    onSuccess: () => {
-      message.success('角色权限更新成功');
-      onSuccess?.();
-    },
-    onError: (error: Error) => {
-      message.error(error.message);
-    },
-  });
-
-  // 构建模块树节点
-  useEffect(() => {
-    if (visible && modules.length > 0) {
-      const moduleNodes = modules.map(moduleName => ({
-        title: moduleName,
-        key: `module_${moduleName}`,
-        id: undefined,
-        isLeaf: false,
-        selectable: false,
-        children: [],
-      }));
-      setTreeData(moduleNodes);
-    }
-  }, [visible, modules]);
-
-  // 加载子节点
-  const onLoadData = async (treeNode: any) => {
-    const { key, title } = treeNode;
-    
-    if (key.startsWith('module_')) {
-      // 加载模块下的权限
-      const moduleName = key.replace('module_', '');
-      const response = await loadPermissions(moduleName);
-      const permissions = response.data;
-      
-      const permissionNodes = permissions.map((permission: PermissionItem) => ({
-        title: `${permission.name} (${permission.code})`,
-        key: `permission_${permission.id}`,
-        id: permission.id,
-        isLeaf: true,
-        selectable: true,
-      }));
-
-      treeNode.children = permissionNodes;
-      setTreeData(prevData => [...prevData]);
-    }
-  };
-
-  // 处理节点选择
-  const onCheck = (checkedKeysValue: any, info: any) => {
-    const checked = checkedKeysValue.checked || checkedKeysValue;
-    const permissionKeys = checked.filter((key: string) => key.startsWith('permission_'));
-    setSelectedPermissionIds(permissionKeys.map((key: string) => 
-      parseInt(key.replace('permission_', ''))
-    ));
-  };
-
-  // 保存权限配置
-  const handleSavePermissions = () => {
-    if (!roleId) return;
-    
-    updateRolePermissionsMutation.mutate(
-      { roleId, permissionIds: selectedPermissionIds },
-      {
-        onSuccess: () => {
-          onClose();
-        }
-      }
-    );
-  };
-
-  // 处理展开/收起
-  const handleExpand = (keys: string[]) => {
-    setExpandedKeys(keys);
-    setAutoExpandParent(false);
-  };
-
-  // 初始化选中状态
-  useEffect(() => {
-    if (visible && rolePermissions.length > 0) {
-      setSelectedPermissionIds(rolePermissions);
-      
-      // 自动展开包含已选权限的模块
-      const expandedModuleKeys: string[] = [];
-      treeData.forEach(moduleNode => {
-        moduleNode.children?.forEach(permissionNode => {
-          if (rolePermissions.includes(permissionNode.id!)) {
-            expandedModuleKeys.push(moduleNode.key);
-          }
-        });
-      });
-      setExpandedKeys(expandedModuleKeys);
-    }
-  }, [visible, rolePermissions, treeData]);
-
-  return (
-    <Modal
-      title={`配置权限 - ${roleName}`}
-      open={visible}
-      onCancel={onClose}
-      onOk={handleSavePermissions}
-      okButtonProps={{ 
-        loading: updateRolePermissionsMutation.isPending,
-        disabled: !roleId
-      }}
-      width={800}
-      destroyOnClose
-    >
-      <Spin spinning={modulesLoading || rolePermissionsLoading}>
-        <Tree
-          checkable
-          treeData={treeData}
-          loadData={onLoadData}
-          checkedKeys={selectedPermissionIds.map(id => `permission_${id}`)}
-          onCheck={onCheck}
-          onExpand={handleExpand}
-          expandedKeys={expandedKeys}
-          autoExpandParent={autoExpandParent}
-          height={400}
-          titleRender={(node) => {
-            if (node.key.startsWith('module_')) {
-              return <strong style={{ color: '#1890ff' }}>{node.title}</strong>;
-            }
-            return <span>{node.title}</span>;
-          }}
-        />
-      </Spin>
-    </Modal>
-  );
-};
-
-export default PermissionConfigModalWithLazyLoading;
-```
-
-### 4. 后端API增强
-
-#### 支持分页和过滤的权限接口
-```typescript
-// 在 permission.entity.ts 中增强查询
-const permissionListQuery = z.object({
-  module: z.string().optional(),
-  parentId: z.coerce.number().optional(),
-  page: z.coerce.number().int().positive().default(1),
-  pageSize: z.coerce.number().int().positive().default(20),
-  keyword: z.string().optional(),
-  filters: z.string().optional()
-});
-```
-
-#### 权限树构建服务
-```typescript
-export class PermissionService extends GenericCrudService<Permission> {
-  async getPermissionTree(module?: string, parentId?: number) {
-    const queryBuilder = this.repository.createQueryBuilder('permission');
-    
-    if (module) {
-      queryBuilder.where('permission.module = :module', { module });
-    }
-    
-    if (parentId) {
-      queryBuilder.where('permission.parentId = :parentId', { parentId });
-    } else if (!module) {
-      // 获取顶级权限
-      queryBuilder.where('permission.parentId IS NULL');
-    }
-    
-    return queryBuilder.getMany();
-  }
-}
-```
-
-### 5. 使用示例
-
-```typescript
-// 在Roles页面中使用懒加载版本
-import PermissionConfigModalWithLazyLoading from '@/client/admin/components/PermissionConfigModalWithLazyLoading';
-
-// 使用方式
-<PermissionConfigModalWithLazyLoading
-  visible={configVisible}
-  roleId={currentRole?.id || null}
-  roleName={currentRole?.name}
-  onClose={() => setConfigVisible(false)}
-  onSuccess={() => {
-    message.success('权限配置成功');
-    queryClient.invalidateQueries({ queryKey: ['roles'] });
-  }}
-/>
-```
-
-## 性能优化
-
-1. **按需加载** - 只加载用户展开的模块权限
-2. **缓存优化** - 已加载的模块数据缓存,避免重复请求
-3. **分页处理** - 支持大量权限的分页加载
-4. **虚拟滚动** - 大量节点时启用虚拟滚动
-
-## 当前限制
-
-1. 需要后端支持 `parentId` 和 `module` 查询参数
-2. 权限数据需要按模块-功能层级组织
-3. 当前实现支持二级结构,可扩展到多级
-
-## 兼容性
-
-- 向后兼容原有权限配置功能
-- 支持渐进式升级
-- 可配置是否启用懒加载模式

+ 0 - 243
docs/permission-config-integration-guide.md

@@ -1,243 +0,0 @@
-# 权限配置组件集成指南
-
-## 组件结构说明
-
-权限配置组件将包含以下文件:
-
-1. `src/client/admin/components/PermissionConfigModal.tsx` - 权限配置弹窗组件
-2. `src/client/admin/hooks/usePermissionConfig.ts` - 权限配置相关React Query hooks
-3. 更新后的 `src/client/admin/pages/Roles.tsx` - 集成新组件的角色管理页面
-
-## 组件实现代码
-
-### 1. PermissionConfigModal.tsx 完整实现
-
-```typescript
-import React, { useEffect, useState } from 'react';
-import { Modal, Tree, Spin, message } from 'antd';
-import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
-import { permissionClient, rolePermissionClient } from '@/client/api';
-import type { InferResponseType } from 'hono/client';
-
-type PermissionListResponse = InferResponseType<typeof permissionClient.$get, 200>;
-type PermissionItem = PermissionListResponse['data'][0];
-
-interface PermissionConfigModalProps {
-  visible: boolean;
-  roleId: number | null;
-  roleName?: string;
-  onClose: () => void;
-  onSuccess?: () => void;
-}
-
-const PermissionConfigModal: React.FC<PermissionConfigModalProps> = ({
-  visible,
-  roleId,
-  roleName,
-  onClose,
-  onSuccess,
-}) => {
-  const queryClient = useQueryClient();
-  const [selectedPermissionIds, setSelectedPermissionIds] = useState<number[]>([]);
-
-  // 获取所有权限
-  const { data: permissions = [], isLoading: permissionsLoading } = useQuery({
-    queryKey: ['permissions'],
-    queryFn: async () => {
-      const response = await permissionClient.$get({ query: {} });
-      if (!response.ok) throw new Error('获取权限列表失败');
-      const data = await response.json();
-      return data.data;
-    },
-    enabled: visible,
-  });
-
-  // 获取角色权限
-  const { data: rolePermissions = [], isLoading: rolePermissionsLoading } = useQuery({
-    queryKey: ['role-permissions', roleId],
-    queryFn: async () => {
-      if (!roleId) return [];
-      const response = await rolePermissionClient.$get({
-        query: { filters: JSON.stringify({ roleId }) }
-      });
-      if (!response.ok) throw new Error('获取角色权限失败');
-      const data = await response.json();
-      return data.data.map((item: any) => item.permissionId);
-    },
-    enabled: visible && !!roleId,
-  });
-
-  // 更新角色权限
-  const updateRolePermissionsMutation = useMutation({
-    mutationFn: async ({ roleId, permissionIds }: { roleId: number; permissionIds: number[] }) => {
-      const permissions = permissionIds.map(permissionId => ({
-        permissionId,
-        dataScopeType: 'COMPANY' as const,
-        customDepartments: [] as number[]
-      }));
-
-      const response = await rolePermissionClient.batch.$post({
-        json: { roleId, permissions }
-      });
-      if (!response.ok) throw new Error('更新角色权限失败');
-      return response.json();
-    },
-    onSuccess: () => {
-      message.success('角色权限更新成功');
-      onSuccess?.();
-    },
-    onError: (error: Error) => {
-      message.error(error.message);
-    },
-  });
-
-  // 权限数据按模块分组
-  const permissionTreeData = React.useMemo(() => {
-    const grouped: Record<string, PermissionItem[]> = {};
-    permissions.forEach(permission => {
-      const module = permission.module || '其他';
-      if (!grouped[module]) {
-        grouped[module] = [];
-      }
-      grouped[module].push(permission);
-    });
-
-    return Object.entries(grouped).map(([module, items]) => ({
-      title: module,
-      key: module,
-      checkable: false,
-      children: items.map(item => ({
-        title: `${item.name} (${item.code})`,
-        key: item.id.toString(),
-      })),
-    }));
-  }, [permissions]);
-
-  // 更新选中状态
-  useEffect(() => {
-    if (visible && rolePermissions.length > 0) {
-      setSelectedPermissionIds(rolePermissions);
-    } else if (!visible) {
-      setSelectedPermissionIds([]);
-    }
-  }, [visible, rolePermissions]);
-
-  const handleSavePermissions = () => {
-    if (!roleId) return;
-    
-    updateRolePermissionsMutation.mutate(
-      { roleId, permissionIds: selectedPermissionIds },
-      {
-        onSuccess: () => {
-          onClose();
-        }
-      }
-    );
-  };
-
-  return (
-    <Modal
-      title={`配置权限 - ${roleName}`}
-      open={visible}
-      onCancel={onClose}
-      onOk={handleSavePermissions}
-      okButtonProps={{ 
-        loading: updateRolePermissionsMutation.isPending,
-        disabled: !roleId
-      }}
-      width={800}
-      destroyOnClose
-    >
-      <Spin spinning={permissionsLoading || rolePermissionsLoading}>
-        <Tree
-          checkable
-          treeData={permissionTreeData}
-          checkedKeys={selectedPermissionIds.map(String)}
-          onCheck={(checkedKeys) => {
-            const checked = checkedKeys as string[];
-            setSelectedPermissionIds(checked.map(Number));
-          }}
-          height={400}
-          titleRender={(node) => {
-            if (node.children) {
-              return <strong>{node.title}</strong>;
-            }
-            return <span>{node.title}</span>;
-          }}
-        />
-      </Spin>
-    </Modal>
-  );
-};
-
-export default PermissionConfigModal;
-```
-
-### 2. 集成到Roles页面的修改方案
-
-#### Roles.tsx 修改要点
-
-1. **删除原有权限相关状态和方法**:
-   - 删除 `permissionModalVisible`
-   - 删除 `selectedRole`
-   - 删除 `selectedPermissionIds`
-   - 删除 `usePermissions()` hook
-   - 删除 `useRolePermissions()` hook
-   - 删除 `useUpdateRolePermissions()` mutation
-   - 删除权限相关的所有方法
-
-2. **新增状态管理**:
-   ```typescript
-   const [configVisible, setConfigVisible] = useState(false);
-   const [currentRole, setCurrentRole] = useState<RoleItem | null>(null);
-   ```
-
-3. **修改权限配置触发方法**:
-   ```typescript
-   const handlePermissionConfig = (role: RoleItem) => {
-     setCurrentRole(role);
-     setConfigVisible(true);
-   };
-   ```
-
-4. **替换权限配置模态框**:
-   ```typescript
-   <PermissionConfigModal
-     visible={configVisible}
-     roleId={currentRole?.id || null}
-     roleName={currentRole?.name}
-     onClose={() => setConfigVisible(false)}
-     onSuccess={() => {
-       message.success('权限配置成功');
-       queryClient.invalidateQueries({ queryKey: ['roles'] });
-     }}
-   />
-   ```
-
-## 集成步骤
-
-### 步骤1:创建组件文件
-在 `src/client/admin/components/` 目录下创建 `PermissionConfigModal.tsx`
-
-### 步骤2:更新Roles页面
-1. 导入新组件:`import PermissionConfigModal from '@/client/admin/components/PermissionConfigModal';`
-2. 删除原有的权限相关代码
-3. 添加新的状态和方法
-4. 替换模态框组件
-
-### 步骤3:验证集成
-1. 测试权限查看功能
-2. 测试权限修改功能
-3. 测试权限保存功能
-4. 验证组件在不同场景下的可复用性
-
-## 预期效果
-
-原Roles.tsx文件将从528行减少到约380行,权限配置相关的200+行代码被封装到独立的组件中,提高了代码的可维护性和复用性。
-
-## 扩展建议
-
-该权限配置组件还可以用于:
-1. 用户权限配置页面
-2. 权限批量配置功能
-3. 权限管理后台的其他场景