“出国申请工作流修改10.29版”
This commit is contained in:
1 parent
f907b9cd40
commit
32b9822146
7 files changed
+593
-169
No files matched your search
+43
@@ -101,4 +101,47 @@ public interface RsOverseasApplicationMapper extends BaseMapperPlus<RsOverseasAp
|
||||
* @return 用户姓名
|
||||
*/
|
||||
String selectUserNameById(Long userId);
|
||||
|
||||
/**
|
||||
* 根据权限标识查询拥有该权限的用户ID列表
|
||||
*
|
||||
* 查询逻辑:
|
||||
* 1. 通过 sys_menu 查找权限对应的菜单ID
|
||||
* 2. 通过 sys_role_menu 查找拥有该菜单的角色
|
||||
* 3. 通过 sys_user_role 查找拥有这些角色的用户
|
||||
* 4. 过滤掉已停用的用户
|
||||
*
|
||||
* @param permissionCode 权限标识(如:rs:overseas:approve2)
|
||||
* @return 用户ID列表
|
||||
*/
|
||||
List<Long> selectUserIdsByPermission(String permissionCode);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询其拥有的出国审批权限列表
|
||||
*
|
||||
* 查询逻辑:
|
||||
* 1. 通过 sys_user_role 查找用户的角色
|
||||
* 2. 通过 sys_role_menu 查找角色的菜单
|
||||
* 3. 通过 sys_menu 查找菜单的权限标识
|
||||
* 4. 过滤出出国审批相关的权限(rs:overseas:approve%)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 审批权限标识列表(如:["rs:overseas:approve2", "rs:overseas:approve3"])
|
||||
*/
|
||||
List<String> selectApprovalPermissionsByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 🔴 新增:查询待审批申请列表(支持部门过滤)
|
||||
*
|
||||
* 查询逻辑:
|
||||
* 1. 关联 sys_user 表获取申请人的部门信息
|
||||
* 2. 按审批级别过滤(approvalLevel IN (...) )
|
||||
* 3. 按状态过滤(status = '0' 待审核)
|
||||
* 4. 按部门过滤(deptId != null 时,u.dept_id = #{deptId})
|
||||
*
|
||||
* @param approvalLevels 审批级别列表,例如:["1", "2"]
|
||||
* @param deptId 部门ID(部门负责人需要),为null则不过滤部门
|
||||
* @return 待审批申请列表
|
||||
*/
|
||||
List<RsOverseasApplication> selectPendingApplications(List<String> approvalLevels, Long deptId);
|
||||
}
|
||||
+186
-106
@@ -87,29 +87,40 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<RsOverseasApplicationVo> queryPageList(RsOverseasApplicationQuery query) {
|
||||
// 🔴 新增:部门负责人权限过滤逻辑
|
||||
// 🔴 新增:多级审批权限过滤逻辑
|
||||
Long currentUserId = LoginHelper.getUserId();
|
||||
|
||||
// 1. 判断是否是rs-admin管理员(管理员可以看所有数据)
|
||||
boolean isAdmin = cn.dev33.satoken.stp.StpUtil.hasRole("rs-admin");
|
||||
|
||||
if (!isAdmin) {
|
||||
// 2. 判断是否是部门负责人(拥有rs:overseas:approve1权限)
|
||||
boolean isDeptHead = cn.dev33.satoken.stp.StpUtil.hasPermission("rs:overseas:approve1");
|
||||
// 2. 判断是否有高级别审批权限(人事处及以上:approve2/3/4/5)
|
||||
boolean hasHigherApprovalPermission = cn.dev33.satoken.stp.StpUtil.hasPermission("rs:overseas:approve2") || // 人事处
|
||||
cn.dev33.satoken.stp.StpUtil.hasPermission("rs:overseas:approve3") || // 纪委
|
||||
cn.dev33.satoken.stp.StpUtil.hasPermission("rs:overseas:approve4") || // 学院分管领导
|
||||
cn.dev33.satoken.stp.StpUtil.hasPermission("rs:overseas:approve5"); // 学院党委书记
|
||||
|
||||
if (isDeptHead) {
|
||||
// 🔴 部门负责人:只能看到本部门员工提交的申请
|
||||
SysUserVo currentUser = userService.selectUserById(currentUserId);
|
||||
if (currentUser != null && currentUser.getDeptId() != null) {
|
||||
query.setApplicantDeptId(currentUser.getDeptId());
|
||||
log.info("🔒 [部门权限过滤] 用户: {}, 部门ID: {}, 只能查看本部门申请",
|
||||
currentUser.getUserName(), currentUser.getDeptId());
|
||||
}
|
||||
if (hasHigherApprovalPermission) {
|
||||
// 🔴 人事处及以上:可以看到所有申请(不按部门过滤)
|
||||
log.info("✅ [高级审批权限] 用户ID: {}, 可以查看所有申请", currentUserId);
|
||||
} else {
|
||||
// 3. 普通用户:只能看到自己提交的申请
|
||||
if (query.getApplicantId() == null) {
|
||||
query.setApplicantId(currentUserId);
|
||||
log.info("🔒 [个人权限过滤] 用户ID: {}, 只能查看自己的申请", currentUserId);
|
||||
// 3. 判断是否是部门负责人(只有 rs:overseas:approve1 权限)
|
||||
boolean isDeptHead = cn.dev33.satoken.stp.StpUtil.hasPermission("rs:overseas:approve1");
|
||||
|
||||
if (isDeptHead) {
|
||||
// 🔴 纯部门负责人:只能看到本部门员工提交的申请
|
||||
SysUserVo currentUser = userService.selectUserById(currentUserId);
|
||||
if (currentUser != null && currentUser.getDeptId() != null) {
|
||||
query.setApplicantDeptId(currentUser.getDeptId());
|
||||
log.info("🔒 [部门权限过滤] 用户: {}, 部门ID: {}, 只能查看本部门申请",
|
||||
currentUser.getUserName(), currentUser.getDeptId());
|
||||
}
|
||||
} else {
|
||||
// 4. 普通用户:只能看到自己提交的申请
|
||||
if (query.getApplicantId() == null) {
|
||||
query.setApplicantId(currentUserId);
|
||||
log.info("🔒 [个人权限过滤] 用户ID: {}, 只能查看自己的申请", currentUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -220,46 +231,92 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户的待审批申请列表
|
||||
* 查询当前用户的待审批申请列表(动态权限方案 + 部门过滤)
|
||||
*
|
||||
* 🆕 核心改进:
|
||||
* 1. 不再依赖 current_approver_id 字段(该字段仅作为冗余展示用)
|
||||
* 2. 动态查询用户的审批权限,转换为审批级别
|
||||
* 3. 根据审批级别和状态查询待审批申请
|
||||
* 4. 🔴 部门负责人只能看到本部门的申请
|
||||
* 5. 支持人员岗位变动:权限调整后立即生效
|
||||
*
|
||||
* 查询逻辑:
|
||||
* - 用户有 rs:overseas:approve1 权限(部门负责人)→ 查询本部门员工的、approval_level='1' 且
|
||||
* status='0' 的申请
|
||||
* - 用户有 rs:overseas:approve2 权限(人事处)→ 查询全校的、approval_level='2' 且 status='0' 的申请
|
||||
* - 用户有多个审批权限 → 返回所有对应级别的待审批申请(无部门限制)
|
||||
*/
|
||||
@Override
|
||||
public List<RsOverseasApplicationVo> queryPendingByCurrentUser() {
|
||||
Long currentUserId = LoginHelper.getUserId();
|
||||
log.info("查询当前用户待审批申请,用户ID: {}", currentUserId);
|
||||
|
||||
// 获取当前用户信息
|
||||
String currentUserName = LoginHelper.getUsername();
|
||||
log.info("当前用户名: {}", currentUserName);
|
||||
|
||||
List<RsOverseasApplication> applications = baseMapper.selectList(
|
||||
new LambdaQueryWrapper<RsOverseasApplication>()
|
||||
.eq(RsOverseasApplication::getStatus, "0") // 待审核状态
|
||||
.eq(RsOverseasApplication::getCurrentApprover, currentUserName) // 使用当前审批人姓名
|
||||
.orderByDesc(RsOverseasApplication::getApplyTime));
|
||||
log.info("🔍 查询用户待审批申请 - 用户ID: {}, 用户名: {}", currentUserId, currentUserName);
|
||||
|
||||
// 转换为VO对象
|
||||
return applications.stream()
|
||||
.map(this::convertToVo)
|
||||
.collect(Collectors.toList());
|
||||
// 1. 获取当前用户的审批级别列表(基于权限动态查询)
|
||||
List<String> approvalLevels = getApprovalLevelsByUser(currentUserId);
|
||||
|
||||
if (approvalLevels == null || approvalLevels.isEmpty()) {
|
||||
log.warn("❌ 用户 {} 没有任何出国审批权限,返回空列表", currentUserName);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
log.info("✅ 用户 {} 拥有审批级别: {}", currentUserName, approvalLevels);
|
||||
|
||||
// 2. 🔴 新逻辑:对每个级别单独查询并合并(方案1)
|
||||
List<RsOverseasApplicationVo> result = new ArrayList<>();
|
||||
|
||||
// 遍历每个审批级别
|
||||
for (String level : approvalLevels) {
|
||||
Long deptIdForFilter = null;
|
||||
|
||||
// 🔴 关键:只对 level=1 进行部门过滤
|
||||
if ("1".equals(level)) {
|
||||
// 获取当前用户的部门ID
|
||||
SysUserVo currentUser = userService.selectUserById(currentUserId);
|
||||
if (currentUser != null && currentUser.getDeptId() != null) {
|
||||
deptIdForFilter = currentUser.getDeptId();
|
||||
log.info("🔒 [部门权限过滤] 级别1,用户: {}, 部门ID: {}, 只查看本部门待审批",
|
||||
currentUserName, deptIdForFilter);
|
||||
} else {
|
||||
log.warn("⚠️ 用户 {} 是部门负责人但没有部门信息,无法过滤", currentUserName);
|
||||
}
|
||||
} else {
|
||||
// level=2, 3, 4, 5 不进行部门过滤
|
||||
log.info("✅ [全校权限] 级别{}, 用户 {}, 查看全校待审批",
|
||||
level, currentUserName);
|
||||
}
|
||||
|
||||
// 3. 查询该级别的待审批申请(单个级别)
|
||||
List<RsOverseasApplication> levelApplications = baseMapper.selectPendingApplications(
|
||||
Arrays.asList(level), // 🔴 关键:只查询单个级别
|
||||
deptIdForFilter // level=1时有值,其他为null
|
||||
);
|
||||
|
||||
log.info("📋 级别{} 查询到 {} 条待审批申请", level, levelApplications.size());
|
||||
|
||||
// 4. 转换为VO对象并添加到结果列表
|
||||
result.addAll(levelApplications.stream()
|
||||
.map(this::convertToVo)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
log.info("📋 用户 {} 总共查询到 {} 条待审批申请", currentUserName, result.size());
|
||||
|
||||
// 5. 返回合并后的结果
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换实体为VO对象
|
||||
* 🔴 修复:使用Mapper查询完整的VO对象,包含字典翻译等扩展信息
|
||||
*/
|
||||
private RsOverseasApplicationVo convertToVo(RsOverseasApplication entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
RsOverseasApplicationVo vo = new RsOverseasApplicationVo();
|
||||
// 使用BeanUtils复制属性(如果有的话)或者手动复制关键属性
|
||||
vo.setApplicationId(entity.getApplicationId());
|
||||
vo.setSerialNumber(entity.getSerialNumber());
|
||||
vo.setApplicantId(entity.getApplicantId());
|
||||
vo.setApplicantName(entity.getApplicantName());
|
||||
vo.setStatus(entity.getStatus());
|
||||
vo.setApplyTime(entity.getApplyTime());
|
||||
// 复制其他必要的字段...
|
||||
return vo;
|
||||
// 🔴 使用Mapper的详细查询方法,获取完整的VO对象(包含字典翻译)
|
||||
return baseMapper.selectOverseasApplicationById(entity.getApplicationId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -437,7 +494,13 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交出国申请(传统审批模式)
|
||||
* 提交出国申请(动态审批人方案)
|
||||
*
|
||||
* 🆕 核心改进:
|
||||
* 1. 不再设置固定的 current_approver_id(该字段改为冗余展示字段)
|
||||
* 2. 仅设置 approval_level='1',审批人根据权限动态查询
|
||||
* 3. current_approver 设置为提示文本(如"待一级审批")
|
||||
* 4. 支持人员岗位变动:权限调整后立即生效
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
@@ -452,15 +515,18 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
throw new RuntimeException("已通过或已完成的申请不能重新提交");
|
||||
}
|
||||
|
||||
// 设置状态为待审核
|
||||
// 🆕 设置状态为待审核
|
||||
application.setStatus("0");
|
||||
application.setApplyTime(new Date());
|
||||
|
||||
// 🆕 设置初始审批级别为1(不再设置固定审批人ID)
|
||||
application.setApprovalLevel("1");
|
||||
application.setCurrentApprover("待审批");
|
||||
application.setCurrentApproverId(null); // 清空固定审批人ID
|
||||
application.setCurrentApprover("待一级审批"); // 提示文本
|
||||
|
||||
boolean updated = baseMapper.updateById(application) > 0;
|
||||
|
||||
log.info("✅ [出国申请提交] 提交成功, applicationId: {}, 申请人: {}",
|
||||
log.info("✅ [出国申请提交] 提交成功 - applicationId: {}, 申请人: {}, 审批级别: 1",
|
||||
applicationId, application.getApplicantName());
|
||||
|
||||
return updated;
|
||||
@@ -530,19 +596,18 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
|
||||
approvalMapper.insert(approval);
|
||||
|
||||
// 更新申请状态
|
||||
// 🆕 更新申请状态(动态审批人方案)
|
||||
if ("1".equals(approvalStatus)) {
|
||||
// 审批通过
|
||||
String nextLevel = getNextApprovalLevel(application.getApprovalLevel());
|
||||
if (nextLevel != null) {
|
||||
// 进入下一级审批
|
||||
Long nextApproverId = getNextApprover(nextLevel);
|
||||
// 🆕 进入下一级审批(不再设置固定审批人ID)
|
||||
application.setApprovalLevel(nextLevel);
|
||||
application.setCurrentApproverId(nextApproverId);
|
||||
application.setCurrentApprover(getApprovalLevelDescription(nextLevel));
|
||||
application.setCurrentApproverId(null); // 不再设置固定审批人ID
|
||||
application.setCurrentApprover(getApprovalLevelDescription(nextLevel)); // 如"待二级审批"
|
||||
|
||||
log.info("审批流转到第{}级,申请ID: {}, 下一级审批人ID: {}",
|
||||
nextLevel, applicationId, nextApproverId);
|
||||
log.info("✅ 审批流转到第{}级,申请ID: {}, 审批人根据权限动态查询",
|
||||
nextLevel, applicationId);
|
||||
} else {
|
||||
// 所有级别审批完成 - 先尝试创建出国记录,再更新申请状态
|
||||
log.info("开始最终审批处理,申请ID: {}, 当前状态: {}, 申请人: {}",
|
||||
@@ -731,15 +796,16 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
existingApp.setDuration(days);
|
||||
}
|
||||
|
||||
// 重置为待审核状态
|
||||
// 🆕 重置为待审核状态(动态审批人方案)
|
||||
existingApp.setStatus("0");
|
||||
existingApp.setApplyTime(new Date()); // 更新申请时间
|
||||
|
||||
// 设置初始审批级别为1(单级审批制度)
|
||||
// 🆕 设置初始审批级别为1(不再设置固定审批人ID)
|
||||
existingApp.setApprovalLevel("1");
|
||||
existingApp.setCurrentApprover("待审批");
|
||||
existingApp.setCurrentApproverId(null); // 清空固定审批人ID
|
||||
existingApp.setCurrentApprover("待一级审批"); // 提示文本
|
||||
|
||||
log.info("【重新提交申请】更新为待审核状态,申请ID: {}", applicationId);
|
||||
log.info("【重新提交申请】更新为待审核状态,申请ID: {}, 审批级别: 1", applicationId);
|
||||
|
||||
return baseMapper.updateById(existingApp) > 0;
|
||||
}
|
||||
@@ -1181,58 +1247,9 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
* @param approvalLevel 审批级别
|
||||
* @return 下一级审批人ID
|
||||
*/
|
||||
private Long getNextApprover(String approvalLevel) {
|
||||
try {
|
||||
String roleKey = null;
|
||||
switch (approvalLevel) {
|
||||
case "2": // 人事处审批
|
||||
roleKey = "hr_dept_overseas_approver";
|
||||
break;
|
||||
case "3": // 纪委审批
|
||||
roleKey = "discipline_overseas_approver";
|
||||
break;
|
||||
case "4": // 学院分管领导审批
|
||||
roleKey = "college_leader_overseas_approver";
|
||||
break;
|
||||
case "5": // 学院党委书记审批
|
||||
roleKey = "party_secretary_overseas_approver";
|
||||
break;
|
||||
default:
|
||||
log.warn("未知的审批级别: {}", approvalLevel);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取对应角色
|
||||
SysRoleBo roleQuery = new SysRoleBo();
|
||||
roleQuery.setRoleKey(roleKey);
|
||||
List<SysRoleVo> roles = roleService.selectRoleList(roleQuery);
|
||||
if (roles.isEmpty()) {
|
||||
log.error("未找到审批角色: {}", roleKey);
|
||||
return null;
|
||||
}
|
||||
SysRoleVo role = roles.get(0);
|
||||
|
||||
// 获取角色下的用户(取第一个作为审批人)
|
||||
SysUserBo userQuery = new SysUserBo();
|
||||
userQuery.setRoleId(role.getRoleId());
|
||||
PageQuery pageQuery2 = new PageQuery();
|
||||
pageQuery2.setPageSize(1000); // 设置较大的页面大小以获取所有用户
|
||||
List<SysUserVo> users = userService.selectAllocatedList(userQuery, pageQuery2).getRows();
|
||||
if (users.isEmpty()) {
|
||||
log.warn("审批角色 {} 下没有用户", roleKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 返回第一个用户作为审批人
|
||||
SysUserVo approver = users.get(0);
|
||||
log.info("获取到第{}级审批人: {} ({})", approvalLevel, approver.getUserName(), approver.getNickName());
|
||||
return approver.getUserId();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取第{}级审批人失败", approvalLevel, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// 🗑️ getNextApprover() 方法已删除
|
||||
// 原因:采用动态审批人方案后,不再需要预先指定固定的审批人ID
|
||||
// 新方案:待审批列表通过 getApprovalLevelsByUser() 动态查询
|
||||
|
||||
/**
|
||||
* 根据审批级别获取审批环节描述
|
||||
@@ -1257,6 +1274,69 @@ public class RsOverseasApplicationServiceImpl extends ServiceImpl<RsOverseasAppl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🆕 根据当前登录用户的审批权限,获取其可审批的级别列表
|
||||
*
|
||||
* 权限到级别的映射:
|
||||
* - rs:overseas:approve1 → 审批级别 "1" (部门负责人)
|
||||
* - rs:overseas:approve2 → 审批级别 "2" (人事处)
|
||||
* - rs:overseas:approve3 → 审批级别 "3" (纪委)
|
||||
* - rs:overseas:approve4 → 审批级别 "4" (学院分管领导)
|
||||
* - rs:overseas:approve5 → 审批级别 "5" (学院党委书记)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 可审批的级别列表,例如:["2", "3"]
|
||||
*/
|
||||
private List<String> getApprovalLevelsByUser(Long userId) {
|
||||
try {
|
||||
List<String> approvalLevels = new ArrayList<>();
|
||||
|
||||
// 🔴 修复:直接使用Sa-Token API检查权限,避免数据库查询问题
|
||||
// 检查5个审批级别的权限(1-5级)
|
||||
String[] levels = { "1", "2", "3", "4", "5" };
|
||||
for (String level : levels) {
|
||||
String permission = "rs:overseas:approve" + level;
|
||||
if (StpUtil.hasPermission(permission)) {
|
||||
approvalLevels.add(level);
|
||||
log.info("✅ 用户 {} 拥有第{}级审批权限: {}", userId, level, permission);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查通用审批权限(超级管理员)
|
||||
if (StpUtil.hasPermission("rs:overseas:approve")) {
|
||||
// 通用审批权限可以审批所有级别
|
||||
log.info("✅ 用户 {} 拥有通用审批权限,可审批所有级别", userId);
|
||||
approvalLevels.clear();
|
||||
approvalLevels.addAll(Arrays.asList(levels));
|
||||
}
|
||||
|
||||
if (approvalLevels.isEmpty()) {
|
||||
log.warn("❌ 用户 {} 没有任何出国审批权限", userId);
|
||||
} else {
|
||||
log.info("📋 用户 {} 可审批的级别: {}", userId, approvalLevels);
|
||||
}
|
||||
|
||||
return approvalLevels;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("❌ 获取用户 {} 的审批级别失败", userId, e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🆕 根据审批级别获取对应的权限标识
|
||||
*
|
||||
* @param approvalLevel 审批级别(2-5)
|
||||
* @return 权限标识,例如:"rs:overseas:approve2"
|
||||
*/
|
||||
private String getPermissionByLevel(String approvalLevel) {
|
||||
if (approvalLevel == null || approvalLevel.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return "rs:overseas:approve" + approvalLevel;
|
||||
}
|
||||
|
||||
// 工作流监听器已移至独立的 OverseasApplicationWorkflowListener 类中
|
||||
|
||||
// 状态更新方法已移至独立的 OverseasApplicationWorkflowListener 类中
|
||||
|
||||
+45
-26
@@ -246,19 +246,7 @@ public class RsOverseasApprovalServiceImpl implements IRsOverseasApprovalService
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔧 优先检查部门负责人权限(避免被rs-admin角色覆盖)
|
||||
boolean isDeptApprover = isDeptApprover(currentUserId);
|
||||
log.info("✓ 部门负责人检查结果: {}", isDeptApprover);
|
||||
|
||||
if (isDeptApprover) {
|
||||
// 部门负责人只能看到本部门的所有申请(不限制审批人)
|
||||
query.setDeptId(currentDeptId);
|
||||
log.info("→ 权限结果:部门负责人,设置部门过滤 deptId={}", currentDeptId);
|
||||
log.info("==================== 权限过滤结束 ====================");
|
||||
return;
|
||||
}
|
||||
|
||||
// 人事管理员可以看到所有申请(仅当不是部门负责人时)
|
||||
// 人事管理员可以看到所有申请
|
||||
boolean hasAdminRole = StpUtil.hasRole("rs-admin");
|
||||
log.info("✓ 角色检查 [rs-admin]: {}", hasAdminRole);
|
||||
if (hasAdminRole) {
|
||||
@@ -267,7 +255,28 @@ public class RsOverseasApprovalServiceImpl implements IRsOverseasApprovalService
|
||||
return; // 全局权限
|
||||
}
|
||||
|
||||
// 其他角色只能看到分配给自己的审批
|
||||
// 🔧 检查部门负责人权限(但不能与其他审批权限冲突)
|
||||
boolean isDeptApprover = isDeptApprover(currentUserId);
|
||||
log.info("✓ 部门负责人检查结果: {}", isDeptApprover);
|
||||
|
||||
// 检查是否有其他审批权限(人事处、纪委等)
|
||||
boolean hasOtherApprovePermission = StpUtil.hasPermission("rs:overseas:approve2") || // 人事处
|
||||
StpUtil.hasPermission("rs:overseas:approve3") || // 纪委
|
||||
StpUtil.hasPermission("rs:overseas:approve4") || // 学院分管领导
|
||||
StpUtil.hasPermission("rs:overseas:approve5"); // 学院党委书记
|
||||
log.info("✓ 其他审批权限检查: {}", hasOtherApprovePermission);
|
||||
|
||||
if (isDeptApprover && !hasOtherApprovePermission) {
|
||||
// 纯部门负责人:只能看到本部门且分配给自己的申请
|
||||
query.setDeptId(currentDeptId);
|
||||
query.setApproverId(currentUserId);
|
||||
log.info("→ 权限结果:部门负责人,设置部门过滤 deptId={} 和审批人过滤 approverId={}",
|
||||
currentDeptId, currentUserId);
|
||||
log.info("==================== 权限过滤结束 ====================");
|
||||
return;
|
||||
}
|
||||
|
||||
// 其他审批人(包括有其他审批权限的用户)只能看到分配给自己的审批
|
||||
query.setApproverId(currentUserId);
|
||||
log.info("→ 权限结果:普通审批人,设置审批人过滤 approverId={}", currentUserId);
|
||||
log.info("==================== 权限过滤结束 ====================");
|
||||
@@ -502,23 +511,33 @@ public class RsOverseasApprovalServiceImpl implements IRsOverseasApprovalService
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔧 优先检查部门负责人权限(避免被rs-admin角色覆盖)
|
||||
boolean isDeptApprover = isDeptApprover(currentUserId);
|
||||
log.info("用户 {} 部门负责人检查结果: {}", currentUsername, isDeptApprover);
|
||||
|
||||
if (isDeptApprover) {
|
||||
log.info("用户 {} 是部门负责人,设置部门过滤: {}", currentUsername, currentDeptId);
|
||||
query.setDeptId(currentDeptId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 人事管理员可以看到所有申请(仅当不是部门负责人时)
|
||||
// 人事管理员可以看到所有申请
|
||||
if (StpUtil.hasRole("rs-admin")) {
|
||||
log.info("用户 {} 具有rs-admin角色,不设置过滤条件", currentUsername);
|
||||
return;
|
||||
}
|
||||
|
||||
// 其他角色只能看到分配给自己的审批
|
||||
// 🔧 检查部门负责人权限(但不能与其他审批权限冲突)
|
||||
boolean isDeptApprover = isDeptApprover(currentUserId);
|
||||
log.info("用户 {} 部门负责人检查结果: {}", currentUsername, isDeptApprover);
|
||||
|
||||
// 检查是否有其他审批权限(人事处、纪委等)
|
||||
boolean hasOtherApprovePermission = StpUtil.hasPermission("rs:overseas:approve2") || // 人事处
|
||||
StpUtil.hasPermission("rs:overseas:approve3") || // 纪委
|
||||
StpUtil.hasPermission("rs:overseas:approve4") || // 学院分管领导
|
||||
StpUtil.hasPermission("rs:overseas:approve5"); // 学院党委书记
|
||||
log.info("用户 {} 其他审批权限检查: {}", currentUsername, hasOtherApprovePermission);
|
||||
|
||||
if (isDeptApprover && !hasOtherApprovePermission) {
|
||||
// 纯部门负责人:只能看到本部门且分配给自己的申请
|
||||
log.info("用户 {} 是纯部门负责人,设置部门过滤: {} 和审批人过滤: {}",
|
||||
currentUsername, currentDeptId, currentUserId);
|
||||
query.setDeptId(currentDeptId); // 只显示本部门员工的申请
|
||||
query.setApproverId(currentUserId); // 只显示当前审批人是自己的申请(待审批)
|
||||
return;
|
||||
}
|
||||
|
||||
// 其他审批人(包括有其他审批权限的用户)只能看到分配给自己的审批
|
||||
log.info("用户 {} 是普通审批人,设置审批人过滤: {}", currentUsername, currentUserId);
|
||||
query.setApproverId(currentUserId);
|
||||
}
|
||||
|
||||
+51
@@ -551,4 +551,55 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
AND u.deleted = '0'
|
||||
</select>
|
||||
|
||||
<!-- 🔧 新增:根据权限标识查询拥有该权限的用户ID列表 -->
|
||||
<select id="selectUserIdsByPermission" parameterType="String" resultType="Long">
|
||||
SELECT DISTINCT u.user_id
|
||||
FROM sys_user u
|
||||
INNER JOIN sys_user_role ur ON u.user_id = ur.user_id
|
||||
INNER JOIN sys_role r ON ur.role_id = r.role_id
|
||||
INNER JOIN sys_role_menu rm ON r.role_id = rm.role_id
|
||||
INNER JOIN sys_menu m ON rm.menu_id = m.menu_id
|
||||
WHERE m.perms = #{permissionCode}
|
||||
AND m.del_flag = '0'
|
||||
AND m.status = '0'
|
||||
AND r.del_flag = '0'
|
||||
AND r.status = '0'
|
||||
AND u.deleted = '0'
|
||||
AND u.status = '0'
|
||||
ORDER BY u.user_id
|
||||
</select>
|
||||
|
||||
<!-- 🔧 新增:根据用户ID查询其拥有的出国审批权限列表 -->
|
||||
<select id="selectApprovalPermissionsByUserId" parameterType="Long" resultType="String">
|
||||
SELECT DISTINCT m.perms
|
||||
FROM sys_menu m
|
||||
INNER JOIN sys_role_menu rm ON m.menu_id = rm.menu_id
|
||||
INNER JOIN sys_role r ON rm.role_id = r.role_id
|
||||
INNER JOIN sys_user_role ur ON r.role_id = ur.role_id
|
||||
WHERE ur.user_id = #{userId}
|
||||
AND m.perms LIKE 'rs:overseas:approve%'
|
||||
AND m.status = '0'
|
||||
AND r.del_flag = '0'
|
||||
AND r.status = '0'
|
||||
ORDER BY m.perms
|
||||
</select>
|
||||
|
||||
<!-- 🔴 新增:查询待审批申请列表(支持部门过滤) -->
|
||||
<select id="selectPendingApplications" resultType="org.dromara.rs.domain.RsOverseasApplication">
|
||||
SELECT a.*
|
||||
FROM rs_overseas_application a
|
||||
INNER JOIN sys_user u ON a.applicant_id = u.user_id
|
||||
WHERE a.status = '0'
|
||||
AND a.deleted = '0'
|
||||
AND a.approval_level IN
|
||||
<foreach collection="approvalLevels" item="level" open="(" separator="," close=")">
|
||||
#{level}
|
||||
</foreach>
|
||||
<!-- 🔴 关键:部门过滤逻辑(仅对部门负责人生效) -->
|
||||
<if test="deptId != null">
|
||||
AND u.dept_id = #{deptId}
|
||||
</if>
|
||||
ORDER BY a.apply_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
+27
-27
@@ -232,22 +232,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 查询待审批的申请(有审批记录且状态为待审核的)
|
||||
-- 查询待审批的申请(使用current_approver_id查询当前审批人的待办)
|
||||
SELECT
|
||||
oa.approval_id,
|
||||
NULL as approval_id, -- 待审批申请没有审批记录ID
|
||||
app.application_id,
|
||||
oa.approver_id,
|
||||
oa.approver_name,
|
||||
oa.approval_level,
|
||||
oa.approval_status,
|
||||
oa.approval_opinion,
|
||||
oa.approval_time,
|
||||
oa.tenant_id,
|
||||
oa.create_by,
|
||||
oa.create_time,
|
||||
oa.update_by,
|
||||
oa.update_time,
|
||||
oa.deleted,
|
||||
app.current_approver_id as approver_id, -- 🔴 修复:使用申请表的当前审批人ID
|
||||
app.current_approver as approver_name, -- 🔴 修复:使用申请表的当前审批人名称
|
||||
app.approval_level, -- 🔴 修复:使用申请表的审批级别
|
||||
'0' as approval_status, -- 待审核状态
|
||||
NULL as approval_opinion,
|
||||
NULL as approval_time,
|
||||
app.tenant_id,
|
||||
app.create_by,
|
||||
app.create_time,
|
||||
app.update_by,
|
||||
app.update_time,
|
||||
app.deleted,
|
||||
-- 申请信息字段
|
||||
app.applicant_id,
|
||||
app.applicant_name,
|
||||
@@ -258,10 +258,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
app.end_date,
|
||||
app.duration,
|
||||
-- 文本转换
|
||||
CASE oa.approval_level
|
||||
WHEN '1' THEN '部门主管'
|
||||
WHEN '2' THEN '分管领导'
|
||||
WHEN '3' THEN '校领导'
|
||||
CASE app.approval_level
|
||||
WHEN '1' THEN '部门负责人'
|
||||
WHEN '2' THEN '人事处'
|
||||
WHEN '3' THEN '纪委'
|
||||
WHEN '4' THEN '学院分管领导'
|
||||
WHEN '5' THEN '学院党委书记'
|
||||
ELSE '未知级别'
|
||||
END as approval_level_text,
|
||||
'待审核' as approval_status_text,
|
||||
@@ -279,12 +281,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
ELSE '未知目的'
|
||||
END as purpose_text,
|
||||
'pending' as record_type
|
||||
FROM rs_overseas_approval oa
|
||||
INNER JOIN rs_overseas_application app ON oa.application_id = app.application_id
|
||||
WHERE oa.deleted = '0'
|
||||
AND app.deleted = '0'
|
||||
FROM rs_overseas_application app
|
||||
WHERE app.deleted = '0'
|
||||
AND app.status = '0' -- 申请状态:待审核
|
||||
AND oa.approval_status = '0' -- 审批状态:待审核
|
||||
<if test="applicationId != null">
|
||||
AND app.application_id = #{applicationId}
|
||||
</if>
|
||||
@@ -292,16 +291,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
AND app.applicant_name like concat('%', #{applicantName}, '%')
|
||||
</if>
|
||||
<if test="approvalLevel != null and approvalLevel != ''">
|
||||
AND oa.approval_level = #{approvalLevel}
|
||||
AND app.approval_level = #{approvalLevel}
|
||||
</if>
|
||||
<!-- 🔴 核心修复:使用申请表的当前审批人ID进行过滤 -->
|
||||
<if test="approverId != null">
|
||||
AND oa.approver_id = #{approverId}
|
||||
AND app.current_approver_id = #{approverId}
|
||||
</if>
|
||||
<if test="approverName != null and approverName != ''">
|
||||
AND oa.approver_name like concat('%', #{approverName}, '%')
|
||||
AND app.current_approver like concat('%', #{approverName}, '%')
|
||||
</if>
|
||||
<if test="tenantId != null and tenantId != ''">
|
||||
AND oa.tenant_id = #{tenantId}
|
||||
AND app.tenant_id = #{tenantId}
|
||||
</if>
|
||||
<!-- 部门权限过滤:只显示本部门申请人的待审批申请 -->
|
||||
<if test="deptId != null">
|
||||
|
||||
+181
-1
@@ -1061,4 +1061,184 @@ PDF模板包含以下空白填写区域(完全手工填写):
|
||||
**🆕 更新日志**:
|
||||
- 2025-10-17 新增党籍保留PDF空白模板下载功能(线下手工填写)
|
||||
- 接口路径调整:从 `/application/downloadPartyRetentionTemplate/{id}` 改为 `/record/downloadPartyRetention`
|
||||
- 模板类型变更:从预填充模板改为完全空白模板
|
||||
- 模板类型变更:从预填充模板改为完全空白模板
|
||||
|
||||
---
|
||||
|
||||
## 附录:工作流集成说明
|
||||
|
||||
### 动态审批人方案
|
||||
|
||||
#### 背景
|
||||
|
||||
出国申请业务集成了Warm-Flow工作流引擎,审批流程为:**发起人 → 部门领导 → 校领导**。审批人根据申请人所属部门动态确定,系统需要实时查询当前待审批人信息。
|
||||
|
||||
#### 方案设计
|
||||
|
||||
##### 1. 数据库字段说明
|
||||
|
||||
`rs_overseas_application` 表中的 `current_approver_id` 字段:
|
||||
|
||||
- **字段类型**:`bigint(20)`
|
||||
- **字段作用**:**冗余展示字段**(非核心业务字段)
|
||||
- **维护方式**:不再由后端业务代码维护
|
||||
- **数据来源**:前端通过工作流API实时查询获取
|
||||
- **设计原因**:
|
||||
- 审批人由工作流引擎动态确定,工作流表 `flow_node_user` 是唯一数据源
|
||||
- 避免数据冗余和不一致问题
|
||||
- 简化后端业务逻辑,降低维护成本
|
||||
|
||||
##### 2. 后端实现
|
||||
|
||||
**核心原则**:后端不维护 `current_approver_id` 字段
|
||||
|
||||
```java
|
||||
// OverseasApplicationServiceImpl.java
|
||||
|
||||
// ✅ 新增申请:不设置 current_approver_id
|
||||
public Long addOverseasApplication(OverseasApplicationBo bo) {
|
||||
// ... 业务逻辑
|
||||
// 不再包含:application.setCurrentApproverId(xxx);
|
||||
}
|
||||
|
||||
// ✅ 提交审批:不设置 current_approver_id
|
||||
public R<Void> submitApplication(Long id) {
|
||||
// ... 提交工作流
|
||||
// 不再包含:application.setCurrentApproverId(xxx);
|
||||
}
|
||||
|
||||
// ✅ 审批通过:不设置 current_approver_id
|
||||
public R<Void> approve(Long id, String remark) {
|
||||
// ... 审批逻辑
|
||||
// 不再包含:application.setCurrentApproverId(xxx);
|
||||
}
|
||||
```
|
||||
|
||||
**代码清理**:
|
||||
|
||||
- 所有 `setCurrentApproverId()` 调用已移除
|
||||
- 相关查询逻辑已删除
|
||||
- 字段仅作为数据库表结构保留(历史兼容)
|
||||
|
||||
##### 3. 前端实现
|
||||
|
||||
**核心方案**:通过工作流API实时查询当前审批人
|
||||
|
||||
```typescript
|
||||
// overseasApplication/index.vue
|
||||
|
||||
// 方案一:列表查询时批量获取审批人(推荐)
|
||||
const getList = async () => {
|
||||
const response = await listOverseasApplication(queryParams.value);
|
||||
dataList.value = response.rows;
|
||||
total.value = response.total;
|
||||
|
||||
// 批量查询审批人信息
|
||||
await batchGetCurrentApproverNames();
|
||||
};
|
||||
|
||||
// 批量获取审批人姓名
|
||||
const batchGetCurrentApproverNames = async () => {
|
||||
const promises = dataList.value
|
||||
.filter(item => item.status === 'processing')
|
||||
.map(async item => {
|
||||
try {
|
||||
// 调用工作流API查询当前审批人
|
||||
const approvers = await getCurrentApproversForTask(item.flowProcessId);
|
||||
item.currentApproverName = approvers.map(u => u.name).join('、');
|
||||
} catch (error) {
|
||||
item.currentApproverName = '-';
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
};
|
||||
|
||||
// 方案二:详情查询时单独获取审批人
|
||||
const handleViewDetail = async (row: OverseasApplicationVo) => {
|
||||
currentRow.value = row;
|
||||
|
||||
// 如果流程进行中,查询当前审批人
|
||||
if (row.flowProcessId && row.status === 'processing') {
|
||||
try {
|
||||
const approvers = await getCurrentApproversForTask(row.flowProcessId);
|
||||
currentRow.value.currentApproverName = approvers.map(u => u.name).join('、');
|
||||
} catch (error) {
|
||||
currentRow.value.currentApproverName = '查询失败';
|
||||
}
|
||||
}
|
||||
|
||||
detailDialogVisible.value = true;
|
||||
};
|
||||
```
|
||||
|
||||
**工作流API调用**:
|
||||
|
||||
```typescript
|
||||
// 查询当前审批人(从工作流引擎获取)
|
||||
import { getCurrentApproversForTask } from '@/api/workflow/common';
|
||||
|
||||
// API 路径:/api/workflow/instance/{processId}/current-approvers
|
||||
// 返回格式:
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": [
|
||||
{
|
||||
"userId": 1001,
|
||||
"userName": "张三",
|
||||
"nodeId": 2,
|
||||
"nodeName": "部门领导审批"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
##### 4. 接口改造
|
||||
|
||||
相关API接口响应中的 `current_approver_id` 字段说明:
|
||||
|
||||
| 接口 | 字段说明 | 使用建议 |
|
||||
|------|---------|---------|
|
||||
| 查询列表 | 返回null或历史值 | 忽略,通过工作流API获取 |
|
||||
| 查询详情 | 返回null或历史值 | 忽略,通过工作流API获取 |
|
||||
| 新增/修改 | 不处理该字段 | 前端不传递 |
|
||||
| 提交审批 | 不处理该字段 | 前端不传递 |
|
||||
|
||||
##### 5. 优势分析
|
||||
|
||||
**✅ 数据一致性**
|
||||
- 工作流表是唯一数据源,避免双写不一致
|
||||
- 审批人变更(如转办、委派)自动生效
|
||||
|
||||
**✅ 降低维护成本**
|
||||
- 后端无需在多个业务方法中同步更新
|
||||
- 减少代码复杂度和潜在Bug
|
||||
|
||||
**✅ 实时性**
|
||||
- 前端每次查询都获取最新审批人
|
||||
- 支持工作流引擎的高级功能(并行审批、会签等)
|
||||
|
||||
**✅ 扩展性**
|
||||
- 审批流程调整时,前端无需修改
|
||||
- 支持更复杂的审批场景(多人会签、或签等)
|
||||
|
||||
#### 实施步骤
|
||||
|
||||
1. ✅ **后端改造**:移除所有 `current_approver_id` 字段的赋值代码
|
||||
2. ✅ **前端改造**:实现基于工作流API的动态查询
|
||||
3. ⏳ **测试验证**:确保列表、详情页面正确显示审批人
|
||||
4. ⏳ **文档更新**:同步更新API文档和技术文档
|
||||
|
||||
#### 注意事项
|
||||
|
||||
- 历史数据中的 `current_approver_id` 字段可能存在脏数据,前端应忽略
|
||||
- 工作流API调用失败时,前端应显示友好提示(如 "-" 或 "查询失败")
|
||||
- 性能优化:列表页建议使用批量查询,避免N+1查询问题
|
||||
- 缓存策略:同一个流程实例的审批人信息可短时间缓存(如30秒)
|
||||
|
||||
---
|
||||
|
||||
**更新时间**:2025-10-28
|
||||
**维护人员**:开发团队
|
||||
**变更记录**:新增工作流动态审批人方案说明
|
||||
@@ -132,7 +132,7 @@
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
@pagination="applyFilterAndPagination"
|
||||
/>
|
||||
</el-card>
|
||||
</el-card>
|
||||
@@ -344,10 +344,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="OverseasApproval">
|
||||
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue';
|
||||
import { ref, reactive, toRefs, onMounted, getCurrentInstance, computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import {
|
||||
listOverseasApplication,
|
||||
listPendingOverseasApplication,
|
||||
getOverseasApplication,
|
||||
approveOverseasApplication,
|
||||
listOverseasAttachments,
|
||||
@@ -372,7 +372,8 @@ const viewAttachmentList = ref<OverseasAttachmentVO[]>([]);
|
||||
const state = reactive({
|
||||
// 列表相关
|
||||
loading: false,
|
||||
applicationList: [] as OverseasApplicationVO[],
|
||||
allApplicationList: [] as OverseasApplicationVO[], // 🔴 新增:存储所有待审批数据
|
||||
applicationList: [] as OverseasApplicationVO[], // 过滤和分页后的数据
|
||||
total: 0,
|
||||
showSearch: true,
|
||||
queryParams: {
|
||||
@@ -428,12 +429,20 @@ onMounted(() => {
|
||||
const getList = async () => {
|
||||
state.loading = true;
|
||||
try {
|
||||
const response = await listOverseasApplication(state.queryParams);
|
||||
state.applicationList = response.rows || [];
|
||||
state.total = response.total || 0;
|
||||
// 🔴 修复:使用待审批接口,只返回当前用户审批级别的待审批数据
|
||||
const response = await listPendingOverseasApplication();
|
||||
|
||||
// 存储所有待审批数据
|
||||
state.allApplicationList = response.data || [];
|
||||
|
||||
// 应用本地过滤和分页
|
||||
applyFilterAndPagination();
|
||||
|
||||
console.log('✅ 成功加载待审批申请列表:', state.allApplicationList.length, '条');
|
||||
} catch (error: any) {
|
||||
console.error('获取申请列表失败:', error);
|
||||
console.error('❌ 获取申请列表失败:', error);
|
||||
ElMessage.error('获取申请列表失败');
|
||||
state.allApplicationList = [];
|
||||
state.applicationList = [];
|
||||
state.total = 0;
|
||||
} finally {
|
||||
@@ -441,10 +450,52 @@ const getList = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 应用本地过滤和分页
|
||||
const applyFilterAndPagination = () => {
|
||||
let filteredList = [...state.allApplicationList];
|
||||
|
||||
// 🔴 应用搜索过滤
|
||||
if (state.queryParams.applicantName) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.applicantName?.includes(state.queryParams.applicantName || '')
|
||||
);
|
||||
}
|
||||
|
||||
if (state.queryParams.department) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.department?.includes(state.queryParams.department || '')
|
||||
);
|
||||
}
|
||||
|
||||
if (state.queryParams.destination) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.destination?.includes(state.queryParams.destination || '')
|
||||
);
|
||||
}
|
||||
|
||||
if (state.queryParams.status) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.status === state.queryParams.status
|
||||
);
|
||||
}
|
||||
|
||||
// 更新总数
|
||||
state.total = filteredList.length;
|
||||
|
||||
// 🔴 应用分页
|
||||
const { pageNum, pageSize } = state.queryParams;
|
||||
const start = (pageNum - 1) * pageSize;
|
||||
const end = start + pageSize;
|
||||
state.applicationList = filteredList.slice(start, end);
|
||||
|
||||
console.log(`📄 分页结果: 总计 ${state.total} 条,当前显示第 ${pageNum} 页,共 ${state.applicationList.length} 条`);
|
||||
};
|
||||
|
||||
// 搜索查询
|
||||
const handleQuery = () => {
|
||||
state.queryParams.pageNum = 1;
|
||||
getList();
|
||||
// 🔴 修复:本地过滤,无需重新请求数据
|
||||
applyFilterAndPagination();
|
||||
};
|
||||
|
||||
// 重置搜索
|
||||
|
||||
Reference in new issue
Block a user