From 7e89a7956769c1d95d14815e5b9fd8da99a25348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=9C=A3=E9=94=8B?= <361882884@qq.com> Date: Sun, 23 Nov 2025 13:35:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-druid.yml | 2 +- .../service/impl/SysUserServiceImpl.java | 29 ++ .../PsyScalePermissionServiceImpl.java | 32 +++ .../src/views/psychology/permission/index.vue | 254 ++++++++++++++++-- .../src/views/psychology/permission/user.vue | 90 +++++-- 5 files changed, 370 insertions(+), 37 deletions(-) diff --git a/ry-xinli-admin/src/main/resources/application-druid.yml b/ry-xinli-admin/src/main/resources/application-druid.yml index 6f7ff468..2127354c 100644 --- a/ry-xinli-admin/src/main/resources/application-druid.yml +++ b/ry-xinli-admin/src/main/resources/application-druid.yml @@ -6,7 +6,7 @@ spring: druid: # 主库数据源 master: - url: jdbc:mysql://1.15.149.240:3306/ry_xinli?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + url: jdbc:mysql://127.0.0.1:3306/ry_xinli?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: ry_xinli password: ZLZBcfGtsWJe5r4z # 从库数据源 diff --git a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/SysUserServiceImpl.java b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/SysUserServiceImpl.java index 30bfe88c..f6f9aa52 100644 --- a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/SysUserServiceImpl.java +++ b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/SysUserServiceImpl.java @@ -463,6 +463,17 @@ public class SysUserServiceImpl implements ISysUserService userRoleMapper.deleteUserRoleByUserId(userId); // 删除用户与岗位表 userPostMapper.deleteUserPostByUserId(userId); + // 删除用户的量表权限(支持多用户授权后,一个用户可能有多条权限记录) + try { + com.ddnai.system.service.psychology.IPsyScalePermissionService permissionService = + SpringUtils.getBean(com.ddnai.system.service.psychology.IPsyScalePermissionService.class); + if (permissionService != null) { + permissionService.deletePermissionByUserId(userId); + } + } catch (Exception e) { + log.warn("删除用户量表权限失败,userId: {}", userId, e); + // 不中断删除流程,继续删除用户 + } return userMapper.deleteUserById(userId); } @@ -485,6 +496,24 @@ public class SysUserServiceImpl implements ISysUserService userRoleMapper.deleteUserRole(userIds); // 删除用户与岗位关联 userPostMapper.deleteUserPost(userIds); + // 删除用户的量表权限(支持多用户授权后,一个用户可能有多条权限记录) + try { + com.ddnai.system.service.psychology.IPsyScalePermissionService permissionService = + SpringUtils.getBean(com.ddnai.system.service.psychology.IPsyScalePermissionService.class); + if (permissionService != null) { + for (Long userId : userIds) { + try { + permissionService.deletePermissionByUserId(userId); + } catch (Exception e) { + log.warn("删除用户量表权限失败,userId: {}", userId, e); + // 继续处理其他用户 + } + } + } + } catch (Exception e) { + log.warn("获取权限服务失败,跳过删除用户量表权限", e); + // 不中断删除流程,继续删除用户 + } return userMapper.deleteUserByIds(userIds); } diff --git a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyScalePermissionServiceImpl.java b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyScalePermissionServiceImpl.java index 727a39d1..e82a1629 100644 --- a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyScalePermissionServiceImpl.java +++ b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyScalePermissionServiceImpl.java @@ -106,6 +106,38 @@ public class PsyScalePermissionServiceImpl implements IPsyScalePermissionService { permission.setStatus("0"); } + + // 检查是否已存在相同的权限记录(避免重复) + PsyScalePermission query = new PsyScalePermission(); + query.setScaleId(permission.getScaleId()); + query.setUserId(permission.getUserId()); + query.setRoleId(permission.getRoleId()); + query.setDeptId(permission.getDeptId()); + query.setClassName(permission.getClassName()); + query.setStatus("0"); // 只检查有效状态的权限 + + List existing = permissionMapper.selectPermissionList(query); + if (existing != null && !existing.isEmpty()) + { + // 检查是否有完全相同的权限记录(除了时间范围) + boolean hasDuplicate = existing.stream().anyMatch(p -> { + boolean sameUser = (p.getUserId() == null && permission.getUserId() == null) + || (p.getUserId() != null && p.getUserId().equals(permission.getUserId())); + boolean sameRole = (p.getRoleId() == null && permission.getRoleId() == null) + || (p.getRoleId() != null && p.getRoleId().equals(permission.getRoleId())); + boolean sameDept = (p.getDeptId() == null && permission.getDeptId() == null) + || (p.getDeptId() != null && p.getDeptId().equals(permission.getDeptId())); + boolean sameClass = (p.getClassName() == null && permission.getClassName() == null) + || (p.getClassName() != null && p.getClassName().equals(permission.getClassName())); + return sameUser && sameRole && sameDept && sameClass; + }); + + if (hasDuplicate) + { + throw new RuntimeException("该权限已存在,请勿重复添加"); + } + } + return permissionMapper.insertPermission(permission); } diff --git a/xinli-ui/src/views/psychology/permission/index.vue b/xinli-ui/src/views/psychology/permission/index.vue index 294ea473..35fe6b7f 100644 --- a/xinli-ui/src/views/psychology/permission/index.vue +++ b/xinli-ui/src/views/psychology/permission/index.vue @@ -96,15 +96,30 @@ - - + + +
+ 提示:可输入姓名或账号搜索,支持多选。留空表示所有用户。 +
import { listPermission, getPermission, delPermission, addPermission, updatePermission } from "@/api/psychology/permission"; import { listScale } from "@/api/psychology/scale"; -import { listUser } from "@/api/system/user"; +import { allocatedUserList } from "@/api/system/role"; +import { listRole } from "@/api/system/role"; +import { getUser } from "@/api/system/user"; export default { name: "PsyScalePermission", @@ -167,8 +184,12 @@ export default { permissionList: [], // 量表列表 scaleList: [], - // 用户列表 - userList: [], + // 用户列表(用于下拉框显示) + userOptions: [], + // 用户搜索加载状态 + userSearchLoading: false, + // 学员角色ID(缓存) + studentRoleId: null, // 弹出层标题 title: "", // 是否显示弹出层 @@ -218,10 +239,96 @@ export default { .filter(scale => !scale.sourceType || scale.sourceType === 'scale'); }); }, - /** 加载用户列表 */ + /** 加载用户列表(只加载学员角色的用户)- 改为远程搜索模式,不预加载 */ loadUsers() { - listUser({ status: '0' }).then(response => { - this.userList = response.rows || []; + // 预加载学员角色ID,用于后续搜索 + this.getStudentRoleId().then(studentRoleId => { + this.studentRoleId = studentRoleId; + if (!studentRoleId) { + console.warn("未找到学员角色,用户搜索功能可能不可用"); + } + // 初始加载少量用户,供用户选择 + this.searchUsers(""); + }).catch(error => { + console.error("获取学员角色ID失败:", error); + }); + }, + /** 搜索用户(远程搜索) */ + searchUsers(keyword) { + if (!this.studentRoleId) { + // 如果还没有获取到学员角色ID,先获取 + this.getStudentRoleId().then(studentRoleId => { + this.studentRoleId = studentRoleId; + if (studentRoleId) { + this.doSearchUsers(keyword); + } + }); + return; + } + this.doSearchUsers(keyword); + }, + /** 执行用户搜索 */ + doSearchUsers(keyword) { + this.userSearchLoading = true; + const searchParams = { + roleId: this.studentRoleId, + status: '0', + pageNum: 1, + pageSize: 100 // 每次搜索返回100条,足够选择使用 + }; + // 如果有关键词,添加搜索条件 + if (keyword && keyword.trim()) { + searchParams.userName = keyword.trim(); + searchParams.phonenumber = keyword.trim(); + } + allocatedUserList(searchParams).then(response => { + const rows = response.rows || []; + // 如果有关键词,进一步过滤(因为allocatedUserList可能只支持userName和phonenumber搜索) + let filteredRows = rows; + if (keyword && keyword.trim()) { + const keywordLower = keyword.trim().toLowerCase(); + filteredRows = rows.filter(item => { + const userName = (item.userName || '').toLowerCase(); + const nickName = (item.nickName || '').toLowerCase(); + return userName.includes(keywordLower) || nickName.includes(keywordLower); + }); + } + this.userOptions = filteredRows.map(item => ({ + userId: item.userId, + userName: item.userName, + nickName: item.nickName + })); + }).catch(error => { + console.error("搜索学员用户失败:", error); + this.userOptions = []; + }).finally(() => { + this.userSearchLoading = false; + }); + }, + /** 获取学员角色ID */ + getStudentRoleId() { + return new Promise((resolve, reject) => { + // 先尝试从角色列表中找到学员角色 + listRole({}).then(response => { + const roles = response.rows || []; + // 查找学员角色:roleId=101 或 roleKey='student' 或 roleName包含'学员' + const studentRole = roles.find(role => { + return (role.roleId === 101) || + (role.roleKey && role.roleKey.toLowerCase() === 'student') || + (role.roleName && role.roleName.includes('学员')); + }); + if (studentRole && studentRole.roleId) { + resolve(studentRole.roleId); + } else { + // 如果找不到,尝试使用默认值101 + console.warn("未找到学员角色,使用默认值101"); + resolve(101); + } + }).catch(error => { + console.error("获取角色列表失败:", error); + // 如果获取角色列表失败,尝试使用默认值101 + resolve(101); + }); }); }, // 取消按钮 @@ -234,7 +341,8 @@ export default { this.form = { permissionId: undefined, scaleId: undefined, - userId: undefined, + userId: undefined, // 保留用于编辑时兼容 + userIds: [], // 多选用户ID数组 deptId: undefined, roleId: undefined, className: undefined, @@ -273,30 +381,136 @@ export default { const permissionId = row.permissionId || this.ids[0]; getPermission(permissionId).then(response => { this.form = response.data; + // 兼容处理:如果form中有userId,转换为userIds数组 + if (this.form.userId && !this.form.userIds) { + this.form.userIds = [this.form.userId]; + } else if (!this.form.userIds) { + this.form.userIds = []; + } + // 如果编辑时选择了用户,需要加载这些用户到选项列表中 + if (this.form.userIds && this.form.userIds.length > 0) { + this.loadSelectedUsers(this.form.userIds); + } this.open = true; this.title = "修改量表权限"; }); }, + /** 加载已选中的用户信息到选项列表 */ + loadSelectedUsers(userIds) { + if (!userIds || userIds.length === 0) { + return; + } + // 为每个用户ID获取用户信息 + const promises = userIds.map(userId => { + return getUser(userId).then(response => { + const userData = response.data || {}; + return { + userId: userData.userId, + userName: userData.userName, + nickName: userData.nickName + }; + }).catch(() => null); + }); + Promise.all(promises).then(users => { + const validUsers = users.filter(u => u !== null); + // 将已选用户添加到选项列表(避免重复) + validUsers.forEach(user => { + if (!this.userOptions.find(u => u.userId === user.userId)) { + this.userOptions.push(user); + } + }); + }); + }, /** 提交按钮 */ submitForm() { this.$refs["form"].validate(valid => { if (valid) { + // 处理多选用户:如果选择了多个用户,需要为每个用户创建一条权限记录 + const userIds = this.form.userIds || []; + + // 编辑模式:先删除原权限记录,然后根据新的用户列表创建新记录 if (this.form.permissionId != undefined) { - updatePermission(this.form).then(response => { - this.$modal.msgSuccess("修改成功"); - this.open = false; - this.getList(); + // 获取原始权限信息 + const originalPermissionId = this.form.permissionId; + + // 先删除原权限记录 + delPermission(originalPermissionId).then(() => { + // 然后根据新的用户列表创建权限记录 + this.createPermissionsForUsers(userIds); + }).catch(error => { + console.error("删除原权限失败:", error); + this.$modal.msgError(error.msg || "修改失败:删除原权限失败"); }); } else { - addPermission(this.form).then(response => { - this.$modal.msgSuccess("新增成功"); - this.open = false; - this.getList(); - }); + // 新增模式:为每个用户创建权限记录 + this.createPermissionsForUsers(userIds); } } }); }, + /** 为多个用户创建权限记录 */ + createPermissionsForUsers(userIds) { + if (userIds.length === 0) { + // 没有选择用户,表示所有用户,创建一条userId为null的记录 + const addForm = { ...this.form }; + delete addForm.userIds; + delete addForm.permissionId; + addForm.userId = null; + addPermission(addForm).then(response => { + this.$modal.msgSuccess("新增成功"); + this.open = false; + this.getList(); + }).catch(error => { + console.error("新增权限失败:", error); + const errorMsg = error.msg || error.message || "新增失败"; + this.$modal.msgError(errorMsg); + }); + } else { + // 为每个用户创建权限记录 + const promises = userIds.map(userId => { + const addForm = { ...this.form }; + delete addForm.userIds; + delete addForm.permissionId; + addForm.userId = userId; + return addPermission(addForm).catch(error => { + // 如果是重复权限错误,返回null而不是reject,这样其他用户仍能成功 + if (error.msg && error.msg.includes("已存在")) { + console.warn(`用户 ${userId} 的权限已存在,跳过`); + return { skipped: true, userId }; + } + throw error; + }); + }); + + Promise.allSettled(promises).then(results => { + const successCount = results.filter(r => r.status === 'fulfilled' && !r.value?.skipped).length; + const skippedCount = results.filter(r => r.status === 'fulfilled' && r.value?.skipped).length; + const failedCount = results.filter(r => r.status === 'rejected').length; + + let message = ""; + if (successCount > 0) { + message = `成功为 ${successCount} 个用户分配权限`; + } + if (skippedCount > 0) { + message += (message ? "," : "") + `${skippedCount} 个用户权限已存在(已跳过)`; + } + if (failedCount > 0) { + message += (message ? "," : "") + `${failedCount} 个用户权限分配失败`; + } + + if (successCount > 0 || skippedCount > 0) { + this.$modal.msgSuccess(message || "操作完成"); + this.open = false; + this.getList(); + } else { + this.$modal.msgError(message || "权限分配失败"); + } + }).catch(error => { + console.error("批量新增权限失败:", error); + this.$modal.msgError(error.msg || error.message || "批量新增权限失败"); + }); + } + }, /** 删除按钮操作 */ handleDelete(row) { const permissionIds = row.permissionId || this.ids; diff --git a/xinli-ui/src/views/psychology/permission/user.vue b/xinli-ui/src/views/psychology/permission/user.vue index 8b188bd9..0c391d13 100644 --- a/xinli-ui/src/views/psychology/permission/user.vue +++ b/xinli-ui/src/views/psychology/permission/user.vue @@ -59,7 +59,9 @@