This commit is contained in:
2026-08-26 13:57:48 +08:00
49 changed files with 2060 additions and 487 deletions
@@ -11,6 +11,8 @@ import com.budwk.app.flow.engine.event.ProcessPublisher;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.enums.*;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
@@ -22,6 +24,7 @@ import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import java.util.List;
import java.util.Optional;
@IocBean
public class FlowCommonService {
@@ -61,11 +64,13 @@ public class FlowCommonService {
args.put(FlowConst.SUBMIT_TYPE, submitType);
Sys_unit sysUnit = dao.fetch(Sys_unit.class, Cnd.where("id", "=", SecurityUtil.getUnitId()));
// 设置办理人信息到表单参数
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "userName", SecurityUtil.getUserUsername());
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "loginName", SecurityUtil.getUserLoginname());
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unitId", SecurityUtil.getUnitId());
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unitName", SecurityUtil.getUnitId());
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unitName", Optional.of(sysUnit).map(Sys_unit::getName).orElse(""));
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unionId", SecurityUtil.getUnionId());
if (ObjectUtil.equals(submitType, ProcessSubmitTypeEnum.ROLLBACK.getCode())) {
@@ -4,7 +4,6 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RedisConstant;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.sys.models.Sys_config;
import com.budwk.app.sys.services.SysConfigService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
@@ -139,17 +138,18 @@ public class SysConfController {
@At
@Ok("json:full")
@SaCheckPermission("sys.manager.conf")
public Object data(@Param("pageNumber") int pageNumber, @Param("pageSize") int pageSize, @Param("pageOrderName") String pageOrderName, @Param("pageOrderBy") String pageOrderBy) {
public Object data(@Param("pageNumber") int pageNumber,
@Param("pageSize") int pageSize,
@Param("pageOrderName") String pageOrderName,
@Param("pageOrderBy") String pageOrderBy,
@Param("configKey") String configKey) {
try {
ensureAppImageConfig("AppHomeImg", "PC首页轮播图");
ensureAppImageConfig("H5AppHomeImg", "移动端首页轮播图");
ensureAppImageConfig("AppFeaturedActivityImg", "精彩活动页顶部图片");
ensureAppImageConfig("AppFestivalBenefitImg", "节日福利页顶部图片");
Cnd cnd = Cnd.NEW();
if (Strings.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
cnd.orderBy(pageOrderName, PageUtil.getOrder(pageOrderBy));
}
return Result.success().addData(sysConfigService.listPage(pageNumber, pageSize, cnd));
return Result.success().addData(sysConfigService.pageData(
pageNumber, pageSize, pageOrderName, pageOrderBy, configKey));
} catch (Exception e) {
return Result.error();
}
@@ -419,14 +419,13 @@ public class SysRoleController {
public Object user(@Param("roleId") String roleId, @Param("searchName") String searchName, @Param("searchKeyword") String searchKeyword,
@Param("pageNumber") int pageNumber, @Param("pageSize") int pageSize, @Param("pageOrderName") String pageOrderName, @Param("pageOrderBy") String pageOrderBy) {
try {
Sql sql = Sqls.create("SELECT a.*,c.name as unitname FROM sys_user a,sys_user_role b,sys_unit c WHERE a.unitid=c.id and a.id=b.userId and b.roleId=@roleId $s $o");
Sql sql = Sqls.create("SELECT a.*,c.name as unitname FROM sys_user a,sys_user_role b,sys_unit c WHERE a.unitid=c.id and a.id=b.userId and enable='1' and b.roleId=@roleId $s $o");
sql.params().set("roleId", roleId);
if (Strings.isNotBlank(searchName) && Strings.isNotBlank(searchKeyword)) {
sql.vars().set("s", " and a." + searchName + " like '%" + searchKeyword + "%'");
}
if (Strings.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
sql.vars().set("o", " order by a." + pageOrderName + " " + PageUtil.getOrder(pageOrderBy));
}
return Result.success().addData(sysUserService.listPage(pageNumber, pageSize, sql));
} catch (Exception e) {
@@ -456,10 +456,16 @@ public class SysUnionController {
unionCadre.setIsJoin(true);
dao.insert(unionCadre);
// 去走工作流
// 校级管理员新增普通干部时直接授权,不生成无实际审核意义的流程数据。
boolean isAdmin = AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name());
if (isAdmin) {
sysUnionService.assignBranchUnionRole(userId, role.getId(), unionId, List.of());
return Result.success();
}
// 非校级管理员仍按原业务发起基层干部授权审核流程。
Dict args = Dict.create();
args.set("submit", isAdmin ? "admin" : "branch");
args.set("submit", "branch");
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
args.set(FlowConst.FORM_DATA, unionCadre);
@@ -470,20 +476,12 @@ public class SysUnionController {
flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
}
if (isAdmin) {
// 如果是管理员,直接加角色
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unionId", "=", unionId));
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId()).add("userId", userId).add("unionId", unionId));
sysRoleService.clearCache();
sysUserService.clearCache();
}
return Result.success();
}
/**
* 发起二级党委书记授权审批。一个审批申请可关联当前分工会下的多个单位。
* 审核通过后由流程拦截器按单位写入角色,避免影响普通分工会角色的授权方式
* 新增二级党委书记授权。校级管理员直接按单位授权,其他用户发起审批,
* 审核通过后由流程拦截器按单位写入角色。
*
* @param userId 人员ID
* @param unionId 分工会ID
@@ -536,11 +534,18 @@ public class SysUnionController {
unionCadre.setIsJoin(true);
dao.insert(unionCadre);
boolean isAdmin = AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name());
if (isAdmin) {
// 校级管理员直接按所选单位授权,不创建 JCGHWY 流程实例和审核任务。
sysUnionService.assignBranchUnionRole(userId, role.getId(), unionId, distinctUnitIds);
return Result.success();
}
// 非校级管理员保留原审批流程,并将所选单位随表单传给审核通过拦截器。
JSONObject formData = JSONUtil.parseObj(unionCadre);
formData.set("unitIds", distinctUnitIds);
Dict args = Dict.create();
boolean isAdmin = AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name());
args.set("submit", isAdmin ? "admin" : "branch");
args.set("submit", "branch");
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
args.set(FlowConst.FORM_DATA, formData.toString());
ProcessInstance instance = flowEngine.startProcessInstanceByKey("JCGHWY", unionCadre.getId(), SecurityUtil.getUserId(), args);
@@ -1,5 +1,6 @@
package com.budwk.app.sys.services;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.sys.models.Sys_config;
import com.budwk.app.base.service.BaseService;
@@ -16,4 +17,17 @@ public interface SysConfigService extends BaseService<Sys_config> {
List<Sys_config> getAllList();
Sys_config getValueByKey(String key);
/**
* 分页查询系统参数,支持按参数名模糊查询和安全排序。
*
* @param pageNumber 页码
* @param pageSize 每页条数
* @param pageOrderName 排序字段
* @param pageOrderBy 排序方向
* @param configKey 参数名关键字
* @return 系统参数分页数据
*/
Pagination<Sys_config> pageData(int pageNumber, int pageSize, String pageOrderName,
String pageOrderBy, String configKey);
}
@@ -3,5 +3,18 @@ package com.budwk.app.sys.services;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.sys.models.Sys_union;
import java.util.List;
public interface SysUnionService extends BaseService<Sys_union> {
/**
* 直接分配分工会干部角色。普通干部传空单位集合时按分工会写入一条角色关系;
* 二级党委书记传单位集合时按单位分别写入角色关系。
*
* @param userId 用户ID
* @param roleId 角色ID
* @param unionId 分工会ID
* @param unitIds 授权单位ID集合,普通干部角色传空集合
*/
void assignBranchUnionRole(String userId, String roleId, String unionId, List<String> unitIds);
}
@@ -1,15 +1,19 @@
package com.budwk.app.sys.services.impl;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.sys.models.Sys_config;
import com.budwk.app.sys.services.SysConfigService;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import java.util.List;
import java.util.Set;
/**
* Created by wizzer on 2016/12/23.
@@ -32,4 +36,32 @@ public class SysConfigServiceImpl extends BaseServiceImpl<Sys_config> implements
}
return sys_config;
}
/**
* 分页查询系统参数。参数名使用模糊匹配,排序字段限定在列表可展示字段内,
* 防止未经校验的前端字段直接进入排序 SQL。
*
* @param pageNumber 页码
* @param pageSize 每页条数
* @param pageOrderName 排序字段
* @param pageOrderBy 排序方向
* @param configKey 参数名关键字
* @return 系统参数分页数据
*/
@Override
@SuppressWarnings("unchecked")
public Pagination<Sys_config> pageData(int pageNumber, int pageSize, String pageOrderName,
String pageOrderBy, String configKey) {
Cnd cnd = Cnd.NEW();
if (Strings.isNotBlank(configKey)) {
cnd.where().andLike("configKey", configKey.trim());
}
Set<String> sortableColumns = Set.of("configKey", "configValue", "note");
if (sortableColumns.contains(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
cnd.orderBy(pageOrderName, PageUtil.getOrder(pageOrderBy));
} else {
cnd.asc("configKey");
}
return listPage(pageNumber, pageSize, cnd);
}
}
@@ -2,13 +2,65 @@ package com.budwk.app.sys.services.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.sys.services.SysUnionService;
import com.budwk.app.sys.services.SysUserService;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import java.util.List;
@IocBean(args = {"refer:dao"})
public class SysUnionServiceImpl extends BaseServiceImpl<Sys_union> implements SysUnionService {
@Inject
private SysRoleService sysRoleService;
@Inject
private SysUserService sysUserService;
public SysUnionServiceImpl(Dao dao) {
super(dao);
}
/**
* 直接分配分工会干部角色,并在授权完成后统一清理权限缓存。
* 普通角色按分工会授权一次,包含单位的角色按每个单位分别授权。
*
* @param userId 用户ID
* @param roleId 角色ID
* @param unionId 分工会ID
* @param unitIds 授权单位ID集合,普通干部角色传空集合
*/
@Override
public void assignBranchUnionRole(String userId, String roleId, String unionId, List<String> unitIds) {
// 先清理同一用户在当前分工会下的相同角色,保证重新授权后不存在重复关系。
dao().clear(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", roleId)
.and(Sys_user_role::getUserId, "=", userId)
.and(Sys_user_role::getUnionId, "=", unionId));
if (unitIds == null || unitIds.isEmpty()) {
Sys_user_role userRole = new Sys_user_role();
userRole.setRoleId(roleId);
userRole.setUserId(userId);
userRole.setUnionId(unionId);
dao().insert(userRole);
} else {
// 二级党委书记按选中的单位分别生成角色关系,供后续单位级权限判断使用。
for (String unitId : unitIds) {
Sys_user_role userRole = new Sys_user_role();
userRole.setRoleId(roleId);
userRole.setUserId(userId);
userRole.setUnionId(unionId);
userRole.setUnitId(unitId);
dao().insert(userRole);
}
}
sysRoleService.clearCache();
sysUserService.clearCache();
}
}
@@ -0,0 +1,31 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service;
import com.budwk.app.base.service.BaseService;
import org.nutz.lang.util.NutMap;
/**
* 分工会预算统计服务。
*
* <p>统一封装分工会预算使用情况和经费收支情况的全量汇总查询,
* 汇总口径与列表查询保持一致,不受分页参数影响。</p>
*/
public interface OutlayManageUnionStatisticsService extends BaseService {
/**
* 查询分工会预算使用情况的全量合计。
*
* @param year 统计年度
* @param unionId 分工会主键,管理员可为空查询全部
* @return 包含 totalQuota、usedQuota、surplusQuota 的合计数据
*/
NutMap queryUseDetailSummary(Integer year, String unionId);
/**
* 查询分工会经费收支使用情况的全量合计。
*
* @param year 统计年度
* @param unionId 分工会主键,管理员可为空查询全部
* @return 包含各项收入、支出和余额字段的合计数据
*/
NutMap queryIncomeExpenseSummary(Integer year, String unionId);
}
@@ -0,0 +1,104 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.impl;
import cn.hutool.core.date.DateUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayManageUnionStatisticsService;
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.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
/**
* 分工会预算统计服务实现。
*
* <p>汇总查询在数据库端完成,避免只汇总当前分页数据,
* 同时复用列表的年度、分工会和权限过滤条件。</p>
*/
@IocBean(args = {"refer:dao"})
public class OutlayManageUnionStatisticsServiceImpl extends BaseServiceImpl implements OutlayManageUnionStatisticsService {
public OutlayManageUnionStatisticsServiceImpl(Dao dao) {
super(dao);
}
@Override
public NutMap queryUseDetailSummary(Integer year, String unionId) {
Cnd cnd = buildUnionManageCondition(year, unionId, false);
Sql sql = Sqls.create("""
SELECT
COALESCE(SUM(totalQuota), 0) AS totalQuota,
COALESCE(SUM(usedQuota), 0) AS usedQuota,
COALESCE(SUM(COALESCE(totalQuota, 0) - COALESCE(usedQuota, 0)), 0) AS surplusQuota
FROM outlay_manage_union mu $condition
""");
sql.setCondition(cnd);
return executeMap(sql);
}
@Override
public NutMap queryIncomeExpenseSummary(Integer year, String unionId) {
Cnd cnd = buildUnionManageCondition(year, unionId, true);
Sql sql = Sqls.create("""
SELECT
COALESCE(SUM(t.beginMoney), 0) AS beginMoney,
COALESCE(SUM(t.feeJanApr), 0) AS feeJanApr,
COALESCE(SUM(t.feeMayAug), 0) AS feeMayAug,
COALESCE(SUM(t.feeSepDec), 0) AS feeSepDec,
COALESCE(SUM(t.awardMoney), 0) AS awardMoney,
COALESCE(SUM(t.usedMoney), 0) AS usedMoney,
COALESCE(SUM(t.remainMoney), 0) AS remainMoney
FROM (
SELECT
mu.unionId,
COALESCE(SUM(CASE WHEN au.quarterly = 1 THEN au.allocateHeadMoney ELSE 0 END), 0) AS beginMoney,
COALESCE(SUM(CASE WHEN au.quarterly = 1 THEN au.allocateMoney ELSE 0 END), 0) AS feeJanApr,
COALESCE(SUM(CASE WHEN au.quarterly = 2 THEN au.allocateMoney ELSE 0 END), 0) AS feeMayAug,
COALESCE(SUM(CASE WHEN au.quarterly = 3 THEN au.allocateMoney ELSE 0 END), 0) AS feeSepDec,
COALESCE(SUM(CASE WHEN au.quarterly = 4 THEN au.allocateMoney ELSE 0 END), 0) AS awardMoney,
COALESCE(mu.usedQuota, 0) AS usedMoney,
COALESCE(mu.totalQuota, 0) - COALESCE(mu.usedQuota, 0) AS remainMoney
FROM outlay_manage_union mu
LEFT JOIN outlay_allocate_union au ON au.year = mu.year
AND au.unionId = mu.unionId
AND au.delFlag = 0
LEFT JOIN sys_union su ON su.id = mu.unionId
$condition
GROUP BY mu.year, mu.unionId, mu.usedQuota, mu.totalQuota
) t
""");
sql.setCondition(cnd);
return executeMap(sql);
}
/**
* 构造两个列表共用的预算主表过滤条件,保证汇总和分页列表权限口径一致。
*/
private Cnd buildUnionManageCondition(Integer year, String unionId, boolean includeDelFlag) {
Cnd cnd = Cnd.NEW();
if (includeDelFlag) {
cnd.and("mu.delFlag", "=", false);
}
cnd.and("mu.year", "=", year == null ? DateUtil.thisYear() : year);
cnd.and("mu.totalQuota", "IS NOT", null);
cnd.andEX("mu.unionId", "=", unionId);
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("mu.unionId", "=", SecurityUtil.getUnionId());
}
return cnd;
}
/**
* 执行单行统计查询,并在无数据时返回各字段为零的结果,方便前端直接展示。
*/
private NutMap executeMap(Sql sql) {
sql.setCallback(Sqls.callback.map());
dao().execute(sql);
NutMap result = (NutMap) sql.getResult();
return result == null ? NutMap.NEW() : result;
}
}
@@ -14,6 +14,7 @@ import com.budwk.app.base.service.BaseService;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayManageUnionStatisticsService;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.vo.OutlayUnionIncomeExpenseVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -44,6 +45,8 @@ public class OutlayManageUnionIncomeExpenseController {
@Inject
private BaseService baseService;
@Inject
private OutlayManageUnionStatisticsService outlayManageUnionStatisticsService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/outlay/outlayManage/union/incomeExpense/index.html")
@@ -60,6 +63,16 @@ public class OutlayManageUnionIncomeExpenseController {
return Result.success(pagination);
}
/**
* 查询当前筛选范围内全部分工会经费收支合计,不受分页参数影响。
*/
@At
@ApiOperation("查询经费收支合计")
@SaCheckPermission("outlay.outlayManage.union.incomeExpense")
public Result summary(Integer year, String unionId) {
return Result.success(outlayManageUnionStatisticsService.queryIncomeExpenseSummary(year, unionId));
}
@At
@Ok("void")
@ApiOperation("导出")
@@ -12,6 +12,7 @@ import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.model.OutlayUseDetail;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayUseDetailService;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayManageUnionStatisticsService;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model.OutLayAllocateUnion;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -46,6 +47,8 @@ public class OutlayManageUnionUseDetailController {
private BaseService baseService;
@Inject
private OutlayUseDetailService outlayUseDetailService;
@Inject
private OutlayManageUnionStatisticsService outlayManageUnionStatisticsService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/outlay/outlayManage/union/useDetail/index.html")
@@ -81,6 +84,16 @@ public class OutlayManageUnionUseDetailController {
return Result.success(pagination);
}
/**
* 查询当前筛选范围内全部分工会预算使用情况合计,不受分页参数影响。
*/
@At
@ApiOperation("查询预算使用情况合计")
@SaCheckPermission("outlay.outlayManage.union.useDetail")
public Result summary(Integer year, String unionId) {
return Result.success(outlayManageUnionStatisticsService.queryUseDetailSummary(year, unionId));
}
@At
@ApiOperation("某个分工会预算使用详情")
@@ -197,34 +197,7 @@ public class TeacherCongressDelegateManageController {
@At
@SaCheckPermission("tc.delegate.manage")
public Result publicUser(@Valid TeacherCongressDelegateManagePublicUserParam param) {
List<Teacher_congress_delegation_unit> units = dao.query(Teacher_congress_delegation_unit.class, Cnd.where("sessionId", "=", param.getSessionId()).and("delegationId", "=", param.getDelegationId()));
List<String> unitIds = units.stream().map(Teacher_congress_delegation_unit::getUnitId).toList();
if (ObjectUtil.isEmpty(unitIds)) {
return Result.error("代表团没有组成单位");
}
Sql sql = Sqls.create("""
SELECT
t1.id,
t1.username AS userName,
t1.loginName AS loginName,
t2.NAME AS unitName
FROM
`sys_user` t1
LEFT JOIN sys_unit t2 ON t2.id = t1.unitId
WHERE
t1.id NOT IN ( SELECT userId FROM teacher_congress_delegate WHERE sessionId = @sessionId AND delegationId = @delegationId )
AND
t1.unitId in (@unitIds)
AND
(t1.loginname like @keyWord or username like @keyWord)
""");
sql.setParam("sessionId", param.getSessionId());
sql.setParam("delegationId", param.getDelegationId());
sql.setParam("unitIds", unitIds);
sql.setParam("keyWord", "%" + param.getKeyWord() + "%");
Pagination pagination = sysUserService.listPageMap(1, 50, sql);
return Result.success(pagination.getList());
return Result.success(teacherDelegateService.listPublicUsers(param));
}
/**
@@ -497,40 +470,7 @@ public class TeacherCongressDelegateManageController {
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("tc.delegate.manage")
public Result doAllocateDelegation(String sessionId) {
List<Teacher_congress_delegate> delegateList = dao.query(Teacher_congress_delegate.class,
Cnd.where(Teacher_congress_delegate::getSessionId, "=", sessionId)
.and(Teacher_congress_delegate::getDelegationId, "is", null));
for (Teacher_congress_delegate delegate : delegateList) {
Teacher_congress_delegation_unit delegation_unit = dao.fetch(Teacher_congress_delegation_unit.class,
Cnd.where(Teacher_congress_delegation_unit::getUnitId, "=", delegate.getUnitId())
.and(Teacher_congress_delegation_unit::getSessionId, "=", sessionId));
if (ObjectUtil.isNotEmpty(delegation_unit)) {
delegate.setDelegationId(delegation_unit.getDelegationId());
dao.update(delegate);
Sys_user_role userRole = new Sys_user_role();
userRole.setTcDelegationId(delegation_unit.getDelegationId());
userRole.setUserId(delegate.getUserId());
userRole.setTcSessionId(sessionId);
Sys_role sys_role = dao.fetch(Sys_role.class, Cnd.where(Sys_role::getCode, "=", RoleConstant.TEACHER_CONGRESS_DELEGATE_FORMAL.name()));
if (sys_role.getId().equals(delegate.getRoleId())) {
delegate.setRoleId(sys_role.getId());
userRole.setRoleId(sys_role.getId());
}
Sys_role sys_role2 = dao.fetch(Sys_role.class, Cnd.where(Sys_role::getCode, "=", RoleConstant.TEACHER_CONGRESS_DELEGATE_ATTENDANCE.name()));
if (sys_role2.getId().equals(delegate.getRoleId())) {
delegate.setRoleId(sys_role2.getId());
userRole.setRoleId(sys_role2.getId());
}
userRole.setTcDelegationId(delegate.getDelegationId());
teacherCongressSessionService.prepareSessionRole(userRole);
dao.insert(userRole);
}
sysUserService.clearCache();
}
return Result.success();
return Result.success(teacherDelegateService.allocateDelegations(sessionId));
}
@@ -1,28 +1,14 @@
package com.budwk.app.zhgh.democratic.teachercongress.delegate.listener;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.event.user.SysUserEvent;
import com.budwk.app.base.event.user.SysUserEventListener;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.models.Teacher_congress_delegate;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation_unit;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.models.Teacher_congress_session;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.service.TeacherCongressSessionService;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.service.TeacherCongressDelegateService;
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.async.Async;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import java.util.List;
/**
* @version 1.0
* @Author zzr
@@ -31,16 +17,11 @@ import java.util.List;
* @注释
*/
@IocBean
@Slf4j
public class TeacherCongressDelegateListener implements SysUserEventListener {
@Inject
private Dao dao;
@Inject
private SysUserService sysUserService;
@Inject
private SysRoleService sysRoleService;
@Inject
private TeacherCongressSessionService teacherCongressSessionService;
private TeacherCongressDelegateService teacherCongressDelegateService;
@Override
@Async
@@ -49,68 +30,11 @@ public class TeacherCongressDelegateListener implements SysUserEventListener {
return;
}
// 人员单位变更只同步当前开启届次,防止误修改历史届次代表及角色关系。
Teacher_congress_session session = dao.fetch(Teacher_congress_session.class,
Cnd.where(Teacher_congress_session::getEnable, "=", true)
.desc(Teacher_congress_session::getStartDate));
if (session == null) {
return;
try {
// 保持原有事件范围,仅将监听器内部归团逻辑下沉到事务服务。
teacherCongressDelegateService.refreshCurrentDelegateOrganization(event.getUserId());
} catch (Exception e) {
log.error("刷新教代会代表组织信息失败,userId={}", event.getUserId(), e);
}
String userId = event.getUserId();
//查询校领导的单位
ProposalConfig config = dao.fetch(ProposalConfig.class, Cnd.NEW());
List<String> schoolLeaderUnitIds = config.getSchoolLeaderUnitIds();
View_user user = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", userId));
//校领导排除在外
if (StrUtil.isNotBlank(user.getUnitId()) && schoolLeaderUnitIds.contains(user.getUnitId())) {
return;
}
//查询当前代表的信息
Teacher_congress_delegate currentDelegate = dao.fetch(Teacher_congress_delegate.class, Cnd.where(Teacher_congress_delegate::getSessionId, "=", session.getId()));
if(currentDelegate == null){
return;
}
//查询当前分配的单位属于哪个代表团
String unitId = user.getUnitId();
Teacher_congress_delegation_unit unit = dao.fetch(Teacher_congress_delegation_unit.class, Cnd.where(Teacher_congress_delegation_unit::getSessionId, "=", session)
.and(Teacher_congress_delegation_unit::getUnitId, "=", unitId));
String delegationId = unit.getDelegationId();
currentDelegate.setDelegationId(delegationId);
currentDelegate.setUnitId(user.getUnitId());
currentDelegate.setUnitName(user.getUnitName());
currentDelegate.setUnionId(user.getUnionId());
currentDelegate.setUnionName(user.getUnionName());
dao.updateIgnoreNull(currentDelegate);
//角色数据
Sys_role delegateFormalRole = sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATE_FORMAL.name());
Sys_role delegateAttendanceRole = sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATE_ATTENDANCE.name());
Sys_role delegateSpeciallyInviteRole = sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATE_SPECIALLY_INVITE.name());
Sys_role delegationHeadRole = sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATION_HEAD.name());
//删除权限
//删除角色数据
dao.clear(Sys_user_role.class, Cnd.where(Sys_user_role::getUserId, "=", userId)
.and(Sys_user_role::getRoleId, "in", List.of(delegateFormalRole.getId(), delegateAttendanceRole.getId(), delegateSpeciallyInviteRole.getId(), delegationHeadRole.getId()))
.and(Sys_user_role::getTcSessionId, "=", session.getId())
);
//再加权限
Sys_user_role sysUserRole = new Sys_user_role();
sysUserRole.setUserId(userId);
sysUserRole.setTcSessionId(session.getId());
sysUserRole.setTcDelegationId(currentDelegate.getDelegationId());
sysUserRole.setRoleId(currentDelegate.getRoleId());
teacherCongressSessionService.prepareSessionRole(sysUserRole);
dao.insert(sysUserRole);
sysUserService.clearCache();
sysRoleService.clearCache();
}
}
@@ -4,6 +4,8 @@ import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.models.Teacher_congress_delegate;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.param.TeacherCongressDelegateManagePageParam;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.param.TeacherCongressDelegateManagePublicUserParam;
import org.nutz.lang.util.NutMap;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@@ -20,4 +22,27 @@ public interface TeacherCongressDelegateService extends BaseService<Teacher_cong
void exportXlsx(TeacherCongressDelegateManagePageParam pageForm, HttpServletResponse response);
void exportDocx(TeacherCongressDelegateManagePageParam pageForm, HttpServletResponse response);
/**
* 查询当前代表团组成范围内、尚未成为本届代表的人员。
*
* @param param 届次、代表团及关键字参数
* @return 候选人员列表
*/
List<NutMap> listPublicUsers(TeacherCongressDelegateManagePublicUserParam param);
/**
* 根据系统配置的单位或分工会组成关系,为尚未归团的代表自动分配代表团。
*
* @param sessionId 届次ID
* @return 已分配、未分配数量及未分配人员名称
*/
NutMap allocateDelegations(String sessionId);
/**
* 人员组织变化后,按当前组成模式刷新其当前届次代表及角色归团信息。
*
* @param userId 用户ID
*/
void refreshCurrentDelegateOrganization(String userId);
}
@@ -12,13 +12,24 @@ import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.models.Teacher_congress_delegate;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.param.TeacherCongressDelegateManagePageParam;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.param.TeacherCongressDelegateManagePublicUserParam;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.vo.TeacherCongressDelegateExcelVO;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.models.Teacher_congress_session;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.service.TeacherCongressSessionService;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.constant.TeacherCongressDelegationCompositionMode;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation_union;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation_unit;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.service.TeacherCongressDelegationService;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
import com.budwk.app.base.exception.BaseException;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
@@ -30,6 +41,8 @@ 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.ioc.aop.Aop;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.lang.util.NutMap;
import javax.servlet.http.HttpServletResponse;
@@ -39,6 +52,8 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
@IocBean(args = {"refer:dao"})
public class TeacherCongressDelegateServiceImpl extends BaseServiceImpl<Teacher_congress_delegate> implements TeacherCongressDelegateService {
@@ -52,6 +67,139 @@ public class TeacherCongressDelegateServiceImpl extends BaseServiceImpl<Teacher_
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
@Inject
private ProposalCommonService proposalCommonService;
@Inject
private SysUserService sysUserService;
@Inject
private TeacherCongressSessionService teacherCongressSessionService;
@Inject
private TeacherCongressDelegationService teacherCongressDelegationService;
/**
* 查询当前组成模式覆盖的候选人员,并按整个届次排除已存在代表,防止一人重复加入多个代表团。
*/
@Override
public List<NutMap> listPublicUsers(TeacherCongressDelegateManagePublicUserParam param) {
TeacherCongressDelegationCompositionMode mode = teacherCongressDelegationService.getCompositionMode();
List<String> organizationIds;
if (mode == TeacherCongressDelegationCompositionMode.UNION) {
organizationIds = dao().query(Teacher_congress_delegation_union.class,
Cnd.where(Teacher_congress_delegation_union::getSessionId, "=", param.getSessionId())
.and(Teacher_congress_delegation_union::getDelegationId, "=", param.getDelegationId()))
.stream().map(Teacher_congress_delegation_union::getUnionId).toList();
} else {
organizationIds = dao().query(Teacher_congress_delegation_unit.class,
Cnd.where(Teacher_congress_delegation_unit::getSessionId, "=", param.getSessionId())
.and(Teacher_congress_delegation_unit::getDelegationId, "=", param.getDelegationId()))
.stream().map(Teacher_congress_delegation_unit::getUnitId).toList();
}
if (organizationIds.isEmpty()) {
throw new BaseException("代表团没有组成" + mode.getLabel());
}
String organizationColumn = mode == TeacherCongressDelegationCompositionMode.UNION ? "u.unionId" : "u.unitId";
Sql sql = Sqls.create("SELECT u.id,u.username AS userName,u.loginname AS loginName,u.unitName,u.unionName " +
"FROM vw_user u WHERE u.id NOT IN (SELECT userId FROM teacher_congress_delegate WHERE sessionId=@sessionId) " +
"AND " + organizationColumn + " IN (@organizationIds) " +
"AND (u.loginname LIKE @keyword OR u.username LIKE @keyword) ORDER BY u.loginname LIMIT 50");
sql.setParam("sessionId", param.getSessionId());
sql.setParam("organizationIds", organizationIds);
sql.setParam("keyword", "%" + param.getKeyWord() + "%");
return listMap(sql);
}
/**
* 为当前届次未归团代表批量解析代表团,同时刷新其届次代表角色,避免重复生成角色关系。
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public NutMap allocateDelegations(String sessionId) {
List<Teacher_congress_delegate> delegates = query(Cnd.where(Teacher_congress_delegate::getSessionId, "=", sessionId)
.and(Teacher_congress_delegate::getDelegationId, "is", null));
List<String> unassignedNames = new ArrayList<>();
int assignedCount = 0;
for (Teacher_congress_delegate delegate : delegates) {
String delegationId = teacherCongressDelegationService.resolveDelegationId(sessionId, delegate.getUnitId(), delegate.getUnionId());
if (StrUtil.isBlank(delegationId)) {
unassignedNames.add(delegate.getUserName() + "" + delegate.getLoginName() + "");
continue;
}
delegate.setDelegationId(delegationId);
updateIgnoreNull(delegate);
replaceDelegateRole(delegate);
assignedCount++;
}
sysUserService.clearCache();
return NutMap.NEW().addv("assignedCount", assignedCount)
.addv("unassignedCount", unassignedNames.size()).addv("unassignedNames", unassignedNames);
}
/**
* 人员组织变更事件只处理当前开启届次;代表身份保留,代表团负责人角色在跨团时清理。
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public void refreshCurrentDelegateOrganization(String userId) {
Teacher_congress_session session = dao().fetch(Teacher_congress_session.class,
Cnd.where(Teacher_congress_session::getEnable, "=", true).desc(Teacher_congress_session::getStartDate));
if (session == null) {
return;
}
View_user user = dao().fetch(View_user.class, Cnd.where(View_user::getId, "=", userId));
if (user == null) {
return;
}
ProposalConfig config = dao().fetch(ProposalConfig.class, Cnd.NEW());
if (config != null && config.getSchoolLeaderUnitIds() != null
&& StrUtil.isNotBlank(user.getUnitId()) && config.getSchoolLeaderUnitIds().contains(user.getUnitId())) {
return;
}
Teacher_congress_delegate delegate = fetch(Cnd.where(Teacher_congress_delegate::getSessionId, "=", session.getId())
.and(Teacher_congress_delegate::getUserId, "=", userId));
if (delegate == null) {
return;
}
String oldDelegationId = delegate.getDelegationId();
String newDelegationId = teacherCongressDelegationService.resolveDelegationId(session.getId(), user.getUnitId(), user.getUnionId());
delegate.setDelegationId(newDelegationId);
delegate.setUnitId(user.getUnitId());
delegate.setUnitName(user.getUnitName());
delegate.setUnionId(user.getUnionId());
delegate.setUnionName(user.getUnionName());
delegate.setMobile(user.getMobile());
update(delegate);
replaceDelegateRole(delegate);
if (!java.util.Objects.equals(oldDelegationId, newDelegationId)) {
clearDelegationManagerRoles(userId, session.getId());
}
sysUserService.clearCache();
sysRoleService.clearCache();
}
/** 替换代表本届次的同一身份角色,确保角色中的代表团ID与代表表一致。 */
private void replaceDelegateRole(Teacher_congress_delegate delegate) {
dao().clear(Sys_user_role.class, Cnd.where(Sys_user_role::getUserId, "=", delegate.getUserId())
.and(Sys_user_role::getRoleId, "=", delegate.getRoleId())
.and(Sys_user_role::getTcSessionId, "=", delegate.getSessionId()));
Sys_user_role role = new Sys_user_role();
role.setUserId(delegate.getUserId());
role.setRoleId(delegate.getRoleId());
role.setTcSessionId(delegate.getSessionId());
role.setTcDelegationId(delegate.getDelegationId());
teacherCongressSessionService.prepareSessionRole(role);
dao().insert(role);
}
/** 跨代表团后清理团长、副团长及联络人角色,避免保留原代表团管理权限。 */
private void clearDelegationManagerRoles(String userId, String sessionId) {
Set<String> roleIds = new HashSet<>();
roleIds.add(sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATION_HEAD).getId());
roleIds.add(sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_VICE_DELEGATION_HEAD).getId());
roleIds.add(sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATION_CONTACT).getId());
dao().clear(Sys_user_role.class, Cnd.where(Sys_user_role::getUserId, "=", userId)
.and(Sys_user_role::getTcSessionId, "=", sessionId)
.and(Sys_user_role::getRoleId, "in", roleIds));
}
@Override
public Pagination<Teacher_congress_delegate> pageData(TeacherCongressDelegateManagePageParam pageForm) {
@@ -0,0 +1,41 @@
package com.budwk.app.zhgh.democratic.teachercongress.delegation.constant;
/**
* 代表团组成模式
*
* <p>系统参数 {@code dbtzc} {@code unit} 时按单位组成
* {@code union} 时按分工会组成空值或非法值统一兼容为单位模式</p>
*/
public enum TeacherCongressDelegationCompositionMode {
UNIT("unit", "单位"),
UNION("union", "分工会");
private final String code;
private final String label;
TeacherCongressDelegationCompositionMode(String code, String label) {
this.code = code;
this.label = label;
}
public String getCode() {
return code;
}
public String getLabel() {
return label;
}
/**
* 将系统参数转换为组成模式非法配置按历史默认行为使用单位模式
*
* @param value 系统参数值
* @return 有效组成模式
*/
public static TeacherCongressDelegationCompositionMode from(String value) {
if (UNION.code.equalsIgnoreCase(value)) {
return UNION;
}
return UNIT;
}
}
@@ -170,45 +170,18 @@ public class TeacherCongressDelegationController {
@At
@SaCheckPermission("tc.delegation")
public Result partUnitTransferData(@Valid String delegationId, @Valid String sessionId) {
//找出本届次已经设置了代表团的所有单位
List<Teacher_congress_delegation_unit> delegationUnits = dao.query(Teacher_congress_delegation_unit.class, Cnd.where("sessionId", "=", sessionId));
List<String> unitIds = delegationUnits.stream().map(Teacher_congress_delegation_unit::getUnitId).toList();
//找出本代表团的单位
List<String> selectUnitIds = delegationUnits.stream().filter(unit -> unit.getDelegationId().equals(delegationId)).map(Teacher_congress_delegation_unit::getUnitId).toList();
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.orEX("id", "not in", unitIds);
seg.orEX("id", "in", selectUnitIds);
// Cnd cnd = Cnd.where("unitLevel", "=", 2);
Cnd cnd = Cnd.where("unitTypeCode", "=", "1");
if (!seg.isEmpty()) {
cnd.and(seg);
}
cnd.asc("unitcode");
List<Sys_unit> units = dao.query(Sys_unit.class, cnd);
NutMap transferData = NutMap.NEW().addv("selectUnitIds", selectUnitIds).addv("allUnits", units);
return Result.success(transferData);
NutMap data = teacherCongressDelegationService.getCompositionTransferData(sessionId, delegationId);
// 保留旧接口字段兼容未同步更新的历史页面调用
data.put("selectUnitIds", data.get("selectedIds"));
data.put("allUnits", data.get("allItems"));
return Result.success(data);
}
@At
@SaCheckPermission("tc.delegation")
@Aop(TransAop.READ_COMMITTED)
public Result partUnitSet(@Valid String delegationId, @Valid String sessionId, @Param("unitIds") String[] unitIds) {
dao.clear(Teacher_congress_delegation_unit.class, Cnd.where("delegationId", "=", delegationId).and("sessionId", "=", sessionId));
List<Teacher_congress_delegation_unit> insertData = Arrays.stream(unitIds).map(unitId -> {
Teacher_congress_delegation_unit delegationUnit = new Teacher_congress_delegation_unit();
delegationUnit.setUnitId(unitId);
delegationUnit.setDelegationId(delegationId);
delegationUnit.setSessionId(sessionId);
return delegationUnit;
}).toList();
dao.insert(insertData);
teacherCongressDelegationService.saveComposition(sessionId, delegationId, unitIds);
return Result.success();
}
@@ -222,24 +195,35 @@ public class TeacherCongressDelegationController {
@At
@SaCheckPermission("tc.delegation")
public Result partUnitPageData(@Valid PageForm pageForm, @Valid String sessionId, @Valid String delegationId) {
Sql sql = Sqls.create("""
SELECT
t2.id,
t2.`name`
FROM
teacher_congress_delegation_unit t1
LEFT JOIN sys_unit t2 ON t2.id = t1.unitId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t1.delegationId", "=", delegationId);
cnd.and("t1.sessionId", "=", sessionId);
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
cnd.where().andLike("t2.name", pageForm.getSearchKeyword());
}
sql.setCondition(cnd);
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
return Result.success(teacherCongressDelegationService.pageComposition(pageForm, sessionId, delegationId));
}
/**
* 获取当前配置模式下的代表团组成选择数据
*/
@At
@SaCheckPermission("tc.delegation")
public Result compositionTransferData(@Valid String delegationId, @Valid String sessionId) {
return Result.success(teacherCongressDelegationService.getCompositionTransferData(sessionId, delegationId));
}
/**
* 保存当前配置模式下的代表团组成关系
*/
@At
@SaCheckPermission("tc.delegation")
public Result compositionSet(@Valid String delegationId, @Valid String sessionId, @Param("itemIds") String[] itemIds) {
teacherCongressDelegationService.saveComposition(sessionId, delegationId, itemIds);
return Result.success();
}
/**
* 分页查询当前配置模式下的代表团组成关系
*/
@At
@SaCheckPermission("tc.delegation")
public Result compositionPageData(@Valid PageForm pageForm, @Valid String sessionId, @Valid String delegationId) {
return Result.success(teacherCongressDelegationService.pageComposition(pageForm, sessionId, delegationId));
}
/**
@@ -1,6 +1,9 @@
package com.budwk.app.zhgh.democratic.teachercongress.delegation.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.constant.TeacherCongressDelegationCompositionMode;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation;
import org.nutz.lang.util.NutMap;
@@ -11,6 +14,51 @@ import java.util.List;
*/
public interface TeacherCongressDelegationService extends BaseService<Teacher_congress_delegation> {
/**
* 获取当前代表团组成模式
*
* @return 单位或分工会模式
*/
TeacherCongressDelegationCompositionMode getCompositionMode();
/**
* 获取代表团组成选择器数据已被其他代表团占用的数据不会返回
*
* @param sessionId 届次ID
* @param delegationId 代表团ID
* @return 组成模式当前选中ID及可选项
*/
NutMap getCompositionTransferData(String sessionId, String delegationId);
/**
* 保存当前模式下的代表团组成关系
*
* @param sessionId 届次ID
* @param delegationId 代表团ID
* @param itemIds 单位ID或分工会ID
*/
void saveComposition(String sessionId, String delegationId, String[] itemIds);
/**
* 分页查询当前模式下的代表团组成数据
*
* @param pageForm 分页查询参数
* @param sessionId 届次ID
* @param delegationId 代表团ID
* @return 组成数据分页结果
*/
Pagination pageComposition(PageForm pageForm, String sessionId, String delegationId);
/**
* 按当前组成模式解析人员所属代表团
*
* @param sessionId 届次ID
* @param unitId 人员单位ID
* @param unionId 人员分工会ID
* @return 代表团ID未配置时返回空
*/
String resolveDelegationId(String sessionId, String unitId, String unionId);
/**
* 按角色查询代表团负责人信息
*
@@ -41,4 +89,4 @@ public interface TeacherCongressDelegationService extends BaseService<Teacher_co
* @param type 负责人角色编码
*/
void deleteHeadUser(String sessionId, String delegationId, String userId, String type);
}
}
@@ -3,15 +3,23 @@ package com.budwk.app.zhgh.democratic.teachercongress.delegation.service.impl;
import cn.hutool.core.util.StrUtil;
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.service.impl.BaseServiceImpl;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_union;
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.sys.services.SysUserService;
import com.budwk.app.zhgh.democratic.teachercongress.delegate.models.Teacher_congress_delegate;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation_union;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation_unit;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.constant.TeacherCongressDelegationCompositionMode;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.service.TeacherCongressDelegationService;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.service.TeacherCongressSessionService;
import com.budwk.app.web.commons.base.Globals;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
@@ -24,6 +32,8 @@ import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -47,6 +57,205 @@ public class TeacherCongressDelegationServiceImpl extends BaseServiceImpl<Teache
super(dao);
}
/**
* 读取代表团组成配置配置缺失或异常时沿用单位模式保证历史环境可正常使用
*
* @return 当前代表团组成模式
*/
@Override
public TeacherCongressDelegationCompositionMode getCompositionMode() {
return TeacherCongressDelegationCompositionMode.from(Globals.MyConfig.getString("dbtzc"));
}
/**
* 获取当前代表团可选择的单位或分工会排除本届次中已归属其他代表团的数据
*/
@Override
public NutMap getCompositionTransferData(String sessionId, String delegationId) {
validateDelegation(sessionId, delegationId);
TeacherCongressDelegationCompositionMode mode = getCompositionMode();
List<String> occupiedIds = new ArrayList<>();
List<String> selectedIds = new ArrayList<>();
List<NutMap> allItems = new ArrayList<>();
if (mode == TeacherCongressDelegationCompositionMode.UNION) {
List<Teacher_congress_delegation_union> relations = dao().query(Teacher_congress_delegation_union.class,
Cnd.where(Teacher_congress_delegation_union::getSessionId, "=", sessionId));
relations.forEach(relation -> {
occupiedIds.add(relation.getUnionId());
if (delegationId.equals(relation.getDelegationId())) {
selectedIds.add(relation.getUnionId());
}
});
Cnd cnd = buildAvailableCondition(occupiedIds, selectedIds);
cnd.asc(Sys_union::getUnionCode);
dao().query(Sys_union.class, cnd).forEach(item -> allItems.add(NutMap.NEW()
.addv("id", item.getId()).addv("name", item.getName()).addv("code", item.getUnionCode())));
} else {
List<Teacher_congress_delegation_unit> relations = dao().query(Teacher_congress_delegation_unit.class,
Cnd.where(Teacher_congress_delegation_unit::getSessionId, "=", sessionId));
relations.forEach(relation -> {
occupiedIds.add(relation.getUnitId());
if (delegationId.equals(relation.getDelegationId())) {
selectedIds.add(relation.getUnitId());
}
});
Cnd cnd = Cnd.where(Sys_unit::getUnitTypeCode, "=", "1");
appendAvailableCondition(cnd, occupiedIds, selectedIds);
cnd.asc(Sys_unit::getUnitcode);
dao().query(Sys_unit.class, cnd).forEach(item -> allItems.add(NutMap.NEW()
.addv("id", item.getId()).addv("name", item.getName()).addv("code", item.getUnitcode())));
}
return NutMap.NEW().addv("mode", mode.getCode()).addv("label", mode.getLabel())
.addv("selectedIds", selectedIds).addv("allItems", allItems);
}
/**
* 保存当前组成模式对应的关联表并在写入前校验跨代表团重复占用
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public void saveComposition(String sessionId, String delegationId, String[] itemIds) {
validateDelegation(sessionId, delegationId);
List<String> normalizedIds = itemIds == null ? Collections.emptyList() : Arrays.stream(itemIds)
.filter(StrUtil::isNotBlank).distinct().toList();
TeacherCongressDelegationCompositionMode mode = getCompositionMode();
if (mode == TeacherCongressDelegationCompositionMode.UNION) {
validateUnionIds(normalizedIds);
int occupied = normalizedIds.isEmpty() ? 0 : dao().count(Teacher_congress_delegation_union.class,
Cnd.where(Teacher_congress_delegation_union::getSessionId, "=", sessionId)
.and(Teacher_congress_delegation_union::getDelegationId, "!=", delegationId)
.and(Teacher_congress_delegation_union::getUnionId, "in", normalizedIds));
if (occupied > 0) {
throw new BaseException("所选分工会已被其他代表团使用,请刷新后重试");
}
dao().clear(Teacher_congress_delegation_union.class, Cnd.where(Teacher_congress_delegation_union::getSessionId, "=", sessionId)
.and(Teacher_congress_delegation_union::getDelegationId, "=", delegationId));
normalizedIds.forEach(itemId -> {
Teacher_congress_delegation_union relation = new Teacher_congress_delegation_union();
relation.setSessionId(sessionId);
relation.setDelegationId(delegationId);
relation.setUnionId(itemId);
dao().insert(relation);
});
return;
}
validateUnitIds(normalizedIds);
int occupied = normalizedIds.isEmpty() ? 0 : dao().count(Teacher_congress_delegation_unit.class,
Cnd.where(Teacher_congress_delegation_unit::getSessionId, "=", sessionId)
.and(Teacher_congress_delegation_unit::getDelegationId, "!=", delegationId)
.and(Teacher_congress_delegation_unit::getUnitId, "in", normalizedIds));
if (occupied > 0) {
throw new BaseException("所选单位已被其他代表团使用,请刷新后重试");
}
dao().clear(Teacher_congress_delegation_unit.class, Cnd.where(Teacher_congress_delegation_unit::getSessionId, "=", sessionId)
.and(Teacher_congress_delegation_unit::getDelegationId, "=", delegationId));
normalizedIds.forEach(itemId -> {
Teacher_congress_delegation_unit relation = new Teacher_congress_delegation_unit();
relation.setSessionId(sessionId);
relation.setDelegationId(delegationId);
relation.setUnitId(itemId);
dao().insert(relation);
});
}
/**
* 分页查询当前模式下的组成关系统一向前端返回 idnamecode 字段
*/
@Override
public Pagination pageComposition(PageForm pageForm, String sessionId, String delegationId) {
validateDelegation(sessionId, delegationId);
boolean unionMode = getCompositionMode() == TeacherCongressDelegationCompositionMode.UNION;
String sqlText = unionMode
? "SELECT t2.id,t2.name,t2.unionCode AS code FROM teacher_congress_delegation_union t1 LEFT JOIN sys_union t2 ON t2.id=t1.unionId $condition"
: "SELECT t2.id,t2.name,t2.unitcode AS code FROM teacher_congress_delegation_unit t1 LEFT JOIN sys_unit t2 ON t2.id=t1.unitId $condition";
Sql sql = Sqls.create(sqlText);
Cnd cnd = Cnd.where("t1.sessionId", "=", sessionId).and("t1.delegationId", "=", delegationId);
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
cnd.where().andLike("t2.name", pageForm.getSearchKeyword());
}
cnd.asc("code");
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
/**
* 按当前模式精确解析代表团同一组织存在多条关系时拒绝随机匹配避免代表被错误归团
*/
@Override
public String resolveDelegationId(String sessionId, String unitId, String unionId) {
TeacherCongressDelegationCompositionMode mode = getCompositionMode();
if (mode == TeacherCongressDelegationCompositionMode.UNION) {
if (StrUtil.isBlank(unionId)) {
return null;
}
List<Teacher_congress_delegation_union> relations = dao().query(Teacher_congress_delegation_union.class,
Cnd.where(Teacher_congress_delegation_union::getSessionId, "=", sessionId)
.and(Teacher_congress_delegation_union::getUnionId, "=", unionId));
return resolveUniqueDelegation(relations.stream().map(Teacher_congress_delegation_union::getDelegationId).toList(), "分工会");
}
if (StrUtil.isBlank(unitId)) {
return null;
}
List<Teacher_congress_delegation_unit> relations = dao().query(Teacher_congress_delegation_unit.class,
Cnd.where(Teacher_congress_delegation_unit::getSessionId, "=", sessionId)
.and(Teacher_congress_delegation_unit::getUnitId, "=", unitId));
return resolveUniqueDelegation(relations.stream().map(Teacher_congress_delegation_unit::getDelegationId).toList(), "单位");
}
private Cnd buildAvailableCondition(List<String> occupiedIds, List<String> selectedIds) {
Cnd cnd = Cnd.NEW();
appendAvailableCondition(cnd, occupiedIds, selectedIds);
return cnd;
}
/** 当前代表团已选项允许继续显示,其余已占用项从选择器中排除。 */
private void appendAvailableCondition(Cnd cnd, List<String> occupiedIds, List<String> selectedIds) {
if (occupiedIds.isEmpty()) {
return;
}
if (selectedIds.isEmpty()) {
cnd.and("id", "not in", occupiedIds);
return;
}
cnd.and(Cnd.exps("id", "not in", occupiedIds).or("id", "in", selectedIds));
}
/** 校验代表团确实属于当前届次,防止跨届次写入组成关系。 */
private void validateDelegation(String sessionId, String delegationId) {
if (dao().count(Teacher_congress_delegation.class, Cnd.where(Teacher_congress_delegation::getId, "=", delegationId)
.and(Teacher_congress_delegation::getSessionId, "=", sessionId)) != 1) {
throw new BaseException("代表团或届次参数错误");
}
}
/** 校验提交的分工会ID均真实存在。 */
private void validateUnionIds(List<String> ids) {
if (!ids.isEmpty() && dao().count(Sys_union.class, Cnd.where(Sys_union::getId, "in", ids)) != ids.size()) {
throw new BaseException("所选分工会数据不存在,请刷新后重试");
}
}
/** 校验提交的单位ID均真实存在且属于代表团可用的单位类型。 */
private void validateUnitIds(List<String> ids) {
if (!ids.isEmpty() && dao().count(Sys_unit.class, Cnd.where(Sys_unit::getId, "in", ids)
.and(Sys_unit::getUnitTypeCode, "=", "1")) != ids.size()) {
throw new BaseException("所选单位数据不存在,请刷新后重试");
}
}
/** 对组织与代表团关系执行唯一性校验。 */
private String resolveUniqueDelegation(List<String> delegationIds, String label) {
if (delegationIds.isEmpty()) {
return null;
}
if (delegationIds.size() > 1) {
throw new BaseException(label + "存在重复代表团关系,请先检查代表团组成配置");
}
return delegationIds.get(0);
}
/**
* 按角色查询代表团负责人信息副团长允许返回多条记录以兼容V3多副团长数据
*
@@ -22,6 +22,7 @@ import com.budwk.app.zhgh.democratic.teachercongress.delegate.models.Teacher_con
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation_union;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation_unit;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.service.TeacherCongressDelegationService;
import com.budwk.app.zhgh.democratic.teachercongress.institution.models.Teacher_congress_institution;
import com.budwk.app.zhgh.democratic.teachercongress.institution.models.Teacher_congress_institution_user;
import com.budwk.app.zhgh.democratic.teachercongress.meetings.models.Teacher_congress_meeting;
@@ -57,6 +58,8 @@ public class TeacherCongressSessionServiceImpl extends BaseServiceImpl<Teacher_c
private SysRoleService sysRoleService;
@Inject
private SysUserService sysUserService;
@Inject
private TeacherCongressDelegationService teacherCongressDelegationService;
public TeacherCongressSessionServiceImpl(Dao dao) {
super(dao);
@@ -237,22 +240,9 @@ public class TeacherCongressSessionServiceImpl extends BaseServiceImpl<Teacher_c
newDelegate.setSex(vwUser.getSex());
newDelegate.setMobile(vwUser.getMobile());
//去查询他当前所处的单位分工会处于哪个代表团
if (StrUtil.isNotBlank(vwUser.getUnionId())) {
Teacher_congress_delegation_union delegationUnion = dao().fetch(Teacher_congress_delegation_union.class, Cnd.where(Teacher_congress_delegation_union::getSessionId, "=", session.getId())
.and(Teacher_congress_delegation_union::getUnionId, "=", vwUser.getUnionId()));
if (ObjectUtil.isNotEmpty(delegationUnion)) {
newDelegate.setDelegationId(delegationUnion.getDelegationId());
}
}
if (StrUtil.isNotBlank(vwUser.getUnitId())) {
Teacher_congress_delegation_unit delegationUnit = dao().fetch(Teacher_congress_delegation_unit.class, Cnd.where(Teacher_congress_delegation_unit::getSessionId, "=", session.getId())
.and(Teacher_congress_delegation_unit::getUnitId, "=", vwUser.getUnitId()));
if (ObjectUtil.isNotEmpty(delegationUnit)) {
newDelegate.setDelegationId(delegationUnit.getDelegationId());
}
}
// 延用代表时严格按 dbtzc 当前模式归团避免单位关系覆盖分工会关系
newDelegate.setDelegationId(teacherCongressDelegationService.resolveDelegationId(
session.getId(), vwUser.getUnitId(), vwUser.getUnionId()));
}
// 以代表团编码判断是否发生代表团异动并完整保存延用前后的组织信息
@@ -5,6 +5,7 @@ import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
@@ -16,10 +17,13 @@ import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.models.Sys_user_history;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
import com.budwk.app.zhgh.staffmanage.member.param.MemberBatchMakeParam;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberInfoPageForm;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberStatisticsPageForm;
@@ -42,11 +46,9 @@ import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @version 1.0
@@ -132,6 +134,25 @@ public class MemberBatchMakeController {
}).toList();
dao.insert(roleList);
// 添加人员变更记录
String MemberChangeTypeName = MemberChangeType.RESTORE.name();
final Date date = new Date();
List<Sys_user> sysUsers = dao.query(Sys_user.class, Cnd.where("id", "in", userIds));
List<Sys_user_history> sysUserHistoryStream = sysUsers.stream().map(e -> {
Sys_user_history sysUserHistory = new Sys_user_history();
BeanUtil.copyProperties(e, sysUserHistory);
sysUserHistory.setChangeTypes(List.of(MemberChangeTypeName));
sysUserHistory.setChangeTime(date);
NutMap change = NutMap.NEW();
change.put("fieldName", "会员状态");
change.put("field", "member");
change.put("sourceValue", "");
change.put("newValue", "");
sysUserHistory.setChangeInfos(List.of(change));
sysUserHistory.setChangeOrigin(MemberChangeOrigin.HAND_MOVEMENT.name());
return sysUserHistory;
}).collect(Collectors.toList());
dao.insert(sysUserHistoryStream);
return Result.success();
}