commit
This commit is contained in:
@@ -14,11 +14,9 @@ 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;
|
||||
import com.budwk.app.sys.models.Sys_dict;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.services.SysDictService;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.sys.services.SysUnitService;
|
||||
import com.budwk.app.sys.services.SysUserService;
|
||||
@@ -26,6 +24,7 @@ import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
@@ -67,8 +66,6 @@ public class SysUnitController {
|
||||
@Inject
|
||||
private SysUserService sysUserService;
|
||||
@Inject
|
||||
private SysDictService sysDictService;
|
||||
@Inject
|
||||
private SysRoleService sysRoleService;
|
||||
|
||||
@At("")
|
||||
@@ -115,37 +112,7 @@ public class SysUnitController {
|
||||
@Ok("json")
|
||||
@SaCheckLogin
|
||||
public Object leaderPageData(PageForm pageForm, String unitId) {
|
||||
List<Sys_dict> unitRoles = sysDictService.getSubListByCode("UNIT_ROLES");
|
||||
if (Lang.isEmpty(unitRoles)) {
|
||||
return Result.success();
|
||||
}
|
||||
List<String> unitRoleCodes = unitRoles.stream().map(Sys_dict::getCode).toList();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t1.userId,
|
||||
t2.username,
|
||||
t2.loginname,
|
||||
t3.`code` AS roleCode,
|
||||
t3.`name` AS roleName
|
||||
FROM
|
||||
sys_user_role t1
|
||||
LEFT JOIN sys_user t2 ON t2.id = t1.userId
|
||||
LEFT JOIN sys_role t3 ON t3.id = t1.roleId
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.where("t3.`code`", "in", unitRoleCodes);
|
||||
cnd.and("t1.unitId", "=", unitId);
|
||||
if (StrUtil.isAllNotBlank(pageForm.getSearchName(), pageForm.getSearchKeyword())) {
|
||||
switch (pageForm.getSearchName()) {
|
||||
case "loginname" -> cnd.where().andLike("t2.loginname", pageForm.getSearchKeyword());
|
||||
case "username" -> cnd.where().andLike("t2.username", pageForm.getSearchKeyword());
|
||||
case "roleName" -> cnd.where().andLike("t3.`name`", pageForm.getSearchKeyword());
|
||||
}
|
||||
}
|
||||
cnd.asc("t2.username");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
return Result.success(sysUnitService.getUnitLeaderPageData(pageForm, unitId));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -182,6 +149,25 @@ public class SysUnitController {
|
||||
@Ok("json")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result insertUnitUserRole(String userId, String roleCode, String unitId) {
|
||||
// 党委书记按分工会归属维护,单位页仅用于展示,避免把分工会角色错误写成单个单位角色。
|
||||
if (RoleConstant.UNIT_PARTY_SECRETARY.name().equals(roleCode)) {
|
||||
return Result.error("单位党委书记请在分工会管理中设置");
|
||||
}
|
||||
// 页面选择“单位分管校领导”时,维护提案流程实际使用的承办单位角色数据。
|
||||
if ("UNIT_SCHOOL_LEADER".equals(roleCode)) {
|
||||
ProposalUndertake undertake = getProposalUndertakeByUnitId(unitId);
|
||||
Sys_role schoolLeaderRole = sysRoleService.fetch(Cnd.where("code", "=", RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name()));
|
||||
if (Lang.isEmpty(schoolLeaderRole)) {
|
||||
throw new BaseException("未找到单位分管校领导角色");
|
||||
}
|
||||
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", schoolLeaderRole.getId())
|
||||
.and("userId", "=", userId).and("underTakeId", "=", undertake.getId()));
|
||||
sysRoleService.insert("sys_user_role", Chain.make("roleId", schoolLeaderRole.getId())
|
||||
.add("userId", userId).add("underTakeId", undertake.getId()));
|
||||
sysRoleService.clearCache();
|
||||
sysUserService.clearCache();
|
||||
return Result.success();
|
||||
}
|
||||
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
||||
if (Lang.isEmpty(role)) {
|
||||
throw new BaseException("无法找到{}对应编码的角色", roleCode);
|
||||
@@ -197,6 +183,23 @@ public class SysUnitController {
|
||||
@Ok("json")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result deleteUnitUserRole(String userId, String roleCode, String unitId) {
|
||||
// 党委书记按分工会归属维护,单位页只展示其现有设置。
|
||||
if (RoleConstant.UNIT_PARTY_SECRETARY.name().equals(roleCode)) {
|
||||
return Result.error("单位党委书记请在分工会管理中设置");
|
||||
}
|
||||
// 分管校领导列表返回的是提案流程实际角色,删除时按承办单位绑定维度清理。
|
||||
if (RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name().equals(roleCode)) {
|
||||
ProposalUndertake undertake = getProposalUndertakeByUnitId(unitId);
|
||||
Sys_role schoolLeaderRole = sysRoleService.fetch(Cnd.where("code", "=", RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name()));
|
||||
if (Lang.isEmpty(schoolLeaderRole)) {
|
||||
throw new BaseException("未找到单位分管校领导角色");
|
||||
}
|
||||
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", schoolLeaderRole.getId())
|
||||
.and("userId", "=", userId).and("underTakeId", "=", undertake.getId()));
|
||||
sysRoleService.clearCache();
|
||||
sysUserService.clearCache();
|
||||
return Result.success();
|
||||
}
|
||||
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
||||
if (Lang.isEmpty(role)) {
|
||||
throw new BaseException("无法找到{}对应编码的角色", roleCode);
|
||||
@@ -207,6 +210,25 @@ public class SysUnitController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据系统单位编码找到对应提案承办单位,保证单位页维护的分管校领导直接用于提案流程。
|
||||
*
|
||||
* @param unitId 系统单位 ID
|
||||
* @return 对应的提案承办单位
|
||||
*/
|
||||
private ProposalUndertake getProposalUndertakeByUnitId(String unitId) {
|
||||
Sys_unit unit = sysUnitService.fetch(unitId);
|
||||
if (unit == null || StrUtil.isBlank(unit.getUnitcode())) {
|
||||
throw new BaseException("当前单位不存在或未设置单位编码");
|
||||
}
|
||||
ProposalUndertake undertake = sysUnitService.dao().fetch(ProposalUndertake.class,
|
||||
Cnd.where("code", "=", unit.getUnitcode()));
|
||||
if (undertake == null) {
|
||||
throw new BaseException("当前单位未同步为提案承办单位,无法设置分管校领导");
|
||||
}
|
||||
return undertake;
|
||||
}
|
||||
|
||||
@At("/child")
|
||||
@Ok("json")
|
||||
@SaCheckLogin
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.budwk.app.sys.services;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
|
||||
@@ -22,6 +24,16 @@ public interface SysUnitService extends BaseService<Sys_unit> {
|
||||
*/
|
||||
void deleteAndChild(Sys_unit unit);
|
||||
|
||||
/**
|
||||
* 查询单位干部。单位党委书记按分工会归属展示,提案分管校领导按承办单位归属展示,
|
||||
* 避免把两类已有业务角色误当作直接绑定在 sys_unit 上的角色。
|
||||
*
|
||||
* @param pageForm 分页及查询条件
|
||||
* @param unitId 当前系统单位 ID
|
||||
* @return 单位干部分页数据,包含数据来源及是否允许在本页维护的标记
|
||||
*/
|
||||
Pagination getUnitLeaderPageData(PageForm pageForm, String unitId);
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.budwk.app.sys.services.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RedisConstant;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.services.SysUnitService;
|
||||
@@ -10,6 +13,7 @@ import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Strings;
|
||||
@@ -69,6 +73,79 @@ public class SysUnitServiceImpl extends BaseServiceImpl<Sys_unit> implements Sys
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单位干部,并按角色的实际维护维度关联数据。
|
||||
* 单位党委书记由分工会干部维护,提案分管校领导由提案承办单位维护,二者均不应按
|
||||
* sys_user_role.unitId 直接过滤,否则迁移和现有配置的数据都无法在单位页展示。
|
||||
*
|
||||
* @param pageForm 分页及查询条件
|
||||
* @param unitId 当前系统单位 ID
|
||||
* @return 含角色来源和页面维护权限的分页结果
|
||||
*/
|
||||
@Override
|
||||
public Pagination getUnitLeaderPageData(PageForm pageForm, String unitId) {
|
||||
String searchCondition = switch (pageForm.getSearchName()) {
|
||||
case "loginname" -> " AND t2.loginname LIKE CONCAT('%', @searchKeyword, '%')";
|
||||
case "username" -> " AND t2.username LIKE CONCAT('%', @searchKeyword, '%')";
|
||||
case "roleName" -> " AND (t3.name LIKE CONCAT('%', @searchKeyword, '%') "
|
||||
+ "OR t3.code = '" + RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name() + "')";
|
||||
default -> "";
|
||||
};
|
||||
if (StrUtil.isBlank(pageForm.getSearchKeyword())) {
|
||||
searchCondition = "";
|
||||
}
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t1.userId,
|
||||
t2.username,
|
||||
t2.loginname,
|
||||
t3.`code` AS roleCode,
|
||||
CASE t3.`code`
|
||||
WHEN 'PROPOSAL_BRANCH_SCHOOL_LEADER' THEN '单位分管校领导'
|
||||
ELSE t3.`name`
|
||||
END AS roleName,
|
||||
CASE
|
||||
WHEN t3.`code` = 'UNIT_PARTY_SECRETARY' THEN 0
|
||||
ELSE 1
|
||||
END AS canManage
|
||||
FROM sys_user_role t1
|
||||
LEFT JOIN sys_user t2 ON t2.id = t1.userId
|
||||
LEFT JOIN sys_role t3 ON t3.id = t1.roleId
|
||||
LEFT JOIN sys_unit currentUnit ON currentUnit.id = @unitId
|
||||
LEFT JOIN proposal_undertake undertake ON undertake.id = t1.underTakeId
|
||||
WHERE currentUnit.id = @unitId
|
||||
AND (
|
||||
(
|
||||
t3.`code` IN (
|
||||
SELECT dictRole.`code`
|
||||
FROM sys_dict dictRole
|
||||
WHERE dictRole.parentId = (
|
||||
SELECT dictParent.id FROM sys_dict dictParent
|
||||
WHERE dictParent.`code` = 'UNIT_ROLES' LIMIT 1
|
||||
)
|
||||
)
|
||||
AND (
|
||||
t1.unitId = currentUnit.id
|
||||
OR (
|
||||
t3.`code` = 'UNIT_PARTY_SECRETARY'
|
||||
AND t1.unionId = currentUnit.unionId
|
||||
)
|
||||
)
|
||||
)
|
||||
OR (
|
||||
t3.`code` = 'PROPOSAL_BRANCH_SCHOOL_LEADER'
|
||||
AND undertake.`code` = currentUnit.unitcode
|
||||
)
|
||||
)
|
||||
""" + searchCondition + " ORDER BY t2.username");
|
||||
sql.setParam("unitId", unitId);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
sql.setParam("searchKeyword", pageForm.getSearchKeyword());
|
||||
}
|
||||
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
}
|
||||
|
||||
@CacheRemoveAll
|
||||
public void clearCache() {
|
||||
|
||||
|
||||
+104
-44
@@ -13,10 +13,10 @@ import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalUndertakeConfigService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
@@ -37,6 +37,7 @@ import org.nutz.mvc.annotation.Param;
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -82,26 +83,34 @@ public class ProposalConfigUnitController {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t1.*,
|
||||
u1.username AS branchSchoolLeader,
|
||||
u2.username AS unitLeader
|
||||
branchLeader.branchSchoolLeader,
|
||||
unitManager.unitLeader
|
||||
FROM
|
||||
proposal_undertake t1
|
||||
LEFT JOIN sys_user_role sur1 ON sur1.underTakeId = t1.id
|
||||
AND sur1.roleId = ( SELECT r.id FROM sys_role r WHERE r.CODE = @PROPOSAL_BRANCH_SCHOOL_LEADER )
|
||||
LEFT JOIN sys_user u1 ON u1.id = sur1.userId
|
||||
LEFT JOIN sys_user_role sur2 ON sur2.underTakeId = t1.id
|
||||
AND sur2.roleId = ( SELECT r.id FROM sys_role r WHERE r.CODE = @PROPOSAL_UNIT_LEADER)
|
||||
LEFT JOIN sys_user u2 ON u2.id = sur2.userId
|
||||
proposal_undertake t1
|
||||
LEFT JOIN sys_unit sysUnit ON sysUnit.unitcode = t1.code
|
||||
LEFT JOIN (
|
||||
SELECT sur.underTakeId,
|
||||
GROUP_CONCAT(DISTINCT u.username ORDER BY u.username SEPARATOR '、') AS branchSchoolLeader
|
||||
FROM sys_user_role sur
|
||||
JOIN sys_role r ON r.id = sur.roleId AND r.CODE = @PROPOSAL_BRANCH_SCHOOL_LEADER
|
||||
LEFT JOIN sys_user u ON u.id = sur.userId
|
||||
GROUP BY sur.underTakeId
|
||||
) branchLeader ON branchLeader.underTakeId = t1.id
|
||||
LEFT JOIN (
|
||||
SELECT sur.unitId,
|
||||
GROUP_CONCAT(DISTINCT u.username ORDER BY u.username SEPARATOR '、') AS unitLeader
|
||||
FROM sys_user_role sur
|
||||
JOIN sys_role r ON r.id = sur.roleId AND r.CODE = 'UNIT_MANAGER'
|
||||
LEFT JOIN sys_user u ON u.id = sur.userId
|
||||
GROUP BY sur.unitId
|
||||
) unitManager ON unitManager.unitId = sysUnit.id
|
||||
$condition
|
||||
""");
|
||||
sql.setParam("PROPOSAL_BRANCH_SCHOOL_LEADER", RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name());
|
||||
sql.setParam("PROPOSAL_UNIT_LEADER", RoleConstant.PROPOSAL_UNIT_LEADER.name());
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.where().orLike("u1.username", pageForm.getSearchKeyword());
|
||||
cnd.where().orLike("u1.loginname", pageForm.getSearchKeyword());
|
||||
cnd.where().orLike("u2.username", pageForm.getSearchKeyword());
|
||||
cnd.where().orLike("u2.loginname", pageForm.getSearchKeyword());
|
||||
cnd.where().orLike("branchLeader.branchSchoolLeader", pageForm.getSearchKeyword());
|
||||
cnd.where().orLike("unitManager.unitLeader", pageForm.getSearchKeyword());
|
||||
cnd.where().orLike("t1.name", pageForm.getSearchKeyword());
|
||||
}
|
||||
// 承办单位列表未指定有效排序时继续按单位编码升序。
|
||||
@@ -167,15 +176,18 @@ public class ProposalConfigUnitController {
|
||||
@SLog(tag = "提案", msg = "设置承办单位领导")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result updateUnitLeader(@Valid String id, @Param("userIds") String[] userIds) {
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER);
|
||||
//删除原来的用户
|
||||
Sys_unit unit = getSystemUnitByUndertakeId(id);
|
||||
Sys_role sysRole = sysRoleService.getByCode("UNIT_MANAGER");
|
||||
// 系统单位负责人是提案承办单位答复的唯一人员来源,按系统单位维度整体覆盖。
|
||||
dao.clear(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId())
|
||||
.and(Sys_user_role::getUnderTakeId, "=", id));
|
||||
.and(Sys_user_role::getUnitId, "=", unit.getId()));
|
||||
List<Sys_user_role> sysUserRoles = Arrays.stream(userIds).map(userId -> {
|
||||
Sys_user_role sysUserRole = new Sys_user_role();
|
||||
sysUserRole.setRoleId(sysRole.getId());
|
||||
sysUserRole.setUserId(userId);
|
||||
sysUserRole.setUnderTakeId(id);
|
||||
sysUserRole.setUnitId(unit.getId());
|
||||
// 与单位管理页保持同一角色关联结构,确保两页均可维护同一位负责人。
|
||||
sysUserRole.setUnderTakeId(unit.getId());
|
||||
return sysUserRole;
|
||||
}).toList();
|
||||
dao.insert(sysUserRoles);
|
||||
@@ -191,25 +203,21 @@ public class ProposalConfigUnitController {
|
||||
@At
|
||||
@SaCheckPermission("proposal.config.unit")
|
||||
public Result branchSchoolLeaderTransferData(@Valid String id) {
|
||||
//已设置的领导
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER);
|
||||
List<Sys_user_role> sysUserRoles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId()).and(Sys_user_role::getUnderTakeId, "=", id));
|
||||
List<String> selectUserIds = sysUserRoles.stream().map(Sys_user_role::getUserId).toList();
|
||||
return Result.success(createBranchSchoolLeaderTransferData(id, null));
|
||||
}
|
||||
|
||||
//查询全部的校领导
|
||||
Sql sql = Sqls.create("select id,username,loginname,unitname,concat(username,'(',loginname,')') label from vw_user where unitId in (@unitId)");
|
||||
ProposalConfig proposalConfig = dao.fetch(ProposalConfig.class, Cnd.NEW());
|
||||
if(ObjectUtil.isNull(proposalConfig)){
|
||||
return Result.error("提案全局配置未配置,请在提案管理-基础配置-提案配置页面进行配置。");
|
||||
}
|
||||
if(ObjectUtil.isEmpty(proposalConfig.getSchoolLeaderUnitIds())){
|
||||
return Result.error("校领导单位未配置,请在提案管理-基础配置-提案配置页面进行配置。");
|
||||
}
|
||||
|
||||
sql.setParam("unitId", proposalConfig.getSchoolLeaderUnitIds());
|
||||
List<NutMap> allUsers = baseService.listMap(sql);
|
||||
|
||||
return Result.success(Map.of("allUsers", allUsers, "selectUserIds", selectUserIds));
|
||||
/**
|
||||
* 单位分管校领导候选人员。首次仅返回前五十人;按姓名或工号搜索时由服务端重新查询。
|
||||
* 已选人员始终补入候选集合,保证不在当前搜索结果中的人员也能回显。
|
||||
*
|
||||
* @param id 承办单位 ID
|
||||
* @param keyword 姓名或工号关键字
|
||||
* @return 候选人员、已选人员和总数
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("proposal.config.unit")
|
||||
public Result branchSchoolLeaderUserPageData(@Valid String id, String keyword) {
|
||||
return Result.success(createBranchSchoolLeaderTransferData(id, keyword));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,18 +229,20 @@ public class ProposalConfigUnitController {
|
||||
@At
|
||||
@SaCheckPermission("proposal.config.unit")
|
||||
public Result unitUsersTransferData(@Valid String id) {
|
||||
//已设置的单位领导
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER);
|
||||
List<Sys_user_role> sysUserRoles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId()).and(Sys_user_role::getUnderTakeId, "=", id));
|
||||
// 已设置的系统单位负责人。
|
||||
Sys_unit unit = getSystemUnitByUndertakeId(id);
|
||||
Sys_role sysRole = sysRoleService.getByCode("UNIT_MANAGER");
|
||||
List<Sys_user_role> sysUserRoles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId()).and(Sys_user_role::getUnitId, "=", unit.getId()));
|
||||
List<String> selectUserIds = sysUserRoles.stream().map(Sys_user_role::getUserId).toList();
|
||||
|
||||
//查询该单位下全部的用户
|
||||
ProposalUndertake proposalUndertake = dao.fetch(ProposalUndertake.class, id);
|
||||
|
||||
Sql sql = Sqls.create("select id,username,loginname,unitname,concat(username,'(',loginname,')') label from vw_user $condition");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("unitCode","=",proposalUndertake.getCode());
|
||||
cnd.orEX("id","in",selectUserIds);
|
||||
cnd.and("unitCode","=",unit.getUnitcode());
|
||||
if (ObjectUtil.isNotEmpty(selectUserIds)) {
|
||||
// 已设置负责人可能不属于当前单位,仍要放入候选集合,才能在穿梭框回显。
|
||||
cnd.orEX("id","in",selectUserIds);
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
// sql.setParam("unitCode", proposalUndertake.getCode());
|
||||
// sql.setParam("selectUserIds", selectUserIds);
|
||||
@@ -241,6 +251,56 @@ public class ProposalConfigUnitController {
|
||||
return Result.success(Map.of("allUsers", allUsers, "selectUserIds", selectUserIds));
|
||||
}
|
||||
|
||||
/** 根据承办单位编码查询系统单位,保证配置页面和流程处理人使用同一单位数据。 */
|
||||
private Sys_unit getSystemUnitByUndertakeId(String undertakeId) {
|
||||
ProposalUndertake undertake = dao.fetch(ProposalUndertake.class, undertakeId);
|
||||
if (undertake == null || StrUtil.isBlank(undertake.getCode())) {
|
||||
throw new IllegalArgumentException("承办单位不存在或未设置单位编码");
|
||||
}
|
||||
Sys_unit unit = dao.fetch(Sys_unit.class, Cnd.where(Sys_unit::getUnitcode, "=", undertake.getCode()));
|
||||
if (unit == null) {
|
||||
throw new IllegalArgumentException("承办单位未关联系统单位,请先同步系统单位");
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装分管校领导穿梭框数据。默认或搜索时均固定返回前五十条候选人,并合并已选人员。
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> createBranchSchoolLeaderTransferData(String undertakeId, String keyword) {
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER);
|
||||
List<String> selectUserIds = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId())
|
||||
.and(Sys_user_role::getUnderTakeId, "=", undertakeId))
|
||||
.stream().map(Sys_user_role::getUserId).toList();
|
||||
|
||||
Sql sql = Sqls.create("select id,username,loginname,unitname,concat(username,'(',loginname,')') label from vw_user $condition");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
cnd.where().orLike("username", keyword);
|
||||
cnd.where().orLike("loginname", keyword);
|
||||
}
|
||||
// 候选人员按所属分工会归类展示,同一分工会内再按姓名、工号排序。
|
||||
cnd.asc("unionName").asc("username").asc("loginname");
|
||||
sql.setCondition(cnd);
|
||||
Pagination<NutMap> page = (Pagination<NutMap>) baseService.listPageMap(1, 50, sql);
|
||||
|
||||
LinkedHashMap<String, NutMap> userMap = new LinkedHashMap<>();
|
||||
for (NutMap user : page.getList()) {
|
||||
userMap.put(user.getString("id"), user);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(selectUserIds)) {
|
||||
Sql selectedSql = Sqls.create("select id,username,loginname,unitname,concat(username,'(',loginname,')') label from vw_user where id in (@userIds)");
|
||||
selectedSql.setParam("userIds", selectUserIds);
|
||||
List<NutMap> selectedUsers = (List<NutMap>) baseService.listMap(selectedSql);
|
||||
for (NutMap user : selectedUsers) {
|
||||
userMap.putIfAbsent(user.getString("id"), user);
|
||||
}
|
||||
}
|
||||
return Map.of("allUsers", new ArrayList<>(userMap.values()), "selectUserIds", selectUserIds,
|
||||
"totalCount", page.getTotalCount());
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.config.unit")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
|
||||
+13
@@ -137,6 +137,19 @@ public class ProposalCommitteeFilingController {
|
||||
return pageData(pageForm, approval);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案委员会立案 H5 撤回。
|
||||
* 复用 PC 端撤回服务,确保并案提案仍按整组撤回处理。
|
||||
*/
|
||||
@At("/h5/revokeTask")
|
||||
@SaCheckPermission("h5.proposal.committeeFiling")
|
||||
@ApiOperation("提案委员会立案 H5 撤回任务")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result h5RevokeTask(@Param("taskId") Long taskId, @Param("proposalId") String proposalId) {
|
||||
proposalCommitteeFilingService.revokeTask(taskId, proposalId);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("proposal.committeeFiling")
|
||||
|
||||
+12
@@ -150,6 +150,18 @@ public class ProposalCommitteeFilingUnitController {
|
||||
return pageData(pageForm, approval);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案委员会确认承办单位 H5 撤回。
|
||||
* 与 PC 端共用现有撤回规则,保证并案提案会整组回退。
|
||||
*/
|
||||
@At("/h5/revokeTask")
|
||||
@SaCheckPermission("h5.proposal.committeeFilingUnit")
|
||||
@ApiOperation("提案委员会确认承办单位 H5 撤回任务")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result h5RevokeTask(@Param("taskId") Long taskId, @Param("proposalId") String proposalId) {
|
||||
return revokeTask(taskId, proposalId);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("proposal.committeeFilingUnit")
|
||||
|
||||
+20
-33
@@ -5,11 +5,11 @@ 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.service.BaseService;
|
||||
import com.budwk.app.flow.enums.ProcessTaskPerformTypeEnum;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalControlService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -36,6 +36,8 @@ public class ProposalControlController {
|
||||
private BaseService baseService;
|
||||
@Inject
|
||||
private ProposalCommonService proposalCommonService;
|
||||
@Inject
|
||||
private ProposalControlService proposalControlService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/democratic/proposal/transact/control/index.html")
|
||||
@@ -58,20 +60,12 @@ public class ProposalControlController {
|
||||
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
|
||||
MIN(t.id) taskId,
|
||||
GROUP_CONCAT(DISTINCT t.taskName ORDER BY t.id) taskKeys,
|
||||
IFNULL(GROUP_CONCAT(DISTINCT t.displayName ORDER BY t.id), '结束') curTaskName
|
||||
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 proposal_info info ON info.id = ins.businessNo
|
||||
LEFT JOIN proposal_type type ON type.id = info.typeId
|
||||
LEFT JOIN teacher_congress_session tcs ON tcs.id = info.sessionId
|
||||
@@ -86,7 +80,8 @@ public class ProposalControlController {
|
||||
}
|
||||
|
||||
ProposalSearchParam.buildSearch(cnd, pageForm);
|
||||
cnd.groupBy("t.id");
|
||||
// 一个提案实例可能有多个并行承办单位答复待办;状态调整按实例聚合,只展示一条提案记录。
|
||||
cnd.groupBy("ins.id");
|
||||
// 状态调整列表未指定有效排序时保留任务创建时间倒序。
|
||||
if (!proposalCommonService.applySafeProposalListOrder(cnd, pageForm, "control")) {
|
||||
cnd.desc("t.createdAt");
|
||||
@@ -100,25 +95,17 @@ public class ProposalControlController {
|
||||
@SaCheckPermission("proposal.control")
|
||||
@ApiOperation("获取可跳转节点")
|
||||
public Result jumpNodes(Long instanceId) {
|
||||
if (instanceId == null) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t.taskName AS value,
|
||||
MAX(t.displayName) AS label,
|
||||
MIN(t.id) AS seq
|
||||
FROM wf_process_task t
|
||||
WHERE t.processInstanceId = @instanceId
|
||||
AND t.taskState IN (@doing, @finish)
|
||||
AND t.performType != @countersign
|
||||
GROUP BY t.taskName
|
||||
ORDER BY seq ASC
|
||||
""");
|
||||
sql.params().set("instanceId", instanceId);
|
||||
sql.params().set("doing", ProcessTaskStateEnum.DOING.getCode());
|
||||
sql.params().set("finish", ProcessTaskStateEnum.FINISHED.getCode());
|
||||
sql.params().set("countersign", ProcessTaskPerformTypeEnum.COUNTERSIGN.getCode());
|
||||
return Result.success(baseService.listMap(sql));
|
||||
return Result.success(proposalControlService.listJumpNodes(instanceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按整个提案流程实例跳转节点,统一清理并行待办后再创建目标节点待办。
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("proposal.control")
|
||||
@ApiOperation("跳转提案流程节点")
|
||||
public Result jump(Long instanceId, String targetTaskName) {
|
||||
proposalControlService.jump(instanceId, targetTaskName);
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -116,6 +116,14 @@ public class ProposalMineController {
|
||||
@SaCheckPermission("proposal.mine")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result pageData(@Valid ProposalSearchParam pageForm, String sessionId) {
|
||||
return queryPageData(pageForm, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录人的提案分页数据。
|
||||
* PC 与 H5 入口共用该私有方法,避免 H5 请求进入带 PC 权限注解的方法。
|
||||
*/
|
||||
private Result queryPageData(ProposalSearchParam pageForm, String sessionId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.*,
|
||||
@@ -163,6 +171,16 @@ public class ProposalMineController {
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的提案 H5 分页列表。
|
||||
* H5 菜单权限与 PC 权限独立,列表查询仍复用 PC 的同一数据口径。
|
||||
*/
|
||||
@At("/h5/pageData")
|
||||
@SaCheckPermission("h5.proposal.mine")
|
||||
public Result h5PageData(@Valid ProposalSearchParam pageForm, String sessionId) {
|
||||
return queryPageData(pageForm, sessionId);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.mine")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
|
||||
+18
@@ -91,6 +91,14 @@ public class ProposalSecondedController {
|
||||
@At
|
||||
@SaCheckPermission("proposal.seconded")
|
||||
public Result pageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return queryPageData(pageForm, approval);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录附议人的提案分页数据。
|
||||
* PC 与 H5 入口共用该私有方法,避免 H5 请求进入带 PC 权限注解的方法。
|
||||
*/
|
||||
private Result queryPageData(ProposalSearchParam pageForm, boolean approval) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.*,
|
||||
@@ -165,6 +173,16 @@ public class ProposalSecondedController {
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案附议 H5 分页列表。
|
||||
* H5 菜单权限与 PC 权限独立,列表查询仍复用 PC 的同一数据口径。
|
||||
*/
|
||||
@At("/h5/pageData")
|
||||
@SaCheckPermission("h5.proposal.seconded")
|
||||
public Result h5PageData(@Valid ProposalSearchParam pageForm, boolean approval) {
|
||||
return queryPageData(pageForm, approval);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("proposal.seconded")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
|
||||
+1
-6
@@ -115,12 +115,7 @@ public class ProposalUnderTakeReadController {
|
||||
String unitIdsStr = "''";
|
||||
|
||||
if (!isSysAdmin) {
|
||||
Sys_role role = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER.name());
|
||||
List<Sys_user_role> userRoles = proposalCommonService.dao().query(Sys_user_role.class,
|
||||
Cnd.where(Sys_user_role::getUserId, "=", SecurityUtil.getUserId())
|
||||
.and(Sys_user_role::getRoleId, "=", role.getId())
|
||||
);
|
||||
unitIds = userRoles.stream().map(Sys_user_role::getUnderTakeId).collect(Collectors.toSet());
|
||||
unitIds = new HashSet<>(proposalCommonService.getUserManagedUndertakeIds(SecurityUtil.getUserId()));
|
||||
unitIdsStr = unitIds.stream()
|
||||
.map(id -> "'" + id + "'")
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
+4
-6
@@ -13,6 +13,7 @@ import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
@@ -29,7 +30,7 @@ public class ProposalMasterUnitAssignmentHandler implements AssignmentHandler {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public List<String> assign(TaskModel model, Execution execution) {
|
||||
Dao dao = ServiceContext.find(Dao.class);
|
||||
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
|
||||
ProposalCommonService proposalCommonService = ServiceContext.find(ProposalCommonService.class);
|
||||
|
||||
// 提案ID
|
||||
String proposalId = execution.getProcessInstance().getBusinessNo();
|
||||
@@ -64,11 +65,8 @@ public class ProposalMasterUnitAssignmentHandler implements AssignmentHandler {
|
||||
throw new BaseException("主办单位不存在");
|
||||
}
|
||||
|
||||
// 获取负责人
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER);
|
||||
|
||||
List<Sys_user_role> sysUserRoles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId()).and(Sys_user_role::getUnderTakeId, "=", undertake.getId()));
|
||||
List<String> selectUserIds = sysUserRoles.stream().map(Sys_user_role::getUserId).toList();
|
||||
// 获取系统单位负责人。
|
||||
List<String> selectUserIds = proposalCommonService.getUndertakeUnitManagerUserIds(undertake.getId());
|
||||
|
||||
if (selectUserIds.isEmpty()) {
|
||||
throw new BaseException("主办单位没有负责人");
|
||||
|
||||
+9
-24
@@ -1,25 +1,11 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.handler;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
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.flow.entity.Candidate;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.web.controllers.open.commons.service.CommonService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,19 +16,18 @@ public class ProposalSchoolLeaderAssignmentHandler implements AssignmentHandler
|
||||
|
||||
@Override
|
||||
public List<String> assign(TaskModel model, Execution execution) {
|
||||
CommonService commonService = ServiceContext.find(CommonService.class);
|
||||
List<Sys_user> users = commonService.findUserInfoByRoleCode(RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name());
|
||||
|
||||
if(Lang.isEmpty(users)) {
|
||||
throw new BaseException("未查询到相关审批人");
|
||||
}
|
||||
|
||||
return users.stream().map(Sys_user::getId).toList();
|
||||
ProposalCommonService proposalCommonService = ServiceContext.find(ProposalCommonService.class);
|
||||
String proposalId = execution.getProcessInstance().getBusinessNo();
|
||||
List<String> userIds = proposalCommonService.getMasterUndertakeSchoolLeaderUserIds(proposalId);
|
||||
if (userIds.isEmpty()) {
|
||||
throw new BaseException("主办单位未设置分管校领导");
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "获取提案主管校领导";
|
||||
return "主办单位分管校领导";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-6
@@ -11,6 +11,7 @@ import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
|
||||
@@ -35,21 +36,19 @@ public class ProposalSlaveUnitAssignmentHandler implements AssignmentHandler {
|
||||
return assignee;
|
||||
}
|
||||
|
||||
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
|
||||
ProposalCommonService proposalCommonService = ServiceContext.find(ProposalCommonService.class);
|
||||
|
||||
// 协办单位id
|
||||
List<String> helpUnitIds = (List<String>) execution.getArgs().get("tf_slaveUnitIds");
|
||||
if (helpUnitIds != null && !helpUnitIds.isEmpty()) {
|
||||
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER);
|
||||
|
||||
for (String helpUnitId : helpUnitIds) {
|
||||
ProposalUndertake undertake = dao.fetch(ProposalUndertake.class, helpUnitId);
|
||||
List<Sys_user_role> sysUserRoles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId()).and(Sys_user_role::getUnderTakeId, "=", undertake.getId()));
|
||||
if (sysUserRoles.isEmpty()) {
|
||||
List<String> unitManagerUserIds = proposalCommonService.getUndertakeUnitManagerUserIds(undertake.getId());
|
||||
if (unitManagerUserIds.isEmpty()) {
|
||||
throw new BaseException(undertake.getName() + "单位没有设置负责人!");
|
||||
}
|
||||
assignee.addAll(sysUserRoles.stream().map(Sys_user_role::getUserId).toList());
|
||||
assignee.addAll(unitManagerUserIds);
|
||||
}
|
||||
return assignee;
|
||||
}
|
||||
|
||||
+6
-12
@@ -16,6 +16,7 @@ import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
@@ -34,7 +35,7 @@ public class ProposalUnitAssignmentHandler implements AssignmentHandler {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public List<String> assign(TaskModel model, Execution execution) {
|
||||
Dao dao = ServiceContext.find(Dao.class);
|
||||
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
|
||||
ProposalCommonService proposalCommonService = ServiceContext.find(ProposalCommonService.class);
|
||||
String proposalId = execution.getProcessInstance().getBusinessNo();
|
||||
|
||||
List<String> unitIds = resolveUnitIds(model, execution, dao, proposalId);
|
||||
@@ -43,11 +44,6 @@ public class ProposalUnitAssignmentHandler implements AssignmentHandler {
|
||||
throw new BaseException("提案没有配置承办单位");
|
||||
}
|
||||
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER);
|
||||
if (sysRole == null) {
|
||||
throw new BaseException("提案承办单位领导角色不存在");
|
||||
}
|
||||
|
||||
List<String> assignee = new ArrayList<>();
|
||||
for (String unitId : unitIds) {
|
||||
ProposalUndertake undertake = dao.fetch(ProposalUndertake.class, unitId);
|
||||
@@ -56,10 +52,8 @@ public class ProposalUnitAssignmentHandler implements AssignmentHandler {
|
||||
}
|
||||
|
||||
// 只要存在单位 ID,就必须找到该单位负责人,否则流程无法继续往下分派。
|
||||
List<Sys_user_role> sysUserRoles = dao.query(Sys_user_role.class,
|
||||
Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId())
|
||||
.and(Sys_user_role::getUnderTakeId, "=", undertake.getId()));
|
||||
if (ObjectUtil.isEmpty(sysUserRoles)) {
|
||||
List<String> unitManagerUserIds = proposalCommonService.getUndertakeUnitManagerUserIds(undertake.getId());
|
||||
if (ObjectUtil.isEmpty(unitManagerUserIds)) {
|
||||
throw new BaseException(undertake.getName() + "单位没有设置负责人!");
|
||||
}
|
||||
/*
|
||||
@@ -67,7 +61,7 @@ public class ProposalUnitAssignmentHandler implements AssignmentHandler {
|
||||
* 同一个用户若同时负责主办、协办多个承办单位,不能在这里跨单位去重;
|
||||
* 否则流程会把多个承办单位合并成一个会签实例,导致“全部承办单位答复完”判断失真。
|
||||
*/
|
||||
assignee.addAll(sysUserRoles.stream().map(Sys_user_role::getUserId).toList());
|
||||
assignee.addAll(unitManagerUserIds);
|
||||
}
|
||||
return assignee;
|
||||
}
|
||||
@@ -177,7 +171,7 @@ public class ProposalUnitAssignmentHandler implements AssignmentHandler {
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "提案单位处理人";
|
||||
return "承办单位负责人";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.service;
|
||||
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提案流程控制服务。
|
||||
* 状态调整必须按流程实例整体处理,避免并行承办单位待办被拆分为多个互相独立的跳转操作。
|
||||
*/
|
||||
public interface ProposalControlService {
|
||||
|
||||
/**
|
||||
* 查询当前流程实例可回退的历史节点。
|
||||
* 节点顺序依据教代会提案流程定义,不依赖迁移任务的插入 ID。
|
||||
*
|
||||
* @param instanceId 流程实例 ID
|
||||
* @return 可跳转节点列表
|
||||
*/
|
||||
List<NutMap> listJumpNodes(Long instanceId);
|
||||
|
||||
/**
|
||||
* 将整个提案流程实例跳转到指定历史节点。
|
||||
* 会先废弃全部当前待办,再创建一个目标节点待办;已完成审核历史保留不动。
|
||||
*
|
||||
* @param instanceId 流程实例 ID
|
||||
* @param targetTaskName 目标任务节点编码
|
||||
*/
|
||||
void jump(Long instanceId, String targetTaskName);
|
||||
}
|
||||
+32
@@ -57,6 +57,38 @@ public interface ProposalCommonService extends BaseService<ProposalInfo> {
|
||||
*/
|
||||
List<String> getProposalUnionRoleUserIds(ProposalInfo proposalInfo, String... roleCodes);
|
||||
|
||||
/**
|
||||
* 按承办单位编码关联系统单位,查询该系统单位已设置的单位负责人。
|
||||
*
|
||||
* @param undertakeId 提案承办单位 ID
|
||||
* @return 可参与提案流程的单位负责人用户 ID
|
||||
*/
|
||||
List<String> getUndertakeUnitManagerUserIds(String undertakeId);
|
||||
|
||||
/**
|
||||
* 获取承办单位的一个单位负责人登录名,供旧 BPM 指派接口使用。
|
||||
*
|
||||
* @param undertakeId 提案承办单位 ID
|
||||
* @return 单位负责人登录名;未设置时返回空字符串
|
||||
*/
|
||||
String getUndertakeUnitManagerLoginName(String undertakeId);
|
||||
|
||||
/**
|
||||
* 查询用户作为系统单位负责人的对应承办单位范围。
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @return 可管理的承办单位 ID
|
||||
*/
|
||||
List<String> getUserManagedUndertakeIds(String userId);
|
||||
|
||||
/**
|
||||
* 查询提案主办单位已设置的分管校领导。
|
||||
*
|
||||
* @param proposalId 提案 ID
|
||||
* @return 主办单位分管校领导用户 ID;多个主办单位或多人时合并去重
|
||||
*/
|
||||
List<String> getMasterUndertakeSchoolLeaderUserIds(String proposalId);
|
||||
|
||||
/**
|
||||
* 按白名单字段对已汇总的统计结果进行后端排序。
|
||||
*
|
||||
|
||||
+113
-7
@@ -30,6 +30,7 @@ import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.flow.vo.ProcessTaskVO;
|
||||
import com.budwk.app.sys.models.Sys_dict;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysDictService;
|
||||
@@ -123,8 +124,14 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
return false;
|
||||
}
|
||||
|
||||
// H5 列表首次加载不会传排序字段;Map.of 实现不接受空键,需在查询白名单前返回。
|
||||
String orderName = pageForm.getPageOrderName();
|
||||
if (StrUtil.isBlank(orderName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 仅允许白名单中的字段参与排序,防止构造任意SQL排序字段。
|
||||
String orderColumn = allowedOrderColumns.get(pageForm.getPageOrderName());
|
||||
String orderColumn = allowedOrderColumns.get(orderName);
|
||||
String orderBy = PageUtil.getOrder(pageForm.getPageOrderBy());
|
||||
if (StrUtil.isBlank(orderColumn) || StrUtil.isBlank(orderBy)) {
|
||||
return false;
|
||||
@@ -251,6 +258,107 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提案承办单位和系统单位通过单位编码一一关联;单位负责人以系统单位角色为唯一来源。
|
||||
* 历史 PROPOSAL_UNIT_LEADER 数据保留用于审计,但不再参与新流程取人。
|
||||
*/
|
||||
@Override
|
||||
public List<String> getUndertakeUnitManagerUserIds(String undertakeId) {
|
||||
ProposalUndertake undertake = dao().fetch(ProposalUndertake.class, undertakeId);
|
||||
if (undertake == null || StrUtil.isBlank(undertake.getCode())) {
|
||||
return List.of();
|
||||
}
|
||||
Sys_unit unit = dao().fetch(Sys_unit.class, Cnd.where(Sys_unit::getUnitcode, "=", undertake.getCode()));
|
||||
Sys_role role = sysRoleService.getByCode("UNIT_MANAGER");
|
||||
if (unit == null || role == null) {
|
||||
return List.of();
|
||||
}
|
||||
return dao().query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
||||
.and(Sys_user_role::getUnitId, "=", unit.getId()))
|
||||
.stream()
|
||||
.map(Sys_user_role::getUserId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUndertakeUnitManagerLoginName(String undertakeId) {
|
||||
for (String userId : getUndertakeUnitManagerUserIds(undertakeId)) {
|
||||
Sys_user user = dao().fetch(Sys_user.class, userId);
|
||||
if (user != null && StrUtil.isNotBlank(user.getLoginname())) {
|
||||
return user.getLoginname();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUserManagedUndertakeIds(String userId) {
|
||||
Sys_role role = sysRoleService.getByCode("UNIT_MANAGER");
|
||||
if (role == null || StrUtil.isBlank(userId)) {
|
||||
return List.of();
|
||||
}
|
||||
List<String> unitIds = dao().query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
||||
.and(Sys_user_role::getUserId, "=", userId))
|
||||
.stream()
|
||||
.map(Sys_user_role::getUnitId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (unitIds.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
List<String> unitCodes = dao().query(Sys_unit.class, Cnd.where(Sys_unit::getId, "in", unitIds))
|
||||
.stream()
|
||||
.map(Sys_unit::getUnitcode)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (unitCodes.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
return dao().query(ProposalUndertake.class, Cnd.where(ProposalUndertake::getCode, "in", unitCodes))
|
||||
.stream()
|
||||
.map(ProposalUndertake::getId)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校领导审批仅处理主办单位的分管校领导。角色关联以承办单位 ID 为范围,
|
||||
* 避免把其他承办单位配置的校领导加入当前提案的待办。
|
||||
*/
|
||||
@Override
|
||||
public List<String> getMasterUndertakeSchoolLeaderUserIds(String proposalId) {
|
||||
if (StrUtil.isBlank(proposalId)) {
|
||||
return List.of();
|
||||
}
|
||||
Sys_role role = sysRoleService.getByCode(RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER);
|
||||
if (role == null) {
|
||||
return List.of();
|
||||
}
|
||||
List<String> masterUndertakeIds = dao().query(ProposalReplyUnit.class,
|
||||
Cnd.where(ProposalReplyUnit::getProposalId, "=", proposalId)
|
||||
.and(ProposalReplyUnit::getIsMaster, "=", true))
|
||||
.stream()
|
||||
.map(ProposalReplyUnit::getUnitId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (masterUndertakeIds.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
return dao().query(Sys_user_role.class,
|
||||
Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
||||
.and(Sys_user_role::getUnderTakeId, "in", masterUndertakeIds))
|
||||
.stream()
|
||||
.map(Sys_user_role::getUserId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.filter(this::isEnabledUser)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/** 校验流程参与人仍是可用系统用户。 */
|
||||
private boolean isEnabledUser(String userId) {
|
||||
Sys_user user = dao().fetch(Sys_user.class, userId);
|
||||
@@ -1039,13 +1147,11 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
|
||||
|
||||
@Override
|
||||
public ProposalUndertake getSelfManageUndertake() {
|
||||
Sys_role role = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER.name());
|
||||
Sys_user_role userRole = dao().fetch(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", role.getId())
|
||||
.and(Sys_user_role::getUserId, "=", SecurityUtil.getUserId()));
|
||||
if (Lang.isEmpty(userRole)) {
|
||||
throw new RuntimeException("当前登录用户不是" + role.getName());
|
||||
List<String> undertakeIds = getUserManagedUndertakeIds(SecurityUtil.getUserId());
|
||||
if (undertakeIds.isEmpty()) {
|
||||
throw new RuntimeException("当前登录用户不是单位负责人");
|
||||
}
|
||||
return dao().fetch(ProposalUndertake.class, Cnd.where(ProposalUndertake::getId, "=", userRole.getUnderTakeId()));
|
||||
return dao().fetch(ProposalUndertake.class, undertakeIds.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+57
-14
@@ -42,6 +42,7 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -82,6 +83,13 @@ public class ProposalCommitteeFilingUnitServiceImpl extends BaseServiceImpl<Prop
|
||||
proposalIds = List.of(proposalId);
|
||||
}
|
||||
|
||||
/*
|
||||
* 必须先同步当前主协办单位,再推进至承办单位答复节点。
|
||||
* 答复节点在协办列表为空时会回退读取 proposal_reply_unit;若流程先推进,
|
||||
* 就会误用上一次确认遗留的协办单位,生成错误的并行答复任务。
|
||||
*/
|
||||
syncCommitteeFilingUnitData(proposalIds, args);
|
||||
|
||||
/*
|
||||
* 并案场景下,同一个节点会在每条提案实例上各有一条待办。
|
||||
* 这里统一按 taskName 找出整组正在办理中的任务,逐条执行,确保并案提案的流程状态保持一致。
|
||||
@@ -95,14 +103,13 @@ public class ProposalCommitteeFilingUnitServiceImpl extends BaseServiceImpl<Prop
|
||||
cloneArgs.put(FlowConst.PROCESS_TASK_ID_KEY, executeTask.getId());
|
||||
flowCommonService.executeTask(cloneArgs);
|
||||
}
|
||||
|
||||
syncCommitteeFilingUnitData(proposalIds, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* old-flow 页面提交后,需要把立案结果以及主协办单位同步落业务表。
|
||||
* 此节点不再维护立案编号,已有提案的历史立案编号保持不变。
|
||||
* 若这次改成“不予立案”等无需承办单位的结果,也要先清掉旧的承办单位记录,避免脏数据残留。
|
||||
* 重新选择承办单位时,仍被选中的单位保留原记录,未再选择的单位才会被清理。
|
||||
*/
|
||||
private void syncCommitteeFilingUnitData(List<String> proposalIds, Dict args) {
|
||||
String caseFilingResult = args.getStr(FlowConst.TASK_FORM_DATA_PREFIX + "caseFilingResult");
|
||||
@@ -113,8 +120,10 @@ public class ProposalCommitteeFilingUnitServiceImpl extends BaseServiceImpl<Prop
|
||||
.add("caseFilingType", caseFilingType),
|
||||
Cnd.where(ProposalInfo::getId, "in", proposalIds));
|
||||
|
||||
dao().clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "in", proposalIds));
|
||||
// 原实现会先清空全部单位,导致跳回后重新确认承办单位时丢失仍被选中单位的答复关联。
|
||||
// dao().clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "in", proposalIds));
|
||||
if (!List.of("CONFIRM_FILING", "SUGGESTION").contains(caseFilingResult)) {
|
||||
dao().clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "in", proposalIds));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,24 +136,58 @@ public class ProposalCommitteeFilingUnitServiceImpl extends BaseServiceImpl<Prop
|
||||
}
|
||||
List<String> slaveUnitIds = getUnitIdList(args, FlowConst.TASK_FORM_DATA_PREFIX + "slaveUnitIds");
|
||||
|
||||
List<String> allUnitIds = new ArrayList<>();
|
||||
allUnitIds.addAll(masterUnitIds);
|
||||
allUnitIds.addAll(slaveUnitIds);
|
||||
if (allUnitIds.isEmpty()) {
|
||||
Map<String, Boolean> selectedUnitRoleMap = new LinkedHashMap<>();
|
||||
masterUnitIds.forEach(unitId -> selectedUnitRoleMap.put(unitId, true));
|
||||
// 同一单位同时被选为主协办时,以主办身份为准,避免重复创建承办单位记录。
|
||||
slaveUnitIds.forEach(unitId -> selectedUnitRoleMap.putIfAbsent(unitId, false));
|
||||
if (selectedUnitRoleMap.isEmpty()) {
|
||||
dao().clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "in", proposalIds));
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, ProposalUndertake> undertakeMap = dao().query(ProposalUndertake.class, Cnd.where(ProposalUndertake::getId, "in", allUnitIds))
|
||||
List<String> selectedUnitIds = new ArrayList<>(selectedUnitRoleMap.keySet());
|
||||
Map<String, ProposalUndertake> undertakeMap = dao().query(ProposalUndertake.class, Cnd.where(ProposalUndertake::getId, "in", selectedUnitIds))
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ProposalUndertake::getId, v -> v));
|
||||
|
||||
List<ProposalReplyUnit> replyUnits = new ArrayList<>();
|
||||
for (String proposalId : proposalIds) {
|
||||
replyUnits.addAll(buildReplyUnits(proposalId, masterUnitIds, undertakeMap, true));
|
||||
replyUnits.addAll(buildReplyUnits(proposalId, slaveUnitIds, undertakeMap, false));
|
||||
List<ProposalReplyUnit> existingReplyUnits = dao().query(ProposalReplyUnit.class,
|
||||
Cnd.where(ProposalReplyUnit::getProposalId, "in", proposalIds));
|
||||
Map<String, ProposalReplyUnit> existingUnitMap = new LinkedHashMap<>();
|
||||
for (ProposalReplyUnit replyUnit : existingReplyUnits) {
|
||||
existingUnitMap.putIfAbsent(replyUnit.getProposalId() + "_" + replyUnit.getUnitId(), replyUnit);
|
||||
}
|
||||
if (!replyUnits.isEmpty()) {
|
||||
dao().insert(replyUnits);
|
||||
|
||||
List<ProposalReplyUnit> newReplyUnits = new ArrayList<>();
|
||||
for (String proposalId : proposalIds) {
|
||||
for (Map.Entry<String, Boolean> selectedUnit : selectedUnitRoleMap.entrySet()) {
|
||||
ProposalUndertake undertake = undertakeMap.get(selectedUnit.getKey());
|
||||
if (undertake == null) {
|
||||
continue;
|
||||
}
|
||||
ProposalReplyUnit existingReplyUnit = existingUnitMap.get(proposalId + "_" + selectedUnit.getKey());
|
||||
if (existingReplyUnit == null) {
|
||||
ProposalReplyUnit replyUnit = new ProposalReplyUnit();
|
||||
replyUnit.setProposalId(proposalId);
|
||||
replyUnit.setUnitId(undertake.getId());
|
||||
replyUnit.setUnitCode(undertake.getCode());
|
||||
replyUnit.setUnitName(undertake.getName());
|
||||
replyUnit.setIsMaster(selectedUnit.getValue());
|
||||
newReplyUnits.add(replyUnit);
|
||||
continue;
|
||||
}
|
||||
// 保留既有记录的 ID、是否答复和审计字段,只同步本次重新确认的单位信息与主协办身份。
|
||||
existingReplyUnit.setUnitCode(undertake.getCode());
|
||||
existingReplyUnit.setUnitName(undertake.getName());
|
||||
existingReplyUnit.setIsMaster(selectedUnit.getValue());
|
||||
dao().update(existingReplyUnit, "unitCode|unitName|isMaster");
|
||||
}
|
||||
}
|
||||
|
||||
// 本次未再选中的单位不再属于当前承办范围,删除其配置;其已完成流程任务历史仍保留可查看。
|
||||
dao().clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "in", proposalIds)
|
||||
.and(ProposalReplyUnit::getUnitId, "not in", selectedUnitIds));
|
||||
if (!newReplyUnits.isEmpty()) {
|
||||
dao().insert(newReplyUnits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.enums.ProcessTaskPerformTypeEnum;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
|
||||
import com.budwk.app.flow.service.FlowCommonService;
|
||||
import com.budwk.app.flow.service.ProcessTaskService;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalControlService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 教代会提案流程状态调整实现。
|
||||
* 迁移任务的数据库 ID 不代表真实流程顺序,统一按 JDHTA_NC 的节点顺序处理。
|
||||
*/
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class ProposalControlServiceImpl extends BaseServiceImpl<ProcessInstance> implements ProposalControlService {
|
||||
|
||||
/** JDHTA_NC 流程节点的稳定业务顺序。 */
|
||||
private static final Map<String, Integer> TASK_ORDERS = Map.ofEntries(
|
||||
Map.entry("startTask", 10),
|
||||
Map.entry("invite", 20),
|
||||
Map.entry("second", 30),
|
||||
Map.entry("secondaryUnionAudit", 40),
|
||||
Map.entry("partyOrganizationAudit", 50),
|
||||
Map.entry("committee", 60),
|
||||
Map.entry("committeeFiling", 60),
|
||||
Map.entry("committeeFilingUnit", 70),
|
||||
Map.entry("unit_reply", 80),
|
||||
Map.entry("unitReply", 80),
|
||||
Map.entry("schoolLeader", 90),
|
||||
Map.entry("feedback", 100),
|
||||
Map.entry("feedbackEvaluation", 100),
|
||||
Map.entry("caseCheck", 110)
|
||||
);
|
||||
|
||||
@Inject
|
||||
private ProcessTaskService processTaskService;
|
||||
@Inject
|
||||
private FlowCommonService flowCommonService;
|
||||
|
||||
public ProposalControlServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> listJumpNodes(Long instanceId) {
|
||||
List<ProcessTask> doingTasks = getDoingTasks(instanceId);
|
||||
int currentOrder = getCurrentOrder(doingTasks);
|
||||
|
||||
List<ProcessTask> doneTasks = dao().query(ProcessTask.class,
|
||||
Cnd.where(ProcessTask::getProcessInstanceId, "=", instanceId)
|
||||
.and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.FINISHED.getCode())
|
||||
.asc(ProcessTask::getFinishTime)
|
||||
.asc(ProcessTask::getId));
|
||||
Map<String, NutMap> nodes = new LinkedHashMap<>();
|
||||
for (ProcessTask task : doneTasks) {
|
||||
Integer taskOrder = TASK_ORDERS.get(task.getTaskName());
|
||||
if (taskOrder == null || taskOrder >= currentOrder
|
||||
|| ProcessTaskPerformTypeEnum.COUNTERSIGN.getCode().equals(task.getPerformType())) {
|
||||
continue;
|
||||
}
|
||||
nodes.putIfAbsent(task.getTaskName(), NutMap.NEW()
|
||||
.setv("value", task.getTaskName())
|
||||
.setv("label", task.getDisplayName())
|
||||
.setv("seq", taskOrder));
|
||||
}
|
||||
return nodes.values().stream()
|
||||
.sorted(Comparator.comparingInt(node -> node.getInt("seq")))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void jump(Long instanceId, String targetTaskName) {
|
||||
if (StrUtil.isBlank(targetTaskName)) {
|
||||
throw new BaseException("请选择目标节点");
|
||||
}
|
||||
List<ProcessTask> doingTasks = getDoingTasks(instanceId);
|
||||
int currentOrder = getCurrentOrder(doingTasks);
|
||||
Integer targetOrder = TASK_ORDERS.get(targetTaskName);
|
||||
if (targetOrder == null || targetOrder >= currentOrder) {
|
||||
throw new BaseException("只能跳转到当前节点之前的流程节点");
|
||||
}
|
||||
if (listJumpNodes(instanceId).stream().noneMatch(node -> targetTaskName.equals(node.getString("value")))) {
|
||||
throw new BaseException("目标节点没有可用的历史审核记录");
|
||||
}
|
||||
|
||||
ProcessTask sourceTask = doingTasks.get(0);
|
||||
String operator = SecurityUtil.getUserId();
|
||||
if (!processTaskService.isAllowed(sourceTask, operator)) {
|
||||
throw new BaseException("当前用户不能调整该流程");
|
||||
}
|
||||
|
||||
Dict args = Dict.create();
|
||||
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.JUMP.getCode());
|
||||
args.set(FlowConst.TASK_NAME, targetTaskName);
|
||||
args.set("tf_sourceTaskKey", sourceTask.getTaskName());
|
||||
args.set("tf_audit", true);
|
||||
|
||||
// 除执行入口外的并行待办必须先废弃,避免跳转后仍遗留承办单位答复等旧待办。
|
||||
for (int index = 1; index < doingTasks.size(); index++) {
|
||||
processTaskService.abandonProcessTask(doingTasks.get(index).getId(), operator, args);
|
||||
}
|
||||
flowCommonService.executeTask(args.set(FlowConst.PROCESS_TASK_ID_KEY, sourceTask.getId()));
|
||||
}
|
||||
|
||||
/** 查询并校验流程实例的当前待办任务。 */
|
||||
private List<ProcessTask> getDoingTasks(Long instanceId) {
|
||||
if (instanceId == null) {
|
||||
throw new BaseException("流程实例不能为空");
|
||||
}
|
||||
List<ProcessTask> doingTasks = dao().query(ProcessTask.class,
|
||||
Cnd.where(ProcessTask::getProcessInstanceId, "=", instanceId)
|
||||
.and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.DOING.getCode())
|
||||
.asc(ProcessTask::getId));
|
||||
if (doingTasks.isEmpty()) {
|
||||
throw new BaseException("流程没有进行中的待办");
|
||||
}
|
||||
return doingTasks;
|
||||
}
|
||||
|
||||
/** 同一实例只允许存在同一业务节点的并行待办,防止异常混合状态被错误跳转。 */
|
||||
private int getCurrentOrder(List<ProcessTask> doingTasks) {
|
||||
Set<String> taskNames = doingTasks.stream().map(ProcessTask::getTaskName).collect(java.util.stream.Collectors.toSet());
|
||||
if (taskNames.size() != 1) {
|
||||
throw new BaseException("流程存在多个不同节点的待办,请先处理异常待办");
|
||||
}
|
||||
Integer taskOrder = TASK_ORDERS.get(doingTasks.get(0).getTaskName());
|
||||
if (taskOrder == null) {
|
||||
throw new BaseException("当前节点不支持流程跳转");
|
||||
}
|
||||
return taskOrder;
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -18,6 +18,7 @@ import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import com.budwk.app.zhgh.democratic.proposal.param.ProposalFeedbackEvaluationParam;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.ProposalFeedbackEvaluationService;
|
||||
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
@@ -34,6 +35,8 @@ public class ProposalFeedbackEvaluationServiceImpl extends BaseServiceImpl<Propo
|
||||
private BpmService bpmService;
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
@Inject
|
||||
private ProposalCommonService proposalCommonService;
|
||||
|
||||
public ProposalFeedbackEvaluationServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
@@ -60,7 +63,7 @@ public class ProposalFeedbackEvaluationServiceImpl extends BaseServiceImpl<Propo
|
||||
|
||||
ProposalUndertake undertake = dao().fetch(ProposalUndertake.class, hostUnitId);
|
||||
|
||||
String approvalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.PROPOSAL_UNIT_LEADER, Cnd.where(Sys_user_role::getUnderTakeId, "=", hostUnitId));
|
||||
String approvalLoginName = proposalCommonService.getUndertakeUnitManagerLoginName(hostUnitId);
|
||||
if (StrUtil.isBlank(approvalLoginName)) {
|
||||
throw new BaseException("{}单位负责人没有配置,请联系校工会!", undertake.getName());
|
||||
}
|
||||
|
||||
+2
-2
@@ -84,7 +84,7 @@ public class ProposalSchoolLeaderApprovalServiceImpl extends BaseServiceImpl<Pro
|
||||
String underTakeId = createVariable.getStr("underTakeId");
|
||||
ProposalUndertake undertake = dao().fetch(ProposalUndertake.class, underTakeId);
|
||||
|
||||
String approvalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.PROPOSAL_UNIT_LEADER, Cnd.where(Sys_user_role::getUnderTakeId, "=", underTakeId));
|
||||
String approvalLoginName = proposalCommonService.getUndertakeUnitManagerLoginName(underTakeId);
|
||||
if (StrUtil.isBlank(approvalLoginName)) {
|
||||
throw new BaseException("{}单位负责人没有配置,请联系校工会!", undertake.getName());
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class ProposalSchoolLeaderApprovalServiceImpl extends BaseServiceImpl<Pro
|
||||
String underTakeId = createVariable.getStr("underTakeId");
|
||||
ProposalUndertake undertake = dao().fetch(ProposalUndertake.class, underTakeId);
|
||||
|
||||
String approvalLoginName = commonService.findUserLoginNameByRoleCode(RoleConstant.PROPOSAL_UNIT_LEADER, Cnd.where(Sys_user_role::getUnderTakeId, "=", underTakeId));
|
||||
String approvalLoginName = proposalCommonService.getUndertakeUnitManagerLoginName(underTakeId);
|
||||
if (StrUtil.isBlank(approvalLoginName)) {
|
||||
throw new BaseException("{}单位负责人没有配置,请联系校工会!", undertake.getName());
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const UNIT_LEADER_MANAGE_TEMPLATE = {
|
||||
<el-table-column label="角色" prop="roleName"></el-table-column>
|
||||
<el-table-column label="操作" width="100px">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="danger" @click="doDelete(scope.row)">删除</el-button>
|
||||
<el-button v-if="scope.row.canManage" size="mini" type="danger" @click="doDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -36,7 +36,10 @@ const UNIT_LEADER_MANAGE_TEMPLATE = {
|
||||
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
|
||||
<el-form :model="formData" ref="form" size="small" label-width="60px">
|
||||
<el-form-item prop="roleCode" label="角色">
|
||||
<dict-select placeholder="请选择角色" v-model="formData.roleCode" code="UNIT_ROLES" @change="onRoleChange"></dict-select>
|
||||
<el-select placeholder="请选择角色" style="width: 100%" v-model="formData.roleCode" @change="onRoleChange">
|
||||
<el-option label="单位负责人" value="UNIT_MANAGER"></el-option>
|
||||
<el-option label="单位分管校领导" value="UNIT_SCHOOL_LEADER"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="userId" label="人员">
|
||||
<user-select
|
||||
|
||||
@@ -27,12 +27,12 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
|
||||
<el-table-column prop="name" label="单位名称" sortable="custom" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="code" label="单位编码" sortable="custom" width="150px"></el-table-column>
|
||||
<!-- <el-table-column prop="branchSchoolLeader" label="分管校领导及联系方式" width="180px"></el-table-column>-->
|
||||
<el-table-column prop="unitLeader" label="单位领导及联系方式" sortable="custom" width="180px" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="branchSchoolLeader" label="单位分管校领导" sortable="custom" width="180px" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="unitLeader" label="单位负责人" sortable="custom" width="180px" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="操作" width="350px">
|
||||
<template slot-scope="{row}">
|
||||
<!-- <el-button size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,true)">设置分管校领导</el-button>-->
|
||||
<el-button size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,false)">设置单位领导</el-button>
|
||||
<el-button size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,true)">设置领导</el-button>
|
||||
<el-button size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,false)">设置负责人</el-button>
|
||||
<el-button size="mini" type="danger" @click="onDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
const USER_COMPONENT = {
|
||||
template: `
|
||||
<el-dialog title="设置领导" :visible.sync="visible" width="1000px" :close-on-click-modal="false">
|
||||
<el-dialog :title="isSchoolLeader ? '设置单位分管校领导' : '设置单位负责人'" :visible.sync="visible" width="1000px" :close-on-click-modal="false">
|
||||
<el-row v-if="isSchoolLeader" type="flex" align="middle" style="margin-bottom: 15px">
|
||||
<el-input v-model="leaderUserKeyword" clearable placeholder="输入姓名或工号搜索" style="width: 300px" @keyup.enter.native="searchLeaderUsers"></el-input>
|
||||
<el-button type="primary" size="small" icon="el-icon-search" style="margin-left: 10px" @click="searchLeaderUsers">搜索</el-button>
|
||||
<span style="margin-left: 15px;color: #606266">共{{leaderUserTotalCount}}人,默认展示前50人</span>
|
||||
</el-row>
|
||||
<el-transfer
|
||||
ref="transferRef"
|
||||
:titles="['可选人员', '已选人员']"
|
||||
filterable
|
||||
:filterable="!isSchoolLeader"
|
||||
:props="{
|
||||
key: 'id',
|
||||
label: 'label'
|
||||
@@ -26,22 +31,58 @@ const USER_COMPONENT = {
|
||||
selectUserIds: [],
|
||||
allUsers: [],
|
||||
unitId: null,
|
||||
isSchoolLeader: ""
|
||||
isSchoolLeader: "",
|
||||
leaderUserKeyword: "",
|
||||
leaderUserTotalCount: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(id, isSchoolLeader) {
|
||||
this.isSchoolLeader = isSchoolLeader
|
||||
this.unitId = id
|
||||
this.visible = true
|
||||
this.$set(this, "isSchoolLeader", isSchoolLeader)
|
||||
this.$set(this, "unitId", id)
|
||||
this.$set(this, "leaderUserKeyword", "")
|
||||
this.$set(this, "visible", true)
|
||||
if (isSchoolLeader) {
|
||||
this.searchLeaderUsers()
|
||||
} else {
|
||||
this.loadUnitManagerUsers()
|
||||
}
|
||||
},
|
||||
|
||||
searchLeaderUsers() {
|
||||
this.$axios
|
||||
.post("/platform/proposal/config/unit/" + (isSchoolLeader ? "branchSchoolLeaderTransferData" : "unitUsersTransferData"), { id })
|
||||
.then((res) => {
|
||||
this.selectUserIds = res.data.selectUserIds
|
||||
this.allUsers = res.data.allUsers
|
||||
.post("/platform/proposal/config/unit/branchSchoolLeaderUserPageData", {
|
||||
id: this.unitId,
|
||||
keyword: this.leaderUserKeyword
|
||||
})
|
||||
this.$refs.transferRef.clearQuery("left")
|
||||
this.$refs.transferRef.clearQuery("right")
|
||||
.then((res) => {
|
||||
this.$set(this, "leaderUserTotalCount", res.code === 0 ? res.data.totalCount : 0)
|
||||
this.applyTransferData(res)
|
||||
})
|
||||
},
|
||||
|
||||
loadUnitManagerUsers() {
|
||||
this.$axios
|
||||
.post("/platform/proposal/config/unit/unitUsersTransferData", { id: this.unitId })
|
||||
.then((res) => {
|
||||
this.$set(this, "leaderUserTotalCount", 0)
|
||||
this.applyTransferData(res)
|
||||
})
|
||||
},
|
||||
|
||||
applyTransferData(res) {
|
||||
if (res.code !== 0) {
|
||||
return
|
||||
}
|
||||
// 穿梭框必须先拿到候选人员,再设置已选人员,已选项才能稳定回显。
|
||||
this.$set(this, "allUsers", res.data.allUsers || [])
|
||||
this.$set(this, "selectUserIds", res.data.selectUserIds || [])
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.transferRef) {
|
||||
this.$refs.transferRef.clearQuery("left")
|
||||
this.$refs.transferRef.clearQuery("right")
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
doSubmit() {
|
||||
|
||||
+2
-1
@@ -206,7 +206,8 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
tableColumns: [
|
||||
{label: "提案编号", prop: "code"},
|
||||
{label: "立案编号", prop: "caseFilingCode"},
|
||||
// 按当前业务要求屏蔽立案编号,避免列表和自定义导出带出该字段。
|
||||
// {label: "立案编号", prop: "caseFilingCode"},
|
||||
{label: "提案名称", prop: "name"},
|
||||
{label: "提案人", prop: "createUserName"},
|
||||
{label: "提案类别", prop: "typeName"},
|
||||
|
||||
+8
-16
@@ -114,18 +114,15 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
|
||||
openJumpDialog(row) {
|
||||
this.jumpCurrentRow = row
|
||||
this.jumpForm = {
|
||||
this.$set(this, "jumpCurrentRow", row)
|
||||
this.$set(this, "jumpForm", {
|
||||
targetTaskName: "",
|
||||
tf_audit: true
|
||||
}
|
||||
this.jumpDialogVisible = true
|
||||
})
|
||||
this.$set(this, "jumpDialogVisible", true)
|
||||
this.$axios.post('/platform/proposal/control/jumpNodes', {instanceId: row.instanceId}).then(res => {
|
||||
if (res.code === 0) {
|
||||
const nodeList = res.data || []
|
||||
const currentNode = nodeList.find(item => item.value === row.taskKey)
|
||||
const currentSeq = currentNode ? Number(currentNode.seq) : Number.MAX_SAFE_INTEGER
|
||||
this.jumpNodeOptions = nodeList.filter(item => item.value !== row.taskKey && Number(item.seq) < currentSeq)
|
||||
this.$set(this, "jumpNodeOptions", res.data || [])
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -139,15 +136,10 @@ layout("/layouts/platform.html"){
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
const params = {
|
||||
processTaskId: this.jumpCurrentRow.taskId,
|
||||
submitType: 4,
|
||||
taskName: this.jumpForm.targetTaskName,
|
||||
tf_sourceTaskKey: this.jumpCurrentRow.taskKey,
|
||||
tf_audit: true
|
||||
instanceId: this.jumpCurrentRow.instanceId,
|
||||
targetTaskName: this.jumpForm.targetTaskName
|
||||
}
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify(params)
|
||||
}).then((res) => {
|
||||
this.$axios.post("/platform/proposal/control/jump", params).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.jumpDialogVisible = false
|
||||
this.$message.success(res.msg)
|
||||
|
||||
@@ -23,9 +23,11 @@ layout("/layouts/platform.html"){
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<table-tool :columns.sync="tableColumns">
|
||||
<el-button class="ml5" icon="el-icon-upload2" type="primary" size="small"
|
||||
@click="openImport">导入提案
|
||||
</el-button>
|
||||
<!-- 导入提案入口按当前业务要求屏蔽,保留导入逻辑以便后续恢复。
|
||||
<el-button class="ml5" icon="el-icon-upload2" type="primary" size="small"
|
||||
@click="openImport">导入提案
|
||||
</el-button>
|
||||
-->
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%" row-key="id">
|
||||
<el-table-column label="序号" width="50" type="index" :index="indexMethod" fixed="left"></el-table-column>
|
||||
@@ -76,8 +78,8 @@ layout("/layouts/platform.html"){
|
||||
<el-button v-if="row.canRevoke" size="mini" type="danger" @click="openRevoke(row)">
|
||||
撤回
|
||||
</el-button>
|
||||
<!-- v-if="row.taskKey === 'startTask' || !row.instanceId"-->
|
||||
<el-button size="mini" type="danger" @click="del(row.id)">
|
||||
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" size="mini" type="danger"
|
||||
@click="del(row.id)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ layout("/layouts/platform.html"){
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end" v-if="row.curTaskCode ==='second'">
|
||||
<el-button @click="$refs.guava.index()" size="small">返回返回</el-button>
|
||||
<el-button @click="$refs.guava.index()" size="small">返回</el-button>
|
||||
<el-button @click="handleTaskAction(20)" size="small" type="danger">不同意</el-button>
|
||||
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意</el-button>
|
||||
</el-row>
|
||||
|
||||
@@ -241,7 +241,36 @@ const PROPOSAL_INFO = {
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data
|
||||
const tasks = res.data || []
|
||||
// 按提案业务流程展示历史记录,避免迁移或并行任务受数据库写入顺序影响。
|
||||
const taskOrders = {
|
||||
startTask: 10,
|
||||
invite: 20,
|
||||
second: 30,
|
||||
secondaryUnionAudit: 40,
|
||||
partyOrganizationAudit: 50,
|
||||
committee: 60,
|
||||
committeeFiling: 60,
|
||||
committeeFilingUnit: 70,
|
||||
unit_reply: 80,
|
||||
unitReply: 80,
|
||||
schoolLeader: 90,
|
||||
feedback: 100,
|
||||
feedbackEvaluation: 100
|
||||
}
|
||||
tasks.sort((first, second) => {
|
||||
const orderDifference = (taskOrders[first.taskName] || 999) - (taskOrders[second.taskName] || 999)
|
||||
if (orderDifference !== 0) {
|
||||
return orderDifference
|
||||
}
|
||||
const firstTime = first.finishTime || ''
|
||||
const secondTime = second.finishTime || ''
|
||||
if (firstTime !== secondTime) {
|
||||
return firstTime.localeCompare(secondTime)
|
||||
}
|
||||
return first.id - second.id
|
||||
})
|
||||
this.$set(this, "doneTasks", tasks)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
+47
-9
@@ -32,6 +32,9 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i><span>立案</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-undo"></i><span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
@@ -50,10 +53,11 @@ layout("/layouts/platform_h5.html"){
|
||||
:placeholder="masterUnitLabel === '办理单位' ? '请选择办理单位' : '请选择主办单位'"
|
||||
@click="openMasterUnitPicker"
|
||||
:rules="[{ required: showUndertakeUnit, message: '请选择承办单位' }]" required></van-field>
|
||||
<van-popup v-model="showMasterUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<van-popup v-model="showMasterUnitPicker" position="bottom" round :style="{height: '70vh'}">
|
||||
<div style="box-sizing: border-box; display: flex; flex-direction: column; height: 100%; padding: 16px">
|
||||
<div class="process-title">{{masterUnitLabel}}</div>
|
||||
<van-checkbox-group v-model="formData.tf_masterUnitIds">
|
||||
<van-search :value="masterUnitKeyword" placeholder="请输入单位名称搜索" @input="changeMasterUnitKeyword"></van-search>
|
||||
<van-checkbox-group v-model="formData.tf_masterUnitIds" style="flex: 1; overflow-y: auto">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableMasterUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleMasterUnit(item.id)">
|
||||
@@ -66,10 +70,11 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-popup>
|
||||
<van-field v-if="formData.tf_caseFilingResult === 'CONFIRM_FILING'" :value="slaveUnitNames" label="协办单位"
|
||||
readonly is-link placeholder="请选择协办单位" @click="openSlaveUnitPicker"></van-field>
|
||||
<van-popup v-model="showSlaveUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<van-popup v-model="showSlaveUnitPicker" position="bottom" round :style="{height: '70vh'}">
|
||||
<div style="box-sizing: border-box; display: flex; flex-direction: column; height: 100%; padding: 16px">
|
||||
<div class="process-title">协办单位</div>
|
||||
<van-checkbox-group v-model="formData.tf_slaveUnitIds">
|
||||
<van-search :value="slaveUnitKeyword" placeholder="请输入单位名称搜索" @input="changeSlaveUnitKeyword"></van-search>
|
||||
<van-checkbox-group v-model="formData.tf_slaveUnitIds" style="flex: 1; overflow-y: auto">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableSlaveUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleSlaveUnit(item.id)">
|
||||
@@ -109,7 +114,9 @@ layout("/layouts/platform_h5.html"){
|
||||
showApprovalForm: false,
|
||||
showResultPicker: false,
|
||||
showMasterUnitPicker: false,
|
||||
showSlaveUnitPicker: false
|
||||
showSlaveUnitPicker: false,
|
||||
masterUnitKeyword: "",
|
||||
slaveUnitKeyword: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -131,10 +138,14 @@ layout("/layouts/platform_h5.html"){
|
||||
return this.getUnitNames(this.formData.tf_slaveUnitIds)
|
||||
},
|
||||
availableMasterUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_slaveUnitIds.includes(item.id))
|
||||
return this.underTakeOptions.filter((item) => {
|
||||
return !this.formData.tf_slaveUnitIds.includes(item.id) && this.matchUnitKeyword(item.name, this.masterUnitKeyword)
|
||||
})
|
||||
},
|
||||
availableSlaveUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_masterUnitIds.includes(item.id))
|
||||
return this.underTakeOptions.filter((item) => {
|
||||
return !this.formData.tf_masterUnitIds.includes(item.id) && this.matchUnitKeyword(item.name, this.slaveUnitKeyword)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -149,17 +160,31 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this, "showResultPicker", false)
|
||||
},
|
||||
openMasterUnitPicker() {
|
||||
this.$set(this, "masterUnitKeyword", "")
|
||||
this.$set(this, "showMasterUnitPicker", true)
|
||||
},
|
||||
closeMasterUnitPicker() {
|
||||
this.$set(this, "masterUnitKeyword", "")
|
||||
this.$set(this, "showMasterUnitPicker", false)
|
||||
},
|
||||
openSlaveUnitPicker() {
|
||||
this.$set(this, "slaveUnitKeyword", "")
|
||||
this.$set(this, "showSlaveUnitPicker", true)
|
||||
},
|
||||
closeSlaveUnitPicker() {
|
||||
this.$set(this, "slaveUnitKeyword", "")
|
||||
this.$set(this, "showSlaveUnitPicker", false)
|
||||
},
|
||||
// 选择弹层按单位名称实时筛选,不影响已选单位的值。
|
||||
matchUnitKeyword(unitName, keyword) {
|
||||
return !keyword || (unitName || "").toLowerCase().includes(keyword.toLowerCase())
|
||||
},
|
||||
changeMasterUnitKeyword(value) {
|
||||
this.$set(this, "masterUnitKeyword", value)
|
||||
},
|
||||
changeSlaveUnitKeyword(value) {
|
||||
this.$set(this, "slaveUnitKeyword", value)
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
@@ -262,6 +287,19 @@ layout("/layouts/platform_h5.html"){
|
||||
}).catch(function () {})
|
||||
} catch (error) {}
|
||||
},
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要撤回吗?"}).then(() => {
|
||||
this.$axios.post("/platform/proposal/committeeFiling/h5/revokeTask", {
|
||||
taskId: row.taskId,
|
||||
proposalId: row.id
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
|
||||
+47
-9
@@ -32,6 +32,9 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i><span>确认</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-undo"></i><span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
@@ -50,10 +53,11 @@ layout("/layouts/platform_h5.html"){
|
||||
:placeholder="masterUnitLabel === '办理单位' ? '请选择办理单位' : '请选择主办单位'"
|
||||
@click="openMasterUnitPicker"
|
||||
:rules="[{ required: showUndertakeUnit, message: '请选择承办单位' }]" required></van-field>
|
||||
<van-popup v-model="showMasterUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<van-popup v-model="showMasterUnitPicker" position="bottom" round :style="{height: '70vh'}">
|
||||
<div style="box-sizing: border-box; display: flex; flex-direction: column; height: 100%; padding: 16px">
|
||||
<div class="process-title">{{masterUnitLabel}}</div>
|
||||
<van-checkbox-group v-model="formData.tf_masterUnitIds">
|
||||
<van-search :value="masterUnitKeyword" placeholder="请输入单位名称搜索" @input="changeMasterUnitKeyword"></van-search>
|
||||
<van-checkbox-group v-model="formData.tf_masterUnitIds" style="flex: 1; overflow-y: auto">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableMasterUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleMasterUnit(item.id)">
|
||||
@@ -66,10 +70,11 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-popup>
|
||||
<van-field v-if="formData.tf_caseFilingResult === 'CONFIRM_FILING'" :value="slaveUnitNames" label="协办单位"
|
||||
readonly is-link placeholder="请选择协办单位" @click="openSlaveUnitPicker"></van-field>
|
||||
<van-popup v-model="showSlaveUnitPicker" position="bottom" round>
|
||||
<div style="padding: 16px">
|
||||
<van-popup v-model="showSlaveUnitPicker" position="bottom" round :style="{height: '70vh'}">
|
||||
<div style="box-sizing: border-box; display: flex; flex-direction: column; height: 100%; padding: 16px">
|
||||
<div class="process-title">协办单位</div>
|
||||
<van-checkbox-group v-model="formData.tf_slaveUnitIds">
|
||||
<van-search :value="slaveUnitKeyword" placeholder="请输入单位名称搜索" @input="changeSlaveUnitKeyword"></van-search>
|
||||
<van-checkbox-group v-model="formData.tf_slaveUnitIds" style="flex: 1; overflow-y: auto">
|
||||
<van-cell-group>
|
||||
<van-cell v-for="item in availableSlaveUnits" :key="item.id" clickable :title="item.name"
|
||||
@click="toggleSlaveUnit(item.id)">
|
||||
@@ -109,7 +114,9 @@ layout("/layouts/platform_h5.html"){
|
||||
showApprovalForm: false,
|
||||
showResultPicker: false,
|
||||
showMasterUnitPicker: false,
|
||||
showSlaveUnitPicker: false
|
||||
showSlaveUnitPicker: false,
|
||||
masterUnitKeyword: "",
|
||||
slaveUnitKeyword: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -131,10 +138,14 @@ layout("/layouts/platform_h5.html"){
|
||||
return this.getUnitNames(this.formData.tf_slaveUnitIds)
|
||||
},
|
||||
availableMasterUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_slaveUnitIds.includes(item.id))
|
||||
return this.underTakeOptions.filter((item) => {
|
||||
return !this.formData.tf_slaveUnitIds.includes(item.id) && this.matchUnitKeyword(item.name, this.masterUnitKeyword)
|
||||
})
|
||||
},
|
||||
availableSlaveUnits() {
|
||||
return this.underTakeOptions.filter((item) => !this.formData.tf_masterUnitIds.includes(item.id))
|
||||
return this.underTakeOptions.filter((item) => {
|
||||
return !this.formData.tf_masterUnitIds.includes(item.id) && this.matchUnitKeyword(item.name, this.slaveUnitKeyword)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -149,17 +160,31 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this, "showResultPicker", false)
|
||||
},
|
||||
openMasterUnitPicker() {
|
||||
this.$set(this, "masterUnitKeyword", "")
|
||||
this.$set(this, "showMasterUnitPicker", true)
|
||||
},
|
||||
closeMasterUnitPicker() {
|
||||
this.$set(this, "masterUnitKeyword", "")
|
||||
this.$set(this, "showMasterUnitPicker", false)
|
||||
},
|
||||
openSlaveUnitPicker() {
|
||||
this.$set(this, "slaveUnitKeyword", "")
|
||||
this.$set(this, "showSlaveUnitPicker", true)
|
||||
},
|
||||
closeSlaveUnitPicker() {
|
||||
this.$set(this, "slaveUnitKeyword", "")
|
||||
this.$set(this, "showSlaveUnitPicker", false)
|
||||
},
|
||||
// 选择弹层按单位名称实时筛选,不影响已选单位的值。
|
||||
matchUnitKeyword(unitName, keyword) {
|
||||
return !keyword || (unitName || "").toLowerCase().includes(keyword.toLowerCase())
|
||||
},
|
||||
changeMasterUnitKeyword(value) {
|
||||
this.$set(this, "masterUnitKeyword", value)
|
||||
},
|
||||
changeSlaveUnitKeyword(value) {
|
||||
this.$set(this, "slaveUnitKeyword", value)
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
@@ -298,6 +323,19 @@ layout("/layouts/platform_h5.html"){
|
||||
}).catch(function () {})
|
||||
} catch (error) {}
|
||||
},
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要撤回吗?"}).then(() => {
|
||||
this.$axios.post("/platform/proposal/committeeFilingUnit/h5/revokeTask", {
|
||||
taskId: row.taskId,
|
||||
proposalId: row.id
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
},
|
||||
closeApproval() {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
},
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/mine/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef"
|
||||
<table-list api="/platform/proposal/mine/h5/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/seconded/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
<table-list api="/platform/proposal/seconded/h5/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
|
||||
+15
-4
@@ -189,19 +189,30 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
},
|
||||
|
||||
onApproval(row) {
|
||||
async onApproval(row) {
|
||||
// 与 PC 端保持一致,确认已沟通后才允许进入答复表单。
|
||||
try {
|
||||
await this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "是否已与提案代表进行充分沟通?",
|
||||
confirmButtonText: "是",
|
||||
cancelButtonText: "否"
|
||||
})
|
||||
} catch (error) {
|
||||
return
|
||||
}
|
||||
this.loadCandidates(row.taskId)
|
||||
|
||||
this.showApprovalForm = true
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.formData = {
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
taskKey: row.taskKey,
|
||||
taskName: row.taskName,
|
||||
proposalId: row.id,
|
||||
underTakeName: row.underTakeName,
|
||||
underTakeIsMaster: row.underTakeIsMaster
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 加载候选人列表
|
||||
|
||||
Reference in New Issue
Block a user