Merge branch 'master' of http://101.35.245.122:3000/hzdyjs-xg/all-project
This commit is contained in:
commit
3e6349112c
19 files changed
+1396
-10
No files matched your search
@@ -632,6 +632,12 @@ const handleStartWorkFlow = async (businessData: any) => {
|
||||
// - 退回 (backProcess)
|
||||
```
|
||||
|
||||
**🔴 退回残留任务清理(强制性,2026-10-15)**:
|
||||
|
||||
- `backProcess` 在 `skip(REJECT)` 后必须清理同实例下非目标节点残留 `flow_task`/`flow_user`(`cleanResidualTasksAfterBack`)
|
||||
- 草稿/撤销/退回重新提交时,`startWorkFlow` 需自愈多任务脏数据并按实例状态解析正确 taskId(`healResidualTasksOnRestart`)
|
||||
- 背景:退回后若残留原审批节点 + draft 申请人任务,移动端再提交会报「启动工作流失败」
|
||||
|
||||
### 3. 流程撤销
|
||||
|
||||
```typescript
|
||||
|
||||
+140
-2
@@ -112,12 +112,18 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
.eq(FlowInstance::getBusinessId, businessId));
|
||||
if (ObjectUtil.isNotNull(flowInstance)) {
|
||||
BusinessStatusEnum.checkStartStatus(flowInstance.getFlowStatus());
|
||||
// 草稿/撤销/退回重新提交前,清理历史残留待办,避免取到错误 taskId
|
||||
healResidualTasksOnRestart(flowInstance);
|
||||
List<Task> taskList = taskService.list(new FlowTask().setInstanceId(flowInstance.getId()));
|
||||
if (CollUtil.isEmpty(taskList)) {
|
||||
throw new ServiceException("当前流程无待办任务,无法重新提交,请联系管理员");
|
||||
}
|
||||
Task currentTask = resolveRestartTask(taskList, flowInstance);
|
||||
taskService.mergeVariable(flowInstance, variables);
|
||||
insService.updateById(flowInstance);
|
||||
StartProcessReturnDTO dto = new StartProcessReturnDTO();
|
||||
dto.setProcessInstanceId(taskList.get(0).getInstanceId());
|
||||
dto.setTaskId(taskList.get(0).getId());
|
||||
dto.setProcessInstanceId(currentTask.getInstanceId());
|
||||
dto.setTaskId(currentTask.getId());
|
||||
return dto;
|
||||
}
|
||||
FlowParams flowParams = FlowParams.build()
|
||||
@@ -421,6 +427,9 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
.hisTaskExt(bo.getFileId());
|
||||
taskService.skip(task.getId(), flowParams);
|
||||
|
||||
// 退回后清理残留待办(原节点未删干净、历史 draft 申请人任务等)
|
||||
cleanResidualTasksAfterBack(task.getInstanceId(), bo.getNodeCode());
|
||||
|
||||
// 保存手写签名到历史任务表(驳回场景)
|
||||
if (StringUtils.isNotBlank(bo.getSignature())) {
|
||||
flwHisTaskExtMapper.updateSignatureByTaskId(taskId, bo.getSignature());
|
||||
@@ -433,6 +442,135 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退回后清理残留待办:仅保留目标节点上最新有效任务,删除其余 flow_task 及关联 flow_user。
|
||||
* <p>
|
||||
* warm-flow skip(REJECT) 后偶发残留原审批节点任务、以及启动时留下的 draft 申请人任务,
|
||||
* 导致学生重新提交时 startWorkFlow 取到错误 taskId,移动端提示「启动工作流失败」。
|
||||
*
|
||||
* @param instanceId 流程实例ID
|
||||
* @param targetNodeCode 退回目标节点编码
|
||||
*/
|
||||
private void cleanResidualTasksAfterBack(Long instanceId, String targetNodeCode) {
|
||||
List<FlowTask> tasks = selectByInstId(instanceId);
|
||||
if (CollUtil.isEmpty(tasks) || tasks.size() == 1) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isBlank(targetNodeCode)) {
|
||||
log.warn("退回清理跳过:目标节点编码为空, instanceId={}", instanceId);
|
||||
return;
|
||||
}
|
||||
|
||||
Comparator<FlowTask> newestFirst = Comparator
|
||||
.comparing(FlowTask::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder()))
|
||||
.thenComparing(FlowTask::getId, Comparator.nullsLast(Comparator.reverseOrder()));
|
||||
|
||||
List<FlowTask> targetTasks = tasks.stream()
|
||||
.filter(t -> StringUtils.equals(targetNodeCode, t.getNodeCode()))
|
||||
.sorted(newestFirst)
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(targetTasks)) {
|
||||
log.warn("退回清理未找到目标节点任务, instanceId={}, targetNodeCode={}, remain={}",
|
||||
instanceId, targetNodeCode, StreamUtils.toList(tasks, FlowTask::getId));
|
||||
return;
|
||||
}
|
||||
|
||||
// 优先保留目标节点上状态为 back 的最新任务,否则取目标节点最新一条
|
||||
FlowTask keepTask = targetTasks.stream()
|
||||
.filter(t -> TaskStatusEnum.BACK.getStatus().equals(t.getFlowStatus()))
|
||||
.findFirst()
|
||||
.orElse(targetTasks.get(0));
|
||||
|
||||
List<Long> deleteIds = tasks.stream()
|
||||
.map(FlowTask::getId)
|
||||
.filter(id -> !Objects.equals(id, keepTask.getId()))
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(deleteIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("退回后清理残留任务 instanceId={}, keepTaskId={}, keepNode={}, deleteTaskIds={}",
|
||||
instanceId, keepTask.getId(), keepTask.getNodeName(), deleteIds);
|
||||
deleteTasksWithUsers(deleteIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 草稿/撤销/退回重新提交前,清理同实例下多余残留待办,只保留与实例状态匹配的有效任务。
|
||||
*/
|
||||
private void healResidualTasksOnRestart(FlowInstance flowInstance) {
|
||||
if (!BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) {
|
||||
return;
|
||||
}
|
||||
List<FlowTask> tasks = selectByInstId(flowInstance.getId());
|
||||
if (CollUtil.isEmpty(tasks) || tasks.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
String status = flowInstance.getFlowStatus();
|
||||
String applyNodeCode = flwCommonService.applyNodeCode(flowInstance.getDefinitionId());
|
||||
Comparator<FlowTask> newestFirst = Comparator
|
||||
.comparing(FlowTask::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder()))
|
||||
.thenComparing(FlowTask::getId, Comparator.nullsLast(Comparator.reverseOrder()));
|
||||
|
||||
FlowTask keepTask = tasks.stream()
|
||||
.filter(t -> status.equals(t.getFlowStatus()))
|
||||
.filter(t -> StringUtils.isBlank(applyNodeCode) || applyNodeCode.equals(t.getNodeCode()))
|
||||
.sorted(newestFirst)
|
||||
.findFirst()
|
||||
.orElseGet(() -> tasks.stream()
|
||||
.filter(t -> status.equals(t.getFlowStatus()))
|
||||
.sorted(newestFirst)
|
||||
.findFirst()
|
||||
.orElse(null));
|
||||
if (keepTask == null) {
|
||||
log.warn("重新提交自愈未找到匹配状态任务, instanceId={}, status={}, remain={}",
|
||||
flowInstance.getId(), status, StreamUtils.toList(tasks, FlowTask::getId));
|
||||
return;
|
||||
}
|
||||
|
||||
List<Long> deleteIds = tasks.stream()
|
||||
.map(FlowTask::getId)
|
||||
.filter(id -> !Objects.equals(id, keepTask.getId()))
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(deleteIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("重新提交前清理残留任务 instanceId={}, keepTaskId={}, keepNode={}, deleteTaskIds={}",
|
||||
flowInstance.getId(), keepTask.getId(), keepTask.getNodeName(), deleteIds);
|
||||
deleteTasksWithUsers(deleteIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从待办列表中解析重新提交应使用的任务(多任务时优先匹配实例状态)。
|
||||
*/
|
||||
private Task resolveRestartTask(List<Task> taskList, FlowInstance flowInstance) {
|
||||
if (taskList.size() == 1) {
|
||||
return taskList.get(0);
|
||||
}
|
||||
String status = flowInstance.getFlowStatus();
|
||||
List<Task> matched = taskList.stream()
|
||||
.filter(t -> status.equals(t.getFlowStatus()))
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(matched)) {
|
||||
return matched.get(0);
|
||||
}
|
||||
log.warn("重新提交存在多个待办且无法按状态匹配, instanceId={}, status={}, taskIds={}",
|
||||
flowInstance.getId(), status, StreamUtils.toList(taskList, Task::getId));
|
||||
return taskList.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除待办任务及其审批人关联。
|
||||
*/
|
||||
private void deleteTasksWithUsers(List<Long> taskIds) {
|
||||
if (CollUtil.isEmpty(taskIds)) {
|
||||
return;
|
||||
}
|
||||
FlowEngine.userService().deleteByTaskIds(taskIds);
|
||||
flowTaskMapper.deleteByIds(taskIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可驳回的前置节点
|
||||
*
|
||||
|
||||
+22
-2
@@ -245,7 +245,16 @@ public class XgHolidayStayServiceImpl implements IXgHolidayStayService {
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(XgHolidayStay entity) {
|
||||
// TODO 做一些数据校验,如唯一约束
|
||||
// 库表 student_phone / emergency_* 为 NOT NULL;null 会被 MyBatis 跳过导致 SQLException
|
||||
if (StringUtils.isBlank(entity.getStudentPhone())) {
|
||||
throw new ServiceException("学生联系电话不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(entity.getEmergencyContact())) {
|
||||
throw new ServiceException("紧急联系人不能为空");
|
||||
}
|
||||
if (StringUtils.isBlank(entity.getEmergencyPhone())) {
|
||||
throw new ServiceException("紧急联系电话不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -787,6 +796,16 @@ public class XgHolidayStayServiceImpl implements IXgHolidayStayService {
|
||||
if (bo.getBedId() == null || bo.getRoomId() == null) {
|
||||
throw new ServiceException("未查询到当前在住宿舍/床位信息,请先完成床位分配后再申请留宿");
|
||||
}
|
||||
// student_phone / emergency_* 为库表 NOT NULL,空值会被 MyBatis 跳过导致 SQL 报错
|
||||
if (StringUtils.isBlank(bo.getStudentPhone())) {
|
||||
throw new ServiceException("请填写联系电话");
|
||||
}
|
||||
if (StringUtils.isBlank(bo.getEmergencyContact())) {
|
||||
throw new ServiceException("请填写紧急联系人");
|
||||
}
|
||||
if (StringUtils.isBlank(bo.getEmergencyPhone())) {
|
||||
throw new ServiceException("请填写紧急联系电话");
|
||||
}
|
||||
bo.setApplyStatus("1");
|
||||
bo.setApplyTime(new Date());
|
||||
bo.setAuditorId(null);
|
||||
@@ -903,7 +922,8 @@ public class XgHolidayStayServiceImpl implements IXgHolidayStayService {
|
||||
}
|
||||
}
|
||||
bo.setCollegeName(student.getCollegeName());
|
||||
if (StringUtils.isBlank(bo.getStudentPhone())) {
|
||||
// 仅在档案有电话时回填,避免把表单空串覆盖成 null 导致 INSERT 省略该字段
|
||||
if (StringUtils.isBlank(bo.getStudentPhone()) && StringUtils.isNotBlank(student.getPhone())) {
|
||||
bo.setStudentPhone(student.getPhone());
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -1,5 +1,6 @@
|
||||
package org.dromara.xg.service.impl;
|
||||
|
||||
import org.dromara.common.core.enums.BusinessStatusEnum;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
@@ -144,6 +145,7 @@ public class XgStudentCancelLeaveServiceImpl implements IXgStudentCancelLeaveSer
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public XgStudentCancelLeaveVo insertByBo(XgStudentCancelLeaveBo bo) {
|
||||
bo.setCancelStatus(resolveCancelStatusForSave(null, bo.getCancelStatus()));
|
||||
XgStudentCancelLeave add = MapstructUtils.convert(bo, XgStudentCancelLeave.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
@@ -178,6 +180,12 @@ public class XgStudentCancelLeaveServiceImpl implements IXgStudentCancelLeaveSer
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateByBo(XgStudentCancelLeaveBo bo) {
|
||||
if (bo.getId() != null) {
|
||||
XgStudentCancelLeave existing = baseMapper.selectById(bo.getId());
|
||||
if (existing != null) {
|
||||
bo.setCancelStatus(resolveCancelStatusForSave(existing.getCancelStatus(), bo.getCancelStatus()));
|
||||
}
|
||||
}
|
||||
XgStudentCancelLeave update = MapstructUtils.convert(bo, XgStudentCancelLeave.class);
|
||||
validEntityBeforeSave(update);
|
||||
boolean flag = baseMapper.updateById(update) > 0;
|
||||
@@ -200,6 +208,34 @@ public class XgStudentCancelLeaveServiceImpl implements IXgStudentCancelLeaveSer
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 销假保存时的状态。
|
||||
* 请假单上的 0/1/2/3 是「未销假、已销假、逾期、无需销假」,不能当作流程状态写入。
|
||||
* 流程已进入待审核、退回、完成等状态后,再次保存销假内容不得把状态盖回去。
|
||||
*/
|
||||
private String resolveCancelStatusForSave(String existingStatus, String incomingStatus) {
|
||||
if (isWorkflowOwnedStatus(existingStatus)) {
|
||||
return existingStatus;
|
||||
}
|
||||
if (StringUtils.isBlank(incomingStatus)
|
||||
|| "0".equals(incomingStatus)
|
||||
|| "1".equals(incomingStatus)
|
||||
|| "2".equals(incomingStatus)
|
||||
|| "3".equals(incomingStatus)) {
|
||||
return BusinessStatusEnum.DRAFT.getStatus();
|
||||
}
|
||||
return incomingStatus;
|
||||
}
|
||||
|
||||
private boolean isWorkflowOwnedStatus(String status) {
|
||||
return BusinessStatusEnum.WAITING.getStatus().equals(status)
|
||||
|| BusinessStatusEnum.FINISH.getStatus().equals(status)
|
||||
|| BusinessStatusEnum.INVALID.getStatus().equals(status)
|
||||
|| BusinessStatusEnum.TERMINATION.getStatus().equals(status)
|
||||
|| BusinessStatusEnum.BACK.getStatus().equals(status)
|
||||
|| BusinessStatusEnum.CANCEL.getStatus().equals(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
|
||||
+38
@@ -561,9 +561,47 @@ public class XgStudentLeaveServiceImpl implements IXgStudentLeaveService {
|
||||
*
|
||||
* @param processTaskEvent 参数
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@EventListener(condition = "#processTaskEvent.flowCode.startsWith('hzdyjs-xj')")
|
||||
public void processTaskHandler_xj(ProcessTaskEvent processTaskEvent) {
|
||||
log.info("当前任务创建了{}", processTaskEvent.toString());
|
||||
if (StringUtils.isBlank(processTaskEvent.getBusinessId())) {
|
||||
return;
|
||||
}
|
||||
if (!BusinessStatusEnum.WAITING.getStatus().equals(processTaskEvent.getStatus())) {
|
||||
return;
|
||||
}
|
||||
XgStudentCancelLeave cancelLeave = xgStudentCancelLeaveMapper
|
||||
.selectById(Long.valueOf(processTaskEvent.getBusinessId()));
|
||||
if (ObjectUtil.isNull(cancelLeave) || !shouldAlignCancelStatusToWaiting(cancelLeave.getCancelStatus())) {
|
||||
return;
|
||||
}
|
||||
String previousStatus = cancelLeave.getCancelStatus();
|
||||
cancelLeave.setCancelStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
xgStudentCancelLeaveMapper.updateById(cancelLeave);
|
||||
if (cancelLeave.getLeaveId() != null) {
|
||||
XgStudentLeave leave = baseMapper.selectById(cancelLeave.getLeaveId());
|
||||
if (ObjectUtil.isNotNull(leave)) {
|
||||
leave.setCancelStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
baseMapper.updateById(leave);
|
||||
}
|
||||
}
|
||||
log.info("销假业务状态已对齐为 waiting, businessId={}, taskId={}, nodeName={}, previousStatus={}",
|
||||
processTaskEvent.getBusinessId(), processTaskEvent.getTaskId(), processTaskEvent.getNodeName(),
|
||||
previousStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 销假流程状态尚未写成 waiting 时需要对齐。
|
||||
* 0/1/2/3 是请假单上的旧销假字典,draft 是提交标记丢失后停留的草稿。
|
||||
*/
|
||||
private boolean shouldAlignCancelStatusToWaiting(String cancelStatus) {
|
||||
return StringUtils.isBlank(cancelStatus)
|
||||
|| "0".equals(cancelStatus)
|
||||
|| "1".equals(cancelStatus)
|
||||
|| "2".equals(cancelStatus)
|
||||
|| "3".equals(cancelStatus)
|
||||
|| BusinessStatusEnum.DRAFT.getStatus().equals(cancelStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# 假期留宿管理 API
|
||||
|
||||
## 学生申请留宿
|
||||
|
||||
- **接口**: `POST /holidayStay/holidayStay/apply`
|
||||
- **权限**: `holidayStay:holidayStay:apply`
|
||||
|
||||
### 必填业务字段(库表 NOT NULL)
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| holidayType | 假期类型 |
|
||||
| applyStartDate / applyEndDate | 留宿起止时间 |
|
||||
| stayReason | 留宿原因 |
|
||||
| studentPhone | 学生联系电话(档案无电话时须前端手动填写) |
|
||||
| emergencyContact | 紧急联系人 |
|
||||
| emergencyPhone | 紧急联系电话 |
|
||||
|
||||
> **说明(2026-10-15)**:
|
||||
> - 库表已支持 `student_phone` 可空(见 `docs/设计文档/database/假期留宿_student_phone允许为空.sql`),仅执行 SQL 即可先解除线上报错、无需发版。
|
||||
> - 代码侧仍建议保留校验/友好提示;档案 `phone` 为空时不会把表单空串覆盖为 `null`。
|
||||
|
||||
### 自动填充
|
||||
|
||||
- 学生信息快照:学号/姓名/班级/专业/学院(按当前登录学生)
|
||||
- 宿舍快照:当前在住床位(无床位则拒绝申请)
|
||||
- 申请状态:`1`(待审批)
|
||||
@@ -307,6 +307,8 @@
|
||||
|
||||
**事务保证**:使用 `@Transactional` 注解确保两个表的更新操作要么全部成功,要么全部回滚。
|
||||
|
||||
**状态保护**(2026-10-19):`cancelStatus` 在销假流程中使用 `draft`、`waiting`、`finish` 等流程状态。请假单上的 `0/1/2/3`(未销假、已销假、逾期未销假、无需销假)传入本接口时按 `draft` 保存,不会写入销假单。销假单已是 `waiting`、`back`、`cancel`、`finish`、`invalid`、`termination` 时,再次保存销假内容不会覆盖该状态。审批任务创建且流程为待审核时,若业务状态仍是旧字典值或 `draft`,会自动对齐为 `waiting`。
|
||||
|
||||
### 5. 删除销假
|
||||
|
||||
- **接口路径**:`DELETE /studentCancelLeave/studentCancelLeave/{ids}`
|
||||
|
||||
@@ -1045,12 +1045,22 @@ public class TestLeaveController {
|
||||
1. 流程定义未发布
|
||||
2. 流程编码不存在
|
||||
3. 业务数据状态不正确
|
||||
4. **退回后残留多个 `flow_task`**(原审批节点未清、历史 draft 申请人任务),重新提交时取到错误 taskId,移动端统一提示「启动工作流失败」
|
||||
|
||||
**解决**:
|
||||
|
||||
1. 检查流程定义是否已发布
|
||||
2. 确认 `flowCode` 参数正确
|
||||
3. 确保业务数据状态为 `draft`
|
||||
3. 确保业务数据状态为 `draft` / `back` / `cancel`(可重新提交)
|
||||
4. **退回清理(已实现)**:`FlwTaskServiceImpl.backProcess` 在 `skip(REJECT)` 后调用 `cleanResidualTasksAfterBack`,只保留退回目标节点最新有效任务;重新提交时 `healResidualTasksOnRestart` 自愈历史脏数据
|
||||
|
||||
**排查 SQL 示例**(同一 `instance_id` 不应长期存在多条无关待办):
|
||||
|
||||
```sql
|
||||
SELECT id, node_name, flow_status, create_time
|
||||
FROM flow_task
|
||||
WHERE instance_id = ? AND IFNULL(del_flag, '0') = '0';
|
||||
```
|
||||
|
||||
### 9.5 日期格式问题
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
-- =============================================================================
|
||||
-- 将入学年份为 2026 或年级为 2026 的学生「是否住校」统一改为「是」
|
||||
--
|
||||
-- 目标表字段:
|
||||
-- xg_student_msg.is_boarder 0-否,1-是
|
||||
-- xg_student_msg.enrollment_year / grade
|
||||
-- 同时兼容班级表 xg_class_msg.enrollment_year / grade(学生字段为空时以班级为准)
|
||||
--
|
||||
-- 用法:
|
||||
-- mysql -h <host> -u root -p hzdyjs_xg < docs/数据库脚本/2026-10-16-xg_student_msg-set-boarder-2026.sql
|
||||
--
|
||||
-- 建议:先执行「一、预览」确认影响范围,再执行「二、更新」
|
||||
-- =============================================================================
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 一、预览:命中范围与当前住校分布
|
||||
-- -----------------------------------------------------------------------------
|
||||
|
||||
SELECT '========== 1. 命中学生数量(含已是住校)==========' AS section;
|
||||
|
||||
SELECT COUNT(*) AS match_total
|
||||
FROM xg_student_msg s
|
||||
LEFT JOIN xg_class_msg c
|
||||
ON c.deleted = 0
|
||||
AND NULLIF(TRIM(s.class_id), '') IS NOT NULL
|
||||
AND c.id = CAST(NULLIF(TRIM(s.class_id), '') AS UNSIGNED)
|
||||
WHERE s.deleted = 0
|
||||
AND (
|
||||
s.enrollment_year = 2026
|
||||
OR s.grade = '2026'
|
||||
OR c.enrollment_year = 2026
|
||||
OR c.grade = '2026'
|
||||
);
|
||||
|
||||
SELECT '========== 2. 命中且尚未住校(将被更新)==========' AS section;
|
||||
|
||||
SELECT COUNT(*) AS need_update_count
|
||||
FROM xg_student_msg s
|
||||
LEFT JOIN xg_class_msg c
|
||||
ON c.deleted = 0
|
||||
AND NULLIF(TRIM(s.class_id), '') IS NOT NULL
|
||||
AND c.id = CAST(NULLIF(TRIM(s.class_id), '') AS UNSIGNED)
|
||||
WHERE s.deleted = 0
|
||||
AND IFNULL(s.is_boarder, 0) <> 1
|
||||
AND (
|
||||
s.enrollment_year = 2026
|
||||
OR s.grade = '2026'
|
||||
OR c.enrollment_year = 2026
|
||||
OR c.grade = '2026'
|
||||
);
|
||||
|
||||
SELECT '========== 3. 命中明细(抽样核对)==========' AS section;
|
||||
|
||||
SELECT
|
||||
s.id,
|
||||
s.student_no,
|
||||
s.name,
|
||||
s.enrollment_year AS student_enrollment_year,
|
||||
s.grade AS student_grade,
|
||||
c.enrollment_year AS class_enrollment_year,
|
||||
c.grade AS class_grade,
|
||||
s.is_boarder,
|
||||
s.class_name,
|
||||
s.college_name,
|
||||
s.student_status
|
||||
FROM xg_student_msg s
|
||||
LEFT JOIN xg_class_msg c
|
||||
ON c.deleted = 0
|
||||
AND NULLIF(TRIM(s.class_id), '') IS NOT NULL
|
||||
AND c.id = CAST(NULLIF(TRIM(s.class_id), '') AS UNSIGNED)
|
||||
WHERE s.deleted = 0
|
||||
AND (
|
||||
s.enrollment_year = 2026
|
||||
OR s.grade = '2026'
|
||||
OR c.enrollment_year = 2026
|
||||
OR c.grade = '2026'
|
||||
)
|
||||
ORDER BY s.enrollment_year, s.student_no
|
||||
LIMIT 200;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 二、更新:是否住校 -> 是(1)
|
||||
-- -----------------------------------------------------------------------------
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
UPDATE xg_student_msg s
|
||||
LEFT JOIN xg_class_msg c
|
||||
ON c.deleted = 0
|
||||
AND NULLIF(TRIM(s.class_id), '') IS NOT NULL
|
||||
AND c.id = CAST(NULLIF(TRIM(s.class_id), '') AS UNSIGNED)
|
||||
SET
|
||||
s.is_boarder = 1,
|
||||
s.update_time = NOW()
|
||||
WHERE s.deleted = 0
|
||||
AND IFNULL(s.is_boarder, 0) <> 1
|
||||
AND (
|
||||
s.enrollment_year = 2026
|
||||
OR s.grade = '2026'
|
||||
OR c.enrollment_year = 2026
|
||||
OR c.grade = '2026'
|
||||
);
|
||||
|
||||
-- 核对更新结果(事务内)
|
||||
SELECT ROW_COUNT() AS updated_rows;
|
||||
|
||||
SELECT COUNT(*) AS still_not_boarder
|
||||
FROM xg_student_msg s
|
||||
LEFT JOIN xg_class_msg c
|
||||
ON c.deleted = 0
|
||||
AND NULLIF(TRIM(s.class_id), '') IS NOT NULL
|
||||
AND c.id = CAST(NULLIF(TRIM(s.class_id), '') AS UNSIGNED)
|
||||
WHERE s.deleted = 0
|
||||
AND IFNULL(s.is_boarder, 0) <> 1
|
||||
AND (
|
||||
s.enrollment_year = 2026
|
||||
OR s.grade = '2026'
|
||||
OR c.enrollment_year = 2026
|
||||
OR c.grade = '2026'
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- 可选:仅预览不更新时,把上面 TRANSACTION 整段注释掉,或改为 ROLLBACK
|
||||
@@ -0,0 +1,342 @@
|
||||
-- ============================================================
|
||||
-- 临时权限修复:学生管理员设置「分配管理范围」
|
||||
-- 背景:
|
||||
-- 页面:学生管理员设置 / 自定义管理员 / 为【xxx】分配管理范围
|
||||
-- 提交接口:POST /xgStudentManagerSource/studentManagerSource/grantDeptAuth
|
||||
-- 后端权限:xgStudentManagerSource:studentManagerSource:grantDeptAuth
|
||||
-- 前端无按钮权限控制,点确定后接口 403:
|
||||
-- 黄条「无访问权限,可能原因:1. 用户权限不足…」
|
||||
-- 红字「分配失败,请重试」
|
||||
-- 该权限码是后加的自定义接口,菜单里往往没有对应按钮,角色也就授不了
|
||||
-- 适用:
|
||||
-- 朱茏老师(user_id=223,角色含 3003-学生信息管理)
|
||||
-- 以及已经能打开本模块(已有管理员列表/授权查询权限)的同类角色
|
||||
-- 执行后:
|
||||
-- 相关用户需重新登录,使权限缓存生效
|
||||
-- ============================================================
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- A) 先查(只读,可单独执行)
|
||||
-- ------------------------------------------------------------
|
||||
|
||||
-- A1. 朱茏当前角色,以及本模块相关权限(无行=该权限没有)
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
r.role_id,
|
||||
r.role_name,
|
||||
m.menu_id,
|
||||
m.menu_name,
|
||||
m.perms
|
||||
FROM sys_user u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.user_id
|
||||
JOIN sys_role r ON r.role_id = ur.role_id
|
||||
JOIN sys_role_menu rm ON rm.role_id = r.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE u.user_id = 223
|
||||
AND (
|
||||
m.perms LIKE 'xgStudentManager%'
|
||||
OR m.menu_name LIKE '%学生管理员%'
|
||||
)
|
||||
ORDER BY m.perms, r.role_id;
|
||||
|
||||
-- A2. 关键权限是否已具备(1=有,0=没有)
|
||||
SELECT
|
||||
p.perms,
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_role ur
|
||||
JOIN sys_role_menu rm ON rm.role_id = ur.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE ur.user_id = 223 AND m.perms = p.perms
|
||||
) AS has_perm
|
||||
FROM (
|
||||
SELECT 'xgStudentManager:studentManager:list' AS perms
|
||||
UNION ALL SELECT 'xgStudentManagerSource:studentManagerSource:list'
|
||||
UNION ALL SELECT 'xgStudentManagerSource:studentManagerSource:query'
|
||||
UNION ALL SELECT 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
) p;
|
||||
|
||||
-- A3. 库里是否已有这些菜单权限码(grantDeptAuth 无行=需要下面的修复段补菜单)
|
||||
SELECT menu_id, menu_name, parent_id, menu_type, perms, status, visible
|
||||
FROM sys_menu
|
||||
WHERE perms IN (
|
||||
'xgStudentManager:studentManager:list',
|
||||
'xgStudentManagerSource:studentManagerSource:list',
|
||||
'xgStudentManagerSource:studentManagerSource:query',
|
||||
'xgStudentManagerSource:studentManagerSource:edit',
|
||||
'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
)
|
||||
OR menu_name LIKE '%学生管理员%'
|
||||
ORDER BY parent_id, order_num, menu_id;
|
||||
|
||||
-- ============================================================
|
||||
-- 以下为修复段:确认缺 grantDeptAuth 后再执行;先备份再改
|
||||
-- ============================================================
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 0) 修改前备份(带时间戳后缀,避免覆盖)
|
||||
-- ------------------------------------------------------------
|
||||
SET @bak_suffix = DATE_FORMAT(NOW(), '%Y%m%d_%H%i%s');
|
||||
|
||||
SET @sql_bak_menu = CONCAT(
|
||||
'CREATE TABLE IF NOT EXISTS sys_menu_bak_', @bak_suffix,
|
||||
' AS SELECT * FROM sys_menu'
|
||||
);
|
||||
PREPARE stmt_bak_menu FROM @sql_bak_menu;
|
||||
EXECUTE stmt_bak_menu;
|
||||
DEALLOCATE PREPARE stmt_bak_menu;
|
||||
|
||||
SET @sql_bak_role_menu = CONCAT(
|
||||
'CREATE TABLE IF NOT EXISTS sys_role_menu_bak_', @bak_suffix,
|
||||
' AS SELECT * FROM sys_role_menu'
|
||||
);
|
||||
PREPARE stmt_bak_role_menu FROM @sql_bak_role_menu;
|
||||
EXECUTE stmt_bak_role_menu;
|
||||
DEALLOCATE PREPARE stmt_bak_role_menu;
|
||||
|
||||
SELECT
|
||||
CONCAT('sys_menu_bak_', @bak_suffix) AS menu_backup_table,
|
||||
CONCAT('sys_role_menu_bak_', @bak_suffix) AS role_menu_backup_table;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1) 解析父菜单(一条 SELECT,避免 Navicat 把 SET+子查询拆段)
|
||||
-- 优先级:授权关系列表菜单 > 其父级 > 同模块按钮父级 > 学生管理员设置 > 管理员列表父级
|
||||
-- ------------------------------------------------------------
|
||||
SET @parent_id = NULL;
|
||||
|
||||
SELECT picked.menu_id INTO @parent_id
|
||||
FROM (
|
||||
SELECT menu_id, 1 AS ord
|
||||
FROM sys_menu
|
||||
WHERE perms = 'xgStudentManagerSource:studentManagerSource:list'
|
||||
AND menu_type IN ('C', 'M')
|
||||
UNION ALL
|
||||
SELECT parent_id, 2
|
||||
FROM sys_menu
|
||||
WHERE perms = 'xgStudentManagerSource:studentManagerSource:list'
|
||||
UNION ALL
|
||||
SELECT parent_id, 3
|
||||
FROM sys_menu
|
||||
WHERE perms IN (
|
||||
'xgStudentManagerSource:studentManagerSource:query',
|
||||
'xgStudentManagerSource:studentManagerSource:edit',
|
||||
'xgStudentManagerSource:studentManagerSource:add'
|
||||
)
|
||||
UNION ALL
|
||||
SELECT menu_id, 4
|
||||
FROM sys_menu
|
||||
WHERE menu_name LIKE '%学生管理员设置%'
|
||||
AND menu_type IN ('C', 'M')
|
||||
UNION ALL
|
||||
SELECT parent_id, 5
|
||||
FROM sys_menu
|
||||
WHERE perms = 'xgStudentManager:studentManager:list'
|
||||
) picked
|
||||
WHERE picked.menu_id IS NOT NULL
|
||||
ORDER BY picked.ord, picked.menu_id
|
||||
LIMIT 1;
|
||||
|
||||
SELECT @parent_id AS resolved_parent_id;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2) 新增「分配管理范围」按钮权限(若不存在,且已解析到父菜单)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_menu (
|
||||
menu_id, menu_name, parent_id, order_num, path, component, query_param,
|
||||
is_frame, is_cache, menu_type, visible, status, perms, icon,
|
||||
create_dept, create_by, create_time, update_by, update_time, remark
|
||||
)
|
||||
SELECT
|
||||
2005461500000000003,
|
||||
'分配管理范围',
|
||||
@parent_id,
|
||||
6,
|
||||
'',
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
'F',
|
||||
'0',
|
||||
'0',
|
||||
'xgStudentManagerSource:studentManagerSource:grantDeptAuth',
|
||||
'',
|
||||
100,
|
||||
1,
|
||||
NOW(),
|
||||
1,
|
||||
NOW(),
|
||||
'补齐自定义管理员分配管理范围接口权限,解决提交403'
|
||||
FROM DUAL
|
||||
WHERE @parent_id IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
);
|
||||
|
||||
-- 父菜单没解析到时,这条会提示,且上面的 INSERT 不会写入
|
||||
SELECT
|
||||
CASE
|
||||
WHEN @parent_id IS NULL THEN '未找到父菜单,未插入按钮。请先看 A3 的菜单结果,手工指定 parent_id 后再执行第 2 步'
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
) THEN 'grantDeptAuth 菜单已存在(含本次新建)'
|
||||
ELSE '未插入,请检查 sys_menu'
|
||||
END AS menu_insert_result;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3) 给「学生信息管理」角色(3003)授权(朱茏已拥有该角色)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 3003, m.menu_id
|
||||
FROM sys_menu m
|
||||
WHERE m.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 3003 AND rm.menu_id = m.menu_id
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4) 兼容:已能使用本模块的角色,一并补上分配范围权限
|
||||
-- 判定:已有管理员列表、授权关系查询/列表/修改,或菜单名含「学生管理员设置」
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT DISTINCT rm.role_id, grant_menu.menu_id
|
||||
FROM sys_role_menu rm
|
||||
JOIN sys_menu owned ON owned.menu_id = rm.menu_id
|
||||
JOIN sys_menu grant_menu
|
||||
ON grant_menu.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
WHERE (
|
||||
owned.perms IN (
|
||||
'xgStudentManager:studentManager:list',
|
||||
'xgStudentManagerSource:studentManagerSource:list',
|
||||
'xgStudentManagerSource:studentManagerSource:query',
|
||||
'xgStudentManagerSource:studentManagerSource:edit',
|
||||
'xgStudentManagerSource:studentManagerSource:add'
|
||||
)
|
||||
OR owned.menu_name LIKE '%学生管理员设置%'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu x
|
||||
WHERE x.role_id = rm.role_id AND x.menu_id = grant_menu.menu_id
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 5) 校验:朱茏是否已具备分配范围权限
|
||||
-- ------------------------------------------------------------
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
r.role_id,
|
||||
r.role_name,
|
||||
m.menu_id,
|
||||
m.menu_name,
|
||||
m.perms
|
||||
FROM sys_user u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.user_id
|
||||
JOIN sys_role r ON r.role_id = ur.role_id
|
||||
JOIN sys_role_menu rm ON rm.role_id = r.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE u.user_id = 223
|
||||
AND m.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth';
|
||||
|
||||
-- 有行=已具备。无行时看她的角色是否在第 3/4 步的授权范围内
|
||||
SELECT
|
||||
'xgStudentManagerSource:studentManagerSource:grantDeptAuth' AS perms,
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_role ur
|
||||
JOIN sys_role_menu rm ON rm.role_id = ur.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE ur.user_id = 223
|
||||
AND m.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
) AS has_perm;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 6) 复查是否执行成功(只读,可单独反复执行)
|
||||
-- 期望:menu_ready=1,role_3003_ready=1,zhulong_ready=1
|
||||
-- ------------------------------------------------------------
|
||||
SELECT
|
||||
EXISTS (
|
||||
SELECT 1 FROM sys_menu
|
||||
WHERE perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
AND menu_type = 'F'
|
||||
AND status = '0'
|
||||
AND parent_id IS NOT NULL
|
||||
) AS menu_ready,
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_role_menu rm
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE rm.role_id = 3003
|
||||
AND m.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
) AS role_3003_ready,
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.user_id
|
||||
JOIN sys_role_menu rm ON rm.role_id = ur.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE u.user_id = 223
|
||||
AND u.nick_name = '朱茏'
|
||||
AND m.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
AND m.status = '0'
|
||||
) AS zhulong_ready;
|
||||
|
||||
-- 明细:按钮挂在哪个菜单下,哪些角色拿到了
|
||||
SELECT
|
||||
m.menu_id,
|
||||
m.menu_name,
|
||||
m.parent_id,
|
||||
p.menu_name AS parent_menu_name,
|
||||
m.perms,
|
||||
m.menu_type,
|
||||
m.status,
|
||||
r.role_id,
|
||||
r.role_name
|
||||
FROM sys_menu m
|
||||
LEFT JOIN sys_menu p ON p.menu_id = m.parent_id
|
||||
LEFT JOIN sys_role_menu rm ON rm.menu_id = m.menu_id
|
||||
LEFT JOIN sys_role r ON r.role_id = rm.role_id
|
||||
WHERE m.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
ORDER BY r.role_id;
|
||||
|
||||
-- 明细:朱茏通过哪个角色拥有该权限(有行即成功)
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
r.role_id,
|
||||
r.role_name,
|
||||
m.menu_id,
|
||||
m.menu_name,
|
||||
m.perms,
|
||||
m.status AS menu_status
|
||||
FROM sys_user u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.user_id
|
||||
JOIN sys_role r ON r.role_id = ur.role_id
|
||||
JOIN sys_role_menu rm ON rm.role_id = r.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE u.user_id = 223
|
||||
AND m.perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 回滚示例(按需执行,把后缀换成上面查出的备份表名)
|
||||
-- ------------------------------------------------------------
|
||||
-- DELETE FROM sys_role_menu
|
||||
-- WHERE menu_id IN (
|
||||
-- SELECT menu_id FROM sys_menu
|
||||
-- WHERE perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
-- );
|
||||
-- DELETE FROM sys_menu
|
||||
-- WHERE perms = 'xgStudentManagerSource:studentManagerSource:grantDeptAuth'
|
||||
-- AND menu_id = 2005461500000000003;
|
||||
-- -- 或整表回滚:
|
||||
-- -- TRUNCATE TABLE sys_role_menu;
|
||||
-- -- INSERT INTO sys_role_menu SELECT * FROM sys_role_menu_bak_YYYYMMDD_HHMMSS;
|
||||
-- -- TRUNCATE TABLE sys_menu;
|
||||
-- -- INSERT INTO sys_menu SELECT * FROM sys_menu_bak_YYYYMMDD_HHMMSS;
|
||||
@@ -0,0 +1,132 @@
|
||||
-- ============================================================
|
||||
-- 临时权限修复:学籍异动「新增」权限(退学/休学/复学/毕业提交接口)
|
||||
-- 背景:
|
||||
-- 前端退学按钮权限:studentMsg:status:tuixue
|
||||
-- 后端提交接口校验:studentMsg:studentStatusChange:add
|
||||
-- 系统菜单中原先缺少 add 权限码,导致有按钮但提交报 403
|
||||
-- 适用:
|
||||
-- 朱茏老师(user_id=223,角色含 3003-学生信息管理)及同类角色
|
||||
-- 执行后:
|
||||
-- 相关用户需重新登录,使权限缓存生效
|
||||
-- ============================================================
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 0) 修改前备份相关表(带时间戳后缀,避免覆盖)
|
||||
-- ------------------------------------------------------------
|
||||
SET @bak_suffix = DATE_FORMAT(NOW(), '%Y%m%d_%H%i%s');
|
||||
|
||||
SET @sql_bak_menu = CONCAT(
|
||||
'CREATE TABLE IF NOT EXISTS sys_menu_bak_', @bak_suffix,
|
||||
' AS SELECT * FROM sys_menu'
|
||||
);
|
||||
PREPARE stmt_bak_menu FROM @sql_bak_menu;
|
||||
EXECUTE stmt_bak_menu;
|
||||
DEALLOCATE PREPARE stmt_bak_menu;
|
||||
|
||||
SET @sql_bak_role_menu = CONCAT(
|
||||
'CREATE TABLE IF NOT EXISTS sys_role_menu_bak_', @bak_suffix,
|
||||
' AS SELECT * FROM sys_role_menu'
|
||||
);
|
||||
PREPARE stmt_bak_role_menu FROM @sql_bak_role_menu;
|
||||
EXECUTE stmt_bak_role_menu;
|
||||
DEALLOCATE PREPARE stmt_bak_role_menu;
|
||||
|
||||
-- 查看本次备份表名
|
||||
SELECT
|
||||
CONCAT('sys_menu_bak_', @bak_suffix) AS menu_backup_table,
|
||||
CONCAT('sys_role_menu_bak_', @bak_suffix) AS role_menu_backup_table;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1) 新增「学籍异动-新增」按钮权限(挂在「学籍异动信息」菜单下)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_menu (
|
||||
menu_id, menu_name, parent_id, order_num, path, component, query_param,
|
||||
is_frame, is_cache, menu_type, visible, status, perms, icon,
|
||||
create_dept, create_by, create_time, update_by, update_time, remark
|
||||
)
|
||||
SELECT
|
||||
2005461500000000001,
|
||||
'新增',
|
||||
2004197349643042818, -- 学籍异动信息
|
||||
0,
|
||||
'',
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
'F',
|
||||
'0',
|
||||
'0',
|
||||
'studentMsg:studentStatusChange:add',
|
||||
'',
|
||||
100,
|
||||
1,
|
||||
NOW(),
|
||||
1,
|
||||
NOW(),
|
||||
'补齐学籍异动提交接口权限,解决退学/休学等提交403'
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE perms = 'studentMsg:studentStatusChange:add'
|
||||
);
|
||||
|
||||
-- 若库中已用其他 menu_id 创建了同名 perms,下面授权统一按 perms 查找 menu_id
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2) 给「学生信息管理(保留)」角色(3003)授权(朱茏已拥有该角色)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 3003, m.menu_id
|
||||
FROM sys_menu m
|
||||
WHERE m.perms = 'studentMsg:studentStatusChange:add'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 3003 AND rm.menu_id = m.menu_id
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3) 兼容:所有已拥有「退学」按钮权限的角色,一并补上 add
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT DISTINCT rm.role_id, add_menu.menu_id
|
||||
FROM sys_role_menu rm
|
||||
JOIN sys_menu tuixue ON tuixue.menu_id = rm.menu_id AND tuixue.perms = 'studentMsg:status:tuixue'
|
||||
JOIN sys_menu add_menu ON add_menu.perms = 'studentMsg:studentStatusChange:add'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu x
|
||||
WHERE x.role_id = rm.role_id AND x.menu_id = add_menu.menu_id
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4) 校验:朱茏是否已具备 add 权限
|
||||
-- ------------------------------------------------------------
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
r.role_id,
|
||||
r.role_name,
|
||||
m.perms,
|
||||
m.menu_name
|
||||
FROM sys_user u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.user_id
|
||||
JOIN sys_role r ON r.role_id = ur.role_id
|
||||
JOIN sys_role_menu rm ON rm.role_id = r.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE u.user_id = 223
|
||||
AND m.perms IN (
|
||||
'studentMsg:status:tuixue',
|
||||
'studentMsg:studentStatusChange:add',
|
||||
'studentMsg:studentStatusChange:list'
|
||||
)
|
||||
ORDER BY m.perms, r.role_id;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 回滚示例(按需执行,把后缀换成上面查出的备份表名)
|
||||
-- ------------------------------------------------------------
|
||||
-- TRUNCATE TABLE sys_role_menu;
|
||||
-- INSERT INTO sys_role_menu SELECT * FROM sys_role_menu_bak_YYYYMMDD_HHMMSS;
|
||||
-- DELETE FROM sys_menu WHERE perms = 'studentMsg:studentStatusChange:add';
|
||||
-- -- 或整表回滚菜单:
|
||||
-- -- TRUNCATE TABLE sys_menu;
|
||||
-- -- INSERT INTO sys_menu SELECT * FROM sys_menu_bak_YYYYMMDD_HHMMSS;
|
||||
@@ -0,0 +1,246 @@
|
||||
-- ============================================================
|
||||
-- 临时权限修复:换班级「新增」权限(学生信息页提交换班级接口)
|
||||
-- 背景:
|
||||
-- 前端换班级按钮权限:studentMsg:class:change
|
||||
-- 后端提交接口校验:studentMsg:studentClassChange:add
|
||||
-- 有按钮但提交报 403 Forbidden(无访问权限)
|
||||
-- 适用:
|
||||
-- 朱茏老师(user_id=223,角色含 3003-学生信息管理)及同类角色
|
||||
-- 执行后:
|
||||
-- 相关用户需重新登录,使权限缓存生效
|
||||
-- ============================================================
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- A) 先查:朱茏是否已具备 add / 前端按钮权限(只读,可单独执行)
|
||||
-- ------------------------------------------------------------
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
r.role_id,
|
||||
r.role_name,
|
||||
m.menu_id,
|
||||
m.menu_name,
|
||||
m.perms
|
||||
FROM sys_user u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.user_id
|
||||
JOIN sys_role r ON r.role_id = ur.role_id
|
||||
JOIN sys_role_menu rm ON rm.role_id = r.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE u.user_id = 223
|
||||
AND m.perms IN (
|
||||
'studentMsg:class:change',
|
||||
'studentMsg:studentClassChange:add',
|
||||
'studentMsg:studentClassChange:list',
|
||||
'studentMsg:studentClassChange:query',
|
||||
'studentMsg:studentClassChange:edit',
|
||||
'studentMsg:studentClassChange:remove',
|
||||
'studentMsg:studentClassChange:export'
|
||||
)
|
||||
ORDER BY m.perms, r.role_id;
|
||||
|
||||
-- 汇总:是否具备关键权限(有行=有,无行=没有)
|
||||
SELECT
|
||||
'studentMsg:class:change' AS perms,
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_role ur
|
||||
JOIN sys_role_menu rm ON rm.role_id = ur.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE ur.user_id = 223 AND m.perms = 'studentMsg:class:change'
|
||||
) AS has_perm
|
||||
UNION ALL
|
||||
SELECT
|
||||
'studentMsg:studentClassChange:add',
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_role ur
|
||||
JOIN sys_role_menu rm ON rm.role_id = ur.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE ur.user_id = 223 AND m.perms = 'studentMsg:studentClassChange:add'
|
||||
);
|
||||
|
||||
-- 库中是否已存在 add 菜单权限码
|
||||
SELECT menu_id, menu_name, parent_id, perms, status, visible
|
||||
FROM sys_menu
|
||||
WHERE perms IN (
|
||||
'studentMsg:class:change',
|
||||
'studentMsg:studentClassChange:add',
|
||||
'studentMsg:studentClassChange:list'
|
||||
)
|
||||
ORDER BY perms;
|
||||
|
||||
-- ============================================================
|
||||
-- 以下为修复段:确认缺权限后再执行;先备份再改
|
||||
-- ============================================================
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 0) 修改前备份相关表(带时间戳后缀,避免覆盖)
|
||||
-- ------------------------------------------------------------
|
||||
SET @bak_suffix = DATE_FORMAT(NOW(), '%Y%m%d_%H%i%s');
|
||||
|
||||
SET @sql_bak_menu = CONCAT(
|
||||
'CREATE TABLE IF NOT EXISTS sys_menu_bak_', @bak_suffix,
|
||||
' AS SELECT * FROM sys_menu'
|
||||
);
|
||||
PREPARE stmt_bak_menu FROM @sql_bak_menu;
|
||||
EXECUTE stmt_bak_menu;
|
||||
DEALLOCATE PREPARE stmt_bak_menu;
|
||||
|
||||
SET @sql_bak_role_menu = CONCAT(
|
||||
'CREATE TABLE IF NOT EXISTS sys_role_menu_bak_', @bak_suffix,
|
||||
' AS SELECT * FROM sys_role_menu'
|
||||
);
|
||||
PREPARE stmt_bak_role_menu FROM @sql_bak_role_menu;
|
||||
EXECUTE stmt_bak_role_menu;
|
||||
DEALLOCATE PREPARE stmt_bak_role_menu;
|
||||
|
||||
SELECT
|
||||
CONCAT('sys_menu_bak_', @bak_suffix) AS menu_backup_table,
|
||||
CONCAT('sys_role_menu_bak_', @bak_suffix) AS role_menu_backup_table;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1) 解析父菜单:优先挂在「换班级」列表菜单下,否则挂在「换班级」按钮同级父菜单
|
||||
-- ------------------------------------------------------------
|
||||
SET @parent_id = (
|
||||
SELECT parent_id
|
||||
FROM sys_menu
|
||||
WHERE perms = 'studentMsg:studentClassChange:list'
|
||||
AND menu_type IN ('C', 'M')
|
||||
ORDER BY menu_id
|
||||
LIMIT 1
|
||||
);
|
||||
|
||||
-- list 本身若是目录/菜单,直接用其 menu_id 作父级
|
||||
SET @parent_id = IFNULL(
|
||||
(
|
||||
SELECT menu_id
|
||||
FROM sys_menu
|
||||
WHERE perms = 'studentMsg:studentClassChange:list'
|
||||
AND menu_type IN ('C', 'M')
|
||||
ORDER BY menu_id
|
||||
LIMIT 1
|
||||
),
|
||||
@parent_id
|
||||
);
|
||||
|
||||
-- 仍找不到时,退化为 class:change 按钮的父菜单
|
||||
SET @parent_id = IFNULL(
|
||||
@parent_id,
|
||||
(
|
||||
SELECT parent_id
|
||||
FROM sys_menu
|
||||
WHERE perms = 'studentMsg:class:change'
|
||||
ORDER BY menu_id
|
||||
LIMIT 1
|
||||
)
|
||||
);
|
||||
|
||||
-- 最终兜底:学籍异动信息菜单(与学籍异动修复脚本同父级,仅当上面都找不到时)
|
||||
SET @parent_id = IFNULL(@parent_id, 2004197349643042818);
|
||||
|
||||
SELECT @parent_id AS resolved_parent_id;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2) 新增「换班级-新增」按钮权限(若不存在)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_menu (
|
||||
menu_id, menu_name, parent_id, order_num, path, component, query_param,
|
||||
is_frame, is_cache, menu_type, visible, status, perms, icon,
|
||||
create_dept, create_by, create_time, update_by, update_time, remark
|
||||
)
|
||||
SELECT
|
||||
2005461500000000002,
|
||||
'新增',
|
||||
@parent_id,
|
||||
1,
|
||||
'',
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
'F',
|
||||
'0',
|
||||
'0',
|
||||
'studentMsg:studentClassChange:add',
|
||||
'',
|
||||
100,
|
||||
1,
|
||||
NOW(),
|
||||
1,
|
||||
NOW(),
|
||||
'补齐换班级提交接口权限,解决学生信息页换班级提交403'
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE perms = 'studentMsg:studentClassChange:add'
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3) 给「学生信息管理(保留)」角色(3003)授权
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 3003, m.menu_id
|
||||
FROM sys_menu m
|
||||
WHERE m.perms = 'studentMsg:studentClassChange:add'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu rm
|
||||
WHERE rm.role_id = 3003 AND rm.menu_id = m.menu_id
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4) 兼容:所有已有「换班级」按钮权限的角色,一并补上 add
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT DISTINCT rm.role_id, add_menu.menu_id
|
||||
FROM sys_role_menu rm
|
||||
JOIN sys_menu btn ON btn.menu_id = rm.menu_id AND btn.perms = 'studentMsg:class:change'
|
||||
JOIN sys_menu add_menu ON add_menu.perms = 'studentMsg:studentClassChange:add'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_role_menu x
|
||||
WHERE x.role_id = rm.role_id AND x.menu_id = add_menu.menu_id
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 5) 校验:朱茏是否已具备 add 权限
|
||||
-- ------------------------------------------------------------
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
r.role_id,
|
||||
r.role_name,
|
||||
m.perms,
|
||||
m.menu_name,
|
||||
m.menu_id
|
||||
FROM sys_user u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.user_id
|
||||
JOIN sys_role r ON r.role_id = ur.role_id
|
||||
JOIN sys_role_menu rm ON rm.role_id = r.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE u.user_id = 223
|
||||
AND m.perms IN (
|
||||
'studentMsg:class:change',
|
||||
'studentMsg:studentClassChange:add',
|
||||
'studentMsg:studentClassChange:list'
|
||||
)
|
||||
ORDER BY m.perms, r.role_id;
|
||||
|
||||
SELECT
|
||||
'studentMsg:studentClassChange:add' AS perms,
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_role ur
|
||||
JOIN sys_role_menu rm ON rm.role_id = ur.role_id
|
||||
JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
WHERE ur.user_id = 223 AND m.perms = 'studentMsg:studentClassChange:add'
|
||||
) AS has_perm;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 回滚示例(按需执行,把后缀换成上面查出的备份表名)
|
||||
-- ------------------------------------------------------------
|
||||
-- TRUNCATE TABLE sys_role_menu;
|
||||
-- INSERT INTO sys_role_menu SELECT * FROM sys_role_menu_bak_YYYYMMDD_HHMMSS;
|
||||
-- DELETE FROM sys_menu WHERE perms = 'studentMsg:studentClassChange:add';
|
||||
-- -- 或整表回滚菜单:
|
||||
-- -- TRUNCATE TABLE sys_menu;
|
||||
-- -- INSERT INTO sys_menu SELECT * FROM sys_menu_bak_YYYYMMDD_HHMMSS;
|
||||
@@ -4622,7 +4622,7 @@ CREATE TABLE `xg_holiday_stay` (
|
||||
`apply_end_date` datetime NOT NULL COMMENT '申请留宿结束日期',
|
||||
`stay_reason` text NOT NULL COMMENT '留宿原因(必填)',
|
||||
`stay_reason_type` varchar(20) DEFAULT NULL COMMENT '留宿原因类型(学习、实习、家庭困难、其他)',
|
||||
`student_phone` varchar(20) NOT NULL COMMENT '学生联系电话',
|
||||
`student_phone` varchar(20) DEFAULT NULL COMMENT '学生联系电话',
|
||||
`emergency_contact` varchar(50) NOT NULL COMMENT '紧急联系人姓名',
|
||||
`emergency_phone` varchar(20) NOT NULL COMMENT '紧急联系人电话',
|
||||
`parent_consent` char(1) NOT NULL DEFAULT '1' COMMENT '家长同意(0否 1是)',
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
-- ============================================================
|
||||
-- 假期留宿:student_phone 允许为空
|
||||
-- 背景:学生档案无手机号时,申请 INSERT 省略 student_phone,
|
||||
-- 原 NOT NULL 无默认值会报 Field 'student_phone' doesn't have a default value
|
||||
-- 目的:仅改库即可恢复申请,无需立即发版
|
||||
-- 日期:2026-10-15
|
||||
-- ============================================================
|
||||
|
||||
-- 主表:允许联系电话为空
|
||||
ALTER TABLE `xg_holiday_stay`
|
||||
MODIFY COLUMN `student_phone` varchar(20) DEFAULT NULL COMMENT '学生联系电话';
|
||||
|
||||
-- 如存在历史表,一并放宽(没有可跳过)
|
||||
-- ALTER TABLE `xg_holiday_stay_his`
|
||||
-- MODIFY COLUMN `student_phone` varchar(20) DEFAULT NULL COMMENT '学生联系电话';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 可选预防:紧急联系人/电话同样是 NOT NULL,表单空串一般能写入;
|
||||
-- 若希望彻底避免同类 SQL 报错,可一并执行:
|
||||
-- ALTER TABLE `xg_holiday_stay`
|
||||
-- MODIFY COLUMN `emergency_contact` varchar(50) DEFAULT NULL COMMENT '紧急联系人姓名',
|
||||
-- MODIFY COLUMN `emergency_phone` varchar(20) DEFAULT NULL COMMENT '紧急联系人电话';
|
||||
-- ------------------------------------------------------------
|
||||
@@ -1420,6 +1420,18 @@ export default {
|
||||
} catch (_) {}
|
||||
},
|
||||
|
||||
// 请假单上的 0/1/2/3 不是流程状态,不能随销假保存回写
|
||||
resolveSubmitCancelStatus(action) {
|
||||
if (action === 'draft') {
|
||||
return 'draft';
|
||||
}
|
||||
const current = this.cancelForm.status;
|
||||
if (!current || ['0', '1', '2', '3'].includes(String(current))) {
|
||||
return 'draft';
|
||||
}
|
||||
return current;
|
||||
},
|
||||
|
||||
// ============== 审批与提交 ==============
|
||||
async handleApprovalVerifyOpen() {
|
||||
this.$refs.submitVerifyRef.openDialog(this.routeParams.taskId || '');
|
||||
@@ -1548,7 +1560,7 @@ export default {
|
||||
cancelLocation: this.cancelForm.cancelLocation,
|
||||
cancelRemark: this.cancelForm.cancelRemark,
|
||||
cancelPhotoOssIds: this.cancelForm.cancelPhotoOssIds,
|
||||
cancelStatus: status === 'draft' ? 'draft' : this.cancelForm.status || 'draft',
|
||||
cancelStatus: this.resolveSubmitCancelStatus(status),
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
@@ -79,13 +79,13 @@
|
||||
count
|
||||
></u-textarea>
|
||||
</u-form-item>
|
||||
<u-form-item label="联系电话" prop="studentPhone">
|
||||
<u-form-item label="联系电话" prop="studentPhone" required>
|
||||
<u-input v-model="form.studentPhone" placeholder="可自动带出,可修改" />
|
||||
</u-form-item>
|
||||
<u-form-item label="紧急联系人" prop="emergencyContact">
|
||||
<u-form-item label="紧急联系人" prop="emergencyContact" required>
|
||||
<u-input v-model="form.emergencyContact" placeholder="请输入紧急联系人" />
|
||||
</u-form-item>
|
||||
<u-form-item label="紧急电话" prop="emergencyPhone">
|
||||
<u-form-item label="紧急电话" prop="emergencyPhone" required>
|
||||
<u-input v-model="form.emergencyPhone" placeholder="请输入紧急联系电话" />
|
||||
</u-form-item>
|
||||
<u-form-item label="家长同意" prop="parentConsent">
|
||||
@@ -308,6 +308,15 @@ export default {
|
||||
if (!this.form.stayReason || !this.form.stayReason.trim()) {
|
||||
return uni.showToast({ title: '请填写留宿原因', icon: 'none' });
|
||||
}
|
||||
if (!this.form.studentPhone || !String(this.form.studentPhone).trim()) {
|
||||
return uni.showToast({ title: '请填写联系电话', icon: 'none' });
|
||||
}
|
||||
if (!this.form.emergencyContact || !String(this.form.emergencyContact).trim()) {
|
||||
return uni.showToast({ title: '请填写紧急联系人', icon: 'none' });
|
||||
}
|
||||
if (!this.form.emergencyPhone || !String(this.form.emergencyPhone).trim()) {
|
||||
return uni.showToast({ title: '请填写紧急联系电话', icon: 'none' });
|
||||
}
|
||||
this.submitting = true;
|
||||
try {
|
||||
await applyHolidayStay({ ...this.form });
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2024-2025, Warm-Flow (290631660@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.warm.flow.core.listener;
|
||||
|
||||
import org.dromara.warm.flow.core.dto.FlowParams;
|
||||
import org.dromara.warm.flow.core.entity.Definition;
|
||||
import org.dromara.warm.flow.core.entity.Instance;
|
||||
import org.dromara.warm.flow.core.entity.Node;
|
||||
import org.dromara.warm.flow.core.entity.Task;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 监听器变量
|
||||
*
|
||||
* @author warm
|
||||
* @see <a href="https://warm-flow.dromara.org/master/advanced/listener.html">文档地址</a>
|
||||
*/
|
||||
public class ListenerVariable {
|
||||
|
||||
/**
|
||||
* 流程定义
|
||||
*/
|
||||
private Definition definition;
|
||||
|
||||
/**
|
||||
* 流程实例
|
||||
*/
|
||||
private Instance instance;
|
||||
|
||||
/**
|
||||
* 监听器对应的节点
|
||||
*/
|
||||
private Node node;
|
||||
|
||||
/**
|
||||
* 当前任务
|
||||
*/
|
||||
private Task task;
|
||||
|
||||
/**
|
||||
* 下一次执行的节点集合
|
||||
*/
|
||||
private List<Node> nextNodes;
|
||||
|
||||
/**
|
||||
* 新创建任务集合
|
||||
*/
|
||||
private List<Task> nextTasks;
|
||||
|
||||
/**
|
||||
* 流程变量
|
||||
*/
|
||||
private Map<String, Object> variable;
|
||||
|
||||
/**
|
||||
* 工作流内置参数
|
||||
*/
|
||||
private FlowParams flowParams;
|
||||
|
||||
|
||||
public ListenerVariable() {
|
||||
}
|
||||
|
||||
public ListenerVariable(Definition definition, Instance instance, Map<String, Object> variable) {
|
||||
this.definition = definition;
|
||||
this.instance = instance;
|
||||
this.variable = variable;
|
||||
}
|
||||
|
||||
public ListenerVariable(Definition definition, Instance instance, Node node, Map<String, Object> variable) {
|
||||
this.definition = definition;
|
||||
this.instance = instance;
|
||||
this.node = node;
|
||||
this.variable = variable;
|
||||
}
|
||||
|
||||
public ListenerVariable(Definition definition, Instance instance, Map<String, Object> variable, Task task) {
|
||||
this.definition = definition;
|
||||
this.instance = instance;
|
||||
this.variable = variable;
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public ListenerVariable(Definition definition, Instance instance, Node node, Map<String, Object> variable, Task task) {
|
||||
this.definition = definition;
|
||||
this.instance = instance;
|
||||
this.node = node;
|
||||
this.variable = variable;
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public ListenerVariable(Definition definition, Instance instance, Node node, Map<String, Object> variable, Task task, List<Node> nextNodes) {
|
||||
this.definition = definition;
|
||||
this.instance = instance;
|
||||
this.node = node;
|
||||
this.variable = variable;
|
||||
this.task = task;
|
||||
this.nextNodes = nextNodes;
|
||||
}
|
||||
|
||||
public ListenerVariable(Definition definition, Instance instance, Node node , Map<String, Object> variable, Task task
|
||||
, List<Node> nextNodes, List<Task> nextTasks) {
|
||||
this.definition = definition;
|
||||
this.instance = instance;
|
||||
this.node = node;
|
||||
this.variable = variable;
|
||||
this.task = task;
|
||||
this.nextNodes = nextNodes;
|
||||
this.nextTasks = nextTasks;
|
||||
}
|
||||
|
||||
public Definition getDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
public ListenerVariable setDefinition(Definition definition) {
|
||||
this.definition = definition;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Instance getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ListenerVariable setInstance(Instance instance) {
|
||||
this.instance = instance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Node getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
public ListenerVariable setNode(Node node) {
|
||||
this.node = node;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Task getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
public ListenerVariable setTask(Task task) {
|
||||
this.task = task;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<Node> getNextNodes() {
|
||||
return nextNodes;
|
||||
}
|
||||
|
||||
public ListenerVariable setNextNodes(List<Node> nextNodes) {
|
||||
this.nextNodes = nextNodes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<Task> getNextTasks() {
|
||||
return nextTasks;
|
||||
}
|
||||
|
||||
public ListenerVariable setNextTasks(List<Task> nextTasks) {
|
||||
this.nextTasks = nextTasks;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String, Object> getVariable() {
|
||||
return variable;
|
||||
}
|
||||
|
||||
public ListenerVariable setVariable(Map<String, Object> variable) {
|
||||
this.variable = variable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FlowParams getFlowParams() {
|
||||
return flowParams;
|
||||
}
|
||||
|
||||
public ListenerVariable setFlowParams(FlowParams flowParams) {
|
||||
this.flowParams = flowParams;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ListenerVariable{" +
|
||||
"definition=" + definition +
|
||||
", instance=" + instance +
|
||||
", node=" + node +
|
||||
", task=" + task +
|
||||
", nextNodes=" + nextNodes +
|
||||
", nextTasks=" + nextTasks +
|
||||
", variable=" + variable +
|
||||
", flowParams=" + flowParams +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -939,6 +939,9 @@ const data = reactive<PageData<HolidayStayForm, HolidayStayQuery>>({
|
||||
studentId: [{ required: true, message: '学生ID', trigger: 'blur' }],
|
||||
studentName: [{ required: true, message: '学生姓名不能为空', trigger: 'blur' }],
|
||||
studentNo: [{ required: true, message: '学号不能为空', trigger: 'blur' }],
|
||||
studentPhone: [{ required: true, message: '学生联系电话不能为空', trigger: 'blur' }],
|
||||
emergencyContact: [{ required: true, message: '紧急联系人不能为空', trigger: 'blur' }],
|
||||
emergencyPhone: [{ required: true, message: '紧急联系电话不能为空', trigger: 'blur' }],
|
||||
applyStartDate: [{ required: true, message: '留宿开始日期不能为空', trigger: 'blur' }],
|
||||
applyEndDate: [{ required: true, message: '留宿结束日期不能为空', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
@@ -770,6 +770,9 @@ const data = reactive<PageData<HolidayStayForm, HolidayStayQuery>>({
|
||||
studentId: [{ required: true, message: '学生ID', trigger: 'blur' }],
|
||||
studentName: [{ required: true, message: '学生姓名不能为空', trigger: 'blur' }],
|
||||
studentNo: [{ required: true, message: '学号不能为空', trigger: 'blur' }],
|
||||
studentPhone: [{ required: true, message: '学生联系电话不能为空', trigger: 'blur' }],
|
||||
emergencyContact: [{ required: true, message: '紧急联系人不能为空', trigger: 'blur' }],
|
||||
emergencyPhone: [{ required: true, message: '紧急联系电话不能为空', trigger: 'blur' }],
|
||||
applyStartDate: [{ required: true, message: '留宿开始日期不能为空', trigger: 'blur' }],
|
||||
applyEndDate: [{ required: true, message: '留宿结束日期不能为空', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user