crm-personal-data-scope-implementation.md 3.2 KB

当前系统支持"查看自己客户"的实现方案

当前实现状态

当前系统已经支持查看自己客户的功能,通过以下机制实现:

1. 客户负责人关联

在客户表 client 中:

  • responsible_user_id 字段直接关联到 users.id
  • 实现原理:每个客户记录都有明确的负责人

2. 数据权限实现代码

// 当前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. 前端实现

// 当前客户列表页面中的权限控制
const { user } = useAuth();
const isAdmin = user?.roles?.some(r => r.name === 'admin');

// 在查询参数中自动添加用户过滤
const queryParams = {
  ...filters,
  ...(isAdmin ? {} : { responsible_user_id: user?.id })
};

支持详情查看

客户详情页权限

// 客户详情权限检查
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进行权限控制
数据隔离: 不同用户的客户数据完全隔离

当前使用示例

-- 普通用户查询自己的客户
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. 所有客户关联数据都继承客户的主权限控制

该功能已在现有代码中实现并正常运行,无需额外开发。