|
|
@@ -0,0 +1,216 @@
|
|
|
+import { DataSource, Repository } from 'typeorm';
|
|
|
+import { Role } from './role.entity';
|
|
|
+import { logger } from '@/server/utils/logger';
|
|
|
+import { AppDataSource } from '@/server/data-source';
|
|
|
+
|
|
|
+export class RoleService {
|
|
|
+ private roleRepository: Repository<Role>;
|
|
|
+
|
|
|
+ constructor(dataSource: DataSource) {
|
|
|
+ this.roleRepository = dataSource.getRepository(Role);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取角色列表,支持分页和条件筛选
|
|
|
+ */
|
|
|
+ async findAll(
|
|
|
+ page: number = 1,
|
|
|
+ pageSize: number = 10,
|
|
|
+ name?: string,
|
|
|
+ status?: number
|
|
|
+ ) {
|
|
|
+ const query = this.roleRepository.createQueryBuilder('role');
|
|
|
+
|
|
|
+ // 条件筛选
|
|
|
+ if (name) {
|
|
|
+ query.andWhere('role.name LIKE :name', { name: `%${name}%` });
|
|
|
+ }
|
|
|
+ if (status !== undefined) {
|
|
|
+ query.andWhere('role.status = :status', { status });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排除已删除的角色
|
|
|
+ query.andWhere('role.isDeleted = 0');
|
|
|
+
|
|
|
+ // 分页处理
|
|
|
+ query.skip((page - 1) * pageSize);
|
|
|
+ query.take(pageSize);
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ query.orderBy('role.createdAt', 'DESC');
|
|
|
+
|
|
|
+ // 执行查询
|
|
|
+ const [items, total] = await query.getManyAndCount();
|
|
|
+
|
|
|
+ logger.api(`获取角色列表成功,共${total}条记录`);
|
|
|
+
|
|
|
+ return {
|
|
|
+ data: items,
|
|
|
+ pagination: {
|
|
|
+ total,
|
|
|
+ current: page,
|
|
|
+ pageSize,
|
|
|
+ totalPages: Math.ceil(total / pageSize)
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据ID获取角色详情
|
|
|
+ */
|
|
|
+ async findById(id: number) {
|
|
|
+ const role = await this.roleRepository.findOne({
|
|
|
+ where: { id, isDeleted: 0 },
|
|
|
+ relations: ['permissions']
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!role) {
|
|
|
+ logger.error(`角色不存在,ID: ${id}`);
|
|
|
+ throw new Error('角色不存在');
|
|
|
+ }
|
|
|
+
|
|
|
+ logger.api(`获取角色详情成功,ID: ${id}`);
|
|
|
+ return role;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建新角色
|
|
|
+ */
|
|
|
+ async create(roleData: Partial<Role>) {
|
|
|
+ // 检查角色名称是否已存在
|
|
|
+ const existingRole = await this.roleRepository.findOne({
|
|
|
+ where: { name: roleData.name, isDeleted: 0 }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (existingRole) {
|
|
|
+ logger.error(`角色名称已存在: ${roleData.name}`);
|
|
|
+ throw new Error('角色名称已存在');
|
|
|
+ }
|
|
|
+
|
|
|
+ const role = this.roleRepository.create({
|
|
|
+ ...roleData,
|
|
|
+ status: roleData.status ?? 1, // 默认启用状态
|
|
|
+ isDeleted: 0,
|
|
|
+ createdAt: new Date(),
|
|
|
+ updatedAt: new Date()
|
|
|
+ });
|
|
|
+
|
|
|
+ const savedRole = await this.roleRepository.save(role);
|
|
|
+ logger.api(`创建角色成功,ID: ${savedRole.id}`);
|
|
|
+ return savedRole;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新角色信息
|
|
|
+ */
|
|
|
+ async update(id: number, roleData: Partial<Role>) {
|
|
|
+ const role = await this.findById(id);
|
|
|
+
|
|
|
+ // 如果更新名称,检查新名称是否已存在
|
|
|
+ if (roleData.name && roleData.name !== role.name) {
|
|
|
+ const existingRole = await this.roleRepository.findOne({
|
|
|
+ where: { name: roleData.name, isDeleted: 0 }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (existingRole) {
|
|
|
+ logger.error(`角色名称已存在: ${roleData.name}`);
|
|
|
+ throw new Error('角色名称已存在');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Object.assign(role, {
|
|
|
+ ...roleData,
|
|
|
+ updatedAt: new Date()
|
|
|
+ });
|
|
|
+
|
|
|
+ const updatedRole = await this.roleRepository.save(role);
|
|
|
+ logger.api(`更新角色成功,ID: ${id}`);
|
|
|
+ return updatedRole;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除角色(软删除)
|
|
|
+ */
|
|
|
+ async delete(id: number) {
|
|
|
+ // 检查是否存在关联用户
|
|
|
+ const userRoleRepo = AppDataSource.getRepository('user_role');
|
|
|
+ const userRoles = await userRoleRepo.find({
|
|
|
+ where: { roleId: id }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (userRoles.length > 0) {
|
|
|
+ logger.error(`删除角色失败,角色已关联用户,ID: ${id}`);
|
|
|
+ throw new Error('该角色已关联用户,无法删除');
|
|
|
+ }
|
|
|
+
|
|
|
+ const role = await this.findById(id);
|
|
|
+
|
|
|
+ role.isDeleted = 1;
|
|
|
+ role.updatedAt = new Date();
|
|
|
+
|
|
|
+ await this.roleRepository.save(role);
|
|
|
+ logger.api(`删除角色成功,ID: ${id}`);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更改角色状态
|
|
|
+ */
|
|
|
+ async changeStatus(id: number, status: number) {
|
|
|
+ if (![0, 1].includes(status)) {
|
|
|
+ logger.error(`无效的角色状态: ${status}`);
|
|
|
+ throw new Error('无效的角色状态,只能是0或1');
|
|
|
+ }
|
|
|
+
|
|
|
+ const role = await this.findById(id);
|
|
|
+ // 不允许禁用系统角色
|
|
|
+ if (role.isSystem && status === 0) {
|
|
|
+ logger.error(`尝试禁用系统角色,ID: ${id}`);
|
|
|
+ throw new Error('不允许禁用系统角色');
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ role.status = status;
|
|
|
+ role.updatedAt = new Date();
|
|
|
+
|
|
|
+ await this.roleRepository.save(role);
|
|
|
+ logger.api(`更改角色状态成功,ID: ${id},新状态: ${status}`);
|
|
|
+ return role;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分配权限给角色
|
|
|
+ */
|
|
|
+ async assignPermissions(id: number, permissionIds: number[]) {
|
|
|
+ const role = await this.findById(id);
|
|
|
+
|
|
|
+ // 这里简化处理,实际项目中应该有专门的权限表和关联表
|
|
|
+ // 假设Role实体有permissions字段存储权限ID数组的JSON字符串
|
|
|
+ role.permissions = JSON.stringify(permissionIds);
|
|
|
+ role.updatedAt = new Date();
|
|
|
+
|
|
|
+ await this.roleRepository.save(role);
|
|
|
+ logger.api(`为角色分配权限成功,ID: ${id},权限数量: ${permissionIds.length}`);
|
|
|
+ return role;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查角色是否有权限
|
|
|
+ */
|
|
|
+ async hasPermission(roleId: number, permissionCode: string): Promise<boolean> {
|
|
|
+ const role = await this.findById(roleId);
|
|
|
+
|
|
|
+ // 超级管理员拥有所有权限
|
|
|
+ if (role.isSuper) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 这里简化处理,实际项目中应该根据permissionCode查询权限ID
|
|
|
+ // 并检查角色是否拥有该权限
|
|
|
+ // 假设permissions字段存储的是权限ID数组
|
|
|
+ // 这里需要根据实际的权限系统实现
|
|
|
+
|
|
|
+ logger.api(`检查角色权限: 角色ID=${roleId}, 权限码=${permissionCode}, 结果=${true}`);
|
|
|
+ return true; // 简化返回true,实际项目中需要根据权限系统实现
|
|
|
+ }
|
|
|
+}
|