This commit is contained in:
2026-07-02 16:06:57 +08:00
parent f637e02c08
commit 4afb3bd835
5 changed files with 143 additions and 4 deletions
@@ -134,6 +134,15 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
*/
void removeTaskActor(Long processTaskId, List<String> actors);
/**
* 按最新办理人配置覆盖同步指定流程任务的参与者。
*
* @param processTaskId 流程任务id
* @param actors 最新办理人用户id集合;为空时不处理,避免误清空任务办理人
* @return 新增和移除的参与者数量合计
*/
int syncTaskActors(Long processTaskId, List<String> actors);
/**
* 根据taskId、operator,判断操作人operator是否允许执行任务
*
@@ -279,6 +279,31 @@ public class ProcessTaskServiceImpl extends BaseServiceImpl<ProcessTask> impleme
dao().clear(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", processTaskId).and(ProcessTaskActor::getActorId, "in", actors));
}
@Override
@Aop(TransAop.READ_COMMITTED)
public int syncTaskActors(Long processTaskId, List<String> actors) {
if (CollectionUtil.isEmpty(actors)) {
return 0;
}
List<String> latestActors = actors.stream().filter(StrUtil::isNotBlank).distinct().toList();
if (CollectionUtil.isEmpty(latestActors)) {
return 0;
}
// 以最新负责人配置为准:缺失的办理人补上,不再是负责人的办理人移除。
List<String> dbActors = getTaskActors(processTaskId);
List<String> addActors = latestActors.stream().filter(actor -> !dbActors.contains(actor)).toList();
List<String> removeActors = dbActors.stream().filter(actor -> !latestActors.contains(actor)).toList();
if (CollectionUtil.isNotEmpty(removeActors)) {
removeTaskActor(processTaskId, removeActors);
}
if (CollectionUtil.isNotEmpty(addActors)) {
addTaskActor(processTaskId, addActors);
}
return addActors.size() + removeActors.size();
}
@Override
public boolean isAllowed(ProcessTask task, String operator) {
// 执行者为超级管理员或自动执行用户
@@ -13,6 +13,9 @@ import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.service.ProcessTaskService;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.models.Sys_user_role;
@@ -57,6 +60,8 @@ public class ProposalConfigUnitController {
private BaseService baseService;
@Inject
private SysRoleService sysRoleService;
@Inject
private ProcessTaskService processTaskService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/proposal/config/unit/index.html")
@@ -146,6 +151,82 @@ public class ProposalConfigUnitController {
return Result.success();
}
/**
* 同步当前进行中的承办单位答复任务办理人。
*
* 按承办单位当前配置的单位负责人覆盖同步 wf_process_task_actor
* 1. 参数:无参数,系统自动扫描所有启用承办单位。
* 2. 单位负责人来源:PROPOSAL_UNIT_LEADER 角色且 underTakeId 等于承办单位id。
* 3. 同步范围:当前进行中的主办答复、协办答复、意见主办答复任务。
* 4. 返回值:Result,msg 中说明同步任务数、办理人变更数、未配置负责人单位数。
*/
@At
@SaCheckPermission("proposal.config.unit")
@SLog(tag = "提案", msg = "同步承办单位答复人")
@Aop(TransAop.READ_COMMITTED)
public Result syncUnitReplyActors() {
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER);
List<ProposalUndertake> undertakes = dao.query(ProposalUndertake.class, Cnd.where(ProposalUndertake::getEnable, "=", true));
int scanTaskCount = 0;
int syncTaskCount = 0;
int syncActorCount = 0;
int skipUnitCount = 0;
for (ProposalUndertake undertake : undertakes) {
List<Sys_user_role> sysUserRoles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId())
.and(Sys_user_role::getUnderTakeId, "=", undertake.getId()));
List<String> userIds = sysUserRoles.stream().map(Sys_user_role::getUserId).distinct().toList();
if (CollectionUtil.isEmpty(userIds)) {
skipUnitCount++;
continue;
}
List<ProcessTask> tasks = queryDoingUnitReplyTasks(undertake.getId());
scanTaskCount += tasks.size();
for (ProcessTask task : tasks) {
int syncCount = processTaskService.syncTaskActors(task.getId(), userIds);
if (syncCount > 0) {
syncTaskCount++;
syncActorCount += syncCount;
}
}
}
return Result.success("同步完成,扫描任务" + scanTaskCount + "个,更新任务" + syncTaskCount + "个,办理人变更" + syncActorCount + "人次,跳过未配置负责人单位" + skipUnitCount + "个。");
}
/**
* 根据承办单位和提案承办单位记录查询正在办理中的答复任务。
*
* 说明:
* 1. 参数 underTakeId 为 proposal_undertake.id,即当前承办单位配置ID。
* 2. 不依赖 wf_process_task.variable 中的 underTakeId,避免历史任务变量和承办单位配置不一致导致漏同步。
* 3. 主办单位只匹配 master_reply、opinion_master_reply,协办单位只匹配 slave_reply。
* 4. 返回值为当前仍在办理中的流程任务列表。
*/
private List<ProcessTask> queryDoingUnitReplyTasks(String underTakeId) {
Sql sql = Sqls.queryEntity("""
SELECT DISTINCT
t.*
FROM
wf_process_task t
INNER JOIN wf_process_instance ins ON ins.id = t.processInstanceId
INNER JOIN proposal_reply_unit pru ON pru.proposalId = ins.businessNo
AND pru.unitId = @underTakeId
WHERE
t.taskState = @taskState
AND (
(t.taskName IN ('master_reply', 'opinion_master_reply') AND pru.isMaster = 1)
OR (t.taskName = 'slave_reply' AND pru.isMaster = 0)
)
""");
sql.setParam("underTakeId", underTakeId);
sql.setParam("taskState", ProcessTaskStateEnum.DOING.getCode());
sql.setEntity(dao.getEntity(ProcessTask.class));
dao.execute(sql);
return sql.getList(ProcessTask.class);
}
/**
* 设置分管校领导
*
@@ -101,8 +101,8 @@ public class ProposalUnderTakeReplyController {
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
IFNULL(GROUP_CONCAT(DISTINCT nt.taskName),'结束') curTaskKey,
CASE WHEN t.taskState = 20 AND ( rt.id IS NULL OR rt.taskState = 10 ) THEN 1 ELSE 0 END AS canRevoke,
t.variable->>'$.underTakeName' AS underTakeName,
IF(JSON_EXTRACT(t.variable, '$.underTakeIsMaster') = true, 1, 0) AS underTakeIsMaster,
IFNULL(pru.unitName, t.variable->>'$.underTakeName') AS underTakeName,
IFNULL(pru.isMaster, IF(JSON_EXTRACT(t.variable, '$.underTakeIsMaster') = true, 1, 0)) AS underTakeIsMaster,
t.variable->>'$.tf_transferUserId' AS tf_transferUserId,
transferUser.username AS transferUserName
FROM
@@ -114,6 +114,11 @@ public class ProposalUnderTakeReplyController {
LEFT JOIN proposal_info info ON info.id = ins.businessNo
LEFT JOIN proposal_type type on type.id = info.typeId
LEFT JOIN proposal_merge mer ON mer.proposalId = info.id
LEFT JOIN proposal_reply_unit pru ON pru.proposalId = ins.businessNo
AND (
(t.taskName IN ('master_reply', 'opinion_master_reply') AND pru.isMaster = 1)
OR (t.taskName = 'slave_reply' AND pru.isMaster = 0)
)
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
LEFT JOIN teacher_congress_delegation tcd on tcd.id = info.delegationId
LEFT JOIN sys_user transferUser on transferUser.id = t.variable->>'$.tf_transferUserId'
@@ -132,7 +137,7 @@ public class ProposalUnderTakeReplyController {
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
}
ProposalSearchParam.buildSearch(cnd, pageForm);
cnd.groupBy("t.id");
cnd.groupBy("t.id", "pru.unitId", "pru.unitName", "pru.isMaster");
cnd.desc("t.createdAt");
sql.setCondition(cnd);
Pagination pagination = proposalCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
@@ -22,6 +22,7 @@ layout("/layouts/platform.html"){
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter);flex: 1;" :body-style="{ height: '100%', display: 'flex' , 'flex-direction': 'column' }">
<table-tool>
<el-button type="primary" size="small" icon="el-icon-refresh" @click="syncSysUnit">同步系统单位</el-button>
<el-button type="primary" size="small" icon="el-icon-refresh" :loading="syncUnitReplyActorsLoading" @click="syncUnitReplyActors">同步承办单位答复人</el-button>
</table-tool>
<el-table :data="tableData" border ref="tableRef" height="100%">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
@@ -69,7 +70,8 @@ layout("/layouts/platform.html"){
data() {
return {
currentTreeNode: null,
currentTreeData: null
currentTreeData: null,
syncUnitReplyActorsLoading: false
}
},
methods: {
@@ -85,6 +87,23 @@ layout("/layouts/platform.html"){
this.$refs.treeRef.listTree()
}
})
},
syncUnitReplyActors() {
this.$confirm("确定要按当前单位领导配置同步进行中的承办单位答复待办吗?", "提示", {
type: "warning"
}).then(() => {
this.syncUnitReplyActorsLoading = true
this.$axios.post(loc() + "/syncUnitReplyActors")
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
}
})
.finally(() => {
this.syncUnitReplyActorsLoading = false
})
})
}
},
created() {