Merge branch 'main' into feature_活动电子档案
# Conflicts: # src/main/resources/views/platform/zhgh/archive/docType/index.html # src/main/resources/views/platform/zhgh/archive/filing/index.html # src/main/resources/views/platform/zhgh/archive/project/index.html
This commit is contained in:
@@ -12,6 +12,8 @@ import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.dao.util.cri.Static;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
@@ -51,7 +53,8 @@ public class FlowTodoCenterController {
|
||||
t.h5FormKey,
|
||||
t.createdAt,
|
||||
t.finishTime,
|
||||
t.variable,
|
||||
t.variable AS taskVariable,
|
||||
ins.variable,
|
||||
ins.state AS instanceState,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo,
|
||||
@@ -66,7 +69,14 @@ public class FlowTodoCenterController {
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
// 普通待办仍按进行中任务查询;提案进入团长审核后,补充展示尚未附议的已废弃 second 任务。
|
||||
SqlExpressionGroup todoTaskGroup = Cnd.exps("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
SqlExpressionGroup proposalSecondGroup = Cnd.exps("t.taskState", "=", ProcessTaskStateEnum.ABANDON.getCode())
|
||||
.and("t.taskName", "=", "second")
|
||||
.and(new Static("EXISTS (SELECT 1 FROM proposal_second ps WHERE ps.proposalId = ins.businessNo AND ps.seconderId = ta.actorId AND ps.isAgree IS NULL)"))
|
||||
.and(new Static("EXISTS (SELECT 1 FROM wf_process_task dt WHERE dt.processInstanceId = t.processInstanceId AND dt.taskName = 'delegation' AND dt.taskState = 10)"));
|
||||
todoTaskGroup.or(proposalSecondGroup);
|
||||
cnd.and(todoTaskGroup);
|
||||
cnd.and("ta.actorId", "=", SecurityUtil.getUserId());
|
||||
cnd.andEX("def.category", "=", category);
|
||||
if (StrUtil.isNotBlank(searchKeyword)) {
|
||||
@@ -96,7 +106,8 @@ public class FlowTodoCenterController {
|
||||
t.h5FormKey,
|
||||
t.createdAt,
|
||||
t.finishTime,
|
||||
t.variable,
|
||||
t.variable AS taskVariable,
|
||||
ins.variable,
|
||||
ins.state AS instanceState,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo,
|
||||
@@ -223,7 +234,27 @@ public class FlowTodoCenterController {
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
WHERE
|
||||
ta.actorId = @userId
|
||||
AND t.taskState = 10
|
||||
AND (
|
||||
t.taskState = 10
|
||||
OR (
|
||||
t.taskState = 99
|
||||
AND t.taskName = 'second'
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM proposal_second ps
|
||||
WHERE ps.proposalId = (SELECT businessNo FROM wf_process_instance WHERE id = t.processInstanceId)
|
||||
AND ps.seconderId = ta.actorId
|
||||
AND ps.isAgree IS NULL
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM wf_process_task dt
|
||||
WHERE dt.processInstanceId = t.processInstanceId
|
||||
AND dt.taskName = 'delegation'
|
||||
AND dt.taskState = 10
|
||||
)
|
||||
)
|
||||
)
|
||||
""");
|
||||
todoSql.setParam("userId", SecurityUtil.getUserId());
|
||||
todoSql.setCallback(Sqls.callback.integer());
|
||||
|
||||
@@ -6,7 +6,9 @@ import lombok.Setter;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Id;
|
||||
import org.nutz.dao.entity.annotation.Index;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableIndexes;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
@@ -22,6 +24,9 @@ import java.util.Date;
|
||||
@Getter
|
||||
@Setter
|
||||
@Table("wf_process_instance")
|
||||
@TableIndexes({
|
||||
@Index(name = "INDEX_WF_PROCESS_INSTANCE_BUSINESS_NO", fields = {"businessNo"}, unique = false)
|
||||
})
|
||||
@Comment("流程实例")
|
||||
public class ProcessInstance extends BaseModel {
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@ import lombok.Setter;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Id;
|
||||
import org.nutz.dao.entity.annotation.Index;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableIndexes;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
@@ -19,6 +21,9 @@ import java.util.Date;
|
||||
@Getter
|
||||
@Setter
|
||||
@Table("wf_process_task")
|
||||
@TableIndexes({
|
||||
@Index(name = "INDEX_WF_PROCESS_TASK_INSTANCE_STATE", fields = {"processInstanceId", "taskState"}, unique = false)
|
||||
})
|
||||
@Comment("流程任务")
|
||||
public class ProcessTask extends BaseModel {
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -154,10 +154,15 @@ public class SysHomeController {
|
||||
.and(Sys_menu::getPlatform, "=", platform)
|
||||
);
|
||||
List<Sys_menu> menus = sysUserService.getMenus(SecurityUtil.getUserId());
|
||||
List<String> allMenuIds = menus.stream().map(Sys_menu::getId).toList();
|
||||
Set<String> allMenuIds = menus.stream().map(Sys_menu::getId).collect(Collectors.toSet());
|
||||
Set<String> allParentMenuIds = menus.stream()
|
||||
.map(Sys_menu::getParentId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
List<Sys_menu> sysMenus = list.stream()
|
||||
// 推荐项必须同时属于当前用户已授权菜单,避免首页展示无权限入口。
|
||||
.filter(menu -> allMenuIds.contains(menu.getId()))
|
||||
// 应用有已授权子菜单,或根菜单自身有链接且已授权时,才允许在首页展示入口。
|
||||
.filter(menu -> allParentMenuIds.contains(menu.getId())
|
||||
|| (StrUtil.isNotBlank(menu.getHref()) && allMenuIds.contains(menu.getId())))
|
||||
.sorted(Comparator.comparing(Sys_menu::getLocation, Comparator.nullsLast(Integer::compareTo))
|
||||
.thenComparing(Sys_menu::getId))
|
||||
.toList();
|
||||
@@ -175,7 +180,7 @@ public class SysHomeController {
|
||||
.and(Sys_menu::getPlatform, "=", platform)
|
||||
);
|
||||
List<Sys_menu> menus = sysUserService.getMenus(SecurityUtil.getUserId());
|
||||
List<String> allMenuIds = menus.stream().map(Sys_menu::getId).toList();
|
||||
Set<String> allMenuIds = menus.stream().map(Sys_menu::getId).collect(Collectors.toSet());
|
||||
List<Sys_menu> sysMenus = list.stream()
|
||||
// 推荐项必须同时属于当前用户已授权菜单,避免首页展示无权限入口。
|
||||
.filter(menu -> allMenuIds.contains(menu.getId()))
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.sys.models.Sys_menu;
|
||||
import com.budwk.app.sys.models.Sys_module;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
@@ -23,6 +24,8 @@ import org.nutz.dao.FieldFilter;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.Daos;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
@@ -120,6 +123,7 @@ public class SysRoleController {
|
||||
@Ok("json:full")
|
||||
@SaCheckPermission("sys.manager.role")
|
||||
public Object pageData(@Param("searchUnit") String searchUnit,
|
||||
@Param("moduleId") String moduleId,
|
||||
@Param("searchName") String searchName,
|
||||
@Param("searchKeyword") String searchKeyword,
|
||||
@Param("searchName2") String searchName2,
|
||||
@@ -130,9 +134,10 @@ public class SysRoleController {
|
||||
try {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
role.*
|
||||
role.*, module.name AS moduleName
|
||||
FROM
|
||||
sys_role role
|
||||
LEFT JOIN sys_module module ON module.id = role.moduleId
|
||||
LEFT JOIN sys_user_role ur ON role.id = ur.roleId
|
||||
LEFT JOIN sys_user u ON u.id = ur.userId
|
||||
$condition
|
||||
@@ -163,6 +168,9 @@ public class SysRoleController {
|
||||
if (StrUtil.isAllNotBlank(searchName2, searchKeyword2)) {
|
||||
cnd.and("u." + searchName2, "like", "%" + searchKeyword2 + "%");
|
||||
}
|
||||
if (StrUtil.isNotBlank(moduleId)) {
|
||||
cnd.and("role.moduleId", "=", moduleId);
|
||||
}
|
||||
if (Strings.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
|
||||
cnd.orderBy(pageOrderName, PageUtil.getOrder(pageOrderBy));
|
||||
} else {
|
||||
@@ -287,8 +295,13 @@ public class SysRoleController {
|
||||
@Ok("json")
|
||||
@SaCheckPermission("sys.manager.role.add")
|
||||
@SLog(tag = "添加角色", msg = "角色名称:${args[1].name}")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object addDo(@Param("..") Sys_role role, HttpServletRequest req) {
|
||||
try {
|
||||
// 所属模块只允许选择已配置的 PC 端模块,避免角色关联无效或 H5 模块。
|
||||
if (!isPcModule(role.getModuleId())) {
|
||||
return Result.error("请选择所属模块");
|
||||
}
|
||||
int num = sysRoleService.count(Cnd.where("code", "=", role.getCode().trim()));
|
||||
if (num > 0) {
|
||||
return Result.error("角色编码已存在");
|
||||
@@ -360,8 +373,13 @@ public class SysRoleController {
|
||||
@Ok("json")
|
||||
@SaCheckPermission("sys.manager.role.edit")
|
||||
@SLog(tag = "修改角色", msg = "角色名称:${args[0].name}")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object editDo(@Param("..") Sys_role role, HttpServletRequest req) {
|
||||
try {
|
||||
// 编辑时同样校验模块,保证历史角色补录后始终关联有效 PC 模块。
|
||||
if (!isPcModule(role.getModuleId())) {
|
||||
return Result.error("请选择所属模块");
|
||||
}
|
||||
Sys_role oldRole = sysRoleService.fetch(role.getId());
|
||||
if (oldRole != null && !Strings.sBlank(oldRole.getCode()).equalsIgnoreCase(role.getCode())) {
|
||||
int num = sysRoleService.count(Cnd.where("code", "=", role.getCode().trim()));
|
||||
@@ -401,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) {
|
||||
@@ -503,24 +520,42 @@ public class SysRoleController {
|
||||
cnd.and(Cnd.exps("parentId", "is", null).or("parentId", "=", ""));
|
||||
return Result.success(Daos.ext(sysRoleService.dao(), fieldFilter).query(Sys_menu.class, cnd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询角色可选择的 PC 端模块。
|
||||
*
|
||||
* @return PC 端模块列表,按模块排序编号升序返回,元素包含模块 ID 和模块名称
|
||||
*/
|
||||
@At
|
||||
@Ok("json:full")
|
||||
@SaCheckPermission("sys.manager.role")
|
||||
public Result listModule() {
|
||||
List<Sys_module> modules = sysRoleService.dao().query(Sys_module.class,
|
||||
Cnd.where(Sys_module::getPlatform, "=", "PC").asc(Sys_module::getSortNum));
|
||||
return Result.success(modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验所属模块是否存在且属于 PC 平台。
|
||||
*
|
||||
* @param moduleId 模块主键,必须来自 sys_module 的 PC 端模块记录
|
||||
* @return 模块有效时返回 true,否则返回 false
|
||||
*/
|
||||
private boolean isPcModule(String moduleId) {
|
||||
if (StrUtil.isBlank(moduleId)) {
|
||||
return false;
|
||||
}
|
||||
Sys_module module = sysRoleService.dao().fetch(Sys_module.class, moduleId);
|
||||
return module != null && "PC".equals(module.getPlatform());
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("json:full")
|
||||
@SaCheckLogin
|
||||
public Result getRoleNames(){
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
GROUP_CONCAT(DISTINCT sr.`name`) roleNames
|
||||
FROM
|
||||
`sys_user_role` sur
|
||||
LEFT JOIN sys_role sr ON sr.id = sur.roleId
|
||||
WHERE
|
||||
sur.userId = @userId
|
||||
ORDER BY
|
||||
sr.sort DESC
|
||||
""").setParam("userId", SecurityUtil.getUserId());
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
sysRoleService.dao().execute(sql);
|
||||
return Result.success(sql.getResult());
|
||||
// 首页身份与菜单、接口权限使用同一启用角色集合。
|
||||
String roleNames = sysUserService.getEnabledRoleNames(SecurityUtil.getUserId());
|
||||
return Result.success(NutMap.NEW().addv("roleNames", roleNames));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,8 @@ public class SysSignatureController {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result update(@Param("file") TempFile tempFile) {
|
||||
String url = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), tempFile);
|
||||
Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class);
|
||||
// 签字记录必须按当前登录用户读取,避免后续用户更新时覆盖其他用户的签字。
|
||||
Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class, Cnd.where(Sys_user_signature::getUserId, "=", SecurityUtil.getUserId()));
|
||||
if (ObjectUtil.isNull(sysUserSignature)) {
|
||||
sysUserSignature = new Sys_user_signature();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNode;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
@@ -263,7 +265,7 @@ public class SysUnionController {
|
||||
if (Lang.isEmpty(branchUnionRoles)) {
|
||||
return Result.success();
|
||||
}
|
||||
List<String> branchUnionRoleCodes = branchUnionRoles.stream().map(Sys_dict::getCode).toList();
|
||||
List<String> branchUnionRoleCodes = getBranchUnionRoleCodes(branchUnionRoles);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -338,7 +340,7 @@ public class SysUnionController {
|
||||
if (Lang.isEmpty(branchUnionRoles)) {
|
||||
return Result.success(List.of());
|
||||
}
|
||||
List<String> branchUnionRoleCodes = branchUnionRoles.stream().map(Sys_dict::getCode).toList();
|
||||
List<String> branchUnionRoleCodes = getBranchUnionRoleCodes(branchUnionRoles);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
@@ -371,6 +373,41 @@ public class SysUnionController {
|
||||
return Result.success(usedJCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分工会干部角色选项,并补充按单位授权的二级党委书记角色。
|
||||
*
|
||||
* @return 角色编码和名称
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union.branchOfficer")
|
||||
public Result branchUnionRoleOptions() {
|
||||
List<NutMap> roleOptions = sysDictService.getSubListByCode("BRANCH_UNION_ROLES").stream()
|
||||
.map(item -> NutMap.NEW().addv("code", item.getCode()).addv("name", item.getName()))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
if (sysRoleService.getByCode(RoleConstant.UNIT_PARTY_SECRETARY) != null
|
||||
&& roleOptions.stream().noneMatch(item -> RoleConstant.UNIT_PARTY_SECRETARY.name().equals(item.getString("code")))) {
|
||||
roleOptions.add(NutMap.NEW().addv("code", RoleConstant.UNIT_PARTY_SECRETARY.name()).addv("name", "二级党委书记"));
|
||||
}
|
||||
return Result.success(roleOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前分工会可配置二级党委书记的组成单位。
|
||||
*
|
||||
* @param unionId 分工会ID
|
||||
* @return 当前分工会的二级单位
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union.branchOfficer")
|
||||
public Result branchUnionPartySecretaryUnitOptions(String unionId) {
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
return Result.error("分工会参数不能为空");
|
||||
}
|
||||
List<Sys_unit> units = dao.query(Sys_unit.class, Cnd.where("unionId", "=", unionId)
|
||||
.and("unitLevel", "=", 2).asc("unitcode"));
|
||||
return Result.success(units);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union.branchOfficer")
|
||||
@ApiOperation("添加分工会人员角色")
|
||||
@@ -419,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);
|
||||
|
||||
@@ -433,14 +476,83 @@ 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
|
||||
* @param unitIds 组成单位ID集合
|
||||
* @param j 届次
|
||||
* @return 处理结果
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("sys.manager.union.branchOfficer")
|
||||
@ApiOperation("添加二级党委书记角色")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result insertBranchUnionPartySecretaryRole(String userId, String unionId, @Param("unitIds") String[] unitIds, String j) {
|
||||
if (StrUtil.isBlank(userId) || StrUtil.isBlank(unionId) || Lang.isEmpty(unitIds)) {
|
||||
return Result.error("人员、分工会和所属单位不能为空");
|
||||
}
|
||||
Sys_role role = sysRoleService.getByCode(RoleConstant.UNIT_PARTY_SECRETARY);
|
||||
if (role == null) {
|
||||
return Result.error("未配置二级党委书记角色");
|
||||
}
|
||||
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", userId));
|
||||
if (user == null || !unionId.equals(user.getUnionId())) {
|
||||
return Result.error("所选人员不属于当前分工会");
|
||||
}
|
||||
List<String> distinctUnitIds = java.util.Arrays.stream(unitIds)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
List<Sys_unit> units = dao.query(Sys_unit.class, Cnd.where("id", "in", distinctUnitIds)
|
||||
.and("unionId", "=", unionId).and("unitLevel", "=", 2));
|
||||
if (units.size() != distinctUnitIds.size()) {
|
||||
return Result.error("所属单位包含非当前分工会的单位");
|
||||
}
|
||||
int roleCount = dao.count(Sys_user_role.class, Cnd.where("roleId", "=", role.getId())
|
||||
.and("userId", "=", userId).and("unionId", "=", unionId));
|
||||
if (roleCount > 0) {
|
||||
return Result.error("该人员已设置二级党委书记,请先删除后再重新设置");
|
||||
}
|
||||
|
||||
Sys_union_cadre unionCadre = new Sys_union_cadre();
|
||||
unionCadre.setUserId(userId);
|
||||
unionCadre.setUnionId(unionId);
|
||||
unionCadre.setMobile(user.getMobile());
|
||||
unionCadre.setUnionName(user.getUnionName());
|
||||
unionCadre.setLoginName(user.getLoginname());
|
||||
unionCadre.setUserName(user.getUsername());
|
||||
unionCadre.setRoleCode(RoleConstant.UNIT_PARTY_SECRETARY.name());
|
||||
unionCadre.setJ(j);
|
||||
unionCadre.setApplyDate(new Date());
|
||||
unionCadre.setIsServing(true);
|
||||
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();
|
||||
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);
|
||||
List<ProcessTask> doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null);
|
||||
for (ProcessTask task : doingTaskList) {
|
||||
flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -504,23 +616,34 @@ public class SysUnionController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字典维护的分工会角色与单位级二级党委书记角色合并为列表查询范围。
|
||||
*/
|
||||
private List<String> getBranchUnionRoleCodes(List<Sys_dict> branchUnionRoles) {
|
||||
List<String> roleCodes = new ArrayList<>(branchUnionRoles.stream().map(Sys_dict::getCode).toList());
|
||||
if (sysRoleService.getByCode(RoleConstant.UNIT_PARTY_SECRETARY) != null
|
||||
&& !roleCodes.contains(RoleConstant.UNIT_PARTY_SECRETARY.name())) {
|
||||
roleCodes.add(RoleConstant.UNIT_PARTY_SECRETARY.name());
|
||||
}
|
||||
return roleCodes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询当前分工会的组成单位。
|
||||
*
|
||||
* @param pageForm 分页和查询参数;pageNumber 为页码,pageSize 为每页条数,searchKeyword 为单位编码或名称
|
||||
* @param unionId 分工会ID,不能为空
|
||||
* @return Result;data 为 Pagination,list 是当前页单位列表,totalCount 是符合条件的单位总数
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("分工会组成单位分页")
|
||||
@SaCheckPermission("sys.manager.union")
|
||||
public Result branchUnionPartUnitPageData(PageForm pageForm, String unionId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("unionId", "=", unionId);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.orLike("`name`", pageForm.getSearchKeyword());
|
||||
seg.orLike("unitcode", pageForm.getSearchKeyword());
|
||||
cnd.and(seg);
|
||||
public Result branchUnionPartUnitPageData(@Valid PageForm pageForm, String unionId) {
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
return Result.error("分工会参数不能为空");
|
||||
}
|
||||
cnd.desc("unitcode");
|
||||
|
||||
List<Sys_unit> list = dao.query(Sys_unit.class, cnd);
|
||||
return Result.success(list);
|
||||
return Result.success(sysUnitService.pageBranchUnionPartUnits(pageForm, unionId));
|
||||
}
|
||||
|
||||
@At
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.sys.controller.v4;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
@@ -50,6 +51,7 @@ public class SysV4MsgController {
|
||||
m.title,
|
||||
m.content,
|
||||
m.type,
|
||||
m.sendTime,
|
||||
r.isRead,
|
||||
r.readTime
|
||||
FROM
|
||||
@@ -69,6 +71,10 @@ public class SysV4MsgController {
|
||||
|
||||
|
||||
cnd.andEX("m.type", "=", type);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
String keyword = "%" + pageForm.getSearchKeyword() + "%";
|
||||
cnd.and(Cnd.exps("m.title", "like", keyword).or("m.content", "like", keyword));
|
||||
}
|
||||
cnd.desc("m.sendTime");
|
||||
sql.setCondition(cnd);
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package com.budwk.app.sys.interceptor;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.FlowInterceptor;
|
||||
import com.budwk.app.flow.engine.core.Execution;
|
||||
@@ -13,6 +17,9 @@ import com.budwk.app.sys.services.SysUserService;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author FKY
|
||||
@@ -35,14 +42,37 @@ public class SysUnionSchoolAuditInterceptor implements FlowInterceptor {
|
||||
SysUserService sysUserService = ServiceContext.find(SysUserService.class);
|
||||
|
||||
// 表单数据
|
||||
Sys_union_cadre unionBean = JSONUtil.toBean(formDataStr, Sys_union_cadre.class);
|
||||
JSONObject formData = JSONUtil.parseObj(formDataStr);
|
||||
Sys_union_cadre unionBean = JSONUtil.toBean(formData, Sys_union_cadre.class);
|
||||
|
||||
// 清除对应角色然后再新增
|
||||
Sys_role role = sysRoleService.getByCode(unionBean.getRoleCode());
|
||||
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId())
|
||||
.and("userId", "=", unionBean.getUserId()).and("unionId", "=", unionBean.getUnionId()));
|
||||
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId())
|
||||
.add("userId", unionBean.getUserId()).add("unionId", unionBean.getUnionId()));
|
||||
if (RoleConstant.UNIT_PARTY_SECRETARY.name().equals(unionBean.getRoleCode())) {
|
||||
// 二级党委书记按申请中选定的单位分别授权,保障流程可按申请人所属单位找到办理人。
|
||||
JSONArray unitIdArray = formData.getJSONArray("unitIds");
|
||||
List<String> unitIds = new ArrayList<>();
|
||||
if (unitIdArray != null) {
|
||||
for (Object unitId : unitIdArray) {
|
||||
String value = StrUtil.toString(unitId);
|
||||
if (StrUtil.isNotBlank(value) && !unitIds.contains(value)) {
|
||||
unitIds.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unitIds.isEmpty()) {
|
||||
throw new IllegalArgumentException("二级党委书记未选择所属单位");
|
||||
}
|
||||
for (String unitId : unitIds) {
|
||||
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId())
|
||||
.add("userId", unionBean.getUserId()).add("unionId", unionBean.getUnionId()).add("unitId", unitId));
|
||||
}
|
||||
} else {
|
||||
// 其他分工会角色保持原有按分工会单条授权的逻辑。
|
||||
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId())
|
||||
.add("userId", unionBean.getUserId()).add("unionId", unionBean.getUnionId()));
|
||||
}
|
||||
|
||||
// 清除缓存
|
||||
sysRoleService.clearCache();
|
||||
|
||||
@@ -60,7 +60,7 @@ public class Sys_log extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Comment("请求结果")
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
@ColDefine(customType = "MEDIUMTEXT")
|
||||
private String param;
|
||||
|
||||
@Column
|
||||
|
||||
@@ -45,6 +45,11 @@ public class Sys_role extends BaseModel implements Serializable {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unitid;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("所属模块ID")
|
||||
private String moduleId;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||
private String note;
|
||||
|
||||
@@ -211,6 +211,12 @@ public class Sys_user extends BaseModel implements Serializable {
|
||||
@DataCenterColumn(name = "教职工类别码", key = "RYLX", dict = "USER_PERSON_TYPE")
|
||||
private String personType;
|
||||
|
||||
@Column
|
||||
@Comment("待确认状态:0不用确认、1待确认、2已确认")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
@Default("0")
|
||||
private Integer pendingConfirmStatus;
|
||||
|
||||
@Column
|
||||
@Comment("编制类别码")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
|
||||
@@ -16,6 +16,15 @@ public class Sys_user_role {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 用户角色关系是否启用。普通角色默认启用,教代会届次切换时按届次统一刷新。
|
||||
*/
|
||||
@Column
|
||||
@Comment("是否启用:1启用,0禁用")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean enable = true;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unitId;
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
@@ -7,6 +9,15 @@ import com.budwk.app.sys.models.Sys_unit;
|
||||
* Created by wizzer on 2016/12/22.
|
||||
*/
|
||||
public interface SysUnitService extends BaseService<Sys_unit> {
|
||||
/**
|
||||
* 分页查询指定分工会的组成单位。
|
||||
*
|
||||
* @param pageForm 分页和查询参数;pageNumber 为页码,pageSize 为每页条数,searchKeyword 为单位编码或名称
|
||||
* @param unionId 分工会ID,用于限制只查询当前分工会的组成单位
|
||||
* @return 分页结果;list 为当前页单位数据,totalCount 为符合条件的单位总数
|
||||
*/
|
||||
Pagination<Sys_unit> pageBranchUnionPartUnits(PageForm pageForm, String unionId);
|
||||
|
||||
/**
|
||||
* 保存单位
|
||||
*
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.exception.UnknownAccountException;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.sys.models.Sys_menu;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -31,6 +32,21 @@ public interface SysUserService extends BaseService<Sys_user> {
|
||||
*/
|
||||
List<String> getRoleCodeList(Sys_user user);
|
||||
|
||||
/**
|
||||
* 查询用户当前启用的角色关系对应角色,供菜单、接口权限和首页身份统一使用。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 当前启用且角色本身未禁用的角色列表
|
||||
*/
|
||||
List<Sys_role> getEnabledRoles(String userId);
|
||||
|
||||
/**
|
||||
* 查询用户当前启用角色的显示名称。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 去重并按角色顺序排列的角色名称
|
||||
*/
|
||||
String getEnabledRoleNames(String userId);
|
||||
|
||||
/**
|
||||
* 获取用户的菜单
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,12 @@ import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -50,6 +53,10 @@ import java.util.stream.Collectors;
|
||||
@IocBean
|
||||
public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService {
|
||||
private static final int BATCH_SIZE = 500;
|
||||
/** 不需要人工确认。 */
|
||||
private static final int PENDING_CONFIRM_STATUS_NONE = 0;
|
||||
/** 数据源缺失,等待人工确认。 */
|
||||
private static final int PENDING_CONFIRM_STATUS_PENDING = 1;
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@@ -154,6 +161,10 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
for (Sys_user_source source : sources) {
|
||||
Sys_user user = userMap.get(source.getLoginname());
|
||||
source.setMember(null);
|
||||
String unitId = source.getUnitId();
|
||||
if (StringUtils.isNotBlank(unitId) && unitId.length() == 5) {
|
||||
source.setUnitId(unitId.substring(0, 3));
|
||||
}
|
||||
|
||||
// 创建用户对象
|
||||
Sys_user u = new Sys_user();
|
||||
@@ -174,7 +185,7 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
* 全量更新已有用户时置空,避免 updateIgnoreNull 把已迁移的基金会员标识覆盖为非会员。
|
||||
*/
|
||||
u.setAidFundMember(null);
|
||||
|
||||
u.setPersonType(null);
|
||||
needDoUpdateList.add(u);
|
||||
}
|
||||
|
||||
@@ -346,6 +357,12 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
RoleEventPublisher.broadcast(new RoleEventMsg(unitId, RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name(), RoleEventMsg.RENEW_ROLE));
|
||||
}
|
||||
|
||||
/*
|
||||
* 所有异步用户更新完成后再校正待确认状态,避免主事务提前锁定 sys_user,
|
||||
* 导致异步更新线程等待主事务释放行锁而形成相互等待。
|
||||
*/
|
||||
reconcilePendingConfirmStatus(updateParam.getPullTime());
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("全量更新用户数据完成,耗时: {} 毫秒", (endTime - startTime));
|
||||
|
||||
@@ -356,6 +373,49 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
||||
+ " 条";
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定批次的完整数据源校正系统用户待确认状态。
|
||||
* 已人工确认且仍未重新出现的人员保持已确认状态,避免每次全量更新重复转为待确认。
|
||||
*
|
||||
* @param pullTime 本次全量数据的拉取时间
|
||||
*/
|
||||
private void reconcilePendingConfirmStatus(String pullTime) {
|
||||
Sql resetStatusSql = Sqls.create("""
|
||||
UPDATE sys_user userInfo
|
||||
SET userInfo.pendingConfirmStatus = @noneStatus
|
||||
WHERE userInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
AND userInfo.pendingConfirmStatus <> @noneStatus
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_source sourceInfo
|
||||
WHERE sourceInfo.pullTime = @pullTime
|
||||
AND sourceInfo.loginname = userInfo.loginname
|
||||
AND sourceInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
)
|
||||
""");
|
||||
resetStatusSql.setParam("noneStatus", PENDING_CONFIRM_STATUS_NONE);
|
||||
resetStatusSql.setParam("pullTime", pullTime);
|
||||
dao.execute(resetStatusSql);
|
||||
|
||||
Sql pendingStatusSql = Sqls.create("""
|
||||
UPDATE sys_user userInfo
|
||||
SET userInfo.pendingConfirmStatus = @pendingStatus
|
||||
WHERE userInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
AND IFNULL(userInfo.pendingConfirmStatus, @noneStatus) = @noneStatus
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_source sourceInfo
|
||||
WHERE sourceInfo.pullTime = @pullTime
|
||||
AND sourceInfo.loginname = userInfo.loginname
|
||||
AND sourceInfo.personType IN ('教职工', '劳务派遣人员')
|
||||
)
|
||||
""");
|
||||
pendingStatusSql.setParam("pendingStatus", PENDING_CONFIRM_STATUS_PENDING);
|
||||
pendingStatusSql.setParam("noneStatus", PENDING_CONFIRM_STATUS_NONE);
|
||||
pendingStatusSql.setParam("pullTime", pullTime);
|
||||
dao.execute(pendingStatusSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建变更的历史数据
|
||||
*
|
||||
|
||||
@@ -148,6 +148,11 @@ public class SysRoleServiceImpl extends BaseServiceImpl<Sys_role> implements Sys
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void saveMenu(String[] menuIds, String roleId, String platform) {
|
||||
// 保存前确认权限均属于当前平台,防止PC端与H5端权限混写。
|
||||
List<Sys_menu> menus = sysMenuService.query(Cnd.where("id", "in", menuIds).and("platform", "=", platform));
|
||||
if (menus.size() != menuIds.length) {
|
||||
throw new BaseException("存在不属于当前平台的权限,无法保存");
|
||||
}
|
||||
//只清除对应平台的即可
|
||||
Sql sql = Sqls.queryString("""
|
||||
SELECT
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ 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.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 +12,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.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Strings;
|
||||
@@ -26,6 +29,22 @@ public class SysUnitServiceImpl extends BaseServiceImpl<Sys_unit> implements Sys
|
||||
super(dao);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按单位编码或名称筛选当前分工会的组成单位,并按单位编码倒序分页。
|
||||
*/
|
||||
@Override
|
||||
public Pagination<Sys_unit> pageBranchUnionPartUnits(PageForm pageForm, String unionId) {
|
||||
Cnd cnd = Cnd.where("unionId", "=", unionId);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup keywordCondition = new SqlExpressionGroup();
|
||||
keywordCondition.orLike("`name`", pageForm.getSearchKeyword());
|
||||
keywordCondition.orLike("unitcode", pageForm.getSearchKeyword());
|
||||
cnd.and(keywordCondition);
|
||||
}
|
||||
cnd.desc("unitcode");
|
||||
return listPage(pageForm.getPageNumber(), pageForm.getPageSize(), Sys_unit.class, cnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增单位
|
||||
*
|
||||
|
||||
@@ -67,19 +67,10 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
@Override
|
||||
@CacheResult(cacheKey = "${userId}_getPermissionList")
|
||||
public List<String> getPermissionList(String userId) {
|
||||
Sys_user user = this.fetch(userId);
|
||||
if (user == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
this.fetchLinks(user, "roles");
|
||||
if (user.getRoles() == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> permissionList = new ArrayList<String>();
|
||||
for (Sys_role role : user.getRoles()) {
|
||||
if (!role.isDisabled()) {
|
||||
permissionList.addAll(sysRoleService.getPermissionList(role));
|
||||
}
|
||||
// Sa-Token接口权限只汇总启用的用户角色关系,历史届次角色不再参与鉴权。
|
||||
for (Sys_role role : getEnabledRoles(userId)) {
|
||||
permissionList.addAll(sysRoleService.getPermissionList(role));
|
||||
}
|
||||
// 追加public公共角色权限
|
||||
permissionList.addAll(sysRoleService.getPermissionList(sysRoleService.fetch(Cnd.where("code", "=", "public"))));
|
||||
@@ -94,12 +85,63 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
*/
|
||||
@CacheResult(cacheKey = "${user.id}_getRoleCodeList")
|
||||
public List<String> getRoleCodeList(Sys_user user) {
|
||||
dao().fetchLinks(user, "roles");
|
||||
List<String> roleNameList = new ArrayList<String>();
|
||||
for (Sys_role role : user.getRoles()) {
|
||||
if (!role.isDisabled()) roleNameList.add(role.getCode());
|
||||
if (user == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return roleNameList;
|
||||
// AuthUtil.hasRole与Sa-Token角色判断共用启用角色集合。
|
||||
return getEnabledRoles(user.getId()).stream()
|
||||
.map(Sys_role::getCode)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户当前启用角色。用户角色关系和角色本身必须同时处于启用状态。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 当前启用角色列表
|
||||
*/
|
||||
@Override
|
||||
@CacheResult(cacheKey = "${userId}_getEnabledRoles")
|
||||
public List<Sys_role> getEnabledRoles(String userId) {
|
||||
if (StrUtil.isBlank(userId) || fetch(userId) == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
role.*
|
||||
FROM
|
||||
sys_role role
|
||||
INNER JOIN sys_user_role userRole ON userRole.roleId = role.id
|
||||
WHERE
|
||||
userRole.userId = @userId
|
||||
AND userRole.enable = @t
|
||||
AND role.disabled = @f
|
||||
ORDER BY role.sort DESC, role.id
|
||||
""");
|
||||
sql.setParam("userId", userId);
|
||||
sql.setParam("t", true);
|
||||
sql.setParam("f", false);
|
||||
sql.setCallback(Sqls.callback.entities());
|
||||
sql.setEntity(dao().getEntity(Sys_role.class));
|
||||
dao().execute(sql);
|
||||
return sql.getList(Sys_role.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇总用户当前启用角色名称,首页展示与菜单及接口权限保持相同数据口径。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 逗号分隔的角色名称
|
||||
*/
|
||||
@Override
|
||||
public String getEnabledRoleNames(String userId) {
|
||||
return getEnabledRoles(userId).stream()
|
||||
.map(Sys_role::getName)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +203,8 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
*/
|
||||
// @CacheResult(cacheKey = "${userId}_getMenus")
|
||||
public List<Sys_menu> getMenus(String userId) {
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + " b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and d.disabled=@f) and a.disabled=@f and a.showit=@t and a.type='menu' order by a.location ASC,a.path asc");
|
||||
// 菜单仅使用启用的用户角色关系,普通角色与当前开启届次角色保持原有权限。
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + " b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and c.enable=@t and d.disabled=@f) and a.disabled=@f and a.showit=@t and a.type='menu' order by a.location ASC,a.path asc");
|
||||
sql.params().set("userId", userId);
|
||||
sql.params().set("f", false);
|
||||
sql.params().set("t", true);
|
||||
@@ -176,9 +219,10 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
*/
|
||||
// @CacheResult(cacheKey = "${userId}_getMenusAndButtons")
|
||||
public List<Sys_menu> getMenusAndButtons(String userId) {
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + " b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and d.disabled=@f) and a.disabled=@f order by a.location ASC,a.path asc");
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + " b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and c.enable=@t and d.disabled=@f) and a.disabled=@f order by a.location ASC,a.path asc");
|
||||
sql.params().set("userId", userId);
|
||||
sql.params().set("f", false);
|
||||
sql.params().set("t", true);
|
||||
return sysMenuService.listEntity(sql);
|
||||
}
|
||||
|
||||
@@ -195,9 +239,10 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
*/
|
||||
@CacheResult(cacheKey = "${userId}_getDatas")
|
||||
public List<Sys_menu> getDatas(String userId) {
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + " b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and d.disabled=@f) and a.disabled=@f and a.type='data' order by a.location ASC,a.path asc");
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + " b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and c.enable=@t and d.disabled=@f) and a.disabled=@f and a.type='data' order by a.location ASC,a.path asc");
|
||||
sql.params().set("userId", userId);
|
||||
sql.params().set("f", false);
|
||||
sql.params().set("t", true);
|
||||
return sysMenuService.listEntity(sql);
|
||||
}
|
||||
|
||||
@@ -232,9 +277,10 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
*/
|
||||
@CacheResult(cacheKey = "${userId}_${pid}_getRoleMenus")
|
||||
public List<Sys_menu> getRoleMenus(String userId, String pid) {
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + "$m and b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and d.disabled=@f) and a.disabled=@f order by a.location ASC,a.path asc");
|
||||
Sql sql = Sqls.create("select distinct a.* from sys_menu a,sys_role_menu b where a.id=b.menuId and " + "$m and b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and c.enable=@t and d.disabled=@f) and a.disabled=@f order by a.location ASC,a.path asc");
|
||||
sql.params().set("userId", userId);
|
||||
sql.params().set("f", false);
|
||||
sql.params().set("t", true);
|
||||
if (Strings.isNotBlank(pid)) {
|
||||
sql.vars().set("m", "a.parentId='" + pid + "'");
|
||||
} else {
|
||||
@@ -251,9 +297,10 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
*/
|
||||
@CacheResult(cacheKey = "${userId}_${pid}_hasChildren")
|
||||
public boolean hasChildren(String userId, String pid) {
|
||||
Sql sql = Sqls.create("select count(*) from sys_menu a,sys_role_menu b where a.id=b.menuId and " + "$m and b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and d.disabled=@f) and a.disabled=@f order by a.location ASC,a.path asc");
|
||||
Sql sql = Sqls.create("select count(*) from sys_menu a,sys_role_menu b where a.id=b.menuId and " + "$m and b.roleId in(select c.roleId from sys_user_role c,sys_role d where c.roleId=d.id and c.userId=@userId and c.enable=@t and d.disabled=@f) and a.disabled=@f order by a.location ASC,a.path asc");
|
||||
sql.params().set("userId", userId);
|
||||
sql.params().set("f", false);
|
||||
sql.params().set("t", true);
|
||||
if (Strings.isNotBlank(pid)) {
|
||||
sql.vars().set("m", "a.parentId='" + pid + "'");
|
||||
} else {
|
||||
@@ -387,6 +434,8 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
user.setUnion(union);
|
||||
}
|
||||
user = this.fillMenu(user);
|
||||
// 登录用户返回给前端的角色同样只保留启用关系,避免历史届次角色继续触发页面 hasRole 判断。
|
||||
user.setRoles(this.getEnabledRoles(userId));
|
||||
user.setPermissions(this.getPermissionList(userId));
|
||||
return user;
|
||||
}
|
||||
|
||||
+22
-9
@@ -133,10 +133,20 @@ public class ActivityBasicScopeUserDataController {
|
||||
|
||||
|
||||
/**
|
||||
* 删除一条记录
|
||||
* 删除活动分组人员。
|
||||
* id 有值时删除单个人员;id 为空时按当前页面的姓名/工号、工会、单位、人员类别和在职状态筛选后批量删除。
|
||||
* groupId 为待删除人员所在的活动分组;existsLoginNameRedisKey 为导入核对名单生成的工号筛选缓存键。
|
||||
* 返回 Result,code 为 0 表示删除处理成功。
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
* @param id 单个人员 ID;批量删除时传空
|
||||
* @param groupId 当前活动分组 ID
|
||||
* @param searchKeyword 姓名或工号关键字
|
||||
* @param unionId 所属工会 ID
|
||||
* @param unitId 所属单位 ID
|
||||
* @param personType 教职工类别
|
||||
* @param userState 在职状态
|
||||
* @param existsLoginNameRedisKey 导入核对名单的 Redis 缓存键
|
||||
* @return 删除结果
|
||||
*/
|
||||
@At
|
||||
@SLog(tag = "活动人员查询", msg = "删除活动人员")
|
||||
@@ -145,7 +155,6 @@ public class ActivityBasicScopeUserDataController {
|
||||
public Result doDelete(@Param(value = "id") String id,
|
||||
@Param(value = "groupId") Integer groupId,
|
||||
@Param(value = "searchKeyword") String searchKeyword,
|
||||
@Param(value = "searchName") String searchName,
|
||||
@Param(value = "unionId") String unionId,
|
||||
@Param(value = "unitId") String unitId,
|
||||
@Param(value = "personType") String personType,
|
||||
@@ -160,7 +169,7 @@ public class ActivityBasicScopeUserDataController {
|
||||
}
|
||||
}
|
||||
|
||||
List<String> targetUserIds = queryGroupUserIds(groupId, id, searchKeyword, searchName, unionId, unitId, personType, userState, existsLoginNames);
|
||||
List<String> targetUserIds = queryGroupUserIds(groupId, id, searchKeyword, unionId, unitId, personType, userState, existsLoginNames);
|
||||
if (Lang.isEmpty(targetUserIds)) {
|
||||
return Result.success();
|
||||
}
|
||||
@@ -282,9 +291,10 @@ public class ActivityBasicScopeUserDataController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除时需要先按页面当前筛选条件圈定目标人员,再根据分组类型删除对应存储表中的快照数据。
|
||||
* 删除时需要先按页面当前筛选条件圈定目标人员。姓名或工号关键字必须与列表查询使用相同的匹配规则,
|
||||
* 再根据分组类型删除对应存储表中的快照数据。
|
||||
*/
|
||||
private List<String> queryGroupUserIds(Integer groupId, String id, String searchKeyword, String searchName,
|
||||
private List<String> queryGroupUserIds(Integer groupId, String id, String searchKeyword,
|
||||
String unionId, String unitId, String personType, String userState,
|
||||
List<String> existsLoginNames) {
|
||||
Sql sql = Sqls.queryString("""
|
||||
@@ -296,8 +306,11 @@ public class ActivityBasicScopeUserDataController {
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("u.id", "in", activityBasicScopeService.buildGroupUserIdSubSql(groupId));
|
||||
if (StrUtil.isNotBlank(searchName) && StrUtil.isNotBlank(searchKeyword)) {
|
||||
cnd.and(Cnd.likeEX(searchName, searchKeyword));
|
||||
if (StrUtil.isNotBlank(searchKeyword)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.orLike("u.username", searchKeyword);
|
||||
group.orLike("u.loginname", searchKeyword);
|
||||
cnd.and(group);
|
||||
}
|
||||
cnd.andEX("u.unionid", "=", unionId);
|
||||
cnd.andEX("u.unitid", "=", unitId);
|
||||
|
||||
+2
@@ -196,6 +196,8 @@ public class ActivityCultureApplyActivityController {
|
||||
}
|
||||
|
||||
private void cleanNewActivityData(ActivityTissue tissue) {
|
||||
// 从模板另存或直接新建的活动必须进入活动列表,不能继承来源活动的模板状态。
|
||||
tissue.setTemplateStatus(ActivityTissue.TEMPLATE_STATUS_UNSET);
|
||||
tissue.setId(null);
|
||||
tissue.setAuditId(null);
|
||||
tissue.setState(null);
|
||||
|
||||
+10
-30
@@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
@@ -69,8 +70,9 @@ public class ActivityCultureInfoManageController {
|
||||
public Result pageData(PageForm page, String year,
|
||||
String name,
|
||||
String unionId,
|
||||
@Valid Integer activity_type) {
|
||||
return Result.success(activityCultureService.pageData(page, year, name, unionId, activity_type));
|
||||
@Valid Integer activity_type,
|
||||
Integer templateStatus) {
|
||||
return Result.success(activityCultureService.pageData(page, year, name, unionId, activity_type, templateStatus));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -90,47 +92,25 @@ public class ActivityCultureInfoManageController {
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("activity.culture.infoManage.school")
|
||||
@SaCheckPermission(value = {"activity.culture.infoManage.school", "activity.culture.infoManage.union"}, mode = SaMode.OR)
|
||||
public Result setTemplate(@Valid String id) {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
ActivityTissue tissue = activityCultureService.fetch(id);
|
||||
if (tissue == null) {
|
||||
return Result.error("活动不存在");
|
||||
String errorMessage = activityCultureService.setTemplate(id);
|
||||
if (StrUtil.isNotBlank(errorMessage)) {
|
||||
return Result.error(errorMessage);
|
||||
}
|
||||
if (tissue.getActivity_type() == null || tissue.getActivity_type() != 40001) {
|
||||
return Result.error("仅校工会文化活动可设为模板");
|
||||
}
|
||||
Sys_home_template oldHomeTemplate = activityCultureService.dao().fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = tissue.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
activityCultureService.dao().insertOrUpdate(sysHomeTemplate);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("activity.culture.infoManage.school")
|
||||
@SaCheckPermission(value = {"activity.culture.infoManage.school", "activity.culture.infoManage.union"}, mode = SaMode.OR)
|
||||
public Result cancelTemplate(@Valid String id) {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
activityCultureService.dao().delete(Sys_home_template.class, id);
|
||||
activityCultureService.cancelTemplate(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ import java.util.List;
|
||||
@Table("activity_tissue")
|
||||
public class ActivityTissue extends BaseModel implements Serializable, SysHomeConvert {
|
||||
|
||||
/** 未设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_UNSET = 0;
|
||||
|
||||
/** 已设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_SET = 1;
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@@ -236,6 +242,12 @@ public class ActivityTissue extends BaseModel implements Serializable, SysHomeCo
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
private Boolean isUnseal;
|
||||
|
||||
@Column
|
||||
@Comment("模板设置状态(0:未设置,1:已设置)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
@Default("0")
|
||||
private Integer templateStatus;
|
||||
|
||||
@Column
|
||||
@Comment("物品")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
|
||||
+27
-1
@@ -21,7 +21,33 @@ public interface ActivityCultureService extends BaseService<ActivityTissue> {
|
||||
|
||||
void doEditActivity(ActivityTissue tissue);
|
||||
|
||||
Object pageData(PageForm page, String year, String name, String unionId, Integer activity_type);
|
||||
/**
|
||||
* 分页查询文化活动。
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @param year 年度
|
||||
* @param name 活动名称
|
||||
* @param unionId 工会ID
|
||||
* @param activity_type 活动类型
|
||||
* @param templateStatus 模板设置状态,为空时不限制
|
||||
* @return 文化活动分页数据
|
||||
*/
|
||||
Object pageData(PageForm page, String year, String name, String unionId, Integer activity_type, Integer templateStatus);
|
||||
|
||||
/**
|
||||
* 将校工会或分工会文化活动设置为工作模板,并同步模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
* @return 空字符串表示成功,否则返回业务错误信息
|
||||
*/
|
||||
String setTemplate(String id);
|
||||
|
||||
/**
|
||||
* 取消校工会或分工会文化活动模板,并同步模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
*/
|
||||
void cancelTemplate(String id);
|
||||
|
||||
NutMap findOne(String id);
|
||||
|
||||
|
||||
+63
-3
@@ -6,6 +6,7 @@ import com.budwk.app.base.model.Audit;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
import com.budwk.app.sys.models.Sys_home_template;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
@@ -14,6 +15,8 @@ import com.budwk.app.zhgh.activity.culture.models.ActivityTissuePerson;
|
||||
import com.budwk.app.zhgh.activity.culture.service.ActivityCultureService;
|
||||
import com.budwk.app.zhgh.club.model.SysClub;
|
||||
import com.budwk.app.zhgh.club.service.SysClubService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
@@ -21,6 +24,7 @@ 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.lang.Strings;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
@@ -85,7 +89,7 @@ public class ActivityCultureServiceImpl extends BaseServiceImpl<ActivityTissue>
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pageData(PageForm page, String year, String name, String unionId, Integer activity_type) {
|
||||
public Object pageData(PageForm page, String year, String name, String unionId, Integer activity_type, Integer templateStatus) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
@@ -110,7 +114,7 @@ public class ActivityCultureServiceImpl extends BaseServiceImpl<ActivityTissue>
|
||||
t.variable taskVariable,
|
||||
IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke,
|
||||
(select MAX(id) from wf_process_task where processInstanceId = ins.id and taskName = 'startTask') AS startTaskId,
|
||||
IF(sht.id IS NULL, 0, 1) AS isTemplate
|
||||
tissue.templateStatus AS isTemplate
|
||||
FROM
|
||||
activity_tissue tissue
|
||||
LEFT JOIN sys_union uni ON uni.id = tissue.unionId
|
||||
@@ -119,7 +123,6 @@ public class ActivityCultureServiceImpl extends BaseServiceImpl<ActivityTissue>
|
||||
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = tissue.id
|
||||
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
LEFT JOIN sys_home_template sht ON sht.id = tissue.id
|
||||
$condition
|
||||
""");
|
||||
|
||||
@@ -127,6 +130,8 @@ public class ActivityCultureServiceImpl extends BaseServiceImpl<ActivityTissue>
|
||||
cnd.andEX("tissue.projectTypeCode", "!=", "50004");
|
||||
cnd.andEX("tissue.unionId", "=", unionId);
|
||||
cnd.andEX("tissue.activity_type", "=", activity_type);
|
||||
// 校工会管理页按页签传入模板状态;其他文化活动页面不传时保持原查询范围。
|
||||
cnd.andEX("tissue.templateStatus", "=", templateStatus);
|
||||
cnd.groupBy("tissue.id");
|
||||
|
||||
if (Strings.isNotBlank(name)) {
|
||||
@@ -159,6 +164,61 @@ public class ActivityCultureServiceImpl extends BaseServiceImpl<ActivityTissue>
|
||||
return this.listPageMap(page.getPageNumber(), page.getPageSize(), sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将校工会或分工会文化活动转换为工作模板,并保留模板中心已维护的展示配置。
|
||||
*
|
||||
* @param id 活动ID
|
||||
* @return 空字符串表示成功,否则返回业务错误信息
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public String setTemplate(String id) {
|
||||
ActivityTissue tissue = fetch(id);
|
||||
if (tissue == null) {
|
||||
return "活动不存在";
|
||||
}
|
||||
if (tissue.getActivity_type() == null || !List.of(40001, 40002).contains(tissue.getActivity_type())) {
|
||||
return "仅校工会或分工会文化活动可设为模板";
|
||||
}
|
||||
|
||||
Sys_home_template oldHomeTemplate = dao().fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = tissue.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
// 重复设置时保留模板中心人工配置,避免覆盖置顶、推送、排序及模板素材。
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao().insertOrUpdate(sysHomeTemplate);
|
||||
dao().update(ActivityTissue.class,
|
||||
Chain.make("templateStatus", ActivityTissue.TEMPLATE_STATUS_SET),
|
||||
Cnd.where("id", "=", id));
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除模板中心记录并将文化活动恢复为未设置模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void cancelTemplate(String id) {
|
||||
dao().delete(Sys_home_template.class, id);
|
||||
dao().update(ActivityTissue.class,
|
||||
Chain.make("templateStatus", ActivityTissue.TEMPLATE_STATUS_UNSET),
|
||||
Cnd.where("id", "=", id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NutMap findOne(String id) {
|
||||
Sql sql = Sqls.create("""
|
||||
|
||||
+7
@@ -87,6 +87,9 @@ public class FamilyActivityApplyController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("id", "=", id);
|
||||
cnd.andEX("`year`", "=", year);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.and("activityName", "like", "%" + pageForm.getSearchKeyword().trim() + "%");
|
||||
}
|
||||
//查询报名中
|
||||
if (activityType == 2) {
|
||||
cnd.and(new Static("now() < activitySignUpEndTime"));
|
||||
@@ -117,6 +120,7 @@ public class FamilyActivityApplyController {
|
||||
@Param(value = "courseTypeId") String courseTypeId,
|
||||
@Param(value = "activityId") String activityId,
|
||||
@Param(value = "assortTypes") String[] assortTypes,
|
||||
@Param(value = "searchKeyword") String searchKeyword,
|
||||
@Param(value = "dataType") String dataType) {
|
||||
FamilyActivity activity = dao.fetch(FamilyActivity.class, activityId);
|
||||
Sql sql = Sqls.create("""
|
||||
@@ -131,6 +135,9 @@ public class FamilyActivityApplyController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("type.id", "=", courseTypeId);
|
||||
cnd.and("tsuc.activityId", "=", activityId);
|
||||
if (StrUtil.isNotBlank(searchKeyword)) {
|
||||
cnd.and("tsuc.courseName", "like", "%" + searchKeyword.trim() + "%");
|
||||
}
|
||||
if(Lang.isNotEmpty(assortTypes)) {
|
||||
cnd.and("tsuc.assort", "in", assortTypes);
|
||||
}
|
||||
|
||||
+9
-31
@@ -6,7 +6,6 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
@@ -68,20 +67,15 @@ public class FamilyActivityController {
|
||||
@SaCheckPermission("family.manage")
|
||||
public Result pageData(PageForm pageForm,
|
||||
@Param(value = "year") Integer year,
|
||||
@Param(value = "activityName") String activityName) {
|
||||
@Param(value = "activityName") String activityName,
|
||||
@Param(value = "templateStatus") Integer templateStatus) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("year", "=", year);
|
||||
cnd.and(Cnd.likeEX("activityName", activityName));
|
||||
// 有模板管理角色时前端按页签传入状态;普通用户不传时保持原列表范围。
|
||||
cnd.andEX("templateStatus", "=", templateStatus);
|
||||
cnd.orderBy("createdAt", "desc");
|
||||
Pagination<FamilyActivity> pagination = familyActivityManageService.pageData(pageForm, cnd);
|
||||
List<FamilyActivity> list = pagination.getList(FamilyActivity.class);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
List<String> ids = list.stream().map(FamilyActivity::getId).toList();
|
||||
List<Sys_home_template> templateList = dao.query(Sys_home_template.class, Cnd.where("id", "in", ids));
|
||||
List<String> templateIds = templateList.stream().map(Sys_home_template::getId).toList();
|
||||
list.forEach(activity -> activity.setIsTemplate(templateIds.contains(activity.getId())));
|
||||
}
|
||||
return Result.success().addData(pagination);
|
||||
return Result.success().addData(familyActivityManageService.pageData(pageForm, cnd));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -91,27 +85,9 @@ public class FamilyActivityController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
FamilyActivity activity = familyActivityManageService.fetch(id);
|
||||
if (activity == null) {
|
||||
if (!familyActivityManageService.setTemplate(id)) {
|
||||
return Result.error("活动不存在");
|
||||
}
|
||||
Sys_home_template oldHomeTemplate = dao.fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = activity.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao.insertOrUpdate(sysHomeTemplate);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -122,7 +98,7 @@ public class FamilyActivityController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
dao.delete(Sys_home_template.class, id);
|
||||
familyActivityManageService.cancelTemplate(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -224,6 +200,8 @@ public class FamilyActivityController {
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
// 直接新建或从模板另存时明确重置状态,防止前端历史字段被带回。
|
||||
activity.setTemplateStatus(FamilyActivity.TEMPLATE_STATUS_UNSET);
|
||||
activity.setId(null);
|
||||
activity.setIsTemplate(false);
|
||||
activity.setCreatedBy(null);
|
||||
|
||||
@@ -25,6 +25,12 @@ import java.util.List;
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class FamilyActivity extends BaseModel implements Serializable, SysHomeConvert {
|
||||
|
||||
/** 未设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_UNSET = 0;
|
||||
|
||||
/** 已设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_SET = 1;
|
||||
|
||||
@Name
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
@@ -114,6 +120,12 @@ public class FamilyActivity extends BaseModel implements Serializable, SysHomeCo
|
||||
|
||||
private Boolean isTemplate;
|
||||
|
||||
@Column
|
||||
@Comment("模板设置状态(0:未设置,1:已设置)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
@Default("0")
|
||||
private Integer templateStatus;
|
||||
|
||||
@Column
|
||||
@Comment("活动类型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
|
||||
@@ -50,6 +50,21 @@ public interface FamilyActivityService extends BaseService<FamilyActivity> {
|
||||
*/
|
||||
Pagination pageData(PageForm pageForm, Cnd cnd);
|
||||
|
||||
/**
|
||||
* 将亲子活动设置为工作模板,并同步模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
* @return true 表示活动存在且设置成功,false 表示活动不存在
|
||||
*/
|
||||
boolean setTemplate(String id);
|
||||
|
||||
/**
|
||||
* 取消亲子活动模板,并同步模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
*/
|
||||
void cancelTemplate(String id);
|
||||
|
||||
|
||||
/**
|
||||
* 手机端分页查询
|
||||
|
||||
+54
-1
@@ -6,6 +6,7 @@ import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
import com.budwk.app.sys.models.Sys_home_template;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.family.models.*;
|
||||
@@ -48,7 +49,8 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl<FamilyActivity> i
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void add(FamilyActivity activity, FamilyCourse course) {
|
||||
|
||||
// 新建活动(包括从模板另存)统一归入活动列表,不能继承来源活动的模板状态。
|
||||
activity.setTemplateStatus(FamilyActivity.TEMPLATE_STATUS_UNSET);
|
||||
dao().insert(activity);
|
||||
|
||||
//插入类型限制
|
||||
@@ -215,6 +217,57 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl<FamilyActivity> i
|
||||
return pagination;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将亲子活动转换为工作模板,并保留模板中心已维护的展示配置。
|
||||
*
|
||||
* @param id 活动ID
|
||||
* @return true 表示活动存在且设置成功,false 表示活动不存在
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public boolean setTemplate(String id) {
|
||||
FamilyActivity activity = fetch(id);
|
||||
if (activity == null) {
|
||||
return false;
|
||||
}
|
||||
Sys_home_template oldHomeTemplate = dao().fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = activity.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
// 重复设置时保留模板中心人工配置,避免覆盖置顶、推送、排序及模板素材。
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao().insertOrUpdate(sysHomeTemplate);
|
||||
dao().update(FamilyActivity.class,
|
||||
Chain.make("templateStatus", FamilyActivity.TEMPLATE_STATUS_SET),
|
||||
Cnd.where("id", "=", id));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除模板中心记录并将亲子活动恢复为未设置模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void cancelTemplate(String id) {
|
||||
dao().delete(Sys_home_template.class, id);
|
||||
dao().update(FamilyActivity.class,
|
||||
Chain.make("templateStatus", FamilyActivity.TEMPLATE_STATUS_UNSET),
|
||||
Cnd.where("id", "=", id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination mPageData(PageForm pageForm, Integer year, int activityStatus, Integer activityType) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
+7
-23
@@ -65,7 +65,8 @@ public class ActivitySportsInfoManageController {
|
||||
@Param(value = "gameStyle") String gameStyle,
|
||||
@Param(value = "query") String query,
|
||||
@Param(value = "activityId") String activityId,
|
||||
@Param(value = "activityLevel") String activityLevel) {
|
||||
@Param(value = "activityLevel") String activityLevel,
|
||||
@Param(value = "templateStatus") Integer templateStatus) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -91,13 +92,12 @@ public class ActivitySportsInfoManageController {
|
||||
school.activityCode,
|
||||
school.foundDate,
|
||||
school.applyType,
|
||||
IF(sht.id IS NULL, 0, 1) isTemplate,
|
||||
school.templateStatus isTemplate,
|
||||
(SELECT COUNT(1) FROM activity_school_apply asa WHERE asa.activityId = school.id and status=2) applyNum
|
||||
FROM
|
||||
activity_school school
|
||||
LEFT JOIN activity_basic_settings ba ON ba.`code` = school.activityLevel
|
||||
LEFT JOIN sys_union un ON un.id = school.belongUnionId
|
||||
LEFT JOIN sys_home_template sht ON sht.id = school.id
|
||||
$condition
|
||||
""");
|
||||
|
||||
@@ -121,6 +121,8 @@ public class ActivitySportsInfoManageController {
|
||||
|
||||
cnd.andEX("school.activityLevel", "=", activityLevel);
|
||||
cnd.andEX("school.gameStyle", "=", gameStyle);
|
||||
// 管理员页签传入模板状态;未展示页签的用户不传该参数,继续查询原完整列表。
|
||||
cnd.andEX("school.templateStatus", "=", templateStatus);
|
||||
cnd.andEX("YEAR(school.applyStartTime)", "=", year);
|
||||
if (StrUtil.isNotBlank(name)) {
|
||||
cnd.and(Cnd.likeEX("school.name", name));
|
||||
@@ -141,27 +143,9 @@ public class ActivitySportsInfoManageController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
ActivitySchool activitySchool = activitySportsService.fetch(id);
|
||||
if (activitySchool == null) {
|
||||
if (!activitySportsService.setTemplate(id)) {
|
||||
return Result.error("活动不存在");
|
||||
}
|
||||
Sys_home_template oldHomeTemplate = dao.fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = activitySchool.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao.insertOrUpdate(sysHomeTemplate);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -172,7 +156,7 @@ public class ActivitySportsInfoManageController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
dao.delete(Sys_home_template.class, id);
|
||||
activitySportsService.cancelTemplate(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
+13
-24
@@ -17,7 +17,7 @@ import com.budwk.app.zhgh.activity.sports.service.ActivitySportsApplyUserService
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.dao.util.cri.Static;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.random.R;
|
||||
@@ -26,8 +26,6 @@ import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
import org.nutz.trans.Trans;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author zhf
|
||||
* @date 2021/5/19 14:58
|
||||
@@ -57,7 +55,8 @@ public class ActivitySportsResultsController {
|
||||
PageForm page,
|
||||
String activityId,
|
||||
String eventId,
|
||||
String[] isMenWomen) {
|
||||
Integer isMenWomen,
|
||||
Integer projectType) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -79,22 +78,10 @@ public class ActivitySportsResultsController {
|
||||
cnd.and("ase.activityId", "=", activityId);
|
||||
cnd.andEX("abs.`name`", "=", groupName);
|
||||
cnd.andEX("ae.`id`", "=", eventId);
|
||||
SqlExpressionGroup sqlExpressionGroup = new SqlExpressionGroup();
|
||||
if (Arrays.stream(isMenWomen).anyMatch(a -> a.equals("2"))) {
|
||||
sqlExpressionGroup.and("ae.isMenWomen", "=", 1);
|
||||
}
|
||||
if (Arrays.stream(isMenWomen).anyMatch(a -> a.equals("3"))) {
|
||||
sqlExpressionGroup.or("ae.isMenWomen", "=", 2);
|
||||
}
|
||||
if (Arrays.stream(isMenWomen).anyMatch(a -> a.equals("4"))) {
|
||||
sqlExpressionGroup.and("ae.projectType", "=", 1);
|
||||
}
|
||||
if (Arrays.stream(isMenWomen).anyMatch(a -> a.equals("5"))) {
|
||||
sqlExpressionGroup.or("ae.projectType", "=", 2);
|
||||
}
|
||||
if (sqlExpressionGroup.getExps().size() > 0) {
|
||||
cnd.and(sqlExpressionGroup);
|
||||
}
|
||||
// 页面男子/女子选项值与活动项目性别字段保持一致:1 为男子,2 为女子。
|
||||
cnd.andEX("ae.isMenWomen", "=", isMenWomen);
|
||||
// 页面项目类型选项值与活动项目类型字段保持一致:1 为单项,2 为团体。
|
||||
cnd.andEX("ae.projectType", "=", projectType);
|
||||
cnd.desc("allName");
|
||||
sql.setCondition(cnd);
|
||||
return Result.success(baseService.listPageMap(page.getPageNumber(), page.getPageSize(), sql));
|
||||
@@ -192,8 +179,9 @@ public class ActivitySportsResultsController {
|
||||
cnd.and("asa.activityId", "=", activityId);
|
||||
cnd.and("asa.eventId", "=", eventId);
|
||||
cnd.and("asa.awardsMode", "=", 1);
|
||||
if (isMenWomen != null && isMenWomen == 1) cnd.and("u.sex", "=", "男性");
|
||||
if (isMenWomen != null && isMenWomen == 2) cnd.and("u.sex", "=", "女性");
|
||||
// 兼容历史人员“男性/女性”和临时添加人员“男/女”的性别值。
|
||||
if (isMenWomen != null && isMenWomen == 1) cnd.and(new Static("u.sex IN ('男', '男性')"));
|
||||
if (isMenWomen != null && isMenWomen == 2) cnd.and(new Static("u.sex IN ('女', '女性')"));
|
||||
sql.setCondition(cnd);
|
||||
return Result.success(activitySchoolApplyViService.listMap(sql));
|
||||
}
|
||||
@@ -268,8 +256,9 @@ public class ActivitySportsResultsController {
|
||||
""");
|
||||
cnd.and("ar.activityId", "=", activityId);
|
||||
cnd.and("ar.eventId", "=", eventId);
|
||||
if (isMenWomen != null && isMenWomen == 1) cnd.and("u.sex", "=", "男性");
|
||||
if (isMenWomen != null && isMenWomen == 2) cnd.and("u.sex", "=", "女性");
|
||||
// 兼容历史人员“男性/女性”和临时添加人员“男/女”的性别值。
|
||||
if (isMenWomen != null && isMenWomen == 1) cnd.and(new Static("u.sex IN ('男', '男性')"));
|
||||
if (isMenWomen != null && isMenWomen == 2) cnd.and(new Static("u.sex IN ('女', '女性')"));
|
||||
cnd.asc("ar.ranking");
|
||||
sql.setCondition(cnd);
|
||||
return Result.success(baseService.listMap(sql));
|
||||
|
||||
+2
-2
@@ -64,8 +64,8 @@ public class H5ActivitySportsApplyUserController {
|
||||
|
||||
@At
|
||||
@SaCheckPermission("h5.activity.sports.applyUser")
|
||||
public Result activityData(Integer year, Integer isActivity, Integer applyStatus) {
|
||||
return Result.success(activitySportsApplyUserService.activityData(year, isActivity, applyStatus));
|
||||
public Result activityData(Integer year, Integer isActivity, Integer applyStatus, String searchKeyword) {
|
||||
return Result.success(activitySportsApplyUserService.activityData(year, isActivity, applyStatus, searchKeyword));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,18 @@ public class ActivitySchool extends BaseModel implements Serializable , SysHomeC
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
private Integer isSave;
|
||||
|
||||
/** 未设置为工作模板。 */
|
||||
public static final int TEMPLATE_STATUS_UNSET = 0;
|
||||
|
||||
/** 已设置为工作模板。 */
|
||||
public static final int TEMPLATE_STATUS_SET = 1;
|
||||
|
||||
@Column
|
||||
@Comment("模板设置状态(0:未设置 1:已设置)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
@Default("0")
|
||||
private Integer templateStatus;
|
||||
|
||||
@Column
|
||||
@Comment("小程序活动封面")
|
||||
@ColDefine(type = ColType.VARCHAR,width = 100)
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ public class ActivitySportsApplyUserPageParam extends PageForm {
|
||||
private String applyType;
|
||||
private String isAudit;
|
||||
private String groupName;
|
||||
private String searchKeyword;
|
||||
private String activityId;
|
||||
private String eventId;
|
||||
private String year;
|
||||
|
||||
+11
@@ -19,6 +19,17 @@ public interface ActivitySportsApplyUserService extends BaseService<ActivityScho
|
||||
|
||||
Pagination activityData(Integer year, Integer isActivity,Integer applyStatus);
|
||||
|
||||
/**
|
||||
* 根据年份、活动状态、报名状态和活动名称查询体育活动。
|
||||
*
|
||||
* @param year 活动年份
|
||||
* @param isActivity 活动状态
|
||||
* @param applyStatus 当前用户报名状态
|
||||
* @param searchKeyword 活动名称模糊查询关键词
|
||||
* @return 体育活动分页数据
|
||||
*/
|
||||
Pagination activityData(Integer year, Integer isActivity, Integer applyStatus, String searchKeyword);
|
||||
|
||||
List<NutMap> getEvents(String activityId);
|
||||
|
||||
Object getUnionCoachLeaderHead(String activityId,String unionId);
|
||||
|
||||
@@ -18,5 +18,20 @@ public interface ActivitySportsService extends BaseService<ActivitySchool> {
|
||||
|
||||
void doDelete(String id);
|
||||
|
||||
/**
|
||||
* 将体育活动设置为工作模板,并同步活动表中的模板设置状态。
|
||||
*
|
||||
* @param id 体育活动ID
|
||||
* @return 活动存在且设置成功时返回 true,活动不存在时返回 false
|
||||
*/
|
||||
boolean setTemplate(String id);
|
||||
|
||||
/**
|
||||
* 取消体育活动的工作模板,并同步活动表中的模板设置状态。
|
||||
*
|
||||
* @param id 体育活动ID
|
||||
*/
|
||||
void cancelTemplate(String id);
|
||||
|
||||
void exportXlsx(String id, String unionId, HttpServletResponse response);
|
||||
}
|
||||
|
||||
+21
@@ -122,6 +122,9 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
|
||||
cnd.and(new Static("(SELECT COUNT(1) FROM activity_school_apply WHERE eventId = ase.eventId AND activityId = ase.activityId AND userId='%s')%s0".formatted(SecurityUtil.getUserId(), (pageParam.getIsAudit().equals("true") ? ">" : "="))));
|
||||
}
|
||||
cnd.and("ase.activityId", "=", pageParam.getActivityId());
|
||||
if (StrUtil.isNotBlank(pageParam.getSearchKeyword())) {
|
||||
cnd.and("eve.allName", "like", "%" + pageParam.getSearchKeyword().trim() + "%");
|
||||
}
|
||||
cnd.andEX("ase.eventId", "=", pageParam.getEventId());
|
||||
cnd.andEX("YEAR(school.applyStartTime)", "=", pageParam.getYear());
|
||||
|
||||
@@ -144,6 +147,20 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
|
||||
|
||||
@Override
|
||||
public Pagination activityData(Integer year, Integer isActivity, Integer applyStatus) {
|
||||
return activityData(year, isActivity, applyStatus, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据筛选条件及活动名称查询当前用户可见的体育活动。
|
||||
*
|
||||
* @param year 活动年份
|
||||
* @param isActivity 活动状态
|
||||
* @param applyStatus 当前用户报名状态
|
||||
* @param searchKeyword 活动名称模糊查询关键词
|
||||
* @return 体育活动分页数据
|
||||
*/
|
||||
@Override
|
||||
public Pagination activityData(Integer year, Integer isActivity, Integer applyStatus, String searchKeyword) {
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -183,6 +200,10 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
|
||||
|
||||
cnd.and("school.isSave", "!=", true);
|
||||
|
||||
if (Lang.isNotEmpty(searchKeyword)) {
|
||||
cnd.and("school.NAME", "like", "%" + searchKeyword.trim() + "%");
|
||||
}
|
||||
|
||||
//查询报名中
|
||||
if (isActivity == 2) {
|
||||
cnd.and(new Static("now() >applyStartTime and now() < applyEndTime"));
|
||||
|
||||
+56
@@ -8,6 +8,7 @@ import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.base.utils.DateUtil;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
import com.budwk.app.sys.models.Sys_home_template;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
||||
@@ -61,6 +62,8 @@ public class ActivitySportsServiceImpl extends BaseServiceImpl<ActivitySchool> i
|
||||
}
|
||||
activitySchool.setFoundDate(DateUtil.getDate());
|
||||
activitySchool.setClose(false);
|
||||
// 新建活动只能从“未设置模板”状态开始,防止客户端提交模板状态造成数据不一致。
|
||||
activitySchool.setTemplateStatus(ActivitySchool.TEMPLATE_STATUS_UNSET);
|
||||
ActivitySchool school = insert(activitySchool);
|
||||
addTeam(school.getId(), events);
|
||||
|
||||
@@ -190,6 +193,59 @@ public class ActivitySportsServiceImpl extends BaseServiceImpl<ActivitySchool> i
|
||||
dao().delete(Sys_home_activity.class, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将活动内容转换为首页工作模板,并在同一事务内更新活动模板状态。
|
||||
* 重复设置时保留管理员在工作模板管理中维护的名称、图标、文件及排序配置。
|
||||
*
|
||||
* @param id 体育活动ID
|
||||
* @return 活动存在且设置成功时返回 true,否则返回 false
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public boolean setTemplate(String id) {
|
||||
ActivitySchool activitySchool = fetch(id);
|
||||
if (activitySchool == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Sys_home_template oldHomeTemplate = dao().fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = activitySchool.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
// 模板业务数据随活动刷新,模板管理页面维护的展示配置继续沿用。
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao().insertOrUpdate(sysHomeTemplate);
|
||||
dao().update(ActivitySchool.class,
|
||||
Chain.make("templateStatus", ActivitySchool.TEMPLATE_STATUS_SET),
|
||||
Cnd.where("id", "=", id));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除首页工作模板,并在同一事务内将活动恢复为未设置模板状态。
|
||||
*
|
||||
* @param id 体育活动ID
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void cancelTemplate(String id) {
|
||||
dao().delete(Sys_home_template.class, id);
|
||||
dao().update(ActivitySchool.class,
|
||||
Chain.make("templateStatus", ActivitySchool.TEMPLATE_STATUS_UNSET),
|
||||
Cnd.where("id", "=", id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportXlsx(String id, String unionId, HttpServletResponse response) {
|
||||
try {
|
||||
|
||||
+7
@@ -93,6 +93,9 @@ public class TrainSignUpApplyController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("id", "=", id);
|
||||
cnd.andEX("`year`", "=", year);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.and(Cnd.likeEX("activityName", pageForm.getSearchKeyword()));
|
||||
}
|
||||
//查询报名中
|
||||
if (activityType == 2) {
|
||||
cnd.and(new Static("now() < activitySignUpEndTime"));
|
||||
@@ -123,6 +126,7 @@ public class TrainSignUpApplyController {
|
||||
@Param(value = "courseTypeId") String courseTypeId,
|
||||
@Param(value = "activityId") String activityId,
|
||||
@Param(value = "assortTypes") String[] assortTypes,
|
||||
@Param(value = "searchKeyword") String searchKeyword,
|
||||
@Param(value = "dataType") String dataType) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -156,6 +160,9 @@ public class TrainSignUpApplyController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("type.id", "=", courseTypeId);
|
||||
cnd.and("tsuc.activityId", "=", activityId);
|
||||
if (StrUtil.isNotBlank(searchKeyword)) {
|
||||
cnd.and("tsuc.courseName", "like", "%" + searchKeyword.trim() + "%");
|
||||
}
|
||||
|
||||
if (Lang.isNotEmpty(assortTypes)) {
|
||||
cnd.and("tsuc.assort", "in", assortTypes);
|
||||
|
||||
+7
-31
@@ -6,7 +6,6 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
@@ -72,20 +71,15 @@ public class TrainSignUpManageController {
|
||||
@SaCheckPermission("trainSignUp.manage")
|
||||
public Result pageData(PageForm pageForm,
|
||||
@Param(value = "year") Integer year,
|
||||
@Param(value = "activityName") String activityName) {
|
||||
@Param(value = "activityName") String activityName,
|
||||
@Param(value = "templateStatus") Integer templateStatus) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("year", "=", year);
|
||||
cnd.and(Cnd.likeEX("activityName", activityName));
|
||||
// 具备模板管理角色时,前端按页签传入状态;普通用户不传时仍保持原列表范围。
|
||||
cnd.andEX("templateStatus", "=", templateStatus);
|
||||
cnd.orderBy("createdAt", "desc");
|
||||
Pagination<TrainSignUpActivity> pagination = trainSignUpActivityManageService.pageData(pageForm, cnd);
|
||||
List<TrainSignUpActivity> list = pagination.getList(TrainSignUpActivity.class);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
List<String> ids = list.stream().map(TrainSignUpActivity::getId).toList();
|
||||
List<Sys_home_template> templateList = dao.query(Sys_home_template.class, Cnd.where("id", "in", ids));
|
||||
List<String> templateIds = templateList.stream().map(Sys_home_template::getId).toList();
|
||||
list.forEach(activity -> activity.setIsTemplate(templateIds.contains(activity.getId())));
|
||||
}
|
||||
return Result.success().addData(pagination);
|
||||
return Result.success().addData(trainSignUpActivityManageService.pageData(pageForm, cnd));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -95,27 +89,9 @@ public class TrainSignUpManageController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
TrainSignUpActivity activity = trainSignUpActivityManageService.fetch(id);
|
||||
if (activity == null) {
|
||||
if (!trainSignUpActivityManageService.setTemplate(id)) {
|
||||
return Result.error("活动不存在");
|
||||
}
|
||||
Sys_home_template oldHomeTemplate = dao.fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = activity.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao.insertOrUpdate(sysHomeTemplate);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -126,7 +102,7 @@ public class TrainSignUpManageController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
dao.delete(Sys_home_template.class, id);
|
||||
trainSignUpActivityManageService.cancelTemplate(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,12 @@ import java.util.List;
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class TrainSignUpActivity extends BaseModel implements Serializable, SysHomeConvert {
|
||||
|
||||
/** 未设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_UNSET = 0;
|
||||
|
||||
/** 已设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_SET = 1;
|
||||
|
||||
@Name
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
@@ -112,6 +118,12 @@ public class TrainSignUpActivity extends BaseModel implements Serializable, SysH
|
||||
|
||||
private Boolean isTemplate;
|
||||
|
||||
@Column
|
||||
@Comment("模板设置状态(0:未设置,1:已设置)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
@Default("0")
|
||||
private Integer templateStatus;
|
||||
|
||||
@Column
|
||||
@Comment("活动类型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
|
||||
+15
@@ -59,6 +59,21 @@ public interface TrainSignUpActivityService extends BaseService<TrainSignUpActiv
|
||||
*/
|
||||
Pagination pageData(PageForm pageForm, Cnd cnd);
|
||||
|
||||
/**
|
||||
* 将品牌活动设置为工作模板,并同步活动表中的模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
* @return true 表示活动存在且设置成功,false 表示活动不存在
|
||||
*/
|
||||
boolean setTemplate(String id);
|
||||
|
||||
/**
|
||||
* 取消品牌活动工作模板,并同步活动表中的模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
*/
|
||||
void cancelTemplate(String id);
|
||||
|
||||
|
||||
/**
|
||||
* 手机端分页查询
|
||||
|
||||
+55
-1
@@ -5,6 +5,7 @@ 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_home_activity;
|
||||
import com.budwk.app.sys.models.Sys_home_template;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.family.models.FamilyActivity;
|
||||
@@ -53,7 +54,8 @@ public class TrainSignUpActivityServiceImpl extends BaseServiceImpl<TrainSignUpA
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void add(TrainSignUpActivity activity, TrainSignUpCourse course) {
|
||||
|
||||
// 新建活动(包括从模板另存)统一归入活动列表,不能继承来源活动的模板状态。
|
||||
activity.setTemplateStatus(TrainSignUpActivity.TEMPLATE_STATUS_UNSET);
|
||||
dao().insert(activity);
|
||||
|
||||
//插入类型限制
|
||||
@@ -289,6 +291,58 @@ public class TrainSignUpActivityServiceImpl extends BaseServiceImpl<TrainSignUpA
|
||||
return pagination;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将品牌活动转换为工作模板,并原样保留模板中心已维护的展示配置。
|
||||
*
|
||||
* @param id 活动ID
|
||||
* @return true 表示活动存在且设置成功,false 表示活动不存在
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public boolean setTemplate(String id) {
|
||||
TrainSignUpActivity activity = fetch(id);
|
||||
if (activity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Sys_home_template oldHomeTemplate = dao().fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = activity.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
// 重复设置时保留模板中心人工配置,避免覆盖置顶、推送、排序及模板素材。
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao().insertOrUpdate(sysHomeTemplate);
|
||||
dao().update(TrainSignUpActivity.class,
|
||||
Chain.make("templateStatus", TrainSignUpActivity.TEMPLATE_STATUS_SET),
|
||||
Cnd.where("id", "=", id));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除模板中心记录并将活动恢复为未设置模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void cancelTemplate(String id) {
|
||||
dao().delete(Sys_home_template.class, id);
|
||||
dao().update(TrainSignUpActivity.class,
|
||||
Chain.make("templateStatus", TrainSignUpActivity.TEMPLATE_STATUS_UNSET),
|
||||
Cnd.where("id", "=", id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination mPageData(PageForm pageForm, Integer year, int activityStatus, Integer activityType) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
+12
-48
@@ -7,10 +7,8 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
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.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
import com.budwk.app.sys.models.Sys_home_template;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
@@ -22,6 +20,7 @@ import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collect
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_subjectType;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_worksType;
|
||||
import com.budwk.app.zhgh.activity.workscollection.service.ActivityWorksCollectionService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
@@ -50,7 +49,7 @@ public class ActivityWorksCollectionManageController {
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private BaseService baseService;
|
||||
private ActivityWorksCollectionService activityWorksCollectionService;
|
||||
@Inject
|
||||
private SysMsgService sysMsgService;
|
||||
@Inject
|
||||
@@ -64,31 +63,8 @@ public class ActivityWorksCollectionManageController {
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.manage")
|
||||
public Result pageData(@Valid PageForm pageForm, Long year) {
|
||||
Sql sql = Sqls.create("""
|
||||
select
|
||||
wc.id,
|
||||
wc.name,
|
||||
wc.createdAt,
|
||||
wc.startDateTime,
|
||||
wc.endDateTime,
|
||||
wc.enable,
|
||||
IF(sht.id IS NULL, 0, 1) isTemplate,
|
||||
u.username as userName
|
||||
from
|
||||
activity_works_collection wc
|
||||
LEFT JOIN vw_user u on u.id = wc.createdBy
|
||||
LEFT JOIN sys_home_template sht ON sht.id = wc.id
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("year(startDateTime)", "=", year);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.where().andLike("name", pageForm.getSearchKeyword());
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
public Result pageData(@Valid PageForm pageForm, Long year, Integer templateStatus) {
|
||||
return Result.success(activityWorksCollectionService.pageData(pageForm, year, templateStatus));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -97,27 +73,9 @@ public class ActivityWorksCollectionManageController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
Activity_works_collection worksCollection = dao.fetch(Activity_works_collection.class, id);
|
||||
if (worksCollection == null) {
|
||||
if (!activityWorksCollectionService.setTemplate(id)) {
|
||||
return Result.error("活动不存在");
|
||||
}
|
||||
Sys_home_template oldHomeTemplate = dao.fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = worksCollection.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao.insertOrUpdate(sysHomeTemplate);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -127,7 +85,7 @@ public class ActivityWorksCollectionManageController {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("无权操作");
|
||||
}
|
||||
dao.delete(Sys_home_template.class, id);
|
||||
activityWorksCollectionService.cancelTemplate(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -162,6 +120,8 @@ public class ActivityWorksCollectionManageController {
|
||||
if (worksCollection == null) {
|
||||
return;
|
||||
}
|
||||
// 新建或从模板另存的活动必须进入活动列表,不能继承来源活动的模板状态。
|
||||
worksCollection.setTemplateStatus(Activity_works_collection.TEMPLATE_STATUS_UNSET);
|
||||
worksCollection.setId(null);
|
||||
worksCollection.setCreatedBy(null);
|
||||
worksCollection.setCreatedAt(null);
|
||||
@@ -202,6 +162,10 @@ public class ActivityWorksCollectionManageController {
|
||||
@SaCheckPermission(value = {"activity.workscollection.manage", "activity.workscollection.new"}, mode = SaMode.OR)
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result update(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||
String validateMessage = activityWorksCollectionService.validateReferencedTypesBeforeUpdate(worksCollection);
|
||||
if (StrUtil.isNotBlank(validateMessage)) {
|
||||
return Result.error(validateMessage);
|
||||
}
|
||||
dao.update(worksCollection);
|
||||
dao.updateLinks(worksCollection, "subjectTypes");
|
||||
dao.insertLinks(worksCollection, "subjectTypes");
|
||||
|
||||
+12
@@ -22,6 +22,12 @@ import java.util.List;
|
||||
@Comment("作品征集活动")
|
||||
public class Activity_works_collection extends BaseModel implements SysHomeConvert {
|
||||
|
||||
/** 未设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_UNSET = 0;
|
||||
|
||||
/** 已设置为活动模板。 */
|
||||
public static final int TEMPLATE_STATUS_SET = 1;
|
||||
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@PrevInsert(uu32 = true)
|
||||
@@ -110,6 +116,12 @@ public class Activity_works_collection extends BaseModel implements SysHomeConve
|
||||
@Default(value = "1")
|
||||
private Boolean isSubmit;
|
||||
|
||||
@Column
|
||||
@Comment("模板设置状态(0:未设置,1:已设置)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
@Default("0")
|
||||
private Integer templateStatus;
|
||||
|
||||
@Column
|
||||
@Comment("主办单位")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.budwk.app.zhgh.activity.workscollection.service;
|
||||
|
||||
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.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||
|
||||
/**
|
||||
* 作品征集活动配置服务。
|
||||
*/
|
||||
public interface ActivityWorksCollectionService extends BaseService<Activity_works_collection> {
|
||||
|
||||
/**
|
||||
* 分页查询作品征集活动。
|
||||
*
|
||||
* @param pageForm 分页及关键字参数
|
||||
* @param year 活动年度
|
||||
* @param templateStatus 模板设置状态,为空时不限制
|
||||
* @return 作品征集活动分页数据
|
||||
*/
|
||||
Pagination pageData(PageForm pageForm, Long year, Integer templateStatus);
|
||||
|
||||
/**
|
||||
* 将作品征集活动设置为工作模板,并同步模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
* @return true 表示设置成功,false 表示活动不存在
|
||||
*/
|
||||
boolean setTemplate(String id);
|
||||
|
||||
/**
|
||||
* 取消作品征集活动模板,并同步模板状态。
|
||||
*
|
||||
* @param id 活动ID
|
||||
*/
|
||||
void cancelTemplate(String id);
|
||||
|
||||
/**
|
||||
* 校验编辑活动时删除的主题类型、作品类型是否已被投稿引用。
|
||||
*
|
||||
* @param worksCollection 前端提交的活动及其主题、作品类型配置
|
||||
* @return 校验通过返回 {@code null};校验不通过返回提示信息
|
||||
*/
|
||||
String validateReferencedTypesBeforeUpdate(Activity_works_collection worksCollection);
|
||||
}
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
package com.budwk.app.zhgh.activity.workscollection.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
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_home_template;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_subjectType;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_worksType;
|
||||
import com.budwk.app.zhgh.activity.workscollection.service.ActivityWorksCollectionService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
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 java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 作品征集活动配置服务实现。
|
||||
*/
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class ActivityWorksCollectionServiceImpl extends BaseServiceImpl<Activity_works_collection> implements ActivityWorksCollectionService {
|
||||
|
||||
private final Dao dao;
|
||||
|
||||
public ActivityWorksCollectionServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按年度、关键字及模板状态分页查询作品征集活动。
|
||||
*/
|
||||
@Override
|
||||
public Pagination pageData(PageForm pageForm, Long year, Integer templateStatus) {
|
||||
Sql sql = Sqls.create("""
|
||||
select
|
||||
wc.id,
|
||||
wc.name,
|
||||
wc.createdAt,
|
||||
wc.startDateTime,
|
||||
wc.endDateTime,
|
||||
wc.enable,
|
||||
wc.templateStatus,
|
||||
wc.templateStatus isTemplate,
|
||||
u.username as userName
|
||||
from
|
||||
activity_works_collection wc
|
||||
LEFT JOIN vw_user u on u.id = wc.createdBy
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("year(wc.startDateTime)", "=", year);
|
||||
cnd.andEX("wc.templateStatus", "=", templateStatus);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.where().andLike("wc.name", pageForm.getSearchKeyword());
|
||||
}
|
||||
cnd.desc("wc.createdAt");
|
||||
sql.setCondition(cnd);
|
||||
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将作品征集活动转换为工作模板,并保留模板中心已维护的展示配置。
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public boolean setTemplate(String id) {
|
||||
Activity_works_collection worksCollection = dao.fetch(Activity_works_collection.class, id);
|
||||
if (worksCollection == null) {
|
||||
return false;
|
||||
}
|
||||
Sys_home_template oldHomeTemplate = dao.fetch(Sys_home_template.class, id);
|
||||
Sys_home_template sysHomeTemplate = worksCollection.covertToSysHomeTemplate();
|
||||
if (oldHomeTemplate != null) {
|
||||
// 重复设置时保留模板中心人工配置,避免覆盖置顶、推送、排序及模板素材。
|
||||
sysHomeTemplate.setTop(oldHomeTemplate.getTop());
|
||||
sysHomeTemplate.setPush(oldHomeTemplate.getPush());
|
||||
sysHomeTemplate.setSortNo(oldHomeTemplate.getSortNo());
|
||||
if (oldHomeTemplate.getTemplateName() != null) {
|
||||
sysHomeTemplate.setTemplateName(oldHomeTemplate.getTemplateName());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateIcon() != null) {
|
||||
sysHomeTemplate.setTemplateIcon(oldHomeTemplate.getTemplateIcon());
|
||||
}
|
||||
if (oldHomeTemplate.getTemplateFile() != null) {
|
||||
sysHomeTemplate.setTemplateFile(oldHomeTemplate.getTemplateFile());
|
||||
}
|
||||
}
|
||||
dao.insertOrUpdate(sysHomeTemplate);
|
||||
dao.update(Activity_works_collection.class,
|
||||
Chain.make("templateStatus", Activity_works_collection.TEMPLATE_STATUS_SET),
|
||||
Cnd.where("id", "=", id));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除模板中心记录并将作品征集活动恢复为未设置模板状态。
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void cancelTemplate(String id) {
|
||||
dao.delete(Sys_home_template.class, id);
|
||||
dao.update(Activity_works_collection.class,
|
||||
Chain.make("templateStatus", Activity_works_collection.TEMPLATE_STATUS_UNSET),
|
||||
Cnd.where("id", "=", id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validateReferencedTypesBeforeUpdate(Activity_works_collection worksCollection) {
|
||||
if (worksCollection == null || StrUtil.isBlank(worksCollection.getId())) {
|
||||
return null;
|
||||
}
|
||||
List<Activity_works_subjectType> persistedSubjectTypes = dao.query(Activity_works_subjectType.class,
|
||||
Cnd.where(Activity_works_subjectType::getActivityId, "=", worksCollection.getId()));
|
||||
List<Activity_works_subjectType> submittedSubjectTypes = CollUtil.defaultIfEmpty(worksCollection.getSubjectTypes(), Collections.emptyList());
|
||||
Set<String> submittedSubjectIds = submittedSubjectTypes.stream()
|
||||
.map(Activity_works_subjectType::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
List<Activity_works_subjectType> deletedSubjectTypes = persistedSubjectTypes.stream()
|
||||
.filter(subjectType -> !submittedSubjectIds.contains(subjectType.getId()))
|
||||
.toList();
|
||||
String subjectError = getReferencedSubjectTypeError(worksCollection.getId(), deletedSubjectTypes);
|
||||
if (subjectError != null) {
|
||||
return subjectError;
|
||||
}
|
||||
|
||||
for (Activity_works_subjectType submittedSubjectType : submittedSubjectTypes) {
|
||||
if (submittedSubjectType == null || StrUtil.isBlank(submittedSubjectType.getId())) {
|
||||
continue;
|
||||
}
|
||||
List<Activity_works_worksType> persistedWorksTypes = dao.query(Activity_works_worksType.class,
|
||||
Cnd.where(Activity_works_worksType::getSubjectId, "=", submittedSubjectType.getId()));
|
||||
List<Activity_works_worksType> submittedWorksTypes = CollUtil.defaultIfEmpty(submittedSubjectType.getWorksTypes(), Collections.emptyList());
|
||||
Set<String> submittedWorksIds = submittedWorksTypes.stream()
|
||||
.map(Activity_works_worksType::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
List<Activity_works_worksType> deletedWorksTypes = persistedWorksTypes.stream()
|
||||
.filter(worksType -> !submittedWorksIds.contains(worksType.getId()))
|
||||
.toList();
|
||||
String worksError = getReferencedWorksTypeError(worksCollection.getId(), deletedWorksTypes);
|
||||
if (worksError != null) {
|
||||
return worksError;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验待删除主题类型是否已有投稿,防止投稿的主题类型关联被清空。
|
||||
*/
|
||||
private String getReferencedSubjectTypeError(String activityId, List<Activity_works_subjectType> deletedSubjectTypes) {
|
||||
if (CollUtil.isEmpty(deletedSubjectTypes)) {
|
||||
return null;
|
||||
}
|
||||
List<String> deletedSubjectIds = deletedSubjectTypes.stream()
|
||||
.map(Activity_works_subjectType::getId)
|
||||
.collect(Collectors.toList());
|
||||
List<Activity_works_collection_upload> uploads = dao.query(Activity_works_collection_upload.class,
|
||||
Cnd.where(Activity_works_collection_upload::getActivityId, "=", activityId)
|
||||
.and(Activity_works_collection_upload::getSubjectId, "in", deletedSubjectIds));
|
||||
if (CollUtil.isEmpty(uploads)) {
|
||||
return null;
|
||||
}
|
||||
Set<String> referencedSubjectIds = uploads.stream()
|
||||
.map(Activity_works_collection_upload::getSubjectId)
|
||||
.collect(Collectors.toSet());
|
||||
String typeNames = deletedSubjectTypes.stream()
|
||||
.filter(subjectType -> referencedSubjectIds.contains(subjectType.getId()))
|
||||
.map(Activity_works_subjectType::getTypeName)
|
||||
.collect(Collectors.joining("、"));
|
||||
return "主题类型“" + typeNames + "”下已有投稿,不能删除";
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验待删除作品类型是否已有投稿,防止投稿的作品类型关联被清空。
|
||||
*/
|
||||
private String getReferencedWorksTypeError(String activityId, List<Activity_works_worksType> deletedWorksTypes) {
|
||||
if (CollUtil.isEmpty(deletedWorksTypes)) {
|
||||
return null;
|
||||
}
|
||||
List<String> deletedWorksIds = deletedWorksTypes.stream()
|
||||
.map(Activity_works_worksType::getId)
|
||||
.collect(Collectors.toList());
|
||||
List<Activity_works_collection_upload> uploads = dao.query(Activity_works_collection_upload.class,
|
||||
Cnd.where(Activity_works_collection_upload::getActivityId, "=", activityId)
|
||||
.and(Activity_works_collection_upload::getWorksId, "in", deletedWorksIds));
|
||||
if (CollUtil.isEmpty(uploads)) {
|
||||
return null;
|
||||
}
|
||||
Set<String> referencedWorksIds = uploads.stream()
|
||||
.map(Activity_works_collection_upload::getWorksId)
|
||||
.collect(Collectors.toSet());
|
||||
String typeNames = deletedWorksTypes.stream()
|
||||
.filter(worksType -> referencedWorksIds.contains(worksType.getId()))
|
||||
.map(Activity_works_worksType::getWorksTypeName)
|
||||
.collect(Collectors.joining("、"));
|
||||
return "作品类型“" + typeNames + "”下已有投稿,不能删除";
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package com.budwk.app.zhgh.archive.constant;
|
||||
|
||||
import org.nutz.lang.Strings;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 活动电子档案常量。
|
||||
*/
|
||||
public final class ArchiveConstant {
|
||||
|
||||
public static final int PROJECT_DRAFT = 0;
|
||||
public static final int PROJECT_FILING = 1;
|
||||
public static final int PROJECT_COMPLETED = 2;
|
||||
|
||||
public static final int DOCUMENT_DRAFT = 0;
|
||||
public static final int DOCUMENT_SUBMITTED = 1;
|
||||
|
||||
public static final String STAGE_PREPARE = "PREPARE";
|
||||
public static final String STAGE_PROCESS = "PROCESS";
|
||||
public static final String STAGE_SUMMARY = "SUMMARY";
|
||||
|
||||
public static final Map<String, String> STAGE_LABELS = Map.of(
|
||||
STAGE_PREPARE, "筹备阶段",
|
||||
STAGE_PROCESS, "实施阶段",
|
||||
STAGE_SUMMARY, "总结阶段"
|
||||
);
|
||||
|
||||
private ArchiveConstant() {
|
||||
}
|
||||
|
||||
public static boolean validStage(String stage) {
|
||||
return Strings.isNotBlank(stage) && STAGE_LABELS.containsKey(stage);
|
||||
}
|
||||
|
||||
public static String stageLabel(String stage) {
|
||||
return STAGE_LABELS.getOrDefault(stage, stage);
|
||||
}
|
||||
|
||||
public static String projectStatusLabel(Integer status) {
|
||||
if (status != null && status == PROJECT_COMPLETED) {
|
||||
return "已完成";
|
||||
}
|
||||
if (status != null && status == PROJECT_FILING) {
|
||||
return "归档中";
|
||||
}
|
||||
return "草稿";
|
||||
}
|
||||
|
||||
public static String documentStatusLabel(Integer status) {
|
||||
return status != null && status == DOCUMENT_SUBMITTED ? "已提交归档" : "草稿";
|
||||
}
|
||||
|
||||
public static List<Map<String, String>> stageOptions() {
|
||||
return List.of(
|
||||
Map.of("value", STAGE_PREPARE, "label", STAGE_LABELS.get(STAGE_PREPARE)),
|
||||
Map.of("value", STAGE_PROCESS, "label", STAGE_LABELS.get(STAGE_PROCESS)),
|
||||
Map.of("value", STAGE_SUMMARY, "label", STAGE_LABELS.get(STAGE_SUMMARY))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
package com.budwk.app.zhgh.archive.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.archive.constant.ArchiveConstant;
|
||||
import com.budwk.app.zhgh.archive.model.ArchiveDocType;
|
||||
import com.budwk.app.zhgh.archive.model.ArchiveDocument;
|
||||
import com.budwk.app.zhgh.archive.model.ArchiveProject;
|
||||
import com.budwk.app.zhgh.archive.service.ArchiveService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Strings;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
/**
|
||||
* 活动电子档案。
|
||||
*/
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/archive")
|
||||
@Api(tags = "活动电子档案")
|
||||
public class ArchiveController {
|
||||
|
||||
@Inject
|
||||
private ArchiveService archiveService;
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
@At("/docType")
|
||||
@Ok("beetl:/platform/zhgh/archive/docType/index.html")
|
||||
@SaCheckPermission("archive.docType")
|
||||
public void docTypeIndex() {
|
||||
}
|
||||
|
||||
@At("/docType/pageData")
|
||||
@SaCheckPermission("archive.docType")
|
||||
public Result docTypePageData(PageForm pageForm, String name,
|
||||
String projectStage, Boolean requiredFlag) {
|
||||
return Result.success(archiveService.pageDocTypes(
|
||||
pageForm, name, projectStage, requiredFlag));
|
||||
}
|
||||
|
||||
@At("/docType/listData")
|
||||
public Result docTypeListData(String projectStage) {
|
||||
return Result.success(archiveService.listDocTypes(projectStage));
|
||||
}
|
||||
|
||||
@At("/docType/fetchOne")
|
||||
@SaCheckPermission("archive.docType")
|
||||
public Result docTypeFetchOne(String id) {
|
||||
return Result.success(dao.fetch(ArchiveDocType.class, id));
|
||||
}
|
||||
|
||||
@At("/docType/onSubmit")
|
||||
@SLog(tag = "活动电子档案-文档类型", msg = "新增或修改文档类型")
|
||||
@SaCheckPermission("archive.docType")
|
||||
public Result docTypeOnSubmit(ArchiveDocType docType) {
|
||||
try {
|
||||
archiveService.saveDocType(docType);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At("/docType/onDelete")
|
||||
@SLog(tag = "活动电子档案-文档类型", msg = "删除文档类型")
|
||||
@SaCheckPermission("archive.docType")
|
||||
public Result docTypeOnDelete(String id) {
|
||||
try {
|
||||
archiveService.deleteDocType(id);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At("/project")
|
||||
@Ok("beetl:/platform/zhgh/archive/project/index.html")
|
||||
@SaCheckPermission("archive.project")
|
||||
public void projectIndex() {
|
||||
}
|
||||
|
||||
@At("/project/pageData")
|
||||
@SaCheckPermission("archive.project")
|
||||
public Result projectPageData(PageForm pageForm, Integer year,
|
||||
String projectName, String unionId, Integer status) {
|
||||
return Result.success(archiveService.pageProjects(
|
||||
pageForm, year, projectName, unionId, status));
|
||||
}
|
||||
|
||||
@At("/project/listData")
|
||||
public Result projectListData() {
|
||||
return Result.success(archiveService.listProjects());
|
||||
}
|
||||
|
||||
@At("/project/fetchOne")
|
||||
@SaCheckPermission("archive.project")
|
||||
public Result projectFetchOne(String id) {
|
||||
return Result.success(dao.fetch(ArchiveProject.class, id));
|
||||
}
|
||||
|
||||
@At("/project/onSubmit")
|
||||
@SLog(tag = "活动电子档案-归档项目", msg = "新增或修改归档项目")
|
||||
@SaCheckPermission("archive.project")
|
||||
public Result projectOnSubmit(ArchiveProject project) {
|
||||
try {
|
||||
archiveService.saveProject(project);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At("/project/onDelete")
|
||||
@SLog(tag = "活动电子档案-归档项目", msg = "删除归档项目")
|
||||
@SaCheckPermission("archive.project")
|
||||
public Result projectOnDelete(String id) {
|
||||
try {
|
||||
archiveService.deleteProject(id);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At("/filing")
|
||||
@Ok("beetl:/platform/zhgh/archive/filing/index.html")
|
||||
@SaCheckPermission("archive.filing")
|
||||
public void filingIndex() {
|
||||
}
|
||||
|
||||
@At("/filing/pageData")
|
||||
@SaCheckPermission("archive.filing")
|
||||
public Result filingPageData(PageForm pageForm, String projectId, Integer year,
|
||||
String projectStage, String docTypeId,
|
||||
String documentName, Integer status) {
|
||||
return Result.success(archiveService.pageDocuments(pageForm, projectId, year,
|
||||
projectStage, docTypeId, documentName, status));
|
||||
}
|
||||
|
||||
@At("/filing/fetchOne")
|
||||
@SaCheckPermission("archive.filing")
|
||||
public Result filingFetchOne(String id) {
|
||||
return Result.success(archiveService.fetchDocument(id));
|
||||
}
|
||||
|
||||
@At("/filing/saveDraft")
|
||||
@ApiOperation("保存归档文档草稿")
|
||||
@SLog(tag = "活动电子档案-资料归档", msg = "保存归档文档草稿")
|
||||
@SaCheckPermission("archive.filing")
|
||||
public Result filingSaveDraft(ArchiveDocument document) {
|
||||
return saveDocument(document, false);
|
||||
}
|
||||
|
||||
@At("/filing/submit")
|
||||
@ApiOperation("提交归档文档")
|
||||
@SLog(tag = "活动电子档案-资料归档", msg = "提交归档文档")
|
||||
@SaCheckPermission("archive.filing")
|
||||
public Result filingSubmit(ArchiveDocument document) {
|
||||
return saveDocument(document, true);
|
||||
}
|
||||
|
||||
@At("/filing/onDelete")
|
||||
@SLog(tag = "活动电子档案-资料归档", msg = "删除归档文档")
|
||||
@SaCheckPermission("archive.filing")
|
||||
public Result filingOnDelete(String id) {
|
||||
archiveService.deleteDocument(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At("/ledger")
|
||||
@Ok("beetl:/platform/zhgh/archive/ledger/index.html")
|
||||
@SaCheckPermission("archive.ledger")
|
||||
public void ledgerIndex() {
|
||||
}
|
||||
|
||||
@At("/ledger/pageData")
|
||||
@SaCheckPermission("archive.ledger")
|
||||
public Result ledgerPageData(PageForm pageForm, Integer year,
|
||||
String projectName, String unionId, Integer status) {
|
||||
return Result.success(archiveService.pageProjects(
|
||||
pageForm, year, projectName, unionId, status));
|
||||
}
|
||||
|
||||
@At("/ledger/detail")
|
||||
@SaCheckPermission("archive.ledger")
|
||||
public Result ledgerDetail(PageForm pageForm, String projectId,
|
||||
String projectStage, String docTypeId,
|
||||
String documentName, Integer status) {
|
||||
return Result.success(archiveService.pageDocuments(pageForm, projectId,
|
||||
null, projectStage, docTypeId, documentName, status));
|
||||
}
|
||||
|
||||
@At("/common/stageOptions")
|
||||
public Result stageOptions() {
|
||||
return Result.success(ArchiveConstant.stageOptions());
|
||||
}
|
||||
|
||||
@At("/common/unionOptions")
|
||||
public Result unionOptions() {
|
||||
return Result.success(archiveService.listUnions());
|
||||
}
|
||||
|
||||
private Result saveDocument(ArchiveDocument document, boolean submit) {
|
||||
try {
|
||||
archiveService.saveDocument(document, submit);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.budwk.app.zhgh.archive.model;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableMeta;
|
||||
|
||||
/**
|
||||
* 活动电子档案文档类型。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("act_archive_doc_type")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("活动电子档案文档类型")
|
||||
public class ArchiveDocType extends BaseModel {
|
||||
|
||||
@Name
|
||||
@PrevInsert(uu32 = true)
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("主键")
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 150)
|
||||
@Comment("类型名称")
|
||||
private String name;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("项目阶段")
|
||||
private String projectStage;
|
||||
|
||||
@Column
|
||||
@Comment("排序编号")
|
||||
private Integer sortNo;
|
||||
|
||||
@Column
|
||||
@Comment("是否必选")
|
||||
private Boolean requiredFlag;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 600)
|
||||
@Comment("备注")
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package com.budwk.app.zhgh.archive.model;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableMeta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 活动电子档案归档文档。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("act_archive_document")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("活动电子档案归档文档")
|
||||
public class ArchiveDocument extends BaseModel {
|
||||
|
||||
@Name
|
||||
@PrevInsert(uu32 = true)
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("主键")
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("项目ID")
|
||||
private String projectId;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 300)
|
||||
@Comment("文档名称")
|
||||
private String documentName;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("项目阶段")
|
||||
private String projectStage;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("文档类型ID")
|
||||
private String docTypeId;
|
||||
|
||||
@Column
|
||||
@Comment("文档状态")
|
||||
private Integer status;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
@Comment("上传人")
|
||||
private String uploader;
|
||||
|
||||
@Column
|
||||
@Comment("上传时间")
|
||||
private Long uploadTime;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
@Comment("附件")
|
||||
private List<JSONObject> files;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 600)
|
||||
@Comment("备注")
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.budwk.app.zhgh.archive.model;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.entity.annotation.TableMeta;
|
||||
|
||||
/**
|
||||
* 活动电子档案项目。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("act_archive_project")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("活动电子档案项目")
|
||||
public class ArchiveProject extends BaseModel {
|
||||
|
||||
@Name
|
||||
@PrevInsert(uu32 = true)
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("主键")
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("年度")
|
||||
private Integer year;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 300)
|
||||
@Comment("项目名称")
|
||||
private String projectName;
|
||||
|
||||
@Column
|
||||
@Comment("项目状态")
|
||||
private Integer status;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("所属工会ID")
|
||||
private String unionId;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 150)
|
||||
@Comment("所属工会名称")
|
||||
private String unionName;
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
package com.budwk.app.zhgh.archive.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
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_union;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.archive.constant.ArchiveConstant;
|
||||
import com.budwk.app.zhgh.archive.model.ArchiveDocType;
|
||||
import com.budwk.app.zhgh.archive.model.ArchiveDocument;
|
||||
import com.budwk.app.zhgh.archive.model.ArchiveProject;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
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;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 活动电子档案领域服务。
|
||||
*/
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class ArchiveService extends BaseServiceImpl<ArchiveProject> {
|
||||
|
||||
public ArchiveService(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
public Pagination<NutMap> pageDocTypes(PageForm pageForm, String name,
|
||||
String projectStage, Boolean requiredFlag) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and(Cnd.likeEX("adt.name", name));
|
||||
cnd.andEX("adt.projectStage", "=", projectStage);
|
||||
cnd.andEX("adt.requiredFlag", "=", requiredFlag);
|
||||
cnd.and("adt.delFlag", "=", false);
|
||||
cnd.asc("adt.projectStage").asc("adt.sortNo").asc("adt.createdAt");
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT adt.*,
|
||||
(SELECT COUNT(1)
|
||||
FROM act_archive_document ad
|
||||
WHERE ad.docTypeId = adt.id
|
||||
AND ad.delFlag = 0) AS documentCount
|
||||
FROM act_archive_doc_type adt
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
Pagination<NutMap> page = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
page.getList().forEach(this::enrichDocType);
|
||||
return page;
|
||||
}
|
||||
|
||||
public List<NutMap> listDocTypes(String projectStage) {
|
||||
Cnd cnd = Cnd.where("adt.delFlag", "=", false);
|
||||
cnd.andEX("adt.projectStage", "=", projectStage);
|
||||
cnd.asc("adt.projectStage").asc("adt.sortNo").asc("adt.createdAt");
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT adt.*,
|
||||
(SELECT COUNT(1)
|
||||
FROM act_archive_document ad
|
||||
WHERE ad.docTypeId = adt.id
|
||||
AND ad.delFlag = 0) AS documentCount
|
||||
FROM act_archive_doc_type adt
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> list = listMap(sql);
|
||||
list.forEach(this::enrichDocType);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void saveDocType(ArchiveDocType docType) {
|
||||
if (docType == null || Strings.isBlank(docType.getName())) {
|
||||
throw new IllegalArgumentException("类型名称不能为空");
|
||||
}
|
||||
if (!ArchiveConstant.validStage(docType.getProjectStage())) {
|
||||
throw new IllegalArgumentException("项目阶段不正确");
|
||||
}
|
||||
docType.setName(docType.getName().trim());
|
||||
if (docType.getSortNo() == null) {
|
||||
docType.setSortNo(0);
|
||||
}
|
||||
if (docType.getRequiredFlag() == null) {
|
||||
docType.setRequiredFlag(false);
|
||||
}
|
||||
Cnd duplicate = Cnd.where("projectStage", "=", docType.getProjectStage())
|
||||
.and("name", "=", docType.getName())
|
||||
.and("delFlag", "=", false);
|
||||
if (Strings.isNotBlank(docType.getId())) {
|
||||
duplicate.and("id", "<>", docType.getId());
|
||||
}
|
||||
if (dao().count(ArchiveDocType.class, duplicate) > 0) {
|
||||
throw new IllegalArgumentException("同一项目阶段下类型名称不能重复");
|
||||
}
|
||||
if (Strings.isBlank(docType.getId())) {
|
||||
dao().insert(docType);
|
||||
} else {
|
||||
ArchiveDocType old = dao().fetch(ArchiveDocType.class, docType.getId());
|
||||
if (old == null) {
|
||||
throw new IllegalArgumentException("文档类型不存在");
|
||||
}
|
||||
dao().updateIgnoreNull(docType);
|
||||
}
|
||||
}
|
||||
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void deleteDocType(String id) {
|
||||
if (Strings.isBlank(id)) {
|
||||
return;
|
||||
}
|
||||
if (dao().count(ArchiveDocument.class,
|
||||
Cnd.where("docTypeId", "=", id).and("delFlag", "=", false)) > 0) {
|
||||
throw new IllegalArgumentException("文档类型已被归档文档引用,不能删除");
|
||||
}
|
||||
dao().delete(ArchiveDocType.class, id);
|
||||
}
|
||||
|
||||
public Pagination<NutMap> pageProjects(PageForm pageForm, Integer year,
|
||||
String projectName, String unionId, Integer status) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("ap.year", "=", year);
|
||||
cnd.and(Cnd.likeEX("ap.projectName", projectName));
|
||||
cnd.andEX("ap.unionId", "=", unionId);
|
||||
cnd.andEX("ap.status", "=", status);
|
||||
cnd.and("ap.delFlag", "=", false);
|
||||
cnd.desc("ap.year").desc("ap.createdAt");
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT ap.*,
|
||||
(SELECT COUNT(1)
|
||||
FROM act_archive_document ad
|
||||
WHERE ad.projectId = ap.id
|
||||
AND ad.delFlag = 0) AS documentCount
|
||||
FROM act_archive_project ap
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
Pagination<NutMap> page = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
page.getList().forEach(this::enrichProject);
|
||||
return page;
|
||||
}
|
||||
|
||||
public List<NutMap> listProjects() {
|
||||
Cnd cnd = Cnd.where("ap.delFlag", "=", false);
|
||||
cnd.desc("ap.year").desc("ap.createdAt");
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT ap.*,
|
||||
(SELECT COUNT(1)
|
||||
FROM act_archive_document ad
|
||||
WHERE ad.projectId = ap.id
|
||||
AND ad.delFlag = 0) AS documentCount
|
||||
FROM act_archive_project ap
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> list = listMap(sql);
|
||||
list.forEach(this::enrichProject);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void saveProject(ArchiveProject project) {
|
||||
if (project == null || project.getYear() == null) {
|
||||
throw new IllegalArgumentException("年度不能为空");
|
||||
}
|
||||
if (Strings.isBlank(project.getProjectName())) {
|
||||
throw new IllegalArgumentException("项目名称不能为空");
|
||||
}
|
||||
if (Strings.isBlank(project.getUnionId())) {
|
||||
throw new IllegalArgumentException("所属工会不能为空");
|
||||
}
|
||||
Sys_union union = dao().fetch(Sys_union.class, project.getUnionId());
|
||||
if (union == null) {
|
||||
throw new IllegalArgumentException("所属工会不存在");
|
||||
}
|
||||
project.setProjectName(project.getProjectName().trim());
|
||||
project.setUnionName(union.getName());
|
||||
Cnd duplicate = Cnd.where("year", "=", project.getYear())
|
||||
.and("projectName", "=", project.getProjectName())
|
||||
.and("unionId", "=", project.getUnionId())
|
||||
.and("delFlag", "=", false);
|
||||
if (Strings.isNotBlank(project.getId())) {
|
||||
duplicate.and("id", "<>", project.getId());
|
||||
}
|
||||
if (dao().count(ArchiveProject.class, duplicate) > 0) {
|
||||
throw new IllegalArgumentException("同年度同工会下项目名称不能重复");
|
||||
}
|
||||
if (Strings.isBlank(project.getId())) {
|
||||
project.setStatus(ArchiveConstant.PROJECT_DRAFT);
|
||||
dao().insert(project);
|
||||
} else {
|
||||
ArchiveProject old = dao().fetch(ArchiveProject.class, project.getId());
|
||||
if (old == null) {
|
||||
throw new IllegalArgumentException("归档项目不存在");
|
||||
}
|
||||
project.setStatus(old.getStatus());
|
||||
dao().updateIgnoreNull(project);
|
||||
}
|
||||
}
|
||||
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void deleteProject(String id) {
|
||||
if (Strings.isBlank(id)) {
|
||||
return;
|
||||
}
|
||||
if (dao().count(ArchiveDocument.class,
|
||||
Cnd.where("projectId", "=", id).and("delFlag", "=", false)) > 0) {
|
||||
throw new IllegalArgumentException("项目下已存在归档文档,不能删除");
|
||||
}
|
||||
dao().delete(ArchiveProject.class, id);
|
||||
}
|
||||
|
||||
public Pagination<NutMap> pageDocuments(PageForm pageForm, String projectId, Integer year,
|
||||
String projectStage, String docTypeId,
|
||||
String documentName, Integer status) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("ad.projectId", "=", projectId);
|
||||
cnd.andEX("ap.year", "=", year);
|
||||
cnd.andEX("ad.projectStage", "=", projectStage);
|
||||
cnd.andEX("ad.docTypeId", "=", docTypeId);
|
||||
cnd.and(Cnd.likeEX("ad.documentName", documentName));
|
||||
cnd.andEX("ad.status", "=", status);
|
||||
cnd.and("ad.delFlag", "=", false);
|
||||
cnd.and("ap.delFlag", "=", false);
|
||||
cnd.desc("ap.year").desc("ad.uploadTime").desc("ad.createdAt");
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT ad.*, ap.year, ap.projectName, ap.unionId, ap.unionName,
|
||||
adt.name AS docTypeName, adt.requiredFlag AS docTypeRequiredFlag
|
||||
FROM act_archive_document ad
|
||||
JOIN act_archive_project ap
|
||||
ON ap.id = ad.projectId
|
||||
LEFT JOIN act_archive_doc_type adt
|
||||
ON adt.id = ad.docTypeId
|
||||
AND adt.delFlag = 0
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
Pagination<NutMap> page = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
page.getList().forEach(this::enrichDocument);
|
||||
return page;
|
||||
}
|
||||
|
||||
public NutMap fetchDocument(String id) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT ad.*, ap.year, ap.projectName, ap.unionId, ap.unionName,
|
||||
adt.name AS docTypeName, adt.requiredFlag AS docTypeRequiredFlag
|
||||
FROM act_archive_document ad
|
||||
JOIN act_archive_project ap
|
||||
ON ap.id = ad.projectId
|
||||
LEFT JOIN act_archive_doc_type adt
|
||||
ON adt.id = ad.docTypeId
|
||||
AND adt.delFlag = 0
|
||||
WHERE ad.id = @id
|
||||
AND ad.delFlag = 0
|
||||
AND ap.delFlag = 0
|
||||
""");
|
||||
sql.params().set("id", id);
|
||||
NutMap map = fetchMap(sql);
|
||||
if (map != null) {
|
||||
enrichDocument(map);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void saveDocument(ArchiveDocument document, boolean submit) {
|
||||
validateDocument(document, submit);
|
||||
ArchiveDocument old = Strings.isBlank(document.getId())
|
||||
? null : dao().fetch(ArchiveDocument.class, document.getId());
|
||||
if (Strings.isNotBlank(document.getId()) && old == null) {
|
||||
throw new IllegalArgumentException("归档文档不存在");
|
||||
}
|
||||
int targetStatus = submit ? ArchiveConstant.DOCUMENT_SUBMITTED : ArchiveConstant.DOCUMENT_DRAFT;
|
||||
if (old != null && old.getStatus() != null
|
||||
&& old.getStatus() == ArchiveConstant.DOCUMENT_SUBMITTED && !submit) {
|
||||
targetStatus = ArchiveConstant.DOCUMENT_SUBMITTED;
|
||||
}
|
||||
document.setStatus(targetStatus);
|
||||
if (targetStatus == ArchiveConstant.DOCUMENT_SUBMITTED) {
|
||||
String uploader = SecurityUtil.getUserUsername();
|
||||
if (Strings.isBlank(uploader)) {
|
||||
uploader = SecurityUtil.getUserLoginname();
|
||||
}
|
||||
document.setUploader(uploader);
|
||||
document.setUploadTime(System.currentTimeMillis());
|
||||
} else if (old != null) {
|
||||
document.setUploader(old.getUploader());
|
||||
document.setUploadTime(old.getUploadTime());
|
||||
}
|
||||
String oldProjectId = old == null ? null : old.getProjectId();
|
||||
if (old == null) {
|
||||
dao().insert(document);
|
||||
} else {
|
||||
dao().updateIgnoreNull(document);
|
||||
}
|
||||
refreshProjectStatus(document.getProjectId());
|
||||
if (Strings.isNotBlank(oldProjectId) && !oldProjectId.equals(document.getProjectId())) {
|
||||
refreshProjectStatus(oldProjectId);
|
||||
}
|
||||
}
|
||||
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void deleteDocument(String id) {
|
||||
ArchiveDocument document = dao().fetch(ArchiveDocument.class, id);
|
||||
if (document == null) {
|
||||
return;
|
||||
}
|
||||
dao().delete(ArchiveDocument.class, id);
|
||||
refreshProjectStatus(document.getProjectId());
|
||||
}
|
||||
|
||||
public List<Sys_union> listUnions() {
|
||||
return dao().query(Sys_union.class, Cnd.where("delFlag", "=", false).asc("unionCode"));
|
||||
}
|
||||
|
||||
private void validateDocument(ArchiveDocument document, boolean submit) {
|
||||
if (document == null || Strings.isBlank(document.getProjectId())) {
|
||||
throw new IllegalArgumentException("归档项目不能为空");
|
||||
}
|
||||
if (Strings.isBlank(document.getDocumentName())) {
|
||||
throw new IllegalArgumentException("文档名称不能为空");
|
||||
}
|
||||
ArchiveProject project = dao().fetch(ArchiveProject.class,
|
||||
Cnd.where("id", "=", document.getProjectId()).and("delFlag", "=", false));
|
||||
if (project == null) {
|
||||
throw new IllegalArgumentException("归档项目不存在");
|
||||
}
|
||||
if (!ArchiveConstant.validStage(document.getProjectStage())) {
|
||||
throw new IllegalArgumentException("项目阶段不正确");
|
||||
}
|
||||
document.setDocumentName(document.getDocumentName().trim());
|
||||
if (Strings.isNotBlank(document.getDocTypeId())) {
|
||||
ArchiveDocType docType = dao().fetch(ArchiveDocType.class,
|
||||
Cnd.where("id", "=", document.getDocTypeId()).and("delFlag", "=", false));
|
||||
if (docType == null) {
|
||||
throw new IllegalArgumentException("文档类型不存在");
|
||||
}
|
||||
if (!document.getProjectStage().equals(docType.getProjectStage())) {
|
||||
throw new IllegalArgumentException("文档类型与项目阶段不匹配");
|
||||
}
|
||||
}
|
||||
if (submit && (document.getFiles() == null || document.getFiles().isEmpty())) {
|
||||
throw new IllegalArgumentException("提交归档前请先上传附件");
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshProjectStatus(String projectId) {
|
||||
if (Strings.isBlank(projectId)) {
|
||||
return;
|
||||
}
|
||||
ArchiveProject project = dao().fetch(ArchiveProject.class, projectId);
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
List<ArchiveDocument> submitted = dao().query(ArchiveDocument.class,
|
||||
Cnd.where("projectId", "=", projectId)
|
||||
.and("status", "=", ArchiveConstant.DOCUMENT_SUBMITTED)
|
||||
.and("delFlag", "=", false));
|
||||
int status = ArchiveConstant.PROJECT_DRAFT;
|
||||
if (!submitted.isEmpty()) {
|
||||
List<ArchiveDocType> requiredTypes = dao().query(ArchiveDocType.class,
|
||||
Cnd.where("requiredFlag", "=", true).and("delFlag", "=", false));
|
||||
if (requiredTypes.isEmpty()) {
|
||||
status = ArchiveConstant.PROJECT_FILING;
|
||||
} else {
|
||||
Set<String> submittedKeys = new HashSet<>();
|
||||
submitted.forEach(item -> {
|
||||
if (Strings.isNotBlank(item.getDocTypeId())) {
|
||||
submittedKeys.add(item.getProjectStage() + "_" + item.getDocTypeId());
|
||||
}
|
||||
});
|
||||
boolean completed = requiredTypes.stream().allMatch(item ->
|
||||
submittedKeys.contains(item.getProjectStage() + "_" + item.getId()));
|
||||
status = completed ? ArchiveConstant.PROJECT_COMPLETED : ArchiveConstant.PROJECT_FILING;
|
||||
}
|
||||
}
|
||||
dao().update(ArchiveProject.class, Chain.make("status", status),
|
||||
Cnd.where("id", "=", projectId));
|
||||
}
|
||||
|
||||
private void enrichDocType(NutMap map) {
|
||||
map.put("projectStageLabel", ArchiveConstant.stageLabel(map.getString("projectStage")));
|
||||
}
|
||||
|
||||
private void enrichProject(NutMap map) {
|
||||
map.put("statusLabel", ArchiveConstant.projectStatusLabel(map.getInt("status")));
|
||||
}
|
||||
|
||||
private void enrichDocument(NutMap map) {
|
||||
map.put("projectStageLabel", ArchiveConstant.stageLabel(map.getString("projectStage")));
|
||||
map.put("statusLabel", ArchiveConstant.documentStatusLabel(map.getInt("status")));
|
||||
Object files = map.get("files");
|
||||
if (files == null || StrUtil.isBlank(String.valueOf(files))) {
|
||||
map.put("files", Collections.emptyList());
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -76,7 +76,8 @@ public class ClubExamineApplyController {
|
||||
if(year == null) {
|
||||
return Result.error("年份信息为空,请核查");
|
||||
}
|
||||
List<SysClubExamineRegister> list = dao.query(SysClubExamineRegister.class, Cnd.where("clubId", "=", clubId).and("year(registerDate)", "=", year).andEX("id", "!=", id));
|
||||
// 同一社团的年度重复申请校验以登记年度为准,不能按申请时间判断。
|
||||
List<SysClubExamineRegister> list = dao.query(SysClubExamineRegister.class, Cnd.where("clubId", "=", clubId).and("year", "=", year).andEX("id", "!=", id));
|
||||
List<ProcessInstance> instanceList = dao.query(
|
||||
ProcessInstance.class,
|
||||
Cnd.where(ProcessInstance::getBusinessNo, "in", list.stream().map(SysClubExamineRegister::getId).toList())
|
||||
@@ -146,8 +147,9 @@ public class ClubExamineApplyController {
|
||||
if(StrUtil.isBlank(clubId)) {
|
||||
return Result.error("社团信息为空,请核查");
|
||||
}
|
||||
// 上年度结余按登记年度查询,避免申请时间跨年导致取错数据。
|
||||
SysClubExamineRegister register = dao.fetch(SysClubExamineRegister.class, Cnd.where("clubId", "=", clubId)
|
||||
.and("YEAR(registerDate)", "=", DateUtil.thisYear() - 1));
|
||||
.and("year", "=", DateUtil.thisYear() - 1));
|
||||
if (Lang.isNotEmpty(register)) {
|
||||
List<JSONObject> list = register.getIncomeCensus();
|
||||
float surplus = list.get(0).getFloat("surplus");
|
||||
|
||||
+2
-1
@@ -87,7 +87,8 @@ public class ClubExamineMineController {
|
||||
nutMap.setv("clubName", register.getClubName());
|
||||
nutMap.setv("create_time", register.getFoundTime());
|
||||
nutMap.setv("dues_standard", register.getDue());
|
||||
nutMap.setv("year", register.getRegisterDate().substring(0, 4));
|
||||
// 生成材料中的年度与列表展示的登记年度保持一致。
|
||||
nutMap.setv("year", register.getYear());
|
||||
nutMap.setv("registerDate", register.getRegisterDate());
|
||||
nutMap.setv("incomeCensus", incomeCensus);
|
||||
nutMap.setv("jgUser", jgUser);
|
||||
|
||||
+3
-1
@@ -90,10 +90,12 @@ public class ClubAuditManagerController {
|
||||
cnd.andEX("year(info.creatTime)", "=", pageForm.getYear());
|
||||
|
||||
cnd.and("t.taskName", "=", "ef81777f-22fb-4fe4-9800-909e6c681210");
|
||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||
if (approval) {
|
||||
// 已审核是全量历史,不能因历史工作流参与人不同而遗漏参考库迁移记录。
|
||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
} else {
|
||||
// 未审核只展示当前登录人实际可以处理的待办任务。
|
||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -200,6 +200,7 @@ public class ClubInfoManageController {
|
||||
@SLog(tag = "社团管理系统-信息管理", msg = "修改身份")
|
||||
public Result updateRoleCode(@Param("id") String id, @Valid String[] roleCodes, @Valid String clubId) {
|
||||
List<String> roleCodeList = Arrays.asList(roleCodes);
|
||||
ClubUser clubUser = clubInfoManageService.dao().fetch(ClubUser.class, id);
|
||||
//查询社团是否存在会长或者秘书长
|
||||
if(Arrays.asList(roleCodes).contains(RoleConstant.CLUB_PRESIDENT.name())) {
|
||||
int count = dao.count(ClubUser.class, Cnd.where("clubId", "=", clubId)
|
||||
@@ -210,14 +211,14 @@ public class ClubInfoManageController {
|
||||
}
|
||||
if(Arrays.asList(roleCodes).contains(RoleConstant.CLUB_SECRETARY.name())) {
|
||||
int count = dao.count(ClubUser.class, Cnd.where("clubId", "=", clubId)
|
||||
.and("id", "!=", id)
|
||||
.and(new Static("JSON_CONTAINS(roleCode, '\"%s\"')".formatted(RoleConstant.CLUB_SECRETARY.name()))));
|
||||
if (count > 0) {
|
||||
// return Result.error("秘书长只能有一位");
|
||||
return Result.error("秘书长只能有一位");
|
||||
}
|
||||
}
|
||||
|
||||
ClubUser clubUser = clubInfoManageService.dao().fetch(ClubUser.class, id);
|
||||
|
||||
// 先清除所有的角色
|
||||
dao.clear(Sys_user_role.class, Cnd.where("userId", "=", clubUser.getUserId()).and("clubId", "=", clubUser.getClubId()));
|
||||
// 再根据传过来的赋值
|
||||
|
||||
+145
-3
@@ -2,10 +2,14 @@ package com.budwk.app.zhgh.club.controller.infoManage;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.sys.models.Sys_file;
|
||||
import com.budwk.app.sys.utils.SysFileMinIoUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.club.param.ClubUserPageForm;
|
||||
import com.budwk.app.zhgh.club.service.SysClubInfoManageService;
|
||||
@@ -14,12 +18,24 @@ import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* @Author: JyuHsin
|
||||
@@ -32,6 +48,8 @@ import java.util.List;
|
||||
@At("/platform/club/infoManage/schoolAuditReport")
|
||||
public class ClubSchoolAuditReportController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ClubSchoolAuditReportController.class);
|
||||
|
||||
@Inject
|
||||
private SysClubInfoManageService clubInfoManageService;
|
||||
|
||||
@@ -44,6 +62,71 @@ public class ClubSchoolAuditReportController {
|
||||
@SaCheckPermission("club.infoManage.schoolAuditReport")
|
||||
public Result pageData(@Valid ClubUserPageForm pageForm,
|
||||
@Param(value = "approval") Boolean approval) {
|
||||
Sql sql = buildPageDataSql(pageForm, approval);
|
||||
Pagination pagination = clubInfoManageService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出当前筛选范围内的换届报告附件压缩包。
|
||||
*
|
||||
* @param pageForm 页面查询条件
|
||||
* @param approval 审核状态,与列表页保持一致
|
||||
* @param response HTTP 下载响应
|
||||
*/
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("club.infoManage.schoolAuditReport")
|
||||
public void exportRefreshReportZip(@Valid ClubUserPageForm pageForm,
|
||||
@Param(value = "approval") Boolean approval,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<NutMap> reportList = clubInfoManageService.listMap(buildPageDataSql(pageForm, approval));
|
||||
response.setContentType("application/zip");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode("换届报告.zip"));
|
||||
|
||||
// 显式指定 UTF-8,确保压缩包内中文目录和文件名正常显示。
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()), StandardCharsets.UTF_8)) {
|
||||
Set<String> entryNames = new HashSet<>();
|
||||
for (NutMap report : reportList) {
|
||||
String filesJson = report.getString("files");
|
||||
if (StrUtil.isBlank(filesJson)) {
|
||||
continue;
|
||||
}
|
||||
List<JSONObject> files = Json.fromJsonAsList(JSONObject.class, filesJson);
|
||||
String folderName = buildFolderName(report);
|
||||
for (int index = 0; index < files.size(); index++) {
|
||||
JSONObject fileInfo = files.get(index);
|
||||
Sys_file sysFile = findSysFile(fileInfo);
|
||||
if (sysFile == null) {
|
||||
log.warn("换届报告附件不存在,报告ID:{},附件:{}", report.getString("id"), fileInfo);
|
||||
continue;
|
||||
}
|
||||
byte[] fileBytes = SysFileMinIoUtil.getFileBytes(sysFile.getBucket(), sysFile.getStoragePath());
|
||||
if (fileBytes == null || fileBytes.length == 0) {
|
||||
log.warn("换届报告附件内容为空,报告ID:{},附件ID:{}", report.getString("id"), sysFile.getId());
|
||||
continue;
|
||||
}
|
||||
String fileName = StrUtil.blankToDefault(fileInfo.getStr("name"), fileInfo.getStr("filename"));
|
||||
if (StrUtil.isBlank(fileName)) {
|
||||
fileName = sysFile.getName();
|
||||
}
|
||||
String entryName = buildUniqueEntryName(folderName + "/" + sanitizeFileName(fileName), entryNames);
|
||||
zipOutputStream.putNextEntry(new ZipEntry(entryName));
|
||||
zipOutputStream.write(fileBytes);
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建列表与导出共用的换届报告查询,确保“查什么导什么”。
|
||||
*
|
||||
* @param pageForm 页面查询条件
|
||||
* @param approval 审核状态
|
||||
* @return 已绑定筛选条件的查询对象
|
||||
*/
|
||||
private Sql buildPageDataSql(ClubUserPageForm pageForm, Boolean approval) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.*,
|
||||
@@ -79,7 +162,7 @@ public class ClubSchoolAuditReportController {
|
||||
|
||||
cnd.and("t.taskName", "=", "d4323546-8d09-419e-88d4-7b15862ca29d");
|
||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||
if (approval) {
|
||||
if (Boolean.TRUE.equals(approval)) {
|
||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
} else {
|
||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
@@ -96,8 +179,67 @@ public class ClubSchoolAuditReportController {
|
||||
|
||||
cnd.groupBy("t.id");
|
||||
sql.setCondition(cnd);
|
||||
return sql;
|
||||
}
|
||||
|
||||
Pagination pagination = clubInfoManageService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
/**
|
||||
* 兼容新旧附件 JSON 结构,按附件 ID 或下载地址查找文件元数据。
|
||||
*
|
||||
* @param fileInfo 附件 JSON 信息
|
||||
* @return 系统文件记录;未找到时返回 null
|
||||
*/
|
||||
private Sys_file findSysFile(JSONObject fileInfo) {
|
||||
String fileId = fileInfo.getStr("id");
|
||||
if (StrUtil.isNotBlank(fileId)) {
|
||||
return clubInfoManageService.dao().fetch(Sys_file.class, fileId);
|
||||
}
|
||||
String fileUrl = fileInfo.getStr("url");
|
||||
if (StrUtil.isBlank(fileUrl)) {
|
||||
return null;
|
||||
}
|
||||
return clubInfoManageService.dao().fetch(Sys_file.class, Cnd.where(Sys_file::getDownloadPath, "=", fileUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用社团名称建立目录,方便按换届报告来源查阅。
|
||||
*
|
||||
* @param report 换届报告记录
|
||||
* @return Zip 内目录名称
|
||||
*/
|
||||
private String buildFolderName(NutMap report) {
|
||||
return sanitizeFileName(report.getString("clubName"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保留附件原始文件名;同一社团目录存在同名文件时追加序号,避免覆盖。
|
||||
*
|
||||
* @param entryName 原始 Zip 条目名称
|
||||
* @param entryNames 已写入的 Zip 条目名称
|
||||
* @return 唯一的 Zip 条目名称
|
||||
*/
|
||||
private String buildUniqueEntryName(String entryName, Set<String> entryNames) {
|
||||
if (entryNames.add(entryName)) {
|
||||
return entryName;
|
||||
}
|
||||
int extensionIndex = entryName.lastIndexOf('.');
|
||||
String name = extensionIndex > entryName.lastIndexOf('/') ? entryName.substring(0, extensionIndex) : entryName;
|
||||
String extension = extensionIndex > entryName.lastIndexOf('/') ? entryName.substring(extensionIndex) : "";
|
||||
int index = 2;
|
||||
String uniqueEntryName;
|
||||
do {
|
||||
uniqueEntryName = name + "(" + index + ")" + extension;
|
||||
index++;
|
||||
} while (!entryNames.add(uniqueEntryName));
|
||||
return uniqueEntryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除 Zip 条目路径分隔符,避免附件名影响压缩包目录结构。
|
||||
*
|
||||
* @param fileName 原始文件名
|
||||
* @return 可安全写入 Zip 的文件名
|
||||
*/
|
||||
private String sanitizeFileName(String fileName) {
|
||||
return StrUtil.blankToDefault(fileName, "未命名文件").replace("/", "_").replace("\\", "_");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,14 @@ public class SysClubExamineRegister extends BaseModel {
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<JSONObject> yearActivityList;
|
||||
|
||||
/**
|
||||
* 旧版年审表保存的年度活动明细,保留该字段用于查看迁移历史数据。
|
||||
*/
|
||||
@Column
|
||||
@Comment("旧版年度活动明细")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<JSONObject> yearActivitys;
|
||||
|
||||
@Column
|
||||
@Comment("财务收支情况统计json")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
|
||||
@@ -24,6 +24,10 @@ public class ClubUserPageForm extends PageForm {
|
||||
private Integer auditType;
|
||||
private Integer source;
|
||||
private Integer year;
|
||||
/** 社团评优申报开始年度筛选条件。 */
|
||||
private String applyStartYear;
|
||||
/** 社团评优申报结束年度筛选条件。 */
|
||||
private String applyEndYear;
|
||||
private Boolean giveMoney;
|
||||
private Integer radioType;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,9 @@ public class SysClubEvaluateServiceImpl extends BaseServiceImpl<SysClubEvaluate>
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
cnd.andEX("info.clubId", "=", pageForm.getClubId());
|
||||
cnd.andEX("year(info.applyTime)", "=", pageForm.getYear());
|
||||
// 评优年度以申报填写的起止年度为准,不能使用申请提交时间所在年份代替。
|
||||
cnd.andEX("info.applyStartYear", "=", pageForm.getApplyStartYear());
|
||||
cnd.andEX("info.applyEndYear", "=", pageForm.getApplyEndYear());
|
||||
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
||||
|
||||
cnd.groupBy("info.id");
|
||||
@@ -144,7 +146,9 @@ public class SysClubEvaluateServiceImpl extends BaseServiceImpl<SysClubEvaluate>
|
||||
""");
|
||||
|
||||
cnd.andEX("ce.clubId", "=", pageForm.getClubId());
|
||||
cnd.andEX("year(ce.applyTime)", "=", pageForm.getYear());
|
||||
// 审核列表与参考项目保持一致,分别按申报开始年度和申报结束年度筛选。
|
||||
cnd.andEX("ce.applyStartYear", "=", pageForm.getApplyStartYear());
|
||||
cnd.andEX("ce.applyEndYear", "=", pageForm.getApplyEndYear());
|
||||
|
||||
if (pageForm.getAudit()) {
|
||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
|
||||
+168
-11
@@ -8,6 +8,7 @@ import com.budwk.app.base.constant.RoleConstant;
|
||||
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.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
@@ -33,8 +34,10 @@ import org.nutz.lang.util.NutMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
@@ -119,6 +122,7 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
||||
Sql applySql = Sqls.create("""
|
||||
SELECT
|
||||
cu.userId,
|
||||
cu.id,
|
||||
cu.mode,
|
||||
cu.applyDate,
|
||||
cu.joinTime,
|
||||
@@ -129,17 +133,25 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
||||
LEFT JOIN sys_user u ON u.id = cu.userId
|
||||
WHERE cu.clubId = @clubId
|
||||
AND COALESCE(cu.delFlag, 0) = 0
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM wf_process_instance ins
|
||||
WHERE ins.businessNo = cu.id
|
||||
AND ins.state = @finishedState
|
||||
)
|
||||
ORDER BY cu.applyDate, cu.mode
|
||||
""")
|
||||
.setParam("clubId", clubId)
|
||||
.setParam("finishedState", ProcessInstanceStateEnum.FINISHED.getCode());
|
||||
.setParam("clubId", clubId);
|
||||
List<NutMap> applications = listMap(applySql);
|
||||
if (!applications.isEmpty()) {
|
||||
// 流程状态改为按当前社团申请批量查询,避免相关子查询对流程实例表重复扫描。
|
||||
List<String> applicationIds = applications.stream()
|
||||
.map(application -> application.getString("id"))
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toList());
|
||||
List<ProcessInstance> finishedInstances = applicationIds.isEmpty() ? new ArrayList<>()
|
||||
: dao().query(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "in", applicationIds)
|
||||
.and(ProcessInstance::getState, "=", ProcessInstanceStateEnum.FINISHED.getCode()));
|
||||
Set<String> finishedBusinessNos = finishedInstances.stream()
|
||||
.map(ProcessInstance::getBusinessNo)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
applications.removeIf(application -> !finishedBusinessNos.contains(application.getString("id")));
|
||||
}
|
||||
applications.sort(Comparator.comparing(row -> row.getTime("applyDate"), Comparator.nullsLast(Date::compareTo)));
|
||||
|
||||
for (NutMap application : applications) {
|
||||
@@ -259,6 +271,10 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
||||
}
|
||||
|
||||
private String normalizeUserState(String userState) {
|
||||
// 历史成员数据可能未同步人员状态,空值不参与在职、退休人数统计。
|
||||
if (StrUtil.isBlank(userState)) {
|
||||
return null;
|
||||
}
|
||||
if (List.of("在职", "在岗").contains(userState)) {
|
||||
return "在职";
|
||||
}
|
||||
@@ -291,7 +307,7 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
||||
|
||||
@Override
|
||||
public List<NutMap> getJgUser(String clubId) {
|
||||
// 构建社团管理人员查询SQL(排除普通成员,按职务排序)
|
||||
// 构建社团成员查询SQL,理事机构成员优先展示,普通成员随后展示。
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
cl.*,
|
||||
@@ -304,7 +320,6 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
||||
LEFT JOIN `vw_user` u ON cl.userId = u.id
|
||||
WHERE
|
||||
cl.clubId = @clubId
|
||||
AND NOT JSON_CONTAINS(cl.roleCode, '"CLUB_MEMBER"')
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN JSON_CONTAINS(cl.roleCode, '"CLUB_PRESIDENT"') THEN 1
|
||||
@@ -477,13 +492,154 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
||||
// 查询主表数据并关联明细数据
|
||||
ClubExamineVo clubExamineVo = fetchVO(sql, ClubExamineVo.class);
|
||||
if (Lang.isNotEmpty(clubExamineVo)) {
|
||||
// 详情页统一使用V4字段,兼容尚未改写JSON内容的V3年审记录。
|
||||
normalizeActivityData(clubExamineVo);
|
||||
List<SysClubExamineRegisterDetailed> detailedList = dao().query(SysClubExamineRegisterDetailed.class,
|
||||
Cnd.where("registerId", "=", id).asc("location"));
|
||||
clubExamineVo.setDetailedList(detailedList);
|
||||
// V3年审审核记录已迁入audit表,作为V4工作流历史为空时的详情回显数据。
|
||||
Sql legacyAuditSql = Sqls.create("""
|
||||
SELECT
|
||||
a.id,
|
||||
a.username AS userName,
|
||||
a.loginname AS loginName,
|
||||
a.auditTime,
|
||||
a.auditPass,
|
||||
a.auditOpinion,
|
||||
a.auditSign,
|
||||
CASE
|
||||
WHEN a.id = scer.clubAuditId THEN '社团审核'
|
||||
WHEN a.id = scer.clubLeaderAuditId THEN '会长审核'
|
||||
WHEN a.id = scer.schoolAuditId THEN '校工会审核'
|
||||
END AS auditName
|
||||
FROM
|
||||
sys_club_examine_register scer
|
||||
INNER JOIN audit a ON a.id IN (scer.clubAuditId, scer.clubLeaderAuditId, scer.schoolAuditId)
|
||||
WHERE
|
||||
scer.id = @id
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN a.id = scer.clubAuditId THEN 1
|
||||
WHEN a.id = scer.clubLeaderAuditId THEN 2
|
||||
WHEN a.id = scer.schoolAuditId THEN 3
|
||||
ELSE 99
|
||||
END
|
||||
""").setParam("id", id);
|
||||
clubExamineVo.setLegacyAuditRecords(listMap(legacyAuditSql));
|
||||
}
|
||||
return clubExamineVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将旧版年审活动和计划字段转换为查看页统一使用的V4字段,避免历史数据在页面中显示为空。
|
||||
*
|
||||
* @param examineVo 年审详情
|
||||
*/
|
||||
private void normalizeActivityData(ClubExamineVo examineVo) {
|
||||
examineVo.setSummaryFiles(normalizeSummaryFiles(examineVo.getSummaryFiles()));
|
||||
examineVo.setChangeUserNum(normalizeChangeUserNum(examineVo.getChangeUserNum()));
|
||||
List<JSONObject> yearActivitySource = examineVo.getYearActivityList();
|
||||
if (yearActivitySource == null || yearActivitySource.isEmpty()) {
|
||||
yearActivitySource = examineVo.getYearActivitys();
|
||||
}
|
||||
examineVo.setYearActivityList(yearActivitySource == null ? new ArrayList<>()
|
||||
: yearActivitySource.stream()
|
||||
.map(item -> normalizeActivityItem(item, true))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
List<JSONObject> planSource = examineVo.getPlans();
|
||||
examineVo.setPlans(planSource == null ? new ArrayList<>()
|
||||
: planSource.stream()
|
||||
.map(item -> normalizeActivityItem(item, false))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将V3年审记录中的年度减少字段转换为查看页统一使用的V4字段。
|
||||
* 历史年审必须展示申请时保存的数据,不能按当前会员状态重新统计。
|
||||
*
|
||||
* @param changeUserNum 年审记录保存的成员变化数据
|
||||
* @return 兼容V3、V4字段的成员变化数据
|
||||
*/
|
||||
private List<JSONObject> normalizeChangeUserNum(List<JSONObject> changeUserNum) {
|
||||
if (changeUserNum == null || changeUserNum.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return changeUserNum.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.peek(item -> {
|
||||
if (!item.containsKey("yearReduceNum") && item.containsKey("yearEditNum")) {
|
||||
item.set("yearReduceNum", item.get("yearEditNum"));
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将V3工作总结附件的文件主键包装为V4文件预览组件所需的response.data格式。
|
||||
*
|
||||
* @param summaryFiles 原始工作总结附件
|
||||
* @return 可供文件预览组件读取的附件数据
|
||||
*/
|
||||
private List<JSONObject> normalizeSummaryFiles(List<JSONObject> summaryFiles) {
|
||||
if (summaryFiles == null || summaryFiles.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return summaryFiles.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(file -> {
|
||||
JSONObject response = file.getJSONObject("response");
|
||||
if (response != null && StrUtil.isNotBlank(response.getStr("data"))) {
|
||||
return file;
|
||||
}
|
||||
String fileId = file.getStr("id");
|
||||
if (StrUtil.isBlank(fileId)) {
|
||||
return null;
|
||||
}
|
||||
JSONObject normalizedFile = new JSONObject();
|
||||
normalizedFile.set("response", new JSONObject().set("data", fileId));
|
||||
return normalizedFile;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容V3活动字段(hdsj、mc、zbdw、hddd、cjrs、hjqk)和V4活动字段。
|
||||
*
|
||||
* @param source 原始活动或计划数据
|
||||
* @param includeResult 是否包含本年度活动的参加人数和获奖情况
|
||||
* @return 供查看页使用的统一字段数据
|
||||
*/
|
||||
private JSONObject normalizeActivityItem(JSONObject source, boolean includeResult) {
|
||||
JSONObject item = new JSONObject();
|
||||
item.set("activityName", getActivityValue(source, "activityName", "mc"));
|
||||
item.set("activityUnit", getActivityValue(source, "activityUnit", "zbdw"));
|
||||
item.set("activityAddress", getActivityValue(source, "activityAddress", "hddd"));
|
||||
if (includeResult) {
|
||||
item.set("activityTime", getActivityValue(source, "activityTime", "hdsj"));
|
||||
item.set("joinNum", getActivityValue(source, "joinNum", "cjrs"));
|
||||
item.set("prize", getActivityValue(source, "prize", "hjqk"));
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* 优先读取V4字段;历史记录没有该字段时回退读取对应的V3字段。
|
||||
*
|
||||
* @param source 原始JSON数据
|
||||
* @param currentField V4字段名
|
||||
* @param legacyField V3字段名
|
||||
* @return 兼容后的字段值
|
||||
*/
|
||||
private String getActivityValue(JSONObject source, String currentField, String legacyField) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
String currentValue = source.getStr(currentField);
|
||||
return StrUtil.isNotBlank(currentValue) ? currentValue : source.getStr(legacyField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> getYearActivityExportData(String id) {
|
||||
ClubExamineVo examineVo = this.findOne(id);
|
||||
@@ -591,7 +747,8 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl<SysClubExamineReg
|
||||
*/
|
||||
private void buildPageBaseCondition(Cnd cnd, ClubUserPageForm pageForm, String tableAlias) {
|
||||
if (pageForm.getYear() != null) {
|
||||
cnd.andEX("YEAR(" + tableAlias + ".registerDate)", "=", pageForm.getYear());
|
||||
// 年度查询应与列表展示的登记年度保持一致,不能使用申请时间推算年度。
|
||||
cnd.andEX(tableAlias + ".year", "=", pageForm.getYear());
|
||||
}
|
||||
if (StrUtil.isNotBlank(pageForm.getClubId())) {
|
||||
cnd.andEX(tableAlias + ".clubId", "=", pageForm.getClubId());
|
||||
|
||||
+110
-77
@@ -86,7 +86,7 @@ public class SysClubInfoManageServiceImpl extends BaseServiceImpl<ClubCommonPage
|
||||
scu.clubId = c.id
|
||||
) currentNum,
|
||||
GROUP_CONCAT(DISTINCT presidentUser.username) AS clubLeader,
|
||||
GROUP_CONCAT(secretaryUser.username) AS clubSecretary
|
||||
GROUP_CONCAT(DISTINCT secretaryUser.username) AS clubSecretary
|
||||
FROM
|
||||
sys_club c
|
||||
LEFT JOIN club_user presidentCu on presidentCu.clubId = c.id AND JSON_CONTAINS(presidentCu.roleCode, '"CLUB_PRESIDENT"')
|
||||
@@ -229,23 +229,19 @@ public class SysClubInfoManageServiceImpl extends BaseServiceImpl<ClubCommonPage
|
||||
public Pagination<ClubUserCommonPageVo> exitManagePageData(ClubUserPageForm pageForm) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
COALESCE(info.id, scu.id) AS id,
|
||||
scu.clubId,
|
||||
scu.userId,
|
||||
COALESCE(info.roleCode, scu.roleCode) AS applyRoleCode,
|
||||
COALESCE(info.clubPosition, scu.position) AS clubPosition,
|
||||
COALESCE(info.email, scu.email, u.email) AS email,
|
||||
COALESCE(info.mobile, u.mobile) AS mobile,
|
||||
COALESCE(info.birthday, u.birthday) AS birthday,
|
||||
COALESCE(info.avatar, scu.avatar, u.avatar) AS avatar,
|
||||
COALESCE(info.sameTimeJoinOtherClubSituation, scu.sameTimeJoinOtherClubSituation) AS sameTimeJoinOtherClubSituation,
|
||||
COALESCE(info.awardsExperience, scu.awardsExperience) AS awardsExperience,
|
||||
info.signature,
|
||||
COALESCE(
|
||||
info.applyDate,
|
||||
STR_TO_DATE(scu.changeTime, '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(JSON_UNQUOTE(JSON_EXTRACT(scu.exitAuditList, '$[0].auditTime')), '%Y-%m-%d %H:%i:%s')
|
||||
) AS applyDate,
|
||||
exitInfo.id,
|
||||
exitInfo.clubId,
|
||||
exitInfo.userId,
|
||||
exitInfo.applyRoleCode,
|
||||
exitInfo.clubPosition,
|
||||
COALESCE(exitInfo.email, u.email) AS email,
|
||||
COALESCE(exitInfo.mobile, u.mobile) AS mobile,
|
||||
COALESCE(exitInfo.birthday, u.birthday) AS birthday,
|
||||
COALESCE(exitInfo.avatar, u.avatar) AS avatar,
|
||||
exitInfo.sameTimeJoinOtherClubSituation,
|
||||
exitInfo.awardsExperience,
|
||||
exitInfo.signature,
|
||||
exitInfo.applyDate,
|
||||
u.username AS userName,
|
||||
u.loginname AS loginName,
|
||||
u.sex,
|
||||
@@ -253,32 +249,14 @@ public class SysClubInfoManageServiceImpl extends BaseServiceImpl<ClubCommonPage
|
||||
u.userState,
|
||||
club.clubName,
|
||||
u.unitname AS unitName,
|
||||
COALESCE(scu.joinTime, DATE_FORMAT(club.foundTime, '%Y-%m-%d %H:%i:%s')) AS joinTime,
|
||||
COALESCE(
|
||||
DATE_FORMAT(info.exitTime, '%Y-%m-%d %H:%i:%s'),
|
||||
JSON_UNQUOTE(JSON_EXTRACT(scu.exitAuditList, '$[0].auditTime')),
|
||||
scu.changeTime
|
||||
) AS exitTime,
|
||||
IF(info.id IS NULL, 'DIRECT_REMOVE', 'AUDIT_EXIT') AS exitType,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo,
|
||||
ins.state instanceState,
|
||||
ins.variable instanceVariable,
|
||||
ins.processDefineId instanceProcessDefineId
|
||||
FROM
|
||||
sys_club_user scu
|
||||
LEFT JOIN club_user_apply info ON info.clubId = scu.clubId
|
||||
AND info.userId = scu.userId
|
||||
AND info.mode = false
|
||||
LEFT JOIN sys_club club ON club.id = scu.clubId
|
||||
INNER JOIN vw_user u ON u.id = scu.userId
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
AND ins.state = 20
|
||||
DATE_FORMAT(COALESCE(exitInfo.joinTime, STR_TO_DATE(club.foundTime, '%Y-%m-%d')), '%Y-%m-%d %H:%i:%s') AS joinTime,
|
||||
DATE_FORMAT(exitInfo.exitTime, '%Y-%m-%d %H:%i:%s') AS exitTime,
|
||||
exitInfo.exitType
|
||||
""" + getExitManageBaseSql() + """
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("scu.isNormal", "=", false);
|
||||
cnd.andEX("scu.clubId", "=", pageForm.getClubId());
|
||||
cnd.andEX("exitInfo.clubId", "=", pageForm.getClubId());
|
||||
cnd.andEX("u.personType", "=", pageForm.getPersonType());
|
||||
cnd.andEX("u.userState", "=", pageForm.getUserState());
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
@@ -287,9 +265,9 @@ public class SysClubInfoManageServiceImpl extends BaseServiceImpl<ClubCommonPage
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.SCHOOL_UNION_CLUB_ADMIN.name())) {
|
||||
List<String> clubIdList = commonService.findUserRoleByRoleCode(List.of(RoleConstant.CLUB_PRESIDENT.name(), RoleConstant.CLUB_VICE_PRESIDENT.name(), RoleConstant.CLUB_SECRETARY.name(), RoleConstant.CLUB_VICE_SECRETARY.name(), RoleConstant.CLUB_OPERATOR.name()));
|
||||
List<Sys_user_role> clubList = dao().query(Sys_user_role.class, Cnd.where("roleId", "in", clubIdList).and("userId", "=", SecurityUtil.getUserId()).and("clubId", "is not", null));
|
||||
cnd.and("scu.clubId", "in", clubList.stream().map(Sys_user_role::getClubId).toList());
|
||||
cnd.and("exitInfo.clubId", "in", clubList.stream().map(Sys_user_role::getClubId).toList());
|
||||
}
|
||||
cnd.groupBy("scu.id");
|
||||
cnd.groupBy("exitInfo.id");
|
||||
cnd.desc("exitTime");
|
||||
sql.setCondition(cnd);
|
||||
Pagination<ClubUserCommonPageVo> pagination = listPageVO(pageForm, sql, ClubUserCommonPageVo.class);
|
||||
@@ -307,55 +285,110 @@ public class SysClubInfoManageServiceImpl extends BaseServiceImpl<ClubCommonPage
|
||||
public ClubUserJoinVo exitManageInfo(String id) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
COALESCE(cua.id, scu.id) AS id,
|
||||
scu.clubId,
|
||||
scu.userId,
|
||||
COALESCE(cua.roleCode, scu.roleCode) AS roleCode,
|
||||
COALESCE(cua.clubPosition, scu.position) AS clubPosition,
|
||||
COALESCE(cua.email, scu.email, u.email) AS email,
|
||||
COALESCE(cua.mobile, u.mobile) AS mobile,
|
||||
COALESCE(cua.birthday, u.birthday) AS birthday,
|
||||
COALESCE(cua.avatar, scu.avatar, u.avatar) AS avatar,
|
||||
COALESCE(cua.sameTimeJoinOtherClubSituation, scu.sameTimeJoinOtherClubSituation) AS sameTimeJoinOtherClubSituation,
|
||||
COALESCE(cua.awardsExperience, scu.awardsExperience) AS awardsExperience,
|
||||
cua.signature,
|
||||
COALESCE(
|
||||
cua.applyDate,
|
||||
STR_TO_DATE(scu.changeTime, '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(JSON_UNQUOTE(JSON_EXTRACT(scu.exitAuditList, '$[0].auditTime')), '%Y-%m-%d %H:%i:%s')
|
||||
) AS applyDate,
|
||||
STR_TO_DATE(scu.joinTime, '%Y-%m-%d %H:%i:%s') AS joinTime,
|
||||
COALESCE(
|
||||
cua.exitTime,
|
||||
STR_TO_DATE(JSON_UNQUOTE(JSON_EXTRACT(scu.exitAuditList, '$[0].auditTime')), '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(scu.changeTime, '%Y-%m-%d %H:%i:%s')
|
||||
) AS exitTime,
|
||||
IF(cua.id IS NULL, 'DIRECT_REMOVE', 'AUDIT_EXIT') AS exitType,
|
||||
exitInfo.id,
|
||||
exitInfo.clubId,
|
||||
exitInfo.userId,
|
||||
exitInfo.applyRoleCode AS roleCode,
|
||||
exitInfo.clubPosition,
|
||||
COALESCE(exitInfo.email, u.email) AS email,
|
||||
COALESCE(exitInfo.mobile, u.mobile) AS mobile,
|
||||
COALESCE(exitInfo.birthday, u.birthday) AS birthday,
|
||||
COALESCE(exitInfo.avatar, u.avatar) AS avatar,
|
||||
exitInfo.sameTimeJoinOtherClubSituation,
|
||||
exitInfo.awardsExperience,
|
||||
exitInfo.signature,
|
||||
exitInfo.applyDate,
|
||||
COALESCE(exitInfo.joinTime, STR_TO_DATE(club.foundTime, '%Y-%m-%d')) AS joinTime,
|
||||
exitInfo.exitTime,
|
||||
exitInfo.exitType,
|
||||
club.clubName,
|
||||
u.loginname AS loginName,
|
||||
u.username AS userName,
|
||||
u.sex,
|
||||
u.mobile,
|
||||
u.unitName,
|
||||
u.unionName,
|
||||
u.technicalTitle,
|
||||
u.education,
|
||||
u.academicDegree,
|
||||
u.position
|
||||
FROM
|
||||
sys_club_user scu
|
||||
LEFT JOIN club_user_apply cua ON cua.clubId = scu.clubId
|
||||
AND cua.userId = scu.userId
|
||||
AND cua.mode = false
|
||||
LEFT JOIN vw_user u ON u.id = scu.userId
|
||||
LEFT JOIN sys_club club ON club.id = scu.clubId
|
||||
WHERE scu.isNormal = false
|
||||
AND COALESCE(cua.id, scu.id) = @id
|
||||
""" + getExitManageBaseSql() + """
|
||||
WHERE exitInfo.id = @id
|
||||
""");
|
||||
sql.setParam("id", id);
|
||||
return fetchVO(sql, ClubUserJoinVo.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退会申请审批完成后会删除club_user成员关系,因此退会管理以退会申请记录为主数据源。
|
||||
* 同时保留旧sys_club_user表中已退会的数据,避免历史直接移出记录无法查询。
|
||||
*
|
||||
* @return 退会管理列表和详情共用的数据来源SQL
|
||||
*/
|
||||
private String getExitManageBaseSql() {
|
||||
return """
|
||||
FROM (
|
||||
SELECT
|
||||
cua.id,
|
||||
cua.clubId,
|
||||
cua.userId,
|
||||
cua.roleCode AS applyRoleCode,
|
||||
cua.clubPosition,
|
||||
cua.email,
|
||||
cua.mobile,
|
||||
cua.birthday,
|
||||
cua.avatar,
|
||||
cua.sameTimeJoinOtherClubSituation,
|
||||
cua.awardsExperience,
|
||||
cua.signature,
|
||||
cua.applyDate,
|
||||
cua.joinTime,
|
||||
cua.exitTime,
|
||||
'AUDIT_EXIT' AS exitType
|
||||
FROM
|
||||
club_user_apply cua
|
||||
INNER JOIN wf_process_instance ins ON ins.businessNo = cua.id AND ins.state = 20
|
||||
WHERE cua.mode = false
|
||||
UNION ALL
|
||||
SELECT
|
||||
scu.id,
|
||||
scu.clubId,
|
||||
scu.userId,
|
||||
scu.roleCode AS applyRoleCode,
|
||||
scu.position AS clubPosition,
|
||||
scu.email,
|
||||
NULL AS mobile,
|
||||
NULL AS birthday,
|
||||
scu.avatar,
|
||||
scu.sameTimeJoinOtherClubSituation,
|
||||
scu.awardsExperience,
|
||||
NULL AS signature,
|
||||
COALESCE(
|
||||
STR_TO_DATE(scu.changeTime, '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(JSON_UNQUOTE(JSON_EXTRACT(scu.exitAuditList, '$[0].auditTime')), '%Y-%m-%d %H:%i:%s')
|
||||
) AS applyDate,
|
||||
STR_TO_DATE(scu.joinTime, '%Y-%m-%d %H:%i:%s') AS joinTime,
|
||||
COALESCE(
|
||||
STR_TO_DATE(JSON_UNQUOTE(JSON_EXTRACT(scu.exitAuditList, '$[0].auditTime')), '%Y-%m-%d %H:%i:%s'),
|
||||
STR_TO_DATE(scu.changeTime, '%Y-%m-%d %H:%i:%s')
|
||||
) AS exitTime,
|
||||
'DIRECT_REMOVE' AS exitType
|
||||
FROM
|
||||
sys_club_user scu
|
||||
WHERE scu.isNormal = false
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM club_user_apply cua
|
||||
INNER JOIN wf_process_instance ins ON ins.businessNo = cua.id AND ins.state = 20
|
||||
WHERE cua.mode = false
|
||||
AND cua.clubId = scu.clubId
|
||||
AND cua.userId = scu.userId
|
||||
)
|
||||
) exitInfo
|
||||
LEFT JOIN sys_club club ON club.id = exitInfo.clubId
|
||||
INNER JOIN vw_user u ON u.id = exitInfo.userId
|
||||
""";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<ClubUserCommonPageVo> clubManagePersonAuditPageData(ClubUserPageForm pageForm) {
|
||||
Sql sql = Sqls.create("""
|
||||
|
||||
@@ -17,6 +17,10 @@ public class ClubEvaluatePageVo {
|
||||
private String foundTime;
|
||||
private String typeName;
|
||||
private Date applyTime;
|
||||
/** 社团评优申报开始年度。 */
|
||||
private String applyStartYear;
|
||||
/** 社团评优申报结束年度。 */
|
||||
private String applyEndYear;
|
||||
|
||||
private String instanceId;
|
||||
private String businessNo;
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.budwk.app.zhgh.club.model.SysClubExamineRegisterDetailed;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -18,4 +19,9 @@ public class ClubExamineVo extends SysClubExamineRegister {
|
||||
private String typeName;
|
||||
@ApiModelProperty("节点审批记录")
|
||||
private List<BpmTaskApprovalRecordVo> nodeTasks;
|
||||
|
||||
/**
|
||||
* V3年审已迁入但未转换为V4工作流任务的历史审核记录。
|
||||
*/
|
||||
private List<NutMap> legacyAuditRecords;
|
||||
}
|
||||
|
||||
+47
-11
@@ -11,6 +11,7 @@ import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
@@ -43,22 +44,26 @@ public class ArticleAnalysisController {
|
||||
@At
|
||||
@SaCheckPermission("article.analysis")
|
||||
@ApiOperation(value = "统计分析")
|
||||
public Result overview() {
|
||||
public Result overview(Date startDate, Date endDate, String unionId, String clubId) {
|
||||
List<ArticleAnalysisOverviewVO> list = new ArrayList<>();
|
||||
|
||||
// 获取总投稿量
|
||||
list.add(ArticleAnalysisOverviewVO.builder()
|
||||
.label("总投稿量")
|
||||
.value(articleService.count())
|
||||
.value(articleService.count(buildStatisticsCondition(startDate, endDate, unionId, clubId)))
|
||||
.icon("el-icon-document")
|
||||
.bgColor("rgba(24, 103, 176, 0.1)")
|
||||
.trend(null)
|
||||
.build());
|
||||
|
||||
// 获取本月投稿量
|
||||
long monthlyCount = articleService.count(Cnd.where("MONTH(submitTime)", "=", DateUtil.thisMonth() + 1));
|
||||
Cnd monthlyCondition = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
monthlyCondition.and("MONTH(submitTime)", "=", DateUtil.thisMonth() + 1);
|
||||
long monthlyCount = articleService.count(monthlyCondition);
|
||||
//上月投稿量
|
||||
long lastMonthCount = articleService.count(Cnd.where("MONTH(submitTime)", "=", DateUtil.offsetMonth(new Date(), -1)));
|
||||
Cnd lastMonthCondition = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
lastMonthCondition.and("MONTH(submitTime)", "=", DateUtil.month(DateUtil.offsetMonth(new Date(), -1)) + 1);
|
||||
long lastMonthCount = articleService.count(lastMonthCondition);
|
||||
|
||||
list.add(ArticleAnalysisOverviewVO.builder()
|
||||
.label("本月投稿")
|
||||
@@ -70,7 +75,9 @@ public class ArticleAnalysisController {
|
||||
|
||||
// 获取活跃投稿人数
|
||||
DateTime dateTime = DateUtil.offsetMonth(new Date(), -1);
|
||||
long activeUsers = Math.max(articleService.count(Cnd.where("submitTime", ">=", dateTime).groupBy("userId")), 0L);
|
||||
Cnd activeUserCondition = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
activeUserCondition.and("submitTime", ">=", dateTime).groupBy("userId");
|
||||
long activeUsers = Math.max(articleService.count(activeUserCondition), 0L);
|
||||
list.add(ArticleAnalysisOverviewVO.builder()
|
||||
.label("活跃投稿人")
|
||||
.value(activeUsers)
|
||||
@@ -81,7 +88,11 @@ public class ArticleAnalysisController {
|
||||
|
||||
|
||||
// 获取参与分工会数量
|
||||
long unionCount = articleService.count(Sqls.create("SELECT COUNT(distinct unionId) FROM article WHERE unionId IS NOT NULL"));
|
||||
Sql unionCountSql = Sqls.create("SELECT COUNT(distinct unionId) FROM article $condition");
|
||||
Cnd unionCountCondition = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
unionCountCondition.and("unionId", "IS NOT", null);
|
||||
unionCountSql.setCondition(unionCountCondition);
|
||||
long unionCount = articleService.count(unionCountSql);
|
||||
list.add(ArticleAnalysisOverviewVO.builder()
|
||||
.label("参与分工会")
|
||||
.value(unionCount)
|
||||
@@ -91,7 +102,11 @@ public class ArticleAnalysisController {
|
||||
.build());
|
||||
|
||||
// 获取参与社团数量
|
||||
long clubCount = articleService.count(Sqls.create("SELECT COUNT(distinct clubId) FROM article WHERE clubId IS NOT NULL"));
|
||||
Sql clubCountSql = Sqls.create("SELECT COUNT(distinct clubId) FROM article $condition");
|
||||
Cnd clubCountCondition = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
clubCountCondition.and("clubId", "IS NOT", null);
|
||||
clubCountSql.setCondition(clubCountCondition);
|
||||
long clubCount = articleService.count(clubCountSql);
|
||||
list.add(ArticleAnalysisOverviewVO.builder()
|
||||
.label("参与社团")
|
||||
.value(clubCount)
|
||||
@@ -102,22 +117,43 @@ public class ArticleAnalysisController {
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建概览统计的筛选条件,与图表接口保持相同的时间范围、分工会和社团口径。
|
||||
*/
|
||||
private Cnd buildStatisticsCondition(Date startDate, Date endDate, String unionId, String clubId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (startDate != null && endDate != null) {
|
||||
cnd.and(Cnd.cri().where().andBetween("submitTime", startDate, endDate));
|
||||
}
|
||||
cnd.andEX("unionId", "=", unionId);
|
||||
cnd.andEX("clubId", "=", clubId);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("article.analysis")
|
||||
@ApiOperation(value = "投稿趋势")
|
||||
public Result trend(@Valid String type, Date startDate, Date endDate) {
|
||||
List<NutMap> submissionTrend = articleAnalysisService.getSubmissionTrend(type, startDate, endDate);
|
||||
public Result trend(@Valid String type, Date startDate, Date endDate, String unionId, String clubId) {
|
||||
List<NutMap> submissionTrend = articleAnalysisService.getSubmissionTrend(type, startDate, endDate, unionId, clubId);
|
||||
return Result.success(submissionTrend);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("article.analysis")
|
||||
@ApiOperation(value = "分工会投稿分布")
|
||||
public Result distribution(Date startDate, Date endDate) {
|
||||
List<NutMap> unionDistribution = articleAnalysisService.getUnionDistribution(startDate, endDate);
|
||||
public Result distribution(Date startDate, Date endDate, String unionId, String clubId) {
|
||||
List<NutMap> unionDistribution = articleAnalysisService.getUnionDistribution(startDate, endDate, unionId, clubId);
|
||||
return Result.success(unionDistribution);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("article.analysis")
|
||||
@ApiOperation(value = "社团投稿分布")
|
||||
public Result clubDistribution(Date startDate, Date endDate, String unionId, String clubId) {
|
||||
List<NutMap> clubDistribution = articleAnalysisService.getClubDistribution(startDate, endDate, unionId, clubId);
|
||||
return Result.success(clubDistribution);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("article.analysis")
|
||||
@ApiOperation(value = "投稿排名")
|
||||
|
||||
+6
-2
@@ -52,6 +52,7 @@ public class ArticleMineController {
|
||||
@SaCheckPermission("article.mine")
|
||||
@ApiOperation("分页查询")
|
||||
public Result pageData(@Valid ArticleInfoPageParam pageForm) {
|
||||
// 每篇投稿仅关联最新的一条待办任务,避免多办理人或并行待办将同一投稿重复展示。
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
info.id,
|
||||
@@ -79,8 +80,11 @@ public class ArticleMineController {
|
||||
FROM
|
||||
article info
|
||||
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
|
||||
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
LEFT JOIN wf_process_task t ON t.id = (
|
||||
SELECT MAX(currentTask.id)
|
||||
FROM wf_process_task currentTask
|
||||
WHERE currentTask.processInstanceId = ins.id AND currentTask.taskState = 10
|
||||
)
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
+1
@@ -49,6 +49,7 @@ public class ArticleQueryController {
|
||||
info.loginName,
|
||||
info.unitName,
|
||||
info.unionName,
|
||||
info.clubName,
|
||||
info.submitTime,
|
||||
info.origin,
|
||||
ins.id AS instanceId,
|
||||
|
||||
+7
-2
@@ -13,12 +13,17 @@ public interface ArticleAnalysisService extends BaseService<Article> {
|
||||
/**
|
||||
* 获取投稿趋势数据
|
||||
*/
|
||||
List<NutMap> getSubmissionTrend(String type, Date startDate, Date endDate);
|
||||
List<NutMap> getSubmissionTrend(String type, Date startDate, Date endDate, String unionId, String clubId);
|
||||
|
||||
/**
|
||||
* 获取分工会投稿分布
|
||||
*/
|
||||
List<NutMap> getUnionDistribution(Date startDate, Date endDate);
|
||||
List<NutMap> getUnionDistribution(Date startDate, Date endDate, String unionId, String clubId);
|
||||
|
||||
/**
|
||||
* 获取社团投稿分布
|
||||
*/
|
||||
List<NutMap> getClubDistribution(Date startDate, Date endDate, String unionId, String clubId);
|
||||
|
||||
/**
|
||||
* 获取排行榜数据
|
||||
|
||||
+46
-10
@@ -22,7 +22,7 @@ public class ArticleAnalysisServiceImpl extends BaseServiceImpl<Article> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> getSubmissionTrend(String type, Date startDate, Date endDate) {
|
||||
public List<NutMap> getSubmissionTrend(String type, Date startDate, Date endDate, String unionId, String clubId) {
|
||||
String groupFormat = switch (type) {
|
||||
case "week" -> "%Y-%u"; // 按周分组
|
||||
case "month" -> "%Y-%m"; // 按月分组
|
||||
@@ -40,10 +40,8 @@ public class ArticleAnalysisServiceImpl extends BaseServiceImpl<Article> impleme
|
||||
""");
|
||||
sql.setParam("groupFormat",groupFormat);
|
||||
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if(ObjectUtil.isAllNotEmpty(startDate,endDate)){
|
||||
cnd.and(Cnd.cri().where().andBetween("submitTime", startDate, endDate));
|
||||
}
|
||||
Cnd cnd = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
cnd.groupBy("DATE_FORMAT(submitTime, @groupFormat)");
|
||||
sql.setCondition(cnd);
|
||||
|
||||
return listMap(sql);
|
||||
@@ -53,7 +51,7 @@ public class ArticleAnalysisServiceImpl extends BaseServiceImpl<Article> impleme
|
||||
* 获取分工会投稿分布
|
||||
*/
|
||||
@Override
|
||||
public List<NutMap> getUnionDistribution(Date startDate, Date endDate) {
|
||||
public List<NutMap> getUnionDistribution(Date startDate, Date endDate, String unionId, String clubId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
unionName AS type,
|
||||
@@ -62,10 +60,7 @@ public class ArticleAnalysisServiceImpl extends BaseServiceImpl<Article> impleme
|
||||
article
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if(ObjectUtil.isAllNotEmpty(startDate,endDate)){
|
||||
cnd.and(Cnd.cri().where().andBetween("submitTime", startDate, endDate));
|
||||
}
|
||||
Cnd cnd = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
cnd.groupBy("unionId","unionName");
|
||||
cnd.desc("value");
|
||||
sql.setCondition(cnd);
|
||||
@@ -73,6 +68,47 @@ public class ArticleAnalysisServiceImpl extends BaseServiceImpl<Article> impleme
|
||||
return listMap(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取社团投稿分布
|
||||
*/
|
||||
@Override
|
||||
public List<NutMap> getClubDistribution(Date startDate, Date endDate, String unionId, String clubId) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
clubName AS type,
|
||||
COUNT(*) AS value
|
||||
FROM
|
||||
article
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = buildStatisticsCondition(startDate, endDate, unionId, clubId);
|
||||
cnd.and("clubId", "IS NOT", null);
|
||||
cnd.groupBy("clubId", "clubName");
|
||||
cnd.desc("value");
|
||||
sql.setCondition(cnd);
|
||||
|
||||
return listMap(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为统计图表统一拼接时间范围和分工会筛选条件,保证各图表的查询口径一致。
|
||||
*
|
||||
* @param startDate 查询开始日期,为空时不限制开始时间
|
||||
* @param endDate 查询结束日期,为空时不限制结束时间
|
||||
* @param unionId 分工会 ID,为空时查询全部分工会
|
||||
* @param clubId 社团 ID,为空时查询全部社团
|
||||
* @return 可直接设置到统计 SQL 的查询条件
|
||||
*/
|
||||
private Cnd buildStatisticsCondition(Date startDate, Date endDate, String unionId, String clubId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (ObjectUtil.isAllNotEmpty(startDate, endDate)) {
|
||||
cnd.and(Cnd.cri().where().andBetween("submitTime", startDate, endDate));
|
||||
}
|
||||
cnd.andEX("unionId", "=", unionId);
|
||||
cnd.andEX("clubId", "=", clubId);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排行榜数据
|
||||
*/
|
||||
|
||||
+15
-4
@@ -5,12 +5,15 @@ 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.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.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.asset.model.Asset;
|
||||
import com.budwk.app.zhgh.dayofficework.asset.model.AssetDepreciationRecord;
|
||||
@@ -26,6 +29,7 @@ import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -153,12 +157,19 @@ public class AssetManageController {
|
||||
|
||||
@At
|
||||
@ApiOperation("查询责任人")
|
||||
@SaCheckPermission("asset.manage")
|
||||
@SaCheckPermission(value = {"asset.manage", "asset.stocktaking", "h5.asset.stocktaking"}, mode = SaMode.OR)
|
||||
public Result searchAssetUseUser(String query) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.where().orLike("username", query);
|
||||
cnd.where().orLike("loginname", query);
|
||||
cnd.where().orLike("id", query);
|
||||
// 三个关键词条件必须整体分组,避免 OR 条件绕过分工会数据范围。
|
||||
SqlExpressionGroup searchGroup = new SqlExpressionGroup();
|
||||
searchGroup.orLike("username", query);
|
||||
searchGroup.orLike("loginname", query);
|
||||
searchGroup.orLike("id", query);
|
||||
cnd.and(searchGroup);
|
||||
// 分工会侧盘点人员只能选择本分工会成员,校工会和系统管理员保留全校查询范围。
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
cnd.and("unionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
id,
|
||||
|
||||
+7
-31
@@ -1,12 +1,8 @@
|
||||
package com.budwk.app.zhgh.dayofficework.birthdayWishes.task;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.budwk.app.sys.models.Sys_msg;
|
||||
import com.budwk.app.sys.services.SysMsgService;
|
||||
import com.budwk.app.zhgh.staffmanage.birthday.service.UserBirthdayService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
@@ -15,16 +11,12 @@ import org.quartz.JobDataMap;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@Slf4j
|
||||
public class BirthdayWishesTask implements Job {
|
||||
|
||||
@Inject
|
||||
protected SysMsgService sysMsgService;
|
||||
@Inject
|
||||
protected Dao dao;
|
||||
private UserBirthdayService userBirthdayService;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -34,28 +26,12 @@ public class BirthdayWishesTask implements Job {
|
||||
log.info("=================================参数:{}", Json.toJson(dataMap));
|
||||
|
||||
String planName = dataMap.getString("name");
|
||||
|
||||
String today = DateUtil.today();
|
||||
String title = planName + today;
|
||||
String content = dataMap.getString("template");
|
||||
|
||||
Sys_msg msg = new Sys_msg();
|
||||
msg.setTitle(planName + today);
|
||||
msg.setType("user");
|
||||
msg.setSendType("show");
|
||||
msg.setSendAt(DateUtil.current());
|
||||
msg.setNote(dataMap.getString("template"));
|
||||
|
||||
// 查询今天生日的会员用户
|
||||
Sql sql = Sqls.create("SELECT loginname FROM sys_user WHERE member = 1 AND MONTH(birthday) = MONTH(CURRENT_DATE) AND DAY(birthday) = DAY(CURRENT_DATE)");
|
||||
sql.setCallback(Sqls.callback.strList());
|
||||
dao.execute(sql);
|
||||
List<String> users = sql.getList(String.class);
|
||||
// 转为数组
|
||||
String[] userArray = users.toArray(String[]::new);
|
||||
log.info("=================================查询今天生日会员用户:{}", users);
|
||||
|
||||
if(userArray.length > 0){
|
||||
log.info("=================================发送消息:{}", msg);
|
||||
sysMsgService.saveMsg(msg, userArray, true);
|
||||
}
|
||||
// 统一由生日服务查询当天生日会员、生成移动端链接并记录系统推送日志。
|
||||
int receiverCount = userBirthdayService.sendTodayBirthdayMessages(title, content);
|
||||
log.info("=================================当天生日通知进入发送队列人数:{}", receiverCount);
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -58,6 +58,10 @@ public class BuildHomeKpiWriteDynamicTableRenderPolicy extends DynamicTableRende
|
||||
// 处理合并
|
||||
if(ObjectUtil.isNotEmpty(dataList)){
|
||||
for (int[] value : groupRanges.values()) {
|
||||
// 单条明细无需合并;POI 不支持对同一行进行纵向合并。
|
||||
if (value[0] == value[1]) {
|
||||
continue;
|
||||
}
|
||||
TableTools.mergeCellsVertically(xwpfTable, 0, value[0] + 1, value[1] + 1);
|
||||
TableTools.mergeCellsVertically(xwpfTable, 1, value[0] + 1, value[1] + 1);
|
||||
TableTools.mergeCellsVertically(xwpfTable, 4, value[0] + 1, value[1] + 1);
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public class BuildHomeKpiWriteController {
|
||||
buildHomeKpiWriteService.exportDocx(id, os);
|
||||
// 下载生成的文件
|
||||
CommonDownloadUtil.download(
|
||||
"南京邮电大学分工会教职工之家建设考核评议自评表.docx",
|
||||
"中国地质大学分工会教职工之家建设考核评议自评表.docx",
|
||||
os.toByteArray(),
|
||||
response
|
||||
);
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ public class BuildHomeLogBookController {
|
||||
template.render(map).writeAndClose(os);
|
||||
// 下载生成的文件
|
||||
CommonDownloadUtil.download(
|
||||
"南京邮电大学分工会建家记录册.docx",
|
||||
"中国地质大学分工会建家记录册.docx",
|
||||
os.toByteArray(),
|
||||
response
|
||||
);
|
||||
|
||||
+21
-2
@@ -2,6 +2,7 @@ package com.budwk.app.zhgh.dayofficework.buildHome.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
@@ -104,8 +105,13 @@ public class BuildHomeMaterialQueryController {
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("buildHome.material.query")
|
||||
public void exportZip(String actId, HttpServletResponse response) throws IOException {
|
||||
BuildHomeAct act = buildHomeActService.fetch(actId);
|
||||
if (act == null) {
|
||||
throw new IllegalArgumentException("未找到评比事项");
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t1.id,
|
||||
@@ -123,7 +129,6 @@ public class BuildHomeMaterialQueryController {
|
||||
AND t2.actId = @actId
|
||||
LEFT JOIN build_home_act t3 ON t3.id = t2.actId
|
||||
AND t3.id = @actId
|
||||
WHERE t1.id = '3742a919fb6847f7a8dbe051a2ef0025'
|
||||
GROUP BY
|
||||
t1.id,
|
||||
t2.unionId
|
||||
@@ -135,7 +140,9 @@ public class BuildHomeMaterialQueryController {
|
||||
|
||||
// 2. 设置响应头
|
||||
response.setContentType("application/zip");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"工会文件汇总.zip\"");
|
||||
// 使用评比事项名称作为压缩包名称,避免下载文件无法区分来源。
|
||||
String zipFileName = sanitizeFileName(act.getName()) + "汇总材料.zip";
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + URLUtil.encode(zipFileName));
|
||||
|
||||
// 3. 使用try-with-resources创建ZIP输出流
|
||||
try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
|
||||
@@ -164,6 +171,18 @@ public class BuildHomeMaterialQueryController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清理评比事项名称中的 Windows 文件名非法字符,确保浏览器可正常保存压缩包。
|
||||
*
|
||||
* @param fileName 原始评比事项名称
|
||||
* @return 可用于下载文件名的评比事项名称
|
||||
*/
|
||||
private String sanitizeFileName(String fileName) {
|
||||
String sanitizedFileName = StrUtil.blankToDefault(fileName, "评比事项");
|
||||
return sanitizedFileName.replaceAll("[\\\\/:*?\"<>|]", "_");
|
||||
}
|
||||
|
||||
|
||||
private void processFileList(ZipOutputStream zos, String unionName, String fileType, String filesJson) throws IOException {
|
||||
if (StrUtil.isNotBlank(filesJson)) {
|
||||
List<NutMap> files = Json.fromJsonAsList(NutMap.class, filesJson);
|
||||
|
||||
+34
-1
@@ -4,12 +4,15 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.model.CadreTrainingAct;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.model.CadreTrainingSignUp;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.service.CadreTrainingActService;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.service.CadreTrainingSignUpService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -29,6 +32,7 @@ import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author : hongqiwei
|
||||
@@ -106,12 +110,41 @@ public class CadreTrainingMineController {
|
||||
cnd.where().andLike(CadreTrainingAct::getName, pageForm.getSearchKeyword());
|
||||
}
|
||||
cnd.desc("info.applyTime");
|
||||
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
||||
// 本人报名和本人代他人报名的记录都应在“我的报名”中展示。
|
||||
cnd.and(Cnd.exps("info.userId", "=", SecurityUtil.getUserId())
|
||||
.or("info.applyUserId", "=", SecurityUtil.getUserId()));
|
||||
sql.setCondition(cnd);
|
||||
Pagination<NutMap> pagination = cadreTrainingSignUpService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询“我的报名”查看页的报名人员。
|
||||
* 管理角色按活动和分工会查看全部报名人员;普通用户仅返回本人记录,避免扩大人员信息可见范围。
|
||||
*
|
||||
* @param activityId 培训活动 ID,对应 cadre_training 表主键
|
||||
* @param unionId 当前查看报名记录所属的分工会 ID
|
||||
* @return 报名记录列表,元素包含人员姓名、工号、单位、分工会、联系方式及备注
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("查询我的报名活动人员")
|
||||
@SaCheckPermission(value = {"cadreTraining.mine", "h5.cadreTraining.mine"}, mode = SaMode.OR)
|
||||
public Result listSignUsers(@Valid String activityId, String unionId) {
|
||||
Cnd cnd = Cnd.where(CadreTrainingSignUp::getCadreTrainingActId, "=", activityId);
|
||||
if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
|
||||
// 管理角色必须携带当前报名记录所属的分工会,防止空参数绕过分工会范围。
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
return Result.error("分工会信息不能为空");
|
||||
}
|
||||
cnd.and(CadreTrainingSignUp::getUnionId, "=", unionId);
|
||||
} else {
|
||||
cnd.and(CadreTrainingSignUp::getUserId, "=", SecurityUtil.getUserId());
|
||||
}
|
||||
cnd.asc(CadreTrainingSignUp::getApplyTime);
|
||||
List<CadreTrainingSignUp> signUsers = dao.query(CadreTrainingSignUp.class, cnd);
|
||||
return Result.success(signUsers);
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("删除")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
|
||||
+5
-1
@@ -67,8 +67,9 @@ public class CadreTrainingSignUpController {
|
||||
@SaCheckPermission("cadreTraining.branchUnionSignUp")
|
||||
@ApiOperation("分页查询")
|
||||
public Result pageData(@Valid PageForm pageForm,Integer year, boolean isEnrolled) {
|
||||
// 同一活动存在多条代报名记录时,活动列表仅展示一次。
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
SELECT DISTINCT
|
||||
info.*,
|
||||
CASE WHEN cts.id IS NOT NULL THEN 1 ELSE 0 END AS isEnrolled
|
||||
FROM
|
||||
@@ -101,6 +102,9 @@ public class CadreTrainingSignUpController {
|
||||
List<ProcessInstance> instances = new ArrayList<>();
|
||||
|
||||
for (CadreTrainingSignUp signUp : cadreTrainingSignUps) {
|
||||
// 代报名记录必须以当前登录人为报名操作人,供“已报名”和“我的报名”按操作人查询。
|
||||
signUp.setApplyUserId(SecurityUtil.getUserId());
|
||||
signUp.setApplyUserUserName(SecurityUtil.getUserUsername());
|
||||
if (StrUtil.isBlank(signUp.getId())) {
|
||||
signUp.setApplyTime(new Date());
|
||||
}
|
||||
|
||||
+2
@@ -84,6 +84,8 @@ public class EnrollmentRegistrationApplyListController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("YEAR(info.applyTime)", "=", year);
|
||||
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
||||
// 同一登记可能关联多个流程任务参与人,按业务主表ID分组后仅展示一条申请记录。
|
||||
cnd.groupBy("info.id");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
|
||||
+1
@@ -74,6 +74,7 @@ public class EvaluateActivityController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("year", "=", year);
|
||||
cnd.and(Cnd.likeEX("eva.name", searchKeyword));
|
||||
cnd.groupBy("eva.id");
|
||||
sql.setCondition(cnd);
|
||||
return Result.success(baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql));
|
||||
}
|
||||
|
||||
+13
@@ -83,6 +83,7 @@ public class EvaluateApplyController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("enable", "=", 1);
|
||||
cnd.andEX("year", "=", year);
|
||||
cnd.groupBy("eva.id");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = evaluateActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pagination);
|
||||
@@ -108,6 +109,10 @@ public class EvaluateApplyController {
|
||||
@ApiOperation("保存")
|
||||
@SLog(tag = "评优评先申请", msg = "保存申请")
|
||||
public Result save(@Param("data") EvaluateApply evaluateApply) {
|
||||
String validateMessage = evaluateService.validateCollectiveHonorApply(evaluateApply);
|
||||
if (validateMessage != null) {
|
||||
return Result.error(validateMessage);
|
||||
}
|
||||
evaluateApply.setApplyDateTime(new Date());
|
||||
evaluateService.insertOrUpdate(evaluateApply);
|
||||
return Result.success();
|
||||
@@ -119,6 +124,10 @@ public class EvaluateApplyController {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SLog( tag = "评优评先申请", msg = "重新提交申请")
|
||||
public Result submitAgain(@Param("data") EvaluateApply evaluateApply, @Param("taskId") Long taskId) {
|
||||
String validateMessage = evaluateService.validateCollectiveHonorApply(evaluateApply);
|
||||
if (validateMessage != null) {
|
||||
return Result.error(validateMessage);
|
||||
}
|
||||
evaluateService.insertOrUpdate(evaluateApply);
|
||||
|
||||
Dict dict = Dict.create();
|
||||
@@ -134,6 +143,10 @@ public class EvaluateApplyController {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SLog(tag = "评优评先申请", msg = "提交申请")
|
||||
public Result submit(@Param("data") EvaluateApply evaluateApply) {
|
||||
String validateMessage = evaluateService.validateCollectiveHonorApply(evaluateApply);
|
||||
if (validateMessage != null) {
|
||||
return Result.error(validateMessage);
|
||||
}
|
||||
evaluateApply.setApplyDateTime(new Date());
|
||||
evaluateService.insertOrUpdate(evaluateApply);
|
||||
|
||||
|
||||
+1
@@ -80,6 +80,7 @@ public class EvaluateMineController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("YEAR(info.year)", "=", year);
|
||||
cnd.and("info.loginName", "=", SecurityUtil.getUserLoginname());
|
||||
cnd.groupBy("info.id");
|
||||
cnd.desc("info.createdAt");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = evaluateService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
|
||||
@@ -10,4 +10,12 @@ public interface EvaluateService extends BaseService<EvaluateApply> {
|
||||
|
||||
|
||||
Sql getSummarySql(EvaluatePageForm pageForm);
|
||||
|
||||
/**
|
||||
* 校验集体荣誉是否已由当前分工会申请。
|
||||
*
|
||||
* @param evaluateApply 待保存或提交的申请
|
||||
* @return 校验通过返回 {@code null};重复申请时返回提示信息
|
||||
*/
|
||||
String validateCollectiveHonorApply(EvaluateApply evaluateApply);
|
||||
}
|
||||
|
||||
+30
@@ -4,9 +4,12 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity;
|
||||
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateApply;
|
||||
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
|
||||
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
|
||||
import com.budwk.app.zhgh.dayofficework.honor.models.HonorBasicSettings;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
@@ -67,6 +70,7 @@ public class EvaluateServiceImpl extends BaseServiceImpl<EvaluateApply> implemen
|
||||
seg.orLike("info.loginName", pageForm.getSearchKeyword());
|
||||
cnd.and(seg);
|
||||
}
|
||||
cnd.groupBy("info.id");
|
||||
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||
cnd.desc("t.createdAt").desc("info.applyDateTime");
|
||||
} else {
|
||||
@@ -76,4 +80,30 @@ public class EvaluateServiceImpl extends BaseServiceImpl<EvaluateApply> implemen
|
||||
sql.setCondition(cnd);
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validateCollectiveHonorApply(EvaluateApply evaluateApply) {
|
||||
if (evaluateApply == null || StrUtil.isBlank(evaluateApply.getEvaluateId())) {
|
||||
return "评优评先活动不能为空";
|
||||
}
|
||||
EvaluateActivity activity = dao().fetch(EvaluateActivity.class, evaluateApply.getEvaluateId());
|
||||
if (activity == null) {
|
||||
return "评优评先活动不存在";
|
||||
}
|
||||
HonorBasicSettings honorType = dao().fetch(HonorBasicSettings.class, activity.getHonorTypeId());
|
||||
if (honorType == null || !StrUtil.equals("集体荣誉", honorType.getName())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Cnd cnd = Cnd.where(EvaluateApply::getUnionId, "=", SecurityUtil.getUnionId())
|
||||
.and(EvaluateApply::getHonorId, "=", activity.getHonorId())
|
||||
.and("YEAR(applyDateTime)", "=", activity.getYear());
|
||||
if (StrUtil.isNotBlank(evaluateApply.getId())) {
|
||||
cnd.and(EvaluateApply::getId, "!=", evaluateApply.getId());
|
||||
}
|
||||
if (dao().count(EvaluateApply.class, cnd) > 0) {
|
||||
return "本分工会已申请该集体荣誉,同一类型只能申请一次";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ public class GhkhKhphController {
|
||||
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||
exportEntities.add(new ExcelExportEntity("序号", "index", 10));
|
||||
exportEntities.add(new ExcelExportEntity("年度", "annual", 10));
|
||||
exportEntities.add(new ExcelExportEntity("分工会名称", "unionName", 30));
|
||||
exportEntities.add(new ExcelExportEntity("分工会名称", "unionname", 30));
|
||||
exportEntities.add(new ExcelExportEntity("线上得分", "xgh_score", 20));
|
||||
exportEntities.add(new ExcelExportEntity("线上最终得分" + (config.getOnLine() != null ? "(" + config.getOnLine() + "%)" : ""), "onLineFinalScore", 20));
|
||||
exportEntities.add(new ExcelExportEntity("线下得分", "offLineScore", 20));
|
||||
|
||||
+6
-1
@@ -3,11 +3,13 @@ package com.budwk.app.zhgh.dayofficework.honor.controller;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
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.sys.models.Sys_union;
|
||||
import com.budwk.app.sys.services.SysUnionService;
|
||||
import com.budwk.app.sys.services.SysUserService;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.honor.models.Honor;
|
||||
import com.budwk.app.zhgh.dayofficework.honor.service.HonorCommonService;
|
||||
@@ -90,7 +92,10 @@ public class HonorRegistrationController {
|
||||
seg.orLike("t1.username",keyWord);
|
||||
cnd.and(seg);
|
||||
}
|
||||
cnd.and("t1.unionId","=", SecurityUtil.getUnionId());
|
||||
// 系统管理员可跨分工会查询人员,其他角色仍限定为当前所属分工会。
|
||||
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
||||
cnd.and("t1.unionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = sysUserService.listPageMap(1, 50, sql);
|
||||
return Result.success(pagination.getList());
|
||||
|
||||
+18
-12
@@ -54,8 +54,8 @@ public class HonorSummaryController {
|
||||
@SaCheckPermission("honor.honorLevel.Summary")
|
||||
public Result unionData(HonorPageForm pageForm) {
|
||||
List<HonorBasicSettings> query = dao.query(HonorBasicSettings.class, Cnd.where("queryTypeCode", "in", List.of(HonorTypeOrigin.HONOR_SINGLE.name(), HonorTypeOrigin.HONOR_LIST.name())));
|
||||
String listHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_LIST.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String singleHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_SINGLE.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String personalHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_SINGLE.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String collectiveHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_LIST.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
Cnd cnd = Cnd.NEW();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -65,7 +65,7 @@ public class HonorSummaryController {
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorType = @collectiveHonor AND h.unionId = un.id $cnd) collectiveHonorNum
|
||||
FROM
|
||||
sys_union un $condition
|
||||
""").setParam("personalHonor", listHonorId).setParam("collectiveHonor", singleHonorId);
|
||||
""").setParam("personalHonor", personalHonorId).setParam("collectiveHonor", collectiveHonorId);
|
||||
cnd.andEX("id", "=", pageForm.getUnionId());
|
||||
if (pageForm.getYear() != null) {
|
||||
sql.setVar("cnd", "and YEAR(grantDate)=" + pageForm.getYear());
|
||||
@@ -79,21 +79,27 @@ public class HonorSummaryController {
|
||||
@At
|
||||
@SaCheckPermission("honor.honorLevel.Summary")
|
||||
public Result honorLevelData(HonorPageForm pageForm) {
|
||||
|
||||
List<HonorBasicSettings> query = dao.query(HonorBasicSettings.class, Cnd.where("queryTypeCode", "in",
|
||||
List.of(HonorTypeOrigin.HONOR_SCHOOL_LEVEL.name(), HonorTypeOrigin.HONOR_PROVINCIAL_LEVEL.name(), HonorTypeOrigin.HONOR_NATIONAL_LEVEL.name())));
|
||||
String schoolHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_SCHOOL_LEVEL.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String provincialHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_PROVINCIAL_LEVEL.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String nationalHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_NATIONAL_LEVEL.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
HonorBasicSettings levelRoot = dao.fetch(HonorBasicSettings.class,
|
||||
Cnd.where("queryTypeCode", "=", HonorTypeOrigin.HONOR_LEVEL.name()));
|
||||
List<HonorBasicSettings> levelList = levelRoot == null ? List.of() : dao.query(HonorBasicSettings.class,
|
||||
Cnd.where("parentId", "=", levelRoot.getId()));
|
||||
String schoolHonorId = levelList.stream().filter(item -> "校内".equals(item.getName()))
|
||||
.findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String provincialHonorId = levelList.stream().filter(item -> "省部级".equals(item.getName()))
|
||||
.findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String nationalHonorId = levelList.stream().filter(item -> "国家级".equals(item.getName()))
|
||||
.findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
|
||||
Cnd cnd = Cnd.NEW();
|
||||
// honor.honorLevel 直接保存荣誉等级项 ID,按“荣誉等级”下的具体等级项统计。
|
||||
// 历史荣誉记录可能未保存 unionId,统计时仅在 unionId 为空时按 unionName 回退关联。
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
id,
|
||||
name as unionname,
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @nationalLevel AND h.unionId = un.id $cnd) nationalLevelNum,
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @provincial AND h.unionId = un.id $cnd) provincialNum ,
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @schoolLevel AND h.unionId = un.id $cnd) schoolLevelNum
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @nationalLevel AND (h.unionId = un.id OR ((h.unionId IS NULL OR h.unionId = '') AND h.unionName = un.name)) $cnd) nationalLevelNum,
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @provincial AND (h.unionId = un.id OR ((h.unionId IS NULL OR h.unionId = '') AND h.unionName = un.name)) $cnd) provincialNum ,
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @schoolLevel AND (h.unionId = un.id OR ((h.unionId IS NULL OR h.unionId = '') AND h.unionName = un.name)) $cnd) schoolLevelNum
|
||||
FROM
|
||||
sys_union un $condition
|
||||
""").setParam("nationalLevel", nationalHonorId).setParam("provincial", provincialHonorId).setParam("schoolLevel", schoolHonorId);
|
||||
|
||||
+47
-3
@@ -3,11 +3,14 @@ package com.budwk.app.zhgh.dayofficework.meeting.controller;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.RepeatSubmit;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.sys.models.Sys_module;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.zhgh.dayofficework.meeting.model.MeetingInfo;
|
||||
import com.budwk.app.zhgh.dayofficework.meeting.model.MeetingTimePeriod;
|
||||
import com.budwk.app.zhgh.dayofficework.meeting.model.MeetingTimePeriodUser;
|
||||
@@ -101,6 +104,7 @@ public class MeetingManageController {
|
||||
@At
|
||||
@ApiOperation("新增/修改会议")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@RepeatSubmit
|
||||
@SaCheckPermission("meeting.manage")
|
||||
@SLog(tag = "会议管理系统-会议管理", msg = "新增/修改会议")
|
||||
public Object submit(@Param("data") MeetingInfo info,
|
||||
@@ -159,13 +163,17 @@ public class MeetingManageController {
|
||||
cnd.andEX("u.unitId", "=", unitId);
|
||||
cnd.and(Cnd.likeEX("u.sex", sex));
|
||||
if (StrUtil.isNotBlank(roleId)) {
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s')".formatted(roleId)));
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s' and enable='1')".formatted(roleId)));
|
||||
}
|
||||
// 选择届次但未选择角色时,按届次筛选全部相关人员;同时选择角色时限定为同一角色关联记录。
|
||||
if (StrUtil.isBlank(roleId) && StrUtil.isNotBlank(teacherCongressSessionId)) {
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where enable='1' and tcSessionId = '%s')".formatted(teacherCongressSessionId)));
|
||||
}
|
||||
if (StrUtil.isNotBlank(roleId) && StrUtil.isNotBlank(teacherCongressSessionId)) {
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s' and tcSessionId = '%s')".formatted(roleId, teacherCongressSessionId)));
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s' and enable='1' and tcSessionId = '%s')".formatted(roleId, teacherCongressSessionId)));
|
||||
}
|
||||
if (StrUtil.isNotBlank(roleId) && StrUtil.isNotBlank(workerCongressSessionId)) {
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s' and wcSessionId = '%s')".formatted(roleId, workerCongressSessionId)));
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s' and enable='1' and wcSessionId = '%s')".formatted(roleId, workerCongressSessionId)));
|
||||
}
|
||||
if (Strings.isNotBlank(pageForm.getSearchName()) && Strings.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.and(pageForm.getSearchName(), "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||
@@ -225,4 +233,40 @@ public class MeetingManageController {
|
||||
List<Worker_congress_session> list = dao.query(Worker_congress_session.class, Cnd.where(Teacher_congress_session::getEnable, "=", true).desc("year"));
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询会议选择用户时可筛选的 PC 端模块。
|
||||
*
|
||||
* @return 模块列表,元素包含模块 ID、名称和平台,按排序编号升序返回
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("查询 PC 端模块")
|
||||
@SaCheckPermission("meeting.manage")
|
||||
public Result listModule() {
|
||||
List<Sys_module> modules = dao.query(Sys_module.class,
|
||||
Cnd.where(Sys_module::getPlatform, "=", "PC").asc(Sys_module::getSortNum));
|
||||
return Result.success(modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按模块查询会议选择用户时可筛选的启用角色。
|
||||
*
|
||||
* @param moduleId PC 端模块 ID,来源于 sys_module 表
|
||||
* @return 角色列表,元素包含角色 ID、名称和角色标识,未传模块时返回空列表
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("按模块查询角色")
|
||||
@SaCheckPermission("meeting.manage")
|
||||
public Result listRole(String moduleId) {
|
||||
if (StrUtil.isBlank(moduleId)) {
|
||||
return Result.success(List.of());
|
||||
}
|
||||
Sys_module module = dao.fetch(Sys_module.class, moduleId);
|
||||
if (module == null || !"PC".equals(module.getPlatform())) {
|
||||
return Result.success(List.of());
|
||||
}
|
||||
List<Sys_role> roles = dao.query(Sys_role.class,
|
||||
Cnd.where(Sys_role::getModuleId, "=", moduleId).and(Sys_role::isDisabled, "=", false).asc(Sys_role::getSort));
|
||||
return Result.success(roles);
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -93,6 +93,10 @@ public class MeetingMineController {
|
||||
|
||||
List<MeetingTimePeriodUser> periodUsers = dao.query(MeetingTimePeriodUser.class, Cnd.where(MeetingTimePeriodUser::getUserId, "=", SecurityUtil.getUserId()));
|
||||
List<String> idList = periodUsers.stream().map(MeetingTimePeriodUser::getMeetingId).toList();
|
||||
// 当前用户未被安排参会时,直接返回空分页,避免生成空 IN 条件导致数据库语法错误。
|
||||
if (idList.isEmpty()) {
|
||||
return Result.success(new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, List.of()));
|
||||
}
|
||||
|
||||
cnd.and("id", "in", idList);
|
||||
cnd.andEX("typeId", "=", type);
|
||||
@@ -217,6 +221,14 @@ public class MeetingMineController {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SLog(tag = "会务管理-我的会议-签到", msg = "会议签到")
|
||||
public Result sign(@Valid String periodId) {
|
||||
MeetingTimePeriod timePeriod = dao.fetch(MeetingTimePeriod.class, periodId);
|
||||
if (timePeriod == null) {
|
||||
return Result.error("会议场次不存在!");
|
||||
}
|
||||
// 以服务端时间校验场次开始时间,避免客户端时间或页面状态被绕过。
|
||||
if (timePeriod.getStartTime() == null || DateUtil.date().before(timePeriod.getStartTime())) {
|
||||
return Result.error("会议尚未开始,暂不能签到!");
|
||||
}
|
||||
MeetingTimePeriodUser user = dao.fetch(
|
||||
MeetingTimePeriodUser.class,
|
||||
Cnd.where(MeetingTimePeriodUser::getTimePeriodId, "=", periodId)
|
||||
|
||||
+4
-2
@@ -115,8 +115,10 @@ public class MeetingOnlineController {
|
||||
@At("/getRealTimeData/?")
|
||||
@Ok("json:full")
|
||||
@SaCheckLogin
|
||||
public Result getRealTimeData(String timePeriodId) {
|
||||
List<MeetingTimePeriodUser> signInUser = onlineService.getSignInUser(timePeriodId);
|
||||
public Result getRealTimeData(String timePeriodId,
|
||||
@Param(value = "signRankOrder") String signRankOrder) {
|
||||
// 签到人员排序统一交由Service处理,控制器只负责接收前端排序方向并返回实时数据。
|
||||
List<MeetingTimePeriodUser> signInUser = onlineService.getSignInUser(timePeriodId, signRankOrder);
|
||||
List<Map<String, Object>> countData = onlineService.getRealTimeData(timePeriodId);
|
||||
return Result.success(Map.of("countData", countData, "userData", signInUser));
|
||||
}
|
||||
|
||||
+10
-1
@@ -18,6 +18,15 @@ import java.util.Map;
|
||||
public interface MeetingOnlineService extends BaseService<MeetingInfo> {
|
||||
|
||||
List<MeetingTimePeriodUser> exportSignature(String timePeriodId);
|
||||
List<MeetingTimePeriodUser> getSignInUser(String timePeriodId);
|
||||
|
||||
/**
|
||||
* 查询指定会议时段的签到人员,并根据签到名次要求排序。
|
||||
*
|
||||
* @param timePeriodId 会议时段ID
|
||||
* @param signRankOrder 签到名次排序方向,ascending为升序,其他值按降序处理
|
||||
* @return 已签到人员列表
|
||||
*/
|
||||
List<MeetingTimePeriodUser> getSignInUser(String timePeriodId, String signRankOrder);
|
||||
|
||||
List<Map<String, Object>> getRealTimeData(String timePeriodId);
|
||||
}
|
||||
|
||||
+25
-5
@@ -19,6 +19,7 @@ import org.nutz.lang.Lang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -44,11 +45,12 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
// 插入会议表和会议场次表
|
||||
info.setCreateTime(DateUtil.now());
|
||||
insertWith(info, "timePeriods");
|
||||
List<MeetingTimePeriodUser> uniqueUsers = distinctUsers(users);
|
||||
// 插入参与人员表
|
||||
if (Lang.isNotEmpty(info.getTimePeriods()) && Lang.isNotEmpty(users)) {
|
||||
if (Lang.isNotEmpty(info.getTimePeriods()) && Lang.isNotEmpty(uniqueUsers)) {
|
||||
List<MeetingTimePeriodUser> relations = info.getTimePeriods()
|
||||
.stream()
|
||||
.flatMap(period -> Arrays.stream(users).map(user -> buildRelation(info.getId(), period.getId(), user)))
|
||||
.flatMap(period -> uniqueUsers.stream().map(user -> buildRelation(info.getId(), period.getId(), user)))
|
||||
.toList();
|
||||
dao().insert(relations);
|
||||
}
|
||||
@@ -58,6 +60,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void edit(MeetingInfo info, MeetingTimePeriodUser[] users) {
|
||||
String meetingId = info.getId();
|
||||
List<MeetingTimePeriodUser> uniqueUsers = distinctUsers(users);
|
||||
|
||||
// 设置外键并保存场次(含新增和修改)
|
||||
info.getTimePeriods().forEach(p -> p.setMeetingId(meetingId));
|
||||
@@ -79,7 +82,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 页面传过来的新人员
|
||||
Set<String> newUserIds = Arrays.stream(users).map(MeetingTimePeriodUser::getUserId).collect(Collectors.toSet());
|
||||
Set<String> newUserIds = uniqueUsers.stream().map(MeetingTimePeriodUser::getUserId).collect(Collectors.toSet());
|
||||
|
||||
// 删除废弃场次及其所有关联
|
||||
Set<String> deletedPeriodIds = Sets.difference(oldPeriodIds, newPeriodIds);
|
||||
@@ -99,7 +102,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
List<MeetingTimePeriodUser> newRelations = new ArrayList<>();
|
||||
|
||||
// 新增的用户 → 所有现存场次
|
||||
List<MeetingTimePeriodUser> newUsers = Arrays.stream(users).filter(u -> StrUtil.isBlank(u.getId())).toList();
|
||||
List<MeetingTimePeriodUser> newUsers = uniqueUsers.stream().filter(u -> StrUtil.isBlank(u.getId())).toList();
|
||||
for (String periodId : newPeriodIds) {
|
||||
for (MeetingTimePeriodUser user : newUsers) {
|
||||
newRelations.add(buildRelation(meetingId, periodId, user));
|
||||
@@ -109,7 +112,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
// 新增的场次 → 所有现存老用户(避免重复插入新用户)
|
||||
Set<String> addedPeriodIds = Sets.difference(newPeriodIds, oldPeriodIds);
|
||||
for (String periodId : addedPeriodIds) {
|
||||
for (MeetingTimePeriodUser user : users) {
|
||||
for (MeetingTimePeriodUser user : uniqueUsers) {
|
||||
if (StrUtil.isBlank(user.getId())) continue;
|
||||
newRelations.add(buildRelation(meetingId, periodId, user));
|
||||
}
|
||||
@@ -131,4 +134,21 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
rel.setJoinStatus(true);
|
||||
return rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按用户 ID 去重会议参会人员,保留首次选择的人员信息。
|
||||
* 同一用户在一个会议的每个场次只允许生成一条参会关系,防止重复提交或重复选择产生重复记录。
|
||||
*
|
||||
* @param users 前端提交的参会人员数组,每项必须包含 userId
|
||||
* @return 去重后的参会人员列表,userId 为空的无效项不会参与保存
|
||||
*/
|
||||
private List<MeetingTimePeriodUser> distinctUsers(MeetingTimePeriodUser[] users) {
|
||||
if (users == null || users.length == 0) {
|
||||
return List.of();
|
||||
}
|
||||
return new ArrayList<>(Arrays.stream(users)
|
||||
.filter(user -> StrUtil.isNotBlank(user.getUserId()))
|
||||
.collect(Collectors.toMap(MeetingTimePeriodUser::getUserId, user -> user, (first, duplicate) -> first, LinkedHashMap::new))
|
||||
.values());
|
||||
}
|
||||
}
|
||||
|
||||
+12
-8
@@ -70,13 +70,16 @@ public class MeetingOnlineServiceImpl extends BaseServiceImpl<MeetingInfo> imple
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MeetingTimePeriodUser> getSignInUser(String timePeriodId) {
|
||||
return dao().query(
|
||||
MeetingTimePeriodUser.class,
|
||||
Cnd.where(MeetingTimePeriodUser::getTimePeriodId, "=", timePeriodId)
|
||||
.and(MeetingTimePeriodUser::getSignStatus, "=", true)
|
||||
.desc("signTime")
|
||||
);
|
||||
public List<MeetingTimePeriodUser> getSignInUser(String timePeriodId, String signRankOrder) {
|
||||
Cnd cnd = Cnd.where(MeetingTimePeriodUser::getTimePeriodId, "=", timePeriodId)
|
||||
.and(MeetingTimePeriodUser::getSignStatus, "=", true);
|
||||
// 签到名次由签到时间确定,只识别固定方向参数,禁止将前端排序内容直接拼接到SQL中。
|
||||
if ("ascending".equals(signRankOrder)) {
|
||||
cnd.asc("signTime");
|
||||
} else {
|
||||
cnd.desc("signTime");
|
||||
}
|
||||
return dao().query(MeetingTimePeriodUser.class, cnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,7 +136,8 @@ public class MeetingOnlineServiceImpl extends BaseServiceImpl<MeetingInfo> imple
|
||||
Sys_role formalRole = roleService.getByCode(formalRoleCode);
|
||||
Sys_role attendanceRole = roleService.getByCode(attendanceRoleCode);
|
||||
|
||||
List<String> signedInUserIds = getSignInUser(timePeriodId).stream()
|
||||
// 代表签到统计只关心已签到人员集合,使用默认降序查询即可。
|
||||
List<String> signedInUserIds = getSignInUser(timePeriodId, "descending").stream()
|
||||
.map(MeetingTimePeriodUser::getUserId)
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user