This commit is contained in:
2026-08-17 11:01:48 +08:00
parent e4485d7b02
commit ac5a2d902e
54 changed files with 2108 additions and 379 deletions
@@ -51,6 +51,11 @@ public class Sys_user_history extends Sys_user {
@Comment("变更原因")
private String changeReason;
@Column
@ColDefine(type = ColType.VARCHAR, customType = "text")
@Comment("备注")
private String remark;
@Column
@Comment("会员变更表记录id")
@ColDefine(type = ColType.VARCHAR, width = 32)
@@ -22,6 +22,7 @@ import com.budwk.app.sys.services.SysUserService;
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 com.budwk.app.zhgh.staffmanage.sourcechange.service.PendingUserHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
@@ -61,6 +62,8 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
private SysUserService sysUserService;
@Inject
private ThreadPoolTaskExecutor executorService;
@Inject
private PendingUserHistoryService pendingUserHistoryService;
private static Map<String, String> unitIdNameMap;
@@ -289,6 +292,12 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
return "更新失败: " + e.getMessage();
}
/*
* 用户及普通变更记录完成后,再以本次完整源数据校正待确认人员。
* 该步骤仅存在于 ALL 实现中,增量更新不会误判未包含在增量数据中的系统用户。
*/
int pendingConfirmCount = pendingUserHistoryService.reconcile(sysUsers, sources);
/* // 4. 异步添加会员角色 - 不等待完成
if (Lang.isNotEmpty(addMemberUserIds)) {
executorService.execute(() -> {
@@ -349,11 +358,11 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
long endTime = System.currentTimeMillis();
log.info("全量更新用户数据完成,耗时: {} 毫秒", (endTime - startTime));
if (needInitUserList.isEmpty() && histories.isEmpty()) {
if (needInitUserList.isEmpty() && histories.isEmpty() && pendingConfirmCount == 0) {
return "本次没有可更新的数据。";
}
return "更新完成: 新增用户 " + needInitUserList.size() + " 个, 有效变更 " + histories.size()
+ "";
+ ", 新增待确认人员 " + pendingConfirmCount + "";
}
/**
@@ -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);
@@ -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)
@@ -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);
@@ -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("""
@@ -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);
/**
* 手机端分页查询
@@ -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();
@@ -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();
}
@@ -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)
@@ -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);
}
@@ -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 {
@@ -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)
@@ -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);
/**
* 手机端分页查询
@@ -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();
@@ -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;
@@ -53,8 +51,6 @@ public class ActivityWorksCollectionManageController {
@Inject
private ActivityWorksCollectionService activityWorksCollectionService;
@Inject
private BaseService baseService;
@Inject
private SysMsgService sysMsgService;
@Inject
private ActivityBasicScopeService activityBasicScopeService;
@@ -67,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
@@ -100,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();
}
@@ -130,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();
}
@@ -165,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);
@@ -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)
@@ -1,11 +1,39 @@
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 {
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);
/**
* 校验编辑活动时删除的主题类型作品类型是否已被投稿引用
@@ -2,13 +2,22 @@ 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;
@@ -20,14 +29,93 @@ import java.util.stream.Collectors;
* 作品征集活动配置服务实现
*/
@IocBean(args = {"refer:dao"})
public class ActivityWorksCollectionServiceImpl implements ActivityWorksCollectionService {
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())) {
@@ -17,6 +17,7 @@ import lombok.Getter;
public enum MemberChangeType {
//变更类型
PENDING_CONFIRM("PENDING_CONFIRM", "待确认"),
NEW("NEW", "新入职"),
RESTORE("RESTORE", "入会"),
WITHDRAWAL("WITHDRAWAL", "退会"),
@@ -168,17 +168,23 @@ public class MemberChangeManageController {
@At
@ApiOperation("获取该人员所有的变更信息")
@SaCheckPermission(value = {"member.change.mange", "staff.member.change.mange"}, mode = SaMode.OR)
@SaCheckPermission(value = {
"member.change.mange",
"staff.member.change.mange",
"staff.sourcechange.manage",
"staff.sourcechange.pending"
}, mode = SaMode.OR)
public Result getAllChangeMemberInfo(String userId){
List<NutMap> mapList = memberCommonService.getAllChangeInfo(userId);
if (Lang.isEmpty(mapList)) {
return Result.error("未获取到异动数据");
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", userId));
if (user == null) {
return Result.error("未获取到人员基础信息");
}
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", userId));
// 基础信息与历史异动相互独立即使没有字段异动明细也必须允许页面展示人员基础信息
NutMap map = Lang.obj2nutmap(user);
map.put("user",user);
map.put("allChangeInfo", mapList);
map.put("allChangeInfo", Lang.isEmpty(mapList) ? null : mapList);
return Result.success(map);
}
@@ -441,8 +441,12 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, Cnd.where("userId", "=", userId).desc("applyDateTime"));
List<Sys_user_history> historyList = dao().query(Sys_user_history.class, Cnd.where("loginname", "=", loginName)
.and("changeInfos", "is not", null).desc("changeTime"));
/*
* 待确认人员来自全量数据差异校正没有常规的字段前后值 changeInfos
* 此处保留该人员的全部历史再在组装时间线时仅接纳普通变更或待确认记录
*/
List<Sys_user_history> historyList = dao().query(Sys_user_history.class,
Cnd.where("loginname", "=", loginName).desc("changeTime"));
List<String> recordList = historyList.stream().map(Sys_user_history::getRecordId).toList();
@@ -455,11 +459,25 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
resultMapList.add(map);
}
for (Sys_user_history history : historyList) {
boolean pendingConfirm = Lang.isNotEmpty(history.getChangeTypes())
&& history.getChangeTypes().contains(MemberChangeType.PENDING_CONFIRM.name());
if (Lang.isEmpty(history.getChangeInfos()) && !pendingConfirm) {
continue;
}
NutMap map = NutMap.NEW();
List<NutMap> changeInfos = history.getChangeInfos();
if (pendingConfirm) {
// 待确认记录没有人工异动表使用差异校正原因构造可阅读的变更说明
changeInfos = List.of(NutMap.NEW()
.setv("field", "pendingConfirm")
.setv("fieldName", "人员状态")
.setv("sourceValue", "系统用户中存在")
.setv("newValue", StrUtil.blankToDefault(history.getChangeReason(), "本次全量人员数据中不存在")));
}
map.put("changeInfos", changeInfos);
map.put("timestamp", DateUtil.format(history.getChangeTime(), "yyyy-MM-dd HH:mm:ss"));
map.put("changeOriginName", MemberChangeOrigin.valueOf(MemberChangeOrigin.class, history.getChangeOrigin()).changeOriginName);
String changeOriginName = MemberChangeOrigin.valueOf(MemberChangeOrigin.class, history.getChangeOrigin()).changeOriginName;
map.put("changeOriginName", pendingConfirm ? changeOriginName + "(待确认)" : changeOriginName);
resultMapList.add(map);
}
return resultMapList;
@@ -0,0 +1,71 @@
package com.budwk.app.zhgh.staffmanage.sourcechange.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.staffmanage.sourcechange.param.PendingUserConfirmParam;
import com.budwk.app.zhgh.staffmanage.sourcechange.param.SourceChangePageForm;
import com.budwk.app.zhgh.staffmanage.sourcechange.service.PendingUserHistoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.validation.Valid;
/**
* 待确认人员记录页面及接口
*/
@IocBean
@At("/platform/sourcechange/pending")
@Ok("json")
@Api(tags = "待确认人员记录")
public class PendingSourceChangeController {
@Inject
private PendingUserHistoryService pendingUserHistoryService;
/**
* 打开待确认人员记录页面
*/
@At("")
@Ok("beetl:/platform/zhgh/staffmanage/sourcechange/pending/index.html")
@SaCheckPermission("staff.sourcechange.pending")
public void index() {
}
/**
* 分页查询当前仍需人工确认的人员记录
*
* @param pageForm 变更记录通用查询条件
* @return 分页结果
*/
@At
@ApiOperation("分页查询待确认人员")
@SaCheckPermission("staff.sourcechange.pending")
public Result pageData(SourceChangePageForm pageForm) {
return Result.success(pendingUserHistoryService.listPage(pageForm));
}
/**
* 将待确认人员记录确认成最终异动类型
*
* @param confirmParam 异动类型及备注
* @return 处理结果
*/
@At
@ApiOperation("确认待确认人员")
@SLog(tag = "待确认人员记录", msg = "确认人员")
@SaCheckPermission("staff.sourcechange.pending")
public Result confirm(@Valid @Param("data") PendingUserConfirmParam confirmParam) {
try {
pendingUserHistoryService.confirm(confirmParam);
return Result.success();
} catch (IllegalArgumentException | IllegalStateException e) {
return Result.error(e.getMessage());
}
}
}
@@ -0,0 +1,28 @@
package com.budwk.app.zhgh.staffmanage.sourcechange.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* 待确认人员确认参数
*/
@Data
@ApiModel("待确认人员确认参数")
public class PendingUserConfirmParam {
@NotBlank(message = "待确认记录不能为空")
@ApiModelProperty("sys_user_history 记录ID")
private String id;
@NotBlank(message = "请选择异动类型")
@ApiModelProperty("最终异动类型")
private String changeType;
@Size(max = 1000, message = "备注不能超过1000个字符")
@ApiModelProperty("确认备注")
private String remark;
}
@@ -0,0 +1,39 @@
package com.budwk.app.zhgh.staffmanage.sourcechange.service;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.models.Sys_user_source;
import com.budwk.app.zhgh.staffmanage.sourcechange.param.PendingUserConfirmParam;
import com.budwk.app.zhgh.staffmanage.sourcechange.param.SourceChangePageForm;
import java.util.List;
/**
* 待确认人员历史记录业务服务
*/
public interface PendingUserHistoryService {
/**
* 根据变更记录页面的查询条件分页查询待确认人员
*
* @param pageForm 查询及分页参数
* @return 待确认人员分页数据
*/
Pagination listPage(SourceChangePageForm pageForm);
/**
* 将待确认记录更新为人工选择的最终异动类型并保存备注
*
* @param confirmParam 确认参数
*/
void confirm(PendingUserConfirmParam confirmParam);
/**
* 依据本次全量源数据校正待确认记录缺失人员补充记录重新出现人员删除待确认记录
*
* @param systemUsers 更新开始时系统中已有的用户
* @param sourceUsers 本次全量拉取的用户
* @return 本次新增的待确认记录数量
*/
int reconcile(List<Sys_user> systemUsers, List<Sys_user_source> sourceUsers);
}
@@ -0,0 +1,197 @@
package com.budwk.app.zhgh.staffmanage.sourcechange.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.models.Sys_user_history;
import com.budwk.app.sys.models.Sys_user_source;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
import com.budwk.app.zhgh.staffmanage.sourcechange.param.PendingUserConfirmParam;
import com.budwk.app.zhgh.staffmanage.sourcechange.param.SourceChangePageForm;
import com.budwk.app.zhgh.staffmanage.sourcechange.service.PendingUserHistoryService;
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.dao.util.cri.SqlExpressionGroup;
import org.nutz.dao.util.cri.Static;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.random.R;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 待确认人员历史记录业务实现
*/
@IocBean
public class PendingUserHistoryServiceImpl implements PendingUserHistoryService {
private static final int BATCH_SIZE = 500;
@Inject
private Dao dao;
@Inject
private SysUserService sysUserService;
/**
* 查询待确认人员查询字段与人员变更记录页面保持一致但未选择日期时查询全部待确认数据
*/
@Override
public Pagination listPage(SourceChangePageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
his.id,
his.loginname,
his.username,
COALESCE(u.sex, his.sex) AS sex,
COALESCE(u.unitName, his.unitName) AS unitName,
COALESCE(u.unionName, his.unionName) AS unionName,
his.userState,
his.personType,
his.preparedBy,
his.changeTime,
his.changeTypes,
his.changeOrigin,
his.remark,
u.id AS userId
FROM sys_user_history his
LEFT JOIN vw_user u ON his.loginname = u.loginname
$condition
""");
Cnd cnd = Cnd.NEW();
// 待确认页面固定限定待确认类型避免已处理记录继续出现在列表中
cnd.and(new Static("JSON_CONTAINS(his.changeTypes, JSON_QUOTE('" + MemberChangeType.PENDING_CONFIRM.name() + "'), '$')"));
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup keywordGroup = new SqlExpressionGroup();
keywordGroup.orLike("his.username", pageForm.getSearchKeyword());
keywordGroup.orLike("his.loginname", pageForm.getSearchKeyword());
cnd.and(keywordGroup);
}
cnd.andEX("u.unionId", "=", pageForm.getUnionId());
cnd.andEX("u.unitId", "=", pageForm.getUnitId());
cnd.andEX("u.sex", "=", pageForm.getSex());
cnd.andEX("his.personType", "=", pageForm.getPersonType());
cnd.andEX("his.preparedBy", "=", pageForm.getPreparedBy());
cnd.andEX("his.userState", "=", pageForm.getUserState());
cnd.andEX("his.changeOrigin", "=", pageForm.getChangeOrigin());
// 日期范围使用参数化条件结束日期按次日零点前处理包含所选结束日期的全部数据
if (StrUtil.isAllNotBlank(pageForm.getChangeDateBefore(), pageForm.getChangeDateEnd())) {
Date startDate = DateUtil.parseDate(pageForm.getChangeDateBefore());
Date endDateExclusive = DateUtil.offsetDay(DateUtil.parseDate(pageForm.getChangeDateEnd()), 1);
cnd.and("his.changeTime", ">=", startDate);
cnd.and("his.changeTime", "<", endDateExclusive);
}
if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
} else {
cnd.desc("his.changeTime");
}
sql.setCondition(cnd);
return sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
/**
* 确认待确认人员记录异动类型只允许选择已定义且非待确认的最终类型
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public void confirm(PendingUserConfirmParam confirmParam) {
MemberChangeType selectedType;
try {
selectedType = MemberChangeType.valueOf(confirmParam.getChangeType());
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("异动类型不存在");
}
if (MemberChangeType.PENDING_CONFIRM == selectedType) {
throw new IllegalArgumentException("请选择最终异动类型");
}
// 更新条件同时校验记录仍处于待确认状态防止重复确认覆盖已经处理的数据
Cnd cnd = Cnd.where("id", "=", confirmParam.getId())
.and(new Static("JSON_CONTAINS(changeTypes, JSON_QUOTE('" + MemberChangeType.PENDING_CONFIRM.name() + "'), '$')"));
Chain chain = Chain.make("changeTypes", Json.toJson(List.of(selectedType.name())))
.add("remark", StrUtil.trim(confirmParam.getRemark()));
int updated = dao.update(Sys_user_history.class, chain, cnd);
if (updated == 0) {
throw new IllegalStateException("待确认记录不存在或已被处理");
}
}
/**
* 根据本次全量源数据双向校正待确认历史源数据重新出现则删除源数据缺失则幂等新增
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public int reconcile(List<Sys_user> systemUsers, List<Sys_user_source> sourceUsers) {
Set<String> sourceLoginNames = sourceUsers.stream()
.map(Sys_user_source::getLoginname)
.filter(StrUtil::isNotBlank)
.collect(Collectors.toSet());
List<Sys_user_history> pendingHistories = dao.query(Sys_user_history.class, pendingCondition());
// 已重新出现在完整源数据中的人员不再需要人工确认仅删除尚未处理的待确认记录
List<String> recoveredPendingIds = pendingHistories.stream()
.filter(history -> sourceLoginNames.contains(history.getLoginname()))
.map(Sys_user_history::getId)
.toList();
for (List<String> idBatch : ListUtil.split(recoveredPendingIds, BATCH_SIZE)) {
dao.clear(Sys_user_history.class, Cnd.where("id", "in", idBatch));
}
Set<String> existingPendingLoginNames = pendingHistories.stream()
.filter(history -> !sourceLoginNames.contains(history.getLoginname()))
.map(Sys_user_history::getLoginname)
.filter(StrUtil::isNotBlank)
.collect(Collectors.toCollection(HashSet::new));
List<Sys_user_history> historiesToInsert = new ArrayList<>();
// 同一工号最多保留一条待确认记录重复执行全部更新不会重复生成数据
for (Sys_user user : systemUsers) {
String loginname = user.getLoginname();
if (StrUtil.isBlank(loginname)
|| sourceLoginNames.contains(loginname)
|| !existingPendingLoginNames.add(loginname)) {
continue;
}
Sys_user_history history = new Sys_user_history();
BeanUtil.copyProperties(user, history);
history.setId(R.UU32());
history.setChangeTime(DateUtil.date());
history.setChangeTypes(List.of(MemberChangeType.PENDING_CONFIRM.name()));
history.setChangeOrigin(MemberChangeOrigin.SYSTEM.name());
history.setChangeReason("全量人员数据中不存在");
historiesToInsert.add(history);
}
for (List<Sys_user_history> historyBatch : ListUtil.split(historiesToInsert, BATCH_SIZE)) {
dao.fastInsert(historyBatch);
}
return historiesToInsert.size();
}
/**
* 构造待确认 JSON 类型条件供查询及差异校正统一使用
*/
private Cnd pendingCondition() {
return Cnd.where(new Static("JSON_CONTAINS(changeTypes, JSON_QUOTE('" + MemberChangeType.PENDING_CONFIRM.name() + "'), '$')"));
}
}