This commit is contained in:
2026-08-13 11:02:26 +08:00
parent 46afff880c
commit 3bd6027670
40 changed files with 1538 additions and 308 deletions
@@ -50,6 +50,7 @@ RoleConstant {
BRANCH_UNION_WENTI_SPORTS("分工会文体福利委员"),
UNIT_PARTY_SECRETARY("单位党委书记"),
UNIT_MANAGER("单位负责人"),
TEACHER_CONGRESS_DELEGATE_FORMAL("教代会正式代表"),
TEACHER_CONGRESS_DELEGATE_ATTENDANCE("教代会列席代表"),
@@ -0,0 +1,50 @@
package com.budwk.app.flow.handler;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.AssignmentHandler;
import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.engine.model.TaskModel;
import com.budwk.app.sys.services.SysUserService;
import java.util.List;
/**
* 按流程发起时固化的分工会 ID 获取二级党组织党委书记。
*
* <p>二级党组织以分工会为范围,通过角色用户所属单位关联分工会,不跨组织兜底。</p>
*/
public class FlowInitiatorPartyOrganizationAssignmentHandler implements AssignmentHandler {
/** 根据流程发起人所属分工会查找全部有效二级党组织党委书记。 */
@Override
public List<String> assign(TaskModel model, Execution execution) {
String unionId = execution.getArgs().getStr(FlowConst.INITIATOR_UNIT_UNION_ID);
if (StrUtil.isBlank(unionId)) {
throw new BaseException("流程发起人缺少所属分工会,无法分配二级党组织审核任务");
}
// 角色关系表不维护分工会范围,通过角色用户的单位关联 sys_unit.unionId。
List<String> userIds = ServiceContext.find(SysUserService.class)
.getEnabledRoleUserIdsByUnion(unionId, RoleConstant.UNIT_PARTY_SECRETARY.name());
if (userIds.isEmpty()) {
throw new BaseException("流程发起人所属二级党组织未设置党委书记,请联系校工会进行设置");
}
return userIds;
}
/** 返回流程设计器展示的参与人说明。 */
@Override
public String getMessage() {
return "流程发起人所属二级党组织党委书记";
}
/** 返回处理类在流程参与者列表中的排序值。 */
@Override
public int getOrder() {
return 240;
}
}
@@ -0,0 +1,50 @@
package com.budwk.app.flow.handler;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.AssignmentHandler;
import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.engine.model.TaskModel;
import com.budwk.app.sys.services.SysUserService;
import java.util.List;
/**
* 按流程发起时固化的单位 ID 获取单位负责人。
*
* <p>审核流程进入后续节点时当前登录人已发生变化,因此不能使用当前登录人的单位信息。</p>
*/
public class FlowInitiatorUnitManagerAssignmentHandler implements AssignmentHandler {
/** 根据流程发起人单位查找全部有效单位负责人。 */
@Override
public List<String> assign(TaskModel model, Execution execution) {
String unitId = execution.getArgs().getStr(FlowConst.INITIATOR_UNIT_ID);
if (StrUtil.isBlank(unitId)) {
throw new BaseException("流程发起人缺少所属单位,无法分配单位审核任务");
}
// 角色关系表不维护单位范围,实际组织归属由角色用户的 sys_user.unitId 确定。
List<String> userIds = ServiceContext.find(SysUserService.class)
.getEnabledRoleUserIdsByUnit(unitId, RoleConstant.UNIT_MANAGER.name());
if (userIds.isEmpty()) {
throw new BaseException("流程发起人所属单位未设置单位负责人,请联系校工会进行设置");
}
return userIds;
}
/** 返回流程设计器展示的参与人说明。 */
@Override
public String getMessage() {
return "流程发起人所属单位负责人";
}
/** 返回处理类在流程参与者列表中的排序值。 */
@Override
public int getOrder() {
return 230;
}
}
@@ -198,4 +198,22 @@ public interface SysUserService extends BaseService<Sys_user> {
String loginPlus(Sys_user user, LoginType loginType, HttpServletRequest request);
Sys_user getByLoginName(String loginName);
/**
* 查询指定单位中具有目标角色的有效用户。
*
* @param unitId 单位 ID
* @param roleCode 角色编码
* @return 符合条件的用户 ID,已去重
*/
List<String> getEnabledRoleUserIdsByUnit(String unitId, String roleCode);
/**
* 查询指定分工会(即二级党组织范围)中具有目标角色的有效用户。
*
* @param unionId 分工会 ID
* @param roleCode 角色编码
* @return 符合条件的用户 ID,已去重
*/
List<String> getEnabledRoleUserIdsByUnion(String unionId, String roleCode);
}
@@ -64,6 +64,78 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
@Inject
private RedisService redisService;
/**
* 按用户当前所属单位查询角色人员。
* sys_user_role 仅用于确认用户具有目标角色,组织范围统一取 sys_user.unitId,
* 避免依赖未维护的 sys_user_role.unitId 字段导致流程无人可分派。
*
* @param unitId 单位 ID
* @param roleCode 角色编码
* @return 对应单位下有效且具有目标角色的用户 ID
*/
@Override
public List<String> getEnabledRoleUserIdsByUnit(String unitId, String roleCode) {
if (StrUtil.hasBlank(unitId, roleCode)) {
return List.of();
}
Sql sql = Sqls.create("""
SELECT DISTINCT u.id
FROM sys_user_role ur
INNER JOIN sys_role r ON r.id = ur.roleId
INNER JOIN sys_user u ON u.id = ur.userId
WHERE r.code = @roleCode
AND r.disabled = 0
AND IFNULL(r.delFlag, 0) = 0
AND u.unitId = @unitId
AND u.disabled = 0
AND IFNULL(u.delFlag, 0) = 0
AND u.loginname IS NOT NULL
AND u.loginname <> ''
""");
sql.setParam("unitId", unitId);
sql.setParam("roleCode", roleCode);
sql.setCallback(Sqls.callback.strList());
dao().execute(sql);
return sql.getList(String.class);
}
/**
* 按用户当前单位关联的分工会查询角色人员。
* 角色用户通过 sys_user.unitId 关联 sys_unit,再以 sys_unit.unionId 确定
* 二级党组织范围,不读取未维护的 sys_user_role.unionId 字段。
*
* @param unionId 分工会 ID
* @param roleCode 角色编码
* @return 对应二级党组织下有效且具有目标角色的用户 ID
*/
@Override
public List<String> getEnabledRoleUserIdsByUnion(String unionId, String roleCode) {
if (StrUtil.hasBlank(unionId, roleCode)) {
return List.of();
}
Sql sql = Sqls.create("""
SELECT DISTINCT u.id
FROM sys_user_role ur
INNER JOIN sys_role r ON r.id = ur.roleId
INNER JOIN sys_user u ON u.id = ur.userId
INNER JOIN sys_unit unit ON unit.id = u.unitId
WHERE r.code = @roleCode
AND r.disabled = 0
AND IFNULL(r.delFlag, 0) = 0
AND unit.unionId = @unionId
AND IFNULL(unit.delFlag, 0) = 0
AND u.disabled = 0
AND IFNULL(u.delFlag, 0) = 0
AND u.loginname IS NOT NULL
AND u.loginname <> ''
""");
sql.setParam("unionId", unionId);
sql.setParam("roleCode", roleCode);
sql.setCallback(Sqls.callback.strList());
dao().execute(sql);
return sql.getList(String.class);
}
@Override
@CacheResult(cacheKey = "${userId}_getPermissionList")
public List<String> getPermissionList(String userId) {
@@ -42,6 +42,7 @@ public class ArticleBranchUnionApprovalController {
@SaCheckPermission("article.branchUnionApproval")
@ApiOperation("分页查询")
public Result pageData(@Valid ArticleInfoPageParam pageForm, boolean approval) {
// 返回流程定义ID,供新闻投稿公共详情组件加载对应的流程图。
Sql sql = Sqls.create("""
SELECT
info.id,
@@ -55,6 +56,7 @@ public class ArticleBranchUnionApprovalController {
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
@@ -61,6 +61,7 @@ public class ArticleClubApprovalController {
@SaCheckPermission("article.clubApproval")
@ApiOperation("分页查询")
public Result pageData(@Valid ArticleInfoPageParam pageForm, boolean approval) {
// 返回流程定义ID,供新闻投稿公共详情组件加载对应的流程图。
Sql sql = Sqls.create("""
SELECT
info.id,
@@ -74,6 +75,7 @@ public class ArticleClubApprovalController {
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
@@ -67,6 +67,7 @@ public class ArticleExamineController {
@SaCheckPermission("article.examine")
@ApiOperation("分页查询")
public Result pageData(@Valid ArticleInfoPageParam pageForm, boolean approval) {
// 返回流程定义ID,供新闻投稿公共详情组件加载对应的流程图。
Sql sql = Sqls.create("""
SELECT
info.id,
@@ -80,6 +81,7 @@ public class ArticleExamineController {
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
@@ -52,6 +52,7 @@ public class ArticleMineController {
@SaCheckPermission("article.mine")
@ApiOperation("分页查询")
public Result pageData(@Valid ArticleInfoPageParam pageForm) {
// 返回流程定义ID,供新闻投稿公共详情组件加载对应的流程图。
Sql sql = Sqls.create("""
SELECT
info.id,
@@ -65,6 +66,7 @@ public class ArticleMineController {
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
@@ -41,6 +41,7 @@ public class ArticleQueryController {
@SaCheckPermission("article.query")
@ApiOperation(value = "分页列表")
public Result pageData(@Valid ArticleInfoPageParam pageForm) {
// 返回流程定义ID,供新闻投稿公共详情组件加载对应的流程图。
Sql sql = Sqls.create("""
SELECT
info.id,
@@ -55,6 +56,7 @@ public class ArticleQueryController {
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
@@ -54,6 +54,7 @@ public class ArticleSchoolUnionApprovalController {
@SaCheckPermission("article.schoolUnionApproval")
@ApiOperation("分页查询")
public Result pageData(@Valid ArticleInfoPageParam pageForm, boolean approval) {
// 返回流程定义ID,供新闻投稿公共详情组件加载对应的流程图。
Sql sql = Sqls.create("""
SELECT
info.id,
@@ -67,6 +68,7 @@ public class ArticleSchoolUnionApprovalController {
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
@@ -7,4 +7,28 @@ public class EvaluateConstant {
*/
public static final String HONOR_TYPE_CODE = "H1000";
/** 流程网关读取的审核路线参数名。 */
public static final String APPROVAL_ROUTE_KEY = "evaluationApprovalRoute";
/** 机关与直属单位工会申请需要先经过单位审核。 */
public static final String UNIT_APPROVAL_ROUTE = "unitApproval";
/** 其他分工会申请直接进入分工会审核。 */
public static final String BRANCH_UNION_APPROVAL_ROUTE = "branchUnionApproval";
/** 机关与直属单位工会编码。 */
public static final String DIRECT_UNIT_UNION_CODE = "01";
/** 流程发起人提交申请后进入的单位负责人审核节点。 */
public static final String UNIT_APPROVAL_TASK_KEY = "b14df33c-053c-4a91-a1b7-283ae70ece56";
/** 分工会主席或管理员审核节点。 */
public static final String BRANCH_UNION_APPROVAL_TASK_KEY = "3bdaa29d-e5eb-4e3e-b7f1-14d03bedd078";
/** 流程发起人所属二级党组织的党委书记审核节点。 */
public static final String PARTY_ORGANIZATION_APPROVAL_TASK_KEY = "7dbdd0ed-05bb-4c31-9f5d-bfad3b3e2e26";
/** 校工会管理员审核节点。 */
public static final String SCHOOL_UNION_APPROVAL_TASK_KEY = "3c158aca-89ef-4188-bbc3-e8db201f02a1";
}
@@ -15,6 +15,7 @@ import com.budwk.app.flow.service.FlowCommonService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateApply;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateActivityService;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import io.swagger.annotations.Api;
@@ -141,6 +142,9 @@ public class EvaluateApplyController {
Dict args = Dict.create();
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
args.set(FlowConst.FORM_DATA, evaluateApply);
// 通用流程决策节点只读取流程参数,提交时根据发起人所属工会固化首次审核路线。
args.set(EvaluateConstant.APPROVAL_ROUTE_KEY,
evaluateService.getApprovalRoute(SecurityUtil.getUnionId()));
ProcessInstance instance = flowEngine.startProcessInstanceByKey("PYPX", evaluateApply.getId(), SecurityUtil.getUserId(), args);
// 自动完成第一个申请任务
@@ -1,117 +1,46 @@
package com.budwk.app.zhgh.dayofficework.evaluation.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.controllers.open.commons.service.CommonService;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
import java.util.List;
/**
* 评优评先分工会审核入口。
*/
@IocBean
@At("/platform/evaluate/branchUnionApproval")
@Ok("json:full")
@Api(tags = "评优评先分工会审核")
public class EvaluateBranchUnionApprovalController {
@Inject
private Dao dao;
@Inject
private BpmService bpmService;
@Inject
private EvaluateService evaluateService;
@Inject
private CommonService commonService;
/** 打开评优评先分工会审核页面。 */
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/evaluation/branchUnionApproval/index.html")
@SaCheckPermission("evaluation.branchUnionApproval")
public void index() {
}
/**
* 查询当前用户在分工会审核节点的待办或已办任务。
*/
@At
@SaCheckPermission("evaluation.branchUnionApproval")
@ApiOperation("数据列表")
@Ok("json")
public Result pageData(@Valid EvaluatePageForm pageForm, Boolean approval){
Sql sql = Sqls.create("""
SELECT
info.*,
ea.name AS evaluateName,
hb.name AS honorName,
bs.name as honorTypeName,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
t.taskType,
t.performType taskPerformType,
t.taskState,
t.finishTime,
t.taskParentId,
t.variable taskVariable,
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
FROM
wf_process_task t
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
LEFT JOIN evaluate_apply info ON info.id = ins.businessNo
LEFT JOIN evaluate_activity ea ON ea.id = info.evaluateId
LEFT JOIN honor_basic_settings hb ON hb.id = info.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = info.honorTypeId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t.taskName", "=", "3bdaa29d-e5eb-4e3e-b7f1-14d03bedd078");
cnd.andEX("info.evaluateId", "=", pageForm.getEvaluateId());
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
if (approval) {
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
} else {
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
}
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.orLike("info.userName", pageForm.getSearchKeyword());
seg.orLike("info.loginName", pageForm.getSearchKeyword());
cnd.and(seg);
}
cnd.andEX("YEAR(info.applyDateTime)", "=", pageForm.getYear());
cnd.groupBy("t.id");
if(StrUtil.isAllBlank(pageForm.getPageOrderName(),pageForm.getPageOrderBy())){
cnd.desc("t.createdAt").desc("info.applyDateTime");
}else{
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
sql.setCondition(cnd);
Pagination pagination = evaluateService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
@ApiOperation("分工会审核数据列表")
public Result pageData(@Valid EvaluatePageForm pageForm, Boolean approval) {
return Result.success(evaluateService.listApprovalPage(pageForm, approval,
EvaluateConstant.BRANCH_UNION_APPROVAL_TASK_KEY));
}
}
@@ -0,0 +1,48 @@
package com.budwk.app.zhgh.dayofficework.evaluation.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
/**
* 评优评先二级党组织审核入口。
*/
@IocBean
@At("/platform/evaluate/partyOrganizationApproval")
@Ok("json:full")
@Api(tags = "评优评先二级党组织审核")
public class EvaluatePartyOrganizationApprovalController {
@Inject
private EvaluateService evaluateService;
/**
* 打开二级党组织审核页面,并复用评优评先审核公共页面。
*/
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/evaluation/branchUnionApproval/index.html")
@SaCheckPermission("evaluation.partyOrganizationApproval")
public void index() {
}
/**
* 查询当前用户在二级党组织审核节点的待办或已办任务。
*/
@At
@SaCheckPermission("evaluation.partyOrganizationApproval")
@ApiOperation("二级党组织审核数据列表")
public Result pageData(@Valid EvaluatePageForm pageForm, Boolean approval) {
return Result.success(evaluateService.listApprovalPage(pageForm, approval,
EvaluateConstant.PARTY_ORGANIZATION_APPROVAL_TASK_KEY));
}
}
@@ -1,159 +1,46 @@
package com.budwk.app.zhgh.dayofficework.evaluation.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.bpm.enums.BpmTaskApprovalTypeEnum;
import com.budwk.app.bpm.param.BpmTaskApprovalParam;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.controllers.open.commons.service.CommonService;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateApply;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 评优评先校工会审核入口。
*/
@IocBean
@At("/platform/evaluate/schoolUnionApproval")
@Ok("json:full")
@Api(tags = "评优评先校工会审核")
public class EvaluateSchoolUnionApprovalController {
@Inject
private Dao dao;
@Inject
private BpmService bpmService;
@Inject
private EvaluateService evaluateService;
@Inject
private CommonService commonService;
/** 打开评优评先校工会审核页面。 */
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/evaluation/schoolUnionApproval/index.html")
@SaCheckPermission("evaluation.schoolUnionApproval")
public void index() {
}
/**
* 查询当前用户在校工会审核节点的待办或已办任务。
*/
@At
@SaCheckPermission("evaluation.schoolUnionApproval")
@ApiOperation("数据列表")
@Ok("json")
public Result pageData(@Valid EvaluatePageForm pageForm, Boolean approval){
Sql sql = Sqls.create("""
SELECT
info.*,
ea.name AS evaluateName,
hb.name AS honorName,
bs.name as honorTypeName,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
t.taskType,
t.performType taskPerformType,
t.taskState,
t.finishTime,
t.taskParentId,
t.variable taskVariable,
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
FROM
wf_process_task t
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
LEFT JOIN evaluate_apply info ON info.id = ins.businessNo
LEFT JOIN evaluate_activity ea ON ea.id = info.evaluateId
LEFT JOIN honor_basic_settings hb ON hb.id = info.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = info.honorTypeId
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t.taskName", "=", "3c158aca-89ef-4188-bbc3-e8db201f02a1");
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
cnd.andEX("info.unionId","=",pageForm.getUnionId());
cnd.andEX("info.unitId","=",pageForm.getUnitId());
cnd.andEX("info.evaluateId","=",pageForm.getEvaluateId());
if (approval) {
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
} else {
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
}
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.orLike("info.userName", pageForm.getSearchKeyword());
seg.orLike("info.loginName", pageForm.getSearchKeyword());
cnd.and(seg);
}
cnd.andEX("YEAR(info.applyDateTime)", "=", pageForm.getYear());
cnd.groupBy("t.id");
if(StrUtil.isAllBlank(pageForm.getPageOrderName(),pageForm.getPageOrderBy())){
cnd.desc("t.createdAt").desc("info.applyDateTime");
}else{
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
sql.setCondition(cnd);
Pagination pagination = evaluateService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
@ApiOperation("校工会审核数据列表")
public Result pageData(@Valid EvaluatePageForm pageForm, Boolean approval) {
return Result.success(evaluateService.listApprovalPage(pageForm, approval,
EvaluateConstant.SCHOOL_UNION_APPROVAL_TASK_KEY));
}
@At
@SaCheckPermission("evaluation.schoolUnionApproval")
@ApiOperation("审核")
@SLog(tag = "评优评先校工会审核", msg = "校工会审核")
@Aop(TransAop.READ_COMMITTED)
public Result approval(@Valid @Param("approval") BpmTaskApprovalParam approvalParam){
approvalParam.getBpmTaskApprovalTypeEnum();
Map<String, Object> variables = BeanUtil.beanToMap(approvalParam);
EvaluateApply evaluateApply = evaluateService.fetch(approvalParam.getProcessInstanceBusinessId());
List<String> assignments = new ArrayList<>();
if(approvalParam.getBpmTaskApprovalTypeEnum().equals(BpmTaskApprovalTypeEnum.PASS)){
String schoolUnionApprovalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.SCHOOL_UNION_ADMIN, Cnd.where(Sys_user_role::getUnionId, "=", evaluateApply.getUnionId()));
assignments.add(schoolUnionApprovalLoginName);
}
bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), variables, assignments);
return Result.success();
}
@At
@SaCheckPermission("evaluation.branchUnionApproval")
@ApiOperation("撤回")
@SLog(tag = "评优评先校工会审核", msg = "撤回")
@Aop(TransAop.READ_COMMITTED)
public Result revoke(@Valid String taskId){
bpmService.revokeTask(taskId);
return Result.success();
}
}
@@ -0,0 +1,48 @@
package com.budwk.app.zhgh.dayofficework.evaluation.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
/**
* 评优评先单位负责人审核入口。
*/
@IocBean
@At("/platform/evaluate/unitApproval")
@Ok("json:full")
@Api(tags = "评优评先单位审核")
public class EvaluateUnitApprovalController {
@Inject
private EvaluateService evaluateService;
/**
* 打开单位审核页面,并复用评优评先审核公共页面。
*/
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/evaluation/branchUnionApproval/index.html")
@SaCheckPermission("evaluation.unitApproval")
public void index() {
}
/**
* 查询当前用户在单位审核节点的待办或已办任务。
*/
@At
@SaCheckPermission("evaluation.unitApproval")
@ApiOperation("单位审核数据列表")
public Result pageData(@Valid EvaluatePageForm pageForm, Boolean approval) {
return Result.success(evaluateService.listApprovalPage(pageForm, approval,
EvaluateConstant.UNIT_APPROVAL_TASK_KEY));
}
}
@@ -1,6 +1,7 @@
package com.budwk.app.zhgh.dayofficework.evaluation.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateApply;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import org.nutz.dao.sql.Sql;
@@ -10,4 +11,22 @@ public interface EvaluateService extends BaseService<EvaluateApply> {
Sql getSummarySql(EvaluatePageForm pageForm);
/**
* 按流程节点查询当前用户的评优评先已办或待办任务。
*
* @param pageForm 查询和分页参数
* @param approval true 查询已审核,false 查询未审核
* @param taskKey 流程任务节点标识
* @return 审核任务分页数据
*/
Pagination listApprovalPage(EvaluatePageForm pageForm, Boolean approval, String taskKey);
/**
* 根据流程发起人的所属工会确定首次审核路线。
*
* @param unionId 流程发起人所属工会 ID
* @return 流程决策节点使用的路线参数值
*/
String getApprovalRoute(String unionId);
}
@@ -1,9 +1,14 @@
package com.budwk.app.zhgh.dayofficework.evaluation.service.impl;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateApply;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
@@ -14,6 +19,8 @@ import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.IocBean;
import java.util.List;
@IocBean(args = {"refer:dao"})
public class EvaluateServiceImpl extends BaseServiceImpl<EvaluateApply> implements EvaluateService {
public EvaluateServiceImpl(Dao dao) {
@@ -76,4 +83,92 @@ public class EvaluateServiceImpl extends BaseServiceImpl<EvaluateApply> implemen
sql.setCondition(cnd);
return sql;
}
/**
* 统一查询评优评先各审核节点任务,确保四级审核页面使用一致的数据权限与查询口径。
*/
@Override
public Pagination listApprovalPage(EvaluatePageForm pageForm, Boolean approval, String taskKey) {
Sql sql = Sqls.create("""
SELECT
info.*,
ea.name AS evaluateName,
hb.name AS honorName,
bs.name AS honorTypeName,
ins.id AS instanceId,
ins.businessNo,
ins.state AS instanceState,
ins.variable AS instanceVariable,
ins.processDefineId AS instanceProcessDefineId,
t.id AS taskId,
t.taskName AS taskKey,
t.displayName AS taskName,
t.taskType,
t.performType AS taskPerformType,
t.taskState,
t.finishTime,
t.taskParentId,
t.variable AS taskVariable,
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName), '结束') AS curTaskName,
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
FROM wf_process_task t
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
LEFT JOIN evaluate_apply info ON info.id = ins.businessNo
LEFT JOIN evaluate_activity ea ON ea.id = info.evaluateId
LEFT JOIN honor_basic_settings hb ON hb.id = info.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = info.honorTypeId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t.taskName", "=", taskKey);
cnd.and("ta.actorId", "=", SecurityUtil.getUserId());
cnd.andEX("info.evaluateId", "=", pageForm.getEvaluateId());
cnd.andEX("info.unionId", "=", pageForm.getUnionId());
cnd.andEX("info.unitId", "=", pageForm.getUnitId());
// 已审核保留完成、后续撤回和中断的历史任务;未审核只返回当前待办。
if (Boolean.TRUE.equals(approval)) {
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(),
ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
} else {
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
}
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup keywordGroup = new SqlExpressionGroup();
keywordGroup.orLike("info.userName", pageForm.getSearchKeyword());
keywordGroup.orLike("info.loginName", pageForm.getSearchKeyword());
cnd.and(keywordGroup);
}
cnd.andEX("YEAR(info.applyDateTime)", "=", pageForm.getYear());
cnd.groupBy("t.id");
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.desc("t.createdAt").desc("info.applyDateTime");
} else {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
/**
* 根据发起人所属工会编码生成流程网关参数。
* 只有编码为 01 的“机关与直属单位工会”需要先走单位审核,其他工会直接进入分工会审核。
*/
@Override
public String getApprovalRoute(String unionId) {
if (StrUtil.isBlank(unionId)) {
throw new BaseException("流程发起人未设置所属工会,无法确定评优评先审核路线");
}
Sys_union union = dao().fetch(Sys_union.class,
Cnd.where(Sys_union::getId, "=", unionId).and(Sys_union::getDelFlag, "=", false));
if (union == null || StrUtil.isBlank(union.getUnionCode())) {
throw new BaseException("流程发起人所属工会不存在或未设置工会编码,无法确定评优评先审核路线");
}
return EvaluateConstant.DIRECT_UNIT_UNION_CODE.equals(union.getUnionCode())
? EvaluateConstant.UNIT_APPROVAL_ROUTE
: EvaluateConstant.BRANCH_UNION_APPROVAL_ROUTE;
}
}
@@ -6,6 +6,7 @@ import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
@@ -34,6 +35,8 @@ import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletResponse;
/**
* @ClassName CondolenceApplyController
* @Author JyuHsin
@@ -72,6 +75,7 @@ public class CondolenceMineController {
SELECT
info.*,
type.name as typeName,
COALESCE(NULLIF(info.typeCode, ''), type.code) AS exportTypeCode,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
@@ -153,6 +157,24 @@ public class CondolenceMineController {
nutMap.put("typeName", type.getName());
return Result.success(nutMap);
}
/**
* 导出当前登录用户本人创建的生育慰问补贴登记表 Word。
*
* @param id 慰问申请 ID
* @param response 文件下载响应,内容为 docx
*/
@At
@Ok("void")
@ApiOperation("导出我的补贴登记表")
@SaCheckPermission(value = {"condolence.mine", "h5.condolence.mine"}, mode = SaMode.OR)
public void onExportSubsidyRegistration(@Param("id") String id, HttpServletResponse response) {
if (StrUtil.isBlank(id)) {
throw new BaseException("慰问申请ID不能为空");
}
condolenceService.exportOwnSubsidyRegistration(id, SecurityUtil.getUserId(), response);
}
@Inject
private SmsService smsService;
}
@@ -65,6 +65,15 @@ public interface CondolenceService extends BaseService<Condolence> {
*/
void exportSubsidyRegistration(String id, HttpServletResponse response);
/**
* 导出当前用户本人创建且已审核完成的生育慰问补贴登记表 Word。
*
* @param id 慰问申请 ID
* @param userId 当前登录用户 ID,用于校验申请归属
* @param response HTTP 文件下载响应
*/
void exportOwnSubsidyRegistration(String id, String userId, HttpServletResponse response);
/**
* 按页面查询条件批量生成慰问资料压缩包。
*
@@ -184,9 +184,31 @@ public class CondolenceServiceImpl extends BaseServiceImpl<Condolence> implement
CommonDownloadUtil.download(fileName, docx, response);
}
/**
* 按统计阅览权限导出生育慰问补贴登记表。
*/
@Override
public void exportSubsidyRegistration(String id, HttpServletResponse response) {
NutMap record = findExportRecord(id);
exportSubsidyRegistration(record, response);
}
/**
* 校验申请创建人后,导出当前用户本人的生育慰问补贴登记表。
*/
@Override
public void exportOwnSubsidyRegistration(String id, String userId, HttpServletResponse response) {
NutMap record = findOwnExportRecord(id, userId);
exportSubsidyRegistration(record, response);
}
/**
* 校验补贴登记表的流程状态和慰问类型,并生成 Word 下载响应。
*
* @param record 已完成访问权限校验的慰问申请导出数据
* @param response HTTP 文件下载响应
*/
private void exportSubsidyRegistration(NutMap record, HttpServletResponse response) {
if (!ProcessInstanceStateEnum.FINISHED.getCode().equals(record.getInt("instanceState"))) {
throw new BaseException("仅流程已完成的慰问申请可以导出补贴登记表");
}
@@ -287,7 +309,7 @@ public class CondolenceServiceImpl extends BaseServiceImpl<Condolence> implement
* @param id 慰问申请 ID
* @return 慰问信息、类型信息和 wf 实例信息
*/
private NutMap findExportRecord(String id) {
private NutMap queryExportRecord(String id) {
Sql sql = Sqls.create("""
SELECT
con.*,
@@ -320,6 +342,17 @@ public class CondolenceServiceImpl extends BaseServiceImpl<Condolence> implement
if (StrUtil.isBlank(record.getString("typeCode"))) {
record.put("typeCode", record.getString("currentTypeCode"));
}
return record;
}
/**
* 查询导出记录并按统计阅览权限校验数据范围。
*
* @param id 慰问申请 ID
* @return 可供导出模板使用的慰问申请数据
*/
private NutMap findExportRecord(String id) {
NutMap record = queryExportRecord(id);
// 非校级管理员只能导出本工会数据,避免通过手工拼接 ID 越权下载。
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())
&& !StrUtil.equals(record.getString("applyUnionId"), SecurityUtil.getUnionId())) {
@@ -328,6 +361,21 @@ public class CondolenceServiceImpl extends BaseServiceImpl<Condolence> implement
return record;
}
/**
* 查询“我的申请”导出记录并校验记录创建人,防止通过手工拼接 ID 导出他人申请。
*
* @param id 慰问申请 ID
* @param userId 当前登录用户 ID
* @return 可供导出模板使用的本人慰问申请数据
*/
private NutMap findOwnExportRecord(String id, String userId) {
NutMap record = queryExportRecord(id);
if (!StrUtil.equals(record.getString("createdBy"), userId)) {
throw new BaseException("无权导出该慰问申请");
}
return record;
}
/**
* 组装模板数据并生成 Word 字节数组。
*
@@ -133,13 +133,21 @@ public class MemberInfoPageForm extends PageForm {
cnd.and(seg);
}
// 权限判断
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.or(prefix + "unionId", "=", SecurityUtil.getUnionId());
seg.or(prefix + "unionId", "is", null);
seg.or(prefix + "unionId", "=", "");
cnd.and(seg);
// 校工会会员管理员与校工会管理员拥有相同的全校会员查询范围,需与前端角色口径保持一致。
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(),
RoleConstant.SCHOOL_UNION_MEMBER_ADMIN.name())) {
String currentUnionId = SecurityUtil.getUnionId();
if (StrUtil.isNotBlank(this.getUnionId())) {
// 普通用户明确选择工会时只查询本人所属工会,不包含未归属工会人员,也不接受越权工会参数。
cnd.and(prefix + "unionId", "=", currentUnionId);
} else {
// 未指定工会时保留原数据范围,允许处理本人所属工会及尚未归属工会的会员。
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.or(prefix + "unionId", "=", currentUnionId);
seg.or(prefix + "unionId", "is", null);
seg.or(prefix + "unionId", "=", "");
cnd.and(seg);
}
} else {
cnd.andEX(prefix + "unionId", "=", this.getUnionId());
}
@@ -0,0 +1,169 @@
-- 评优评先新增“单位审核、二级党组织审核”节点。
-- 脚本保留历史流程定义,新申请使用新版本;重复执行不会重复新增菜单和角色授权。
START TRANSACTION;
SET @evaluation_menu_id = '32bd9853db494301bb59757a55dc1c5d';
SET @unit_menu_id = 'e8f0f73512de4a8db7d95478dd1885ad';
SET @party_menu_id = '76c7148f8cc84d29b4b0ee791620eb7e';
-- 调整原菜单顺序,为两个新增审核入口预留业务流程顺序。
UPDATE sys_menu SET path = 'evaluation_tmp_branch', location = 330
WHERE permission = 'evaluation.branchUnionApproval';
UPDATE sys_menu SET path = 'evaluation_tmp_school', location = 332
WHERE permission = 'evaluation.schoolUnionApproval';
UPDATE sys_menu SET path = 'evaluation_tmp_summary', location = 333
WHERE permission = 'evaluation.summary';
UPDATE sys_menu SET path = '0053' WHERE permission = 'evaluation.branchUnionApproval';
UPDATE sys_menu SET path = '0055' WHERE permission = 'evaluation.schoolUnionApproval';
UPDATE sys_menu SET path = '0056' WHERE permission = 'evaluation.summary';
INSERT INTO sys_menu
(id, parentId, path, name, type, href, showit, disabled, permission, location, hasChildren,
createdBy, createdAt, delFlag, platform, moduleId, isQuickEntry, initialPinyinName,
isRecommendApp, isRecommendService)
SELECT @unit_menu_id, @evaluation_menu_id, '0052', CONVERT(0xE58D95E4BD8DE5AEA1E6A0B8 USING utf8mb4), 'menu',
'/platform/evaluate/unitApproval', 1, 0, 'evaluation.unitApproval', 329, 0,
'system', UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000, 0, 'PC', moduleId, 0, 'd', 0, 0
FROM sys_menu
WHERE id = @evaluation_menu_id
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'evaluation.unitApproval') existing_menu);
INSERT INTO sys_menu
(id, parentId, path, name, type, href, showit, disabled, permission, location, hasChildren,
createdBy, createdAt, delFlag, platform, moduleId, isQuickEntry, initialPinyinName,
isRecommendApp, isRecommendService)
SELECT @party_menu_id, @evaluation_menu_id, '0054', CONVERT(0xE4BA8CE7BAA7E5859AE7BB84E7BB87E5AEA1E6A0B8 USING utf8mb4), 'menu',
'/platform/evaluate/partyOrganizationApproval', 1, 0, 'evaluation.partyOrganizationApproval', 331, 0,
'system', UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000, 0, 'PC', moduleId, 0, 'e', 0, 0
FROM sys_menu
WHERE id = @evaluation_menu_id
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'evaluation.partyOrganizationApproval') existing_menu);
-- 无论菜单是首次新增还是重复执行,均统一校正名称,十六进制字面量避免终端编码影响中文。
UPDATE sys_menu SET name = CONVERT(0xE58D95E4BD8DE5AEA1E6A0B8 USING utf8mb4)
WHERE permission = 'evaluation.unitApproval';
UPDATE sys_menu SET name = CONVERT(0xE4BA8CE7BAA7E5859AE7BB84E7BB87E5AEA1E6A0B8 USING utf8mb4)
WHERE permission = 'evaluation.partyOrganizationApproval';
-- 单位负责人和单位党委书记同时需要父菜单与各自审核菜单权限,确保菜单树可见。
INSERT INTO sys_role_menu (roleId, menuId)
SELECT role.id, menu.id
FROM sys_role role
JOIN sys_menu menu ON menu.permission IN ('evaluation', 'evaluation.unitApproval')
WHERE role.code = 'UNIT_MANAGER'
AND NOT EXISTS (SELECT 1 FROM sys_role_menu relation WHERE relation.roleId = role.id AND relation.menuId = menu.id);
INSERT INTO sys_role_menu (roleId, menuId)
SELECT role.id, menu.id
FROM sys_role role
JOIN sys_menu menu ON menu.permission IN ('evaluation', 'evaluation.partyOrganizationApproval')
WHERE role.code = 'UNIT_PARTY_SECRETARY'
AND NOT EXISTS (SELECT 1 FROM sys_role_menu relation WHERE relation.roleId = role.id AND relation.menuId = menu.id);
-- 设计稿已有两个节点,本次补齐表单地址和严格按发起人组织范围取人的处理类。
UPDATE wf_process_design
SET content = JSON_SET(
IF(
JSON_SEARCH(content, 'one', '3a833b92-badd-4569-994e-9a675a4e0e54') IS NULL,
content,
JSON_REMOVE(content, REPLACE(
JSON_UNQUOTE(JSON_SEARCH(content, 'one', '3a833b92-badd-4569-994e-9a675a4e0e54')),
'.id', ''))
),
'$.nodes[5].properties.form', '/platform/evaluate/unitApproval',
'$.nodes[5].properties.assignee', '',
'$.nodes[5].properties.assigneeMode', 'manual',
'$.nodes[5].properties.assigneeText', '',
'$.nodes[5].properties.assignmentHandler', 'com.budwk.app.flow.handler.FlowInitiatorUnitManagerAssignmentHandler',
'$.nodes[6].text.value', CONVERT(0xE4BA8CE7BAA7E5859AE7BB84E7BB87E5AEA1E6A0B8 USING utf8mb4),
'$.nodes[6].properties.form', '/platform/evaluate/partyOrganizationApproval',
'$.nodes[6].properties.assignee', '',
'$.nodes[6].properties.assigneeMode', 'manual',
'$.nodes[6].properties.assigneeText', '',
'$.nodes[6].properties.assignmentHandler', 'com.budwk.app.flow.handler.FlowInitiatorPartyOrganizationAssignmentHandler'
),
isDeployed = 1,
updatedBy = 'system',
updatedAt = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000
WHERE name = 'PYPX';
-- 提交申请后复用设计稿中已有的通用决策节点,不创建业务专用判断类或重复网关。
SET @route_decision_id = '7d03f3fd-7fc4-4865-9dc9-c1895c677624';
SET @route_unit_edge_id = '7b3af019-a8af-419c-9f83-aacca0c71d2e';
SET @route_branch_edge_id = 'ca809b7a-f5dc-4f4a-9780-35f47a6babfc';
-- 清理首次执行旧脚本可能生成的重复节点和连线,按精确 ID 定位,避免影响其他流程元素。
UPDATE wf_process_design
SET content = JSON_REMOVE(
content,
REPLACE(JSON_UNQUOTE(JSON_SEARCH(content, 'one', 'evaluateApprovalRouteToUnit')), '.id', '')
)
WHERE name = 'PYPX'
AND JSON_SEARCH(content, 'one', 'evaluateApprovalRouteToUnit') IS NOT NULL;
UPDATE wf_process_design
SET content = JSON_REMOVE(
content,
REPLACE(JSON_UNQUOTE(JSON_SEARCH(content, 'one', 'evaluateApprovalRouteToBranch')), '.id', '')
)
WHERE name = 'PYPX'
AND JSON_SEARCH(content, 'one', 'evaluateApprovalRouteToBranch') IS NOT NULL;
UPDATE wf_process_design
SET content = JSON_REMOVE(
content,
REPLACE(JSON_UNQUOTE(JSON_SEARCH(content, 'one', 'evaluateApprovalRouteDecision')), '.id', '')
)
WHERE name = 'PYPX'
AND JSON_SEARCH(content, 'one', 'evaluateApprovalRouteDecision') IS NOT NULL;
-- 在现有网关的两条输出线上配置参数表达式。
UPDATE wf_process_design
SET content = JSON_SET(
content,
CONCAT(REPLACE(JSON_UNQUOTE(JSON_SEARCH(content, 'one', @route_unit_edge_id)), '.id', ''),
'.properties.expr'),
'{evaluationApprovalRoute==\'unitApproval\'}',
CONCAT(REPLACE(JSON_UNQUOTE(JSON_SEARCH(content, 'one', @route_branch_edge_id)), '.id', ''),
'.properties.expr'),
'{evaluationApprovalRoute==\'branchUnionApproval\'}'
)
WHERE name = 'PYPX'
AND JSON_SEARCH(content, 'one', @route_decision_id) IS NOT NULL
AND JSON_SEARCH(content, 'one', @route_unit_edge_id) IS NOT NULL
AND JSON_SEARCH(content, 'one', @route_branch_edge_id) IS NOT NULL;
-- 插入新流程版本,旧申请继续绑定原有版本,不改写历史实例。
INSERT INTO wf_process_define
(createdBy, createdAt, updatedBy, updatedAt, delFlag, name, displayName, type, state,
content, version, category, instanceUrl, h5InstanceUrl, icon, instanceViewUrl,
h5InstanceViewUrl, pinyinName, description)
SELECT 'system', UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000, 'system',
UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000, 0, design.name, design.displayName,
design.type, 1, CAST(design.content AS BINARY), latest.version + 1, design.category,
design.instanceUrl, design.h5InstanceUrl, design.icon, design.instanceViewUrl,
design.h5InstanceViewUrl, 'p', design.description
FROM wf_process_design design
JOIN (SELECT MAX(version) AS version FROM wf_process_define WHERE name = 'PYPX') latest
WHERE design.name = 'PYPX'
AND NOT EXISTS (
SELECT 1
FROM wf_process_define deployed
WHERE deployed.name = 'PYPX'
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
'com.budwk.app.flow.handler.FlowInitiatorUnitManagerAssignmentHandler') IS NOT NULL
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
'com.budwk.app.flow.handler.FlowInitiatorPartyOrganizationAssignmentHandler') IS NOT NULL
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
@route_decision_id) IS NOT NULL
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
'{evaluationApprovalRoute==\'unitApproval\'}') IS NOT NULL
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
'{evaluationApprovalRoute==\'branchUnionApproval\'}') IS NOT NULL
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
'evaluateApprovalRouteDecision') IS NULL
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
'evaluateApprovalRouteToUnit') IS NULL
AND JSON_SEARCH(CONVERT(deployed.content USING utf8mb4), 'one',
'evaluateApprovalRouteToBranch') IS NULL
);
COMMIT;
@@ -0,0 +1,669 @@
-- 将 v3 评优评先业务数据和审批状态迁移到 v4,并重建 v4 流程实例、任务及参与人。
-- 说明:v3 没有流程引擎表,审批链由 evaluate_apply 的状态、四个审核记录 ID 和 audit 表还原。
USE zhgh_swufe;
START TRANSACTION;
SET @now_ms = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000;
SET @process_define_id = (
SELECT id FROM zhgh_swufe.wf_process_define
WHERE name = 'PYPX' AND state = 1 AND IFNULL(delFlag, 0) = 0
ORDER BY version DESC LIMIT 1
);
-- 缺少已部署流程定义时主动中断,禁止生成无法继续办理的孤立流程。
DROP TEMPORARY TABLE IF EXISTS tmp_evaluation_migration_guard;
CREATE TEMPORARY TABLE tmp_evaluation_migration_guard (
checkName VARCHAR(64) NOT NULL,
passed TINYINT NOT NULL
);
INSERT INTO tmp_evaluation_migration_guard (checkName, passed)
VALUES ('active_process_definition', IF(@process_define_id IS NOT NULL, 1, NULL));
-- 当前任务节点采用固定业务键,部署定义缺少任一节点时立即中断,避免创建无法继续办理的待办。
SET @process_definition_content = (
SELECT CAST(content AS CHAR)
FROM zhgh_swufe.wf_process_define
WHERE id = @process_define_id
);
DELETE FROM tmp_evaluation_migration_guard;
INSERT INTO tmp_evaluation_migration_guard (checkName, passed) VALUES
('unit_node', IF(LOCATE('b14df33c-053c-4a91-a1b7-283ae70ece56', @process_definition_content) > 0, 1, NULL)),
('branch_node', IF(LOCATE('3bdaa29d-e5eb-4e3e-b7f1-14d03bedd078', @process_definition_content) > 0, 1, NULL)),
('party_node', IF(LOCATE('7dbdd0ed-05bb-4c31-9f5d-bfad3b3e2e26', @process_definition_content) > 0, 1, NULL)),
('school_node', IF(LOCATE('3c158aca-89ef-4188-bbc3-e8db201f02a1', @process_definition_content) > 0, 1, NULL));
-- v3 的两个荣誉在 v4 中没有原主键;保留原 ID、名称和层级,确保历史活动及申请关联完整。
INSERT INTO zhgh_swufe.honor_basic_settings
(id, parentId, code, name, level, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT oldHonor.id, oldHonor.parentId, oldHonor.code, oldHonor.name, oldHonor.level,
oldHonor.hasChildren, 'migration', @now_ms, 'migration', @now_ms, 0
FROM union_swufe.honor_basic_settings oldHonor
WHERE oldHonor.id IN ('275c2ddff5ee4edbb961bc73654686ff', '00a4a86f2713403485322fd9786cafc8')
AND NOT EXISTS (
SELECT 1 FROM zhgh_swufe.honor_basic_settings currentHonor WHERE currentHonor.id = oldHonor.id
);
-- 仅清理 v4 当前评优评先申请关联的流程运行数据,不影响流程设计、定义和其他模块。
DROP TEMPORARY TABLE IF EXISTS tmp_old_evaluation_instance;
CREATE TEMPORARY TABLE tmp_old_evaluation_instance (id BIGINT PRIMARY KEY);
INSERT INTO tmp_old_evaluation_instance (id)
SELECT DISTINCT instance.id
FROM zhgh_swufe.wf_process_instance instance
JOIN zhgh_swufe.evaluate_apply apply ON apply.id = instance.businessNo
JOIN zhgh_swufe.wf_process_define processDefine
ON processDefine.id = instance.processDefineId AND processDefine.name = 'PYPX';
DELETE actor
FROM zhgh_swufe.wf_process_task_actor actor
JOIN zhgh_swufe.wf_process_task task ON task.id = actor.processTaskId
JOIN tmp_old_evaluation_instance oldInstance ON oldInstance.id = task.processInstanceId;
DELETE cc
FROM zhgh_swufe.wf_process_cc_instance cc
JOIN tmp_old_evaluation_instance oldInstance ON oldInstance.id = cc.processInstanceId;
DELETE task
FROM zhgh_swufe.wf_process_task task
JOIN tmp_old_evaluation_instance oldInstance ON oldInstance.id = task.processInstanceId;
DELETE instance
FROM zhgh_swufe.wf_process_instance instance
JOIN tmp_old_evaluation_instance oldInstance ON oldInstance.id = instance.id;
DELETE home
FROM zhgh_swufe.sys_home_activity home
JOIN zhgh_swufe.evaluate_activity activity ON activity.id = home.id;
DELETE FROM zhgh_swufe.evaluate_apply;
DELETE FROM zhgh_swufe.evaluate_activity;
-- 活动字段仅做语义一致的映射;conditions、program、xlFlag 在 v4 无对应字段,不强制写入其他字段。
INSERT INTO zhgh_swufe.evaluate_activity
(id, honorId, honorTypeId, name, year, startTime, endTime, notice, directions,
quotaAllocations, enable, activityGroupId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT activity.id,
activity.honorId,
activity.honorTypeId,
activity.name,
YEAR(STR_TO_DATE(activity.startTime, '%Y-%m-%d %H:%i:%s')),
STR_TO_DATE(activity.startTime, '%Y-%m-%d %H:%i:%s'),
STR_TO_DATE(activity.endTime, '%Y-%m-%d %H:%i:%s'),
NULL,
activity.directions,
activity.unionLimit,
1,
activity.groupId,
COALESCE(NULLIF(activity.userid, ''), 'migration'),
UNIX_TIMESTAMP(STR_TO_DATE(activity.startTime, '%Y-%m-%d %H:%i:%s')) * 1000,
COALESCE(NULLIF(activity.userid, ''), 'migration'),
UNIX_TIMESTAMP(STR_TO_DATE(activity.startTime, '%Y-%m-%d %H:%i:%s')) * 1000,
0
FROM union_swufe.evaluate activity;
-- 同步首页活动记录,使迁移后的历史活动在现有活动入口保持一致的数据关系。
INSERT INTO zhgh_swufe.sys_home_activity
(id, name, cover, url, h5Url, groupId, enable, createdBy, createdAt, updatedBy, updatedAt,
delFlag, classPath, sortNo, top, allowUserGroupId, startDate, endDate, push)
SELECT activity.id, activity.name, '', '/platform/evaluate/apply', '', NULL, activity.enable,
activity.createdBy, activity.createdAt, activity.updatedBy, activity.updatedAt, 0,
'com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity', 0, 0,
activity.activityGroupId, activity.startTime, activity.endTime, 0
FROM zhgh_swufe.evaluate_activity activity;
-- 申请人、单位和分工会名称从 v4 源数据补齐;v3 业务字段有直接对应关系的才迁移。
INSERT INTO zhgh_swufe.evaluate_apply
(id, evaluateId, honorId, honorTypeId, loginName, userName, mobile, birthday, sex, nation,
political, education, technicalTitle, governmentPosition, historyHonor, briefDeeds,
unitName, unitId, unionName, unionId, clubName, clubId, applyDateTime, isClub, files,
memberNumber, unionGroupNumber, unionLeader, applyUnionName,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT apply.id,
apply.evaluateId,
apply.honorId,
apply.honorTypeId,
user.loginname,
user.username,
user.mobile,
STR_TO_DATE(NULLIF(apply.birthday, ''), '%Y-%m-%d'),
apply.userSex,
apply.nation,
apply.political,
user.education,
apply.jobTitle,
apply.position,
apply.award,
apply.deeds,
unit.name,
apply.unitId,
COALESCE(NULLIF(apply.unionName, ''), branchUnion.name),
apply.unionId,
NULL,
NULL,
STR_TO_DATE(apply.applyTime, '%Y-%m-%d'),
0,
apply.files,
apply.memberNumber,
apply.unionGroupNumber,
apply.unionLeader,
apply.applyUnionName,
apply.userId,
UNIX_TIMESTAMP(STR_TO_DATE(apply.applyTime, '%Y-%m-%d')) * 1000,
apply.userId,
UNIX_TIMESTAMP(STR_TO_DATE(apply.applyTime, '%Y-%m-%d')) * 1000,
0
FROM union_swufe.evaluate_apply apply
JOIN zhgh_swufe.sys_user user ON user.id = apply.userId
LEFT JOIN zhgh_swufe.sys_unit unit ON unit.id = apply.unitId
LEFT JOIN zhgh_swufe.sys_union branchUnion ON branchUnion.id = apply.unionId;
-- 72 条已提交或有审批历史的申请需要流程实例;6 条纯草稿只保留业务数据。
INSERT INTO zhgh_swufe.wf_process_instance
(parentId, processDefineId, state, parentNodeName, businessNo, operator, expireTime, variable,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT NULL,
@process_define_id,
IF(oldApply.stateId = 1900, 20, 10),
NULL,
currentApply.id,
currentApply.createdBy,
NULL,
JSON_OBJECT(
'submitType', 0,
'f_data', JSON_OBJECT(
'id', currentApply.id,
'evaluateId', currentApply.evaluateId,
'honorId', currentApply.honorId,
'honorTypeId', currentApply.honorTypeId,
'loginName', currentApply.loginName,
'userName', currentApply.userName,
'mobile', currentApply.mobile,
'birthday', UNIX_TIMESTAMP(currentApply.birthday) * 1000,
'sex', currentApply.sex,
'nation', currentApply.nation,
'political', currentApply.political,
'education', currentApply.education,
'technicalTitle', currentApply.technicalTitle,
'governmentPosition', currentApply.governmentPosition,
'historyHonor', currentApply.historyHonor,
'briefDeeds', currentApply.briefDeeds,
'unitName', currentApply.unitName,
'unitId', currentApply.unitId,
'unionName', currentApply.unionName,
'unionId', currentApply.unionId,
'applyDateTime', UNIX_TIMESTAMP(currentApply.applyDateTime) * 1000,
'memberNumber', currentApply.memberNumber,
'unionGroupNumber', currentApply.unionGroupNumber,
'unionLeader', currentApply.unionLeader,
'applyUnionName', currentApply.applyUnionName,
'createdBy', currentApply.createdBy,
'createdAt', currentApply.createdAt,
'updatedBy', currentApply.updatedBy,
'updatedAt', currentApply.updatedAt,
'delFlag', FALSE
),
'evaluationApprovalRoute', IF(branchUnion.unionCode = '01', 'unitApproval', 'branchUnionApproval'),
'u_userId', currentApply.createdBy,
'initiator', currentApply.createdBy,
'initiatorName', currentApply.userName,
'initiatorAccount', currentApply.loginName,
'initiatorUnitId', currentApply.unitId,
'initiatorUnitName', currentApply.unitName,
'initiatorUnionId', currentApply.unionId,
'initiatorUnionName', currentApply.unionName,
'instanceName', CONCAT(currentApply.userName, '的评优评先申请')
),
currentApply.createdBy,
currentApply.createdAt,
currentApply.createdBy,
COALESCE(
UNIX_TIMESTAMP(schoolAudit.auditTime) * 1000,
UNIX_TIMESTAMP(partyAudit.auditTime) * 1000,
UNIX_TIMESTAMP(unionAudit.auditTime) * 1000,
UNIX_TIMESTAMP(unitAudit.auditTime) * 1000,
currentApply.updatedAt
),
0
FROM zhgh_swufe.evaluate_apply currentApply
JOIN union_swufe.evaluate_apply oldApply ON oldApply.id = currentApply.id
LEFT JOIN zhgh_swufe.sys_union branchUnion ON branchUnion.id = currentApply.unionId
LEFT JOIN union_swufe.audit unitAudit ON unitAudit.id = oldApply.unitAuditId
LEFT JOIN union_swufe.audit unionAudit ON unionAudit.id = oldApply.unionAuditId
LEFT JOIN union_swufe.audit partyAudit ON partyAudit.id = oldApply.partyAuditId
LEFT JOIN union_swufe.audit schoolAudit ON schoolAudit.id = oldApply.schoolAuditId
WHERE oldApply.stateId <> 1400
OR NULLIF(oldApply.unitAuditId, '') IS NOT NULL
OR NULLIF(oldApply.unionAuditId, '') IS NOT NULL
OR NULLIF(oldApply.partyAuditId, '') IS NOT NULL
OR NULLIF(oldApply.schoolAuditId, '') IS NOT NULL;
DROP TEMPORARY TABLE IF EXISTS tmp_evaluation_task_plan;
CREATE TEMPORARY TABLE tmp_evaluation_task_plan (
rowKey VARCHAR(100) PRIMARY KEY,
parentRowKey VARCHAR(100),
businessNo VARCHAR(32) NOT NULL,
taskName VARCHAR(128) NOT NULL,
displayName VARCHAR(128) NOT NULL,
formKey VARCHAR(128),
taskState INT NOT NULL,
operator VARCHAR(128),
finishTime DATETIME,
createdAt BIGINT,
auditId VARCHAR(32),
submitType INT
);
-- 退回待修改申请可能已有多级审核历史,只有最后一次审核标记为退回,之前节点仍保留原审核结果。
DROP TEMPORARY TABLE IF EXISTS tmp_evaluation_returned_last_audit;
CREATE TEMPORARY TABLE tmp_evaluation_returned_last_audit (
businessNo VARCHAR(32) PRIMARY KEY,
auditId VARCHAR(32) NOT NULL
);
INSERT INTO tmp_evaluation_returned_last_audit (businessNo, auditId)
SELECT oldApply.id,
SUBSTRING_INDEX(
GROUP_CONCAT(audit.id ORDER BY audit.auditTime DESC, audit.opAt DESC, audit.id DESC SEPARATOR ','),
',', 1
)
FROM union_swufe.evaluate_apply oldApply
JOIN union_swufe.audit audit
ON audit.id IN (oldApply.unitAuditId, oldApply.unionAuditId, oldApply.partyAuditId, oldApply.schoolAuditId)
WHERE oldApply.stateId = 1400
GROUP BY oldApply.id;
-- 每个流程首先保留一条已完成的“提交申请”任务。
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(apply.id, ':start:finished'), NULL, apply.id, 'startTask', '提交申请', NULL,
20, apply.createdBy, apply.applyDateTime, apply.createdAt, NULL, 0
FROM zhgh_swufe.evaluate_apply apply
JOIN zhgh_swufe.wf_process_instance instance
ON instance.businessNo = apply.id AND instance.processDefineId = @process_define_id;
-- 按 v3 四个审核记录 ID 还原已发生的历史审核任务,节点顺序遵循当前 PYPX 流程。
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':unit'), CONCAT(oldApply.id, ':start:finished'), oldApply.id,
'b14df33c-053c-4a91-a1b7-283ae70ece56', '单位审核', '/platform/evaluate/unitApproval',
20, audit.auditor, audit.auditTime, UNIX_TIMESTAMP(audit.auditTime) * 1000, audit.id,
IF(returnedAudit.auditId = audit.id, 6, IF(audit.auditPass = 1, 1, 2))
FROM union_swufe.evaluate_apply oldApply
JOIN union_swufe.audit audit ON audit.id = oldApply.unitAuditId
LEFT JOIN tmp_evaluation_returned_last_audit returnedAudit ON returnedAudit.businessNo = oldApply.id;
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':union'),
IF(oldApply.unitAuditId IS NOT NULL AND oldApply.unitAuditId <> '',
CONCAT(oldApply.id, ':unit'), CONCAT(oldApply.id, ':start:finished')),
oldApply.id, '3bdaa29d-e5eb-4e3e-b7f1-14d03bedd078', '分工会审核',
'/platform/evaluate/branchUnionApproval', 20, audit.auditor, audit.auditTime,
UNIX_TIMESTAMP(audit.auditTime) * 1000, audit.id,
IF(returnedAudit.auditId = audit.id, 6, IF(audit.auditPass = 1, 1, 2))
FROM union_swufe.evaluate_apply oldApply
JOIN union_swufe.audit audit ON audit.id = oldApply.unionAuditId
LEFT JOIN tmp_evaluation_returned_last_audit returnedAudit ON returnedAudit.businessNo = oldApply.id;
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':party'),
IF(oldApply.unionAuditId IS NOT NULL AND oldApply.unionAuditId <> '',
CONCAT(oldApply.id, ':union'),
IF(oldApply.unitAuditId IS NOT NULL AND oldApply.unitAuditId <> '',
CONCAT(oldApply.id, ':unit'), CONCAT(oldApply.id, ':start:finished'))),
oldApply.id, '7dbdd0ed-05bb-4c31-9f5d-bfad3b3e2e26', '二级党组织审核',
'/platform/evaluate/partyOrganizationApproval', 20, audit.auditor, audit.auditTime,
UNIX_TIMESTAMP(audit.auditTime) * 1000, audit.id,
IF(returnedAudit.auditId = audit.id, 6, IF(audit.auditPass = 1, 1, 2))
FROM union_swufe.evaluate_apply oldApply
JOIN union_swufe.audit audit ON audit.id = oldApply.partyAuditId
LEFT JOIN tmp_evaluation_returned_last_audit returnedAudit ON returnedAudit.businessNo = oldApply.id;
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':school'),
IF(oldApply.partyAuditId IS NOT NULL AND oldApply.partyAuditId <> '',
CONCAT(oldApply.id, ':party'),
IF(oldApply.unionAuditId IS NOT NULL AND oldApply.unionAuditId <> '',
CONCAT(oldApply.id, ':union'), CONCAT(oldApply.id, ':start:finished'))),
oldApply.id, '3c158aca-89ef-4188-bbc3-e8db201f02a1', '校工会审核',
'/platform/evaluate/schoolUnionApproval', 20, audit.auditor, audit.auditTime,
UNIX_TIMESTAMP(audit.auditTime) * 1000, audit.id,
IF(returnedAudit.auditId = audit.id, 6, IF(audit.auditPass = 1, 1, 2))
FROM union_swufe.evaluate_apply oldApply
JOIN union_swufe.audit audit ON audit.id = oldApply.schoolAuditId
LEFT JOIN tmp_evaluation_returned_last_audit returnedAudit ON returnedAudit.businessNo = oldApply.id;
-- 根据 v3 当前状态生成唯一待办节点;退回状态生成新的发起人“提交申请”待办。
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':start:doing'),
COALESCE(
IF(oldApply.schoolAuditId IS NOT NULL AND oldApply.schoolAuditId <> '', CONCAT(oldApply.id, ':school'), NULL),
IF(oldApply.partyAuditId IS NOT NULL AND oldApply.partyAuditId <> '', CONCAT(oldApply.id, ':party'), NULL),
IF(oldApply.unionAuditId IS NOT NULL AND oldApply.unionAuditId <> '', CONCAT(oldApply.id, ':union'), NULL),
IF(oldApply.unitAuditId IS NOT NULL AND oldApply.unitAuditId <> '', CONCAT(oldApply.id, ':unit'), NULL),
CONCAT(oldApply.id, ':start:finished')
),
oldApply.id, 'startTask', '提交申请', NULL, 10, NULL, NULL,
COALESCE(
UNIX_TIMESTAMP(schoolAudit.auditTime) * 1000,
UNIX_TIMESTAMP(partyAudit.auditTime) * 1000,
UNIX_TIMESTAMP(unionAudit.auditTime) * 1000,
UNIX_TIMESTAMP(unitAudit.auditTime) * 1000
), NULL, 5
FROM union_swufe.evaluate_apply oldApply
JOIN zhgh_swufe.wf_process_instance instance
ON instance.businessNo = oldApply.id AND instance.processDefineId = @process_define_id
LEFT JOIN union_swufe.audit unitAudit ON unitAudit.id = oldApply.unitAuditId
LEFT JOIN union_swufe.audit unionAudit ON unionAudit.id = oldApply.unionAuditId
LEFT JOIN union_swufe.audit partyAudit ON partyAudit.id = oldApply.partyAuditId
LEFT JOIN union_swufe.audit schoolAudit ON schoolAudit.id = oldApply.schoolAuditId
WHERE oldApply.stateId = 1400;
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':unit:doing'), CONCAT(oldApply.id, ':start:finished'), oldApply.id,
'b14df33c-053c-4a91-a1b7-283ae70ece56', '单位审核', '/platform/evaluate/unitApproval',
10, NULL, NULL, currentApply.createdAt, NULL, NULL
FROM union_swufe.evaluate_apply oldApply
JOIN zhgh_swufe.evaluate_apply currentApply ON currentApply.id = oldApply.id
WHERE oldApply.stateId = 1500;
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':union:doing'),
IF(oldApply.unitAuditId IS NOT NULL AND oldApply.unitAuditId <> '',
CONCAT(oldApply.id, ':unit'), CONCAT(oldApply.id, ':start:finished')),
oldApply.id, '3bdaa29d-e5eb-4e3e-b7f1-14d03bedd078', '分工会审核',
'/platform/evaluate/branchUnionApproval', 10, NULL, NULL,
COALESCE(UNIX_TIMESTAMP(unitAudit.auditTime) * 1000, currentApply.createdAt), NULL, NULL
FROM union_swufe.evaluate_apply oldApply
JOIN zhgh_swufe.evaluate_apply currentApply ON currentApply.id = oldApply.id
LEFT JOIN union_swufe.audit unitAudit ON unitAudit.id = oldApply.unitAuditId
WHERE oldApply.stateId = 1600;
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':party:doing'), CONCAT(oldApply.id, ':union'), oldApply.id,
'7dbdd0ed-05bb-4c31-9f5d-bfad3b3e2e26', '二级党组织审核',
'/platform/evaluate/partyOrganizationApproval', 10, NULL, NULL,
COALESCE(UNIX_TIMESTAMP(unionAudit.auditTime) * 1000, currentApply.createdAt), NULL, NULL
FROM union_swufe.evaluate_apply oldApply
JOIN zhgh_swufe.evaluate_apply currentApply ON currentApply.id = oldApply.id
LEFT JOIN union_swufe.audit unionAudit ON unionAudit.id = oldApply.unionAuditId
WHERE oldApply.stateId = 1700;
INSERT INTO tmp_evaluation_task_plan
SELECT CONCAT(oldApply.id, ':school:doing'), CONCAT(oldApply.id, ':party'), oldApply.id,
'3c158aca-89ef-4188-bbc3-e8db201f02a1', '校工会审核',
'/platform/evaluate/schoolUnionApproval', 10, NULL, NULL,
COALESCE(UNIX_TIMESTAMP(partyAudit.auditTime) * 1000, currentApply.createdAt), NULL, NULL
FROM union_swufe.evaluate_apply oldApply
JOIN zhgh_swufe.evaluate_apply currentApply ON currentApply.id = oldApply.id
LEFT JOIN union_swufe.audit partyAudit ON partyAudit.id = oldApply.partyAuditId
WHERE oldApply.stateId = 1800;
-- 先插入任务,再通过业务号、节点和状态建立临时行键与自增 ID 的对应关系。
INSERT INTO zhgh_swufe.wf_process_task
(processInstanceId, taskName, displayName, taskType, performType, taskState, operator,
finishTime, expireTime, formKey, h5FormKey, taskParentId, variable,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT instance.id, plan.taskName, plan.displayName, 0, 0, plan.taskState, plan.operator,
plan.finishTime, NULL, plan.formKey, NULL, NULL,
JSON_MERGE_PATCH(
instance.variable,
JSON_OBJECT(
'processInstanceId', instance.id,
'isFirstTaskNode', IF(plan.taskName = 'startTask', TRUE, FALSE),
'taskName', plan.displayName
),
CASE WHEN plan.auditId IS NULL THEN
JSON_OBJECT('submitType', COALESCE(plan.submitType, 0))
ELSE JSON_OBJECT(
'submitType', plan.submitType,
'tf_approvalComment', audit.auditOpinion,
'tf_opinion', audit.auditOpinion,
'tf_userSign', audit.auditSign,
'tf_userName', COALESCE(audit.username, reviewer.username),
'tf_loginName', COALESCE(audit.loginname, reviewer.loginname),
'tf_unitId', reviewer.unitId,
'tf_unitName', reviewerUnit.name,
'tf_unionId', reviewerUnit.unionId,
'migrationAuditId', audit.id
) END
),
COALESCE(plan.operator, apply.createdBy),
COALESCE(plan.createdAt, apply.createdAt),
COALESCE(plan.operator, apply.createdBy),
COALESCE(UNIX_TIMESTAMP(plan.finishTime) * 1000, plan.createdAt, apply.createdAt),
0
FROM tmp_evaluation_task_plan plan
JOIN zhgh_swufe.wf_process_instance instance
ON instance.businessNo = plan.businessNo AND instance.processDefineId = @process_define_id
JOIN zhgh_swufe.evaluate_apply apply ON apply.id = plan.businessNo
LEFT JOIN union_swufe.audit audit ON audit.id = plan.auditId
LEFT JOIN zhgh_swufe.sys_user reviewer ON reviewer.id = audit.auditor
LEFT JOIN zhgh_swufe.sys_unit reviewerUnit ON reviewerUnit.id = reviewer.unitId;
DROP TEMPORARY TABLE IF EXISTS tmp_evaluation_task_id;
CREATE TEMPORARY TABLE tmp_evaluation_task_id (
rowKey VARCHAR(100) PRIMARY KEY,
taskId BIGINT NOT NULL
);
INSERT INTO tmp_evaluation_task_id (rowKey, taskId)
SELECT plan.rowKey, task.id
FROM tmp_evaluation_task_plan plan
JOIN zhgh_swufe.wf_process_instance instance
ON instance.businessNo = plan.businessNo AND instance.processDefineId = @process_define_id
JOIN zhgh_swufe.wf_process_task task
ON task.processInstanceId = instance.id
AND task.taskName = plan.taskName
AND task.taskState = plan.taskState
AND (plan.auditId IS NULL OR JSON_UNQUOTE(JSON_EXTRACT(task.variable, '$.migrationAuditId')) = plan.auditId);
-- MySQL 同一语句不能重复打开同一临时表,复制一份父任务映射后再更新父子链。
DROP TEMPORARY TABLE IF EXISTS tmp_evaluation_parent_task_id;
CREATE TEMPORARY TABLE tmp_evaluation_parent_task_id (
rowKey VARCHAR(100) PRIMARY KEY,
taskId BIGINT NOT NULL
);
INSERT INTO tmp_evaluation_parent_task_id (rowKey, taskId)
SELECT rowKey, taskId FROM tmp_evaluation_task_id;
UPDATE zhgh_swufe.wf_process_task task
JOIN tmp_evaluation_task_id currentTask ON currentTask.taskId = task.id
JOIN tmp_evaluation_task_plan plan ON plan.rowKey = currentTask.rowKey
LEFT JOIN tmp_evaluation_parent_task_id parentTask ON parentTask.rowKey = plan.parentRowKey
SET task.taskParentId = parentTask.taskId;
-- 已完成节点的参与人使用 v3 原审核人;提交申请任务使用原申请人。
INSERT INTO zhgh_swufe.wf_process_task_actor
(processTaskId, actorId, actorAccount, actorName, actorUnitId, actorUnitName,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT taskId.taskId,
CASE WHEN plan.taskName = 'startTask' THEN apply.createdBy ELSE plan.operator END,
CASE WHEN plan.taskName = 'startTask' THEN apply.loginName
ELSE COALESCE(audit.loginname, reviewer.loginname) END,
CASE WHEN plan.taskName = 'startTask' THEN apply.userName
ELSE COALESCE(audit.username, reviewer.username) END,
CASE WHEN plan.taskName = 'startTask' THEN apply.unitId ELSE reviewer.unitId END,
CASE WHEN plan.taskName = 'startTask' THEN apply.unitName ELSE reviewerUnit.name END,
'migration', COALESCE(plan.createdAt, apply.createdAt),
'migration', COALESCE(plan.createdAt, apply.createdAt), 0
FROM tmp_evaluation_task_plan plan
JOIN tmp_evaluation_task_id taskId ON taskId.rowKey = plan.rowKey
JOIN zhgh_swufe.evaluate_apply apply ON apply.id = plan.businessNo
LEFT JOIN union_swufe.audit audit ON audit.id = plan.auditId
LEFT JOIN zhgh_swufe.sys_user reviewer ON reviewer.id = plan.operator
LEFT JOIN zhgh_swufe.sys_unit reviewerUnit ON reviewerUnit.id = reviewer.unitId
WHERE plan.taskState = 20 OR plan.taskName = 'startTask';
-- 单位审核参与人:实际审核人已在上一步保留;再按当前角色组织范围补齐候选人,
-- 使迁移后的已审核页面与正常 v4 流程一样,可由同单位现任负责人查看历史任务。
INSERT INTO zhgh_swufe.wf_process_task_actor
(processTaskId, actorId, actorAccount, actorName, actorUnitId, actorUnitName,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT DISTINCT taskId.taskId, user.id, user.loginname, user.username, user.unitId, unit.name,
'migration', @now_ms, 'migration', @now_ms, 0
FROM tmp_evaluation_task_plan plan
JOIN tmp_evaluation_task_id taskId ON taskId.rowKey = plan.rowKey
JOIN zhgh_swufe.evaluate_apply apply ON apply.id = plan.businessNo
JOIN zhgh_swufe.sys_role role ON role.code = 'UNIT_MANAGER' AND role.disabled = 0
JOIN zhgh_swufe.sys_user_role userRole ON userRole.roleId = role.id
JOIN zhgh_swufe.sys_user user ON user.id = userRole.userId AND user.unitId = apply.unitId
LEFT JOIN zhgh_swufe.sys_unit unit ON unit.id = user.unitId
LEFT JOIN zhgh_swufe.wf_process_task_actor existingActor
ON existingActor.processTaskId = taskId.taskId AND existingActor.actorId = user.id
WHERE plan.taskState IN (10, 20)
AND plan.taskName = 'b14df33c-053c-4a91-a1b7-283ae70ece56'
AND user.disabled = 0 AND IFNULL(user.delFlag, 0) = 0
AND existingActor.id IS NULL;
-- 分工会审核参与人:沿用现有处理器的主席、管理员角色及 sys_user_role.unionId 范围。
INSERT INTO zhgh_swufe.wf_process_task_actor
(processTaskId, actorId, actorAccount, actorName, actorUnitId, actorUnitName,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT DISTINCT taskId.taskId, user.id, user.loginname, user.username, user.unitId, unit.name,
'migration', @now_ms, 'migration', @now_ms, 0
FROM tmp_evaluation_task_plan plan
JOIN tmp_evaluation_task_id taskId ON taskId.rowKey = plan.rowKey
JOIN zhgh_swufe.evaluate_apply apply ON apply.id = plan.businessNo
JOIN zhgh_swufe.sys_role role ON role.code IN ('BRANCH_UNION_CHAIRMAN', 'BRANCH_UNION_ADMIN')
JOIN zhgh_swufe.sys_user_role userRole ON userRole.roleId = role.id AND userRole.unionId = apply.unionId
JOIN zhgh_swufe.sys_user user ON user.id = userRole.userId
LEFT JOIN zhgh_swufe.sys_unit unit ON unit.id = user.unitId
LEFT JOIN zhgh_swufe.wf_process_task_actor existingActor
ON existingActor.processTaskId = taskId.taskId AND existingActor.actorId = user.id
WHERE plan.taskState IN (10, 20)
AND plan.taskName = '3bdaa29d-e5eb-4e3e-b7f1-14d03bedd078'
AND user.disabled = 0 AND IFNULL(user.delFlag, 0) = 0
AND existingActor.id IS NULL;
-- 二级党组织审核参与人:角色用户所属单位关联的 unionId 必须匹配申请人分工会。
INSERT INTO zhgh_swufe.wf_process_task_actor
(processTaskId, actorId, actorAccount, actorName, actorUnitId, actorUnitName,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT DISTINCT taskId.taskId, user.id, user.loginname, user.username, user.unitId, unit.name,
'migration', @now_ms, 'migration', @now_ms, 0
FROM tmp_evaluation_task_plan plan
JOIN tmp_evaluation_task_id taskId ON taskId.rowKey = plan.rowKey
JOIN zhgh_swufe.evaluate_apply apply ON apply.id = plan.businessNo
JOIN zhgh_swufe.sys_role role ON role.code = 'UNIT_PARTY_SECRETARY' AND role.disabled = 0
JOIN zhgh_swufe.sys_user_role userRole ON userRole.roleId = role.id
JOIN zhgh_swufe.sys_user user ON user.id = userRole.userId
JOIN zhgh_swufe.sys_unit unit ON unit.id = user.unitId AND unit.unionId = apply.unionId
LEFT JOIN zhgh_swufe.wf_process_task_actor existingActor
ON existingActor.processTaskId = taskId.taskId AND existingActor.actorId = user.id
WHERE plan.taskState IN (10, 20)
AND plan.taskName = '7dbdd0ed-05bb-4c31-9f5d-bfad3b3e2e26'
AND user.disabled = 0 AND IFNULL(user.delFlag, 0) = 0
AND existingActor.id IS NULL;
-- 校工会审核参与人:按当前校工会管理员角色配置补齐候选人。
INSERT INTO zhgh_swufe.wf_process_task_actor
(processTaskId, actorId, actorAccount, actorName, actorUnitId, actorUnitName,
createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT DISTINCT taskId.taskId, user.id, user.loginname, user.username, user.unitId, unit.name,
'migration', @now_ms, 'migration', @now_ms, 0
FROM tmp_evaluation_task_plan plan
JOIN tmp_evaluation_task_id taskId ON taskId.rowKey = plan.rowKey
JOIN zhgh_swufe.sys_role role ON role.code = 'SCHOOL_UNION_ADMIN' AND role.disabled = 0
JOIN zhgh_swufe.sys_user_role userRole ON userRole.roleId = role.id
JOIN zhgh_swufe.sys_user user ON user.id = userRole.userId
LEFT JOIN zhgh_swufe.sys_unit unit ON unit.id = user.unitId
LEFT JOIN zhgh_swufe.wf_process_task_actor existingActor
ON existingActor.processTaskId = taskId.taskId AND existingActor.actorId = user.id
WHERE plan.taskState IN (10, 20)
AND plan.taskName = '3c158aca-89ef-4188-bbc3-e8db201f02a1'
AND user.disabled = 0 AND IFNULL(user.delFlag, 0) = 0
AND existingActor.id IS NULL;
-- 提交前输出并校验关键数量;任一校验失败会触发 NOT NULL 错误并由连接关闭回滚整个事务。
SELECT 'activity' AS metric, COUNT(*) AS amount FROM zhgh_swufe.evaluate_activity
UNION ALL SELECT 'application', COUNT(*) FROM zhgh_swufe.evaluate_apply
UNION ALL SELECT 'flow_instance', COUNT(*)
FROM zhgh_swufe.wf_process_instance WHERE processDefineId = @process_define_id
AND businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
UNION ALL SELECT 'flow_task', COUNT(*)
FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
UNION ALL SELECT 'pending_task', COUNT(*)
FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
AND task.taskState = 10;
DELETE FROM tmp_evaluation_migration_guard;
INSERT INTO tmp_evaluation_migration_guard (checkName, passed) VALUES
('activity_count', IF((SELECT COUNT(*) FROM zhgh_swufe.evaluate_activity) = 11, 1, NULL)),
('application_count', IF((SELECT COUNT(*) FROM zhgh_swufe.evaluate_apply) = 78, 1, NULL)),
('home_activity_count', IF((SELECT COUNT(*) FROM zhgh_swufe.sys_home_activity home
JOIN zhgh_swufe.evaluate_activity activity ON activity.id = home.id) = 11, 1, NULL)),
('flow_instance_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_instance instance
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)) = 72, 1, NULL)),
('doing_instance_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_instance instance
WHERE instance.processDefineId = @process_define_id AND instance.state = 10
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)) = 27, 1, NULL)),
('finished_instance_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_instance instance
WHERE instance.processDefineId = @process_define_id AND instance.state = 20
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)) = 45, 1, NULL)),
('pending_task_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
AND task.taskState = 10) = 27, 1, NULL)),
('pending_start_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
AND task.taskState = 10 AND task.taskName = 'startTask') = 5, 1, NULL)),
('pending_unit_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
AND task.taskState = 10
AND task.taskName = 'b14df33c-053c-4a91-a1b7-283ae70ece56') = 6, 1, NULL)),
('pending_branch_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
AND task.taskState = 10
AND task.taskName = '3bdaa29d-e5eb-4e3e-b7f1-14d03bedd078') = 5, 1, NULL)),
('pending_party_count', IF((SELECT COUNT(*) FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
AND task.taskState = 10
AND task.taskName = '7dbdd0ed-05bb-4c31-9f5d-bfad3b3e2e26') = 11, 1, NULL)),
('pending_actor_exists', IF(NOT EXISTS (
SELECT 1
FROM zhgh_swufe.wf_process_task task
JOIN zhgh_swufe.wf_process_instance instance ON instance.id = task.processInstanceId
WHERE instance.processDefineId = @process_define_id
AND instance.businessNo IN (SELECT id FROM zhgh_swufe.evaluate_apply)
AND task.taskState = 10
AND NOT EXISTS (
SELECT 1 FROM zhgh_swufe.wf_process_task_actor actor WHERE actor.processTaskId = task.id
)
), 1, NULL));
-- 涉及临时任务表的校验必须拆成独立语句,规避 MySQL 同一语句重复打开临时表的限制。
INSERT INTO tmp_evaluation_migration_guard (checkName, passed)
VALUES ('task_plan_count', IF((SELECT COUNT(*) FROM tmp_evaluation_task_plan) = 253, 1, NULL));
INSERT INTO tmp_evaluation_migration_guard (checkName, passed)
VALUES ('task_id_map_count', IF((SELECT COUNT(*) FROM tmp_evaluation_task_id) = 253, 1, NULL));
DROP TEMPORARY TABLE IF EXISTS tmp_evaluation_parent_check_plan;
CREATE TEMPORARY TABLE tmp_evaluation_parent_check_plan (
rowKey VARCHAR(100) PRIMARY KEY,
parentRowKey VARCHAR(100)
);
INSERT INTO tmp_evaluation_parent_check_plan (rowKey, parentRowKey)
SELECT rowKey, parentRowKey FROM tmp_evaluation_task_plan;
INSERT INTO tmp_evaluation_migration_guard (checkName, passed)
VALUES ('task_parent_complete', IF(NOT EXISTS (
SELECT 1
FROM tmp_evaluation_parent_check_plan plan
JOIN tmp_evaluation_task_id taskId ON taskId.rowKey = plan.rowKey
JOIN zhgh_swufe.wf_process_task task ON task.id = taskId.taskId
LEFT JOIN tmp_evaluation_parent_task_id parentTaskId ON parentTaskId.rowKey = plan.parentRowKey
LEFT JOIN zhgh_swufe.wf_process_task parentTask
ON parentTask.id = task.taskParentId AND parentTask.processInstanceId = task.processInstanceId
WHERE plan.parentRowKey IS NOT NULL
AND (parentTaskId.taskId IS NULL OR task.taskParentId <> parentTaskId.taskId OR parentTask.id IS NULL)
), 1, NULL));
COMMIT;
@@ -63,10 +63,10 @@ layout("/layouts/platform.html"){
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="慰问类型">
<el-form-item prop="type" label="慰问类型">
<el-descriptions-item label="补贴类型">
<el-form-item prop="type" label="补贴类型">
<el-select v-model="formData.type" @change="typeChange" style="width: 100%"
placeholder="请选择慰问类型">
placeholder="请选择补贴类型">
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
@@ -226,7 +226,7 @@ layout("/layouts/platform.html"){
},
methods: {
/**
* 查询慰问申报截止日期。
* 查询补贴申报截止日期。
* @returns {Promise<Object>} Axios 请求 Promise,响应 data 为 yyyy-MM-dd 日期字符串。
*/
queryApplyEndDate() {
@@ -245,7 +245,7 @@ layout("/layouts/platform.html"){
this.$set(this, "applyPeriodDialogVisible", false)
},
/**
* 保存慰问申报截止日期。
* 保存补贴申报截止日期。
* @returns {void} 保存成功后刷新截止日期并关闭弹框。
*/
saveApplyEndDate() {
@@ -433,8 +433,8 @@ layout("/layouts/platform.html"){
}
},
/**
* 按当前用户角色过滤可申请的慰问类型。
* @param {Array} options 接口返回的全部启用慰问类型。
* 按当前用户角色过滤可申请的补贴类型。
* @param {Array} options 接口返回的全部启用补贴类型。
* @returns {Array} 系统管理员、校工会管理员返回全部类型,其他角色仅返回编码 A、B 的类型。
*/
filterTypeOptions(options) {
@@ -21,9 +21,9 @@ layout("/layouts/platform.html"){
@keyup.enter.native="doSearch">
</el-input>
</search-item>
<search-item label="慰问类型">
<search-item label="补贴类型">
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
placeholder="请选择慰问类型" filterable clearable>
placeholder="请选择补贴类型" filterable clearable>
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
@@ -110,12 +110,12 @@ layout("/layouts/platform.html"){
},
typeOptions: [],
tableColumns: [
{prop: 'helpUserName', label: '慰问对象'},
{prop: 'helpLoginName', label: '慰问对象工号'},
{prop: 'helpUserName', label: '补贴对象'},
{prop: 'helpLoginName', label: '补贴对象工号'},
{prop: 'applyUserName', label: '申请人'},
{prop: 'applyUnionName', label: '所属工会'},
{prop: 'applyUnitName', label: '所属单位'},
{prop: 'typeName', label: '慰问类型'},
{prop: 'typeName', label: '补贴类型'},
{prop: 'curTaskName', label: '当前节点'},
{prop: 'instanceState', label: '流程状态'},
],
@@ -20,9 +20,9 @@ layout("/layouts/platform.html"){
@keyup.enter.native="doSearch">
</el-input>
</search-item>
<search-item label="慰问类型">
<search-item label="补贴类型">
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
placeholder="请选择慰问类型" filterable clearable>
placeholder="请选择补贴类型" filterable clearable>
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
@@ -60,6 +60,13 @@ layout("/layouts/platform.html"){
<el-table-column label="操作" fixed="right" width="300">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button
v-if="row.instanceState === 20 && ['A', 'B'].includes(row.exportTypeCode)"
@click="onExportSubsidyRegistration(row)"
size="mini"
type="primary">
导出补贴登记表
</el-button>
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button v-if="row.canRevoke" size="mini" type="danger" @click="onRevoke(row)">撤回</el-button>
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">
@@ -90,12 +97,12 @@ layout("/layouts/platform.html"){
return {
typeOptions: [],
tableColumns: [
{prop: 'helpUserName', label: '慰问对象'},
{prop: 'helpLoginName', label: '慰问对象工号'},
{prop: 'helpUserName', label: '补贴对象'},
{prop: 'helpLoginName', label: '补贴对象工号'},
{prop: 'applyUserName', label: '申请人'},
{prop: 'applyUnionName', label: '所属工会'},
{prop: 'applyUnitName', label: '所属单位'},
{prop: 'typeName', label: '慰问类型'},
{prop: 'typeName', label: '补贴类型'},
{prop: 'taskName', label: '当前节点'},
{prop: 'instanceState', label: '流程状态'},
],
@@ -113,6 +120,10 @@ layout("/layouts/platform.html"){
onEdit(row) {
commonUtil.pjaxPush('/platform/condolence/apply?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
},
// 下载当前登录用户本人已完成的生育补贴登记表。
onExportSubsidyRegistration(row) {
this.$downLoad(loc() + '/onExportSubsidyRegistration', {id: row.id})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
@@ -23,9 +23,9 @@ layout("/layouts/platform.html"){
@keyup.enter.native="doSearch">
</el-input>
</search-item>
<search-item label="慰问类型">
<search-item label="补贴类型">
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
placeholder="请选择慰问类型" filterable clearable>
placeholder="请选择补贴类型" filterable clearable>
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
@@ -131,12 +131,12 @@ layout("/layouts/platform.html"){
endMonth: ""
},
tableColumns: [
{prop: 'helpUserName', label: '慰问对象'},
{prop: 'helpLoginName', label: '慰问对象工号'},
{prop: 'helpUserName', label: '补贴对象'},
{prop: 'helpLoginName', label: '补贴对象工号'},
{prop: 'applyUserName', label: '申请人'},
{prop: 'applyUnionName', label: '所属工会'},
{prop: 'applyUnitName', label: '所属单位'},
{prop: 'typeName', label: '慰问类型'},
{prop: 'typeName', label: '补贴类型'},
{prop: 'taskName', label: '当前节点'},
{prop: 'instanceState', label: '流程状态'},
],
@@ -22,9 +22,9 @@ layout("/layouts/platform.html"){
@keyup.enter.native="doSearch">
</el-input>
</search-item>
<search-item label="慰问类型">
<search-item label="补贴类型">
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
placeholder="请选择慰问类型" filterable clearable>
placeholder="请选择补贴类型" filterable clearable>
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
@@ -131,12 +131,12 @@ layout("/layouts/platform.html"){
},
typeOptions: [],
tableColumns: [
{prop: 'helpUserName', label: '慰问对象'},
{prop: 'helpLoginName', label: '慰问对象工号'},
{prop: 'helpUserName', label: '补贴对象'},
{prop: 'helpLoginName', label: '补贴对象工号'},
{prop: 'applyUserName', label: '申请人'},
{prop: 'applyUnionName', label: '所属工会'},
{prop: 'applyUnitName', label: '所属单位'},
{prop: 'typeName', label: '慰问类型'},
{prop: 'typeName', label: '补贴类型'},
{prop: 'curTaskName', label: '当前节点'},
{prop: 'instanceState', label: '流程状态'},
],
@@ -22,9 +22,9 @@ layout("/layouts/platform.html"){
@keyup.enter.native="doSearch">
</el-input>
</search-item>
<search-item label="慰问类型">
<search-item label="补贴类型">
<el-select v-model="pageForm.type" @change="doSearch" style="width: 100%"
placeholder="请选择慰问类型" filterable clearable>
placeholder="请选择补贴类型" filterable clearable>
<el-option v-for="item in typeOptions"
:value="item.id"
:key="item.id"
@@ -131,12 +131,12 @@ layout("/layouts/platform.html"){
},
typeOptions: [],
tableColumns: [
{prop: 'helpUserName', label: '慰问对象'},
{prop: 'helpLoginName', label: '慰问对象工号'},
{prop: 'helpUserName', label: '补贴对象'},
{prop: 'helpLoginName', label: '补贴对象工号'},
{prop: 'applyUserName', label: '申请人'},
{prop: 'applyUnionName', label: '所属工会'},
{prop: 'applyUnitName', label: '所属单位'},
{prop: 'typeName', label: '慰问类型'},
{prop: 'typeName', label: '补贴类型'},
{prop: 'curTaskName', label: '当前节点'},
{prop: 'instanceState', label: '流程状态'},
],
@@ -10,14 +10,14 @@ const basicForm = {
<el-input type="text" v-model="formData.name" maxlength="50"
placeholder="请填写类型名称"></el-input>
</el-form-item>
<el-form-item label="慰问费用" prop="money">
<el-form-item label="补贴费用" prop="money">
<el-input-number style="width: 100%" v-model="formData.money"
placeholder="请填写慰问费用" controls-position="right" :controls="false"
placeholder="请填写补贴费用" controls-position="right" :controls="false"
precision="2"
:min="0"
:max="10000"></el-input-number>
</el-form-item>
<el-form-item label="慰问方式" prop="way">
<el-form-item label="补贴方式" prop="way">
<el-radio-group v-model="formData.way">
<el-radio-button label="慰问金 (A)" border>慰问金 (A)</el-radio-button>
<el-radio-button label="提货券 (B)" border>提货券 (B)</el-radio-button>
@@ -84,7 +84,7 @@ layout("/layouts/platform.html"){
{prop: 'code', label: '类型编码'},
{prop: 'name', label: '类型名称'},
{prop: 'money', label: '金额'},
{prop: 'way', label: '慰问方式'},
{prop: 'way', label: '补贴方式'},
// {prop: 'isUploadFile', label: '是否上传附件'},
{prop: 'enable', label: '是否启用'},
],
@@ -10,6 +10,7 @@ const COMMON_QUERY = {
mixins: [initTableMixins],
data() {
return{
orgDataRequestVersion: 0,
userList: [],
unions: [],
units: [],
@@ -26,6 +27,15 @@ const COMMON_QUERY = {
}
}
},
watch: {
"$store.state.user": {
// 登录用户由公共布局异步写入 store,用户就绪后再初始化工会和单位选项。
handler() {
this.initData()
},
immediate: true
}
},
methods: {
async queryUser(val) {
const resp = await $.get("/open/common/userOptions", {query: val})
@@ -53,19 +63,46 @@ const COMMON_QUERY = {
this.flushUnits()
},
async initData(){
if (this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN")) {
// 每次用户状态变化都使旧请求失效,完整用户加载后始终重新请求当前权限范围的数据。
const requestVersion = ++this.orgDataRequestVersion
const user = this.$store.state.user
// 角色信息尚未加载时等待 store 更新,避免访问空用户对象。
if (!user || !Array.isArray(user.roles)) {
return
}
const hasAdmin = this.$auth.hasRoleOr("SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN")
const unionId = hasAdmin ? '' : (user.union && user.union.id)
// 非校工会管理员只能查询所属工会,所属工会未就绪时不发送错误请求。
if (!hasAdmin && !unionId) {
this.unions = []
this.units = []
return
}
if (hasAdmin) {
this.$businessTool.listUnion(this.pageForm.unionId).then((data) => {
this.unions = data
// 仅接收当前用户权限范围的响应,避免账号切换时旧请求覆盖新数据。
if (requestVersion === this.orgDataRequestVersion) {
this.unions = Array.isArray(data) ? data : []
// 将查询组件已验证的工会选项同步给父页面组织树,避免重复请求产生状态差异。
this.$emit("union-options-loaded", this.unions)
}
})
this.$businessTool.listUnit().then((data) => {
this.units = data
if (requestVersion === this.orgDataRequestVersion) {
this.units = data
}
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unions = data
this.$businessTool.listUnion(unionId).then((data) => {
if (requestVersion === this.orgDataRequestVersion) {
this.unions = Array.isArray(data) ? data : []
this.$emit("union-options-loaded", this.unions)
}
})
this.$businessTool.listUnit(this.$store.state.user.union.id).then((data) => {
this.units = data
this.$businessTool.listUnit(unionId).then((data) => {
if (requestVersion === this.orgDataRequestVersion) {
this.units = data
}
})
}
},
@@ -78,9 +115,6 @@ const COMMON_QUERY = {
})
}
}
},
async created() {
this.initData()
}
}
@@ -46,7 +46,12 @@ layout("/layouts/platform.html"){
</aside>
<main class="member-group-content">
<el-card shadow="never" class="member-group-query-card" v-show="tabActive === 'memberList'">
<common-query ref="commonQueryRef" @search="search" @union-change="queryUnionChange"></common-query>
<common-query
ref="commonQueryRef"
@search="search"
@union-change="queryUnionChange"
@union-options-loaded="setTreeData">
</common-query>
</el-card>
<el-card shadow="never" class="member-group-overview-card" v-show="tabActive !== 'memberList' && currentUnionId">
<div style="display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 600; color: #303133;">
@@ -634,27 +639,25 @@ layout("/layouts/platform.html"){
}
return null
},
getTreeData() {
const hasAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN", "SCHOOL_UNION_MEMBER_ADMIN"])
const unionId = hasAdmin ? null : this.$store.state.user.union.id
this.$businessTool.listUnion(unionId).then((data) => {
this.treeData = [{
id: this.unionRootId,
name: "工会委员会",
type: "root",
children: (data || []).map((item) => ({
id: item.id,
name: item.name,
type: "union"
}))
}]
this.$nextTick(() => {
this.currentTreeData = this.treeData[0]
this.setCurrentTreeNode(this.unionRootId)
if (this.tabActive !== "memberList") {
this.tabActive = "memberList"
}
})
setTreeData(data) {
// 组织树与查询组件共用同一份工会选项,确保下拉框与左侧树始终保持一致。
const unions = Array.isArray(data) ? data : []
this.treeData = [{
id: this.unionRootId,
name: "工会委员会",
type: "root",
children: unions.map((item) => ({
id: item.id,
name: item.name,
type: "union"
}))
}]
this.$nextTick(() => {
this.currentTreeData = this.treeData[0]
this.setCurrentTreeNode(this.unionRootId)
if (this.tabActive !== "memberList") {
this.tabActive = "memberList"
}
})
},
setCurrentTreeNode(nodeKey) {
@@ -756,7 +759,7 @@ layout("/layouts/platform.html"){
created() {
this.checkedFields = this.tableColumns.filter(c => c.checked !== 0).map(c => c.prop);
this.initDefaultView()
this.getTreeData()
// 会员列表查询不依赖前端组织树,避免组织信息异步加载影响列表展示。
this.pageData()
},
mounted() {
@@ -3,7 +3,7 @@ layout("/layouts/platform_h5.html"){
#-->
<div id="app">
<van-nav-bar title="填写慰问申请" left-text="返回" left-arrow @click-left="historyBack" fixed
<van-nav-bar title="填写补贴申请" left-text="返回" left-arrow @click-left="historyBack" fixed
placeholder></van-nav-bar>
<van-form ref="formRef" class="form-container">
@@ -85,11 +85,11 @@ layout("/layouts/platform_h5.html"){
<van-field
v-model="formData.typeName"
name="typeName"
label="慰问类型"
label="补贴类型"
required
readonly
:rules="[{ required: true, message: '请选择慰问类型' }]"
placeholder="请点击选择慰问类型"
:rules="[{ required: true, message: '请选择补贴类型' }]"
placeholder="请点击选择补贴类型"
@click="showTypePickerClick"
clickable
is-link
@@ -254,7 +254,7 @@ layout("/layouts/platform_h5.html"){
},
methods: {
/**
* 查询慰问申报截止日期。
* 查询补贴申报截止日期。
* @returns {Promise<Object>} Axios 请求 Promise,响应 data 为 yyyy-MM-dd 日期字符串。
*/
queryApplyEndDate() {
@@ -471,8 +471,8 @@ layout("/layouts/platform_h5.html"){
}
},
/**
* 按当前用户角色过滤可申请的慰问类型。
* @param {Array} options 接口返回的全部启用慰问类型。
* 按当前用户角色过滤可申请的补贴类型。
* @param {Array} options 接口返回的全部启用补贴类型。
* @returns {Array} 系统管理员、校工会管理员返回全部类型,其他角色仅返回编码 A、B 的类型。
*/
filterTypeOptions(options) {
@@ -32,12 +32,12 @@ layout("/layouts/platform_h5.html"){
<table-list api="/platform/condolence/branchUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
<template v-slot="{index,row}">
<table-column label="慰问对象">{{row.helpUserName}}</table-column>
<table-column label="慰问对象工号">{{row.helpLoginName}}</table-column>
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
<table-column label="申请人">{{row.applyUserName}}</table-column>
<table-column label="所属工会">{{row.applyUnionName}}</table-column>
<table-column label="所属单位">{{row.applyUnitName}}</table-column>
<table-column label="慰问类型">{{row.typeName}}</table-column>
<table-column label="补贴类型">{{row.typeName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
@@ -110,7 +110,7 @@ layout("/layouts/platform_h5.html"){
const typeList = await this.queryCondolenceType()
this.typeOptions = [
{
text: "全部慰问类型",
text: "全部补贴类型",
value: null
}
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
@@ -27,12 +27,12 @@ layout("/layouts/platform_h5.html"){
<table-list api="/platform/condolence/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
<template v-slot="{index,row}">
<table-column label="慰问对象">{{row.helpUserName}}</table-column>
<table-column label="慰问对象工号">{{row.helpLoginName}}</table-column>
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
<table-column label="申请人">{{row.applyUserName}}</table-column>
<table-column label="所属工会">{{row.applyUnionName}}</table-column>
<table-column label="所属单位">{{row.applyUnitName}}</table-column>
<table-column label="慰问类型">{{row.typeName}}</table-column>
<table-column label="补贴类型">{{row.typeName}}</table-column>
<table-column label="当前节点">{{row.taskName}}</table-column>
</template>
<template #actions="{index,row}">
@@ -86,7 +86,7 @@ layout("/layouts/platform_h5.html"){
const typeList = await this.queryCondolenceType()
this.typeOptions = [
{
text: "全部慰问类型",
text: "全部补贴类型",
value: null
}
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
@@ -32,12 +32,12 @@ layout("/layouts/platform_h5.html"){
<table-list api="/platform/condolence/schoolPrincipalApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
<template v-slot="{index,row}">
<table-column label="慰问对象">{{row.helpUserName}}</table-column>
<table-column label="慰问对象工号">{{row.helpLoginName}}</table-column>
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
<table-column label="申请人">{{row.applyUserName}}</table-column>
<table-column label="所属工会">{{row.applyUnionName}}</table-column>
<table-column label="所属单位">{{row.applyUnitName}}</table-column>
<table-column label="慰问类型">{{row.typeName}}</table-column>
<table-column label="补贴类型">{{row.typeName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
@@ -110,7 +110,7 @@ layout("/layouts/platform_h5.html"){
const typeList = await this.queryCondolenceType()
this.typeOptions = [
{
text: "全部慰问类型",
text: "全部补贴类型",
value: null
}
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
@@ -32,12 +32,12 @@ layout("/layouts/platform_h5.html"){
<table-list api="/platform/condolence/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
<template v-slot="{index,row}">
<table-column label="慰问对象">{{row.helpUserName}}</table-column>
<table-column label="慰问对象工号">{{row.helpLoginName}}</table-column>
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
<table-column label="申请人">{{row.applyUserName}}</table-column>
<table-column label="所属工会">{{row.applyUnionName}}</table-column>
<table-column label="所属单位">{{row.applyUnitName}}</table-column>
<table-column label="慰问类型">{{row.typeName}}</table-column>
<table-column label="补贴类型">{{row.typeName}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
</template>
<template #actions="{index,row}">
@@ -110,7 +110,7 @@ layout("/layouts/platform_h5.html"){
const typeList = await this.queryCondolenceType()
this.typeOptions = [
{
text: "全部慰问类型",
text: "全部补贴类型",
value: null
}
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))