diff --git a/src/main/java/com/budwk/app/sys/models/Sys_user_history.java b/src/main/java/com/budwk/app/sys/models/Sys_user_history.java index f0b60c5e..0522a724 100644 --- a/src/main/java/com/budwk/app/sys/models/Sys_user_history.java +++ b/src/main/java/com/budwk/app/sys/models/Sys_user_history.java @@ -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) diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java index fbf37f69..243b121c 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java @@ -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 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 + " 人"; } /** diff --git a/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureApplyActivityController.java b/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureApplyActivityController.java index d9d212be..b2099079 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureApplyActivityController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureApplyActivityController.java @@ -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); diff --git a/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureInfoManageController.java b/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureInfoManageController.java index 72c2b436..14a62d4e 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureInfoManageController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/culture/controller/ActivityCultureInfoManageController.java @@ -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(); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/culture/models/ActivityTissue.java b/src/main/java/com/budwk/app/zhgh/activity/culture/models/ActivityTissue.java index 3acb2ba0..c6e99ede 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/culture/models/ActivityTissue.java +++ b/src/main/java/com/budwk/app/zhgh/activity/culture/models/ActivityTissue.java @@ -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) diff --git a/src/main/java/com/budwk/app/zhgh/activity/culture/service/ActivityCultureService.java b/src/main/java/com/budwk/app/zhgh/activity/culture/service/ActivityCultureService.java index e5c86ab5..2d167a62 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/culture/service/ActivityCultureService.java +++ b/src/main/java/com/budwk/app/zhgh/activity/culture/service/ActivityCultureService.java @@ -21,7 +21,33 @@ public interface ActivityCultureService extends BaseService { 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); diff --git a/src/main/java/com/budwk/app/zhgh/activity/culture/service/impl/ActivityCultureServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/culture/service/impl/ActivityCultureServiceImpl.java index 762aebcb..d29c9cdc 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/culture/service/impl/ActivityCultureServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/culture/service/impl/ActivityCultureServiceImpl.java @@ -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 } @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 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 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 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 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(""" diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityController.java index 3375b394..78dc5189 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityController.java @@ -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 pagination = familyActivityManageService.pageData(pageForm, cnd); - List list = pagination.getList(FamilyActivity.class); - if (list != null && !list.isEmpty()) { - List ids = list.stream().map(FamilyActivity::getId).toList(); - List templateList = dao.query(Sys_home_template.class, Cnd.where("id", "in", ids)); - List 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); diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java index 9410d729..aca9c1de 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java @@ -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) diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityService.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityService.java index 08ffb68d..7ebdd66c 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityService.java +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityService.java @@ -50,6 +50,21 @@ public interface FamilyActivityService extends BaseService { */ Pagination pageData(PageForm pageForm, Cnd cnd); + /** + * 将亲子活动设置为工作模板,并同步模板状态。 + * + * @param id 活动ID + * @return true 表示活动存在且设置成功,false 表示活动不存在 + */ + boolean setTemplate(String id); + + /** + * 取消亲子活动模板,并同步模板状态。 + * + * @param id 活动ID + */ + void cancelTemplate(String id); + /** * 手机端分页查询 diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java index 50fbbae1..54f2e5d8 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java @@ -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 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 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(); diff --git a/src/main/java/com/budwk/app/zhgh/activity/sports/controller/ActivitySportsInfoManageController.java b/src/main/java/com/budwk/app/zhgh/activity/sports/controller/ActivitySportsInfoManageController.java index fb631300..485c20e7 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/sports/controller/ActivitySportsInfoManageController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/sports/controller/ActivitySportsInfoManageController.java @@ -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(); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/sports/models/ActivitySchool.java b/src/main/java/com/budwk/app/zhgh/activity/sports/models/ActivitySchool.java index b9143e94..1e1c1b60 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/sports/models/ActivitySchool.java +++ b/src/main/java/com/budwk/app/zhgh/activity/sports/models/ActivitySchool.java @@ -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) diff --git a/src/main/java/com/budwk/app/zhgh/activity/sports/service/ActivitySportsService.java b/src/main/java/com/budwk/app/zhgh/activity/sports/service/ActivitySportsService.java index 452eb811..071f66b0 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/sports/service/ActivitySportsService.java +++ b/src/main/java/com/budwk/app/zhgh/activity/sports/service/ActivitySportsService.java @@ -18,5 +18,20 @@ public interface ActivitySportsService extends BaseService { 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); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/sports/service/impl/ActivitySportsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/sports/service/impl/ActivitySportsServiceImpl.java index 3a5c5610..dd8ec1af 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/sports/service/impl/ActivitySportsServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/sports/service/impl/ActivitySportsServiceImpl.java @@ -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 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 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 { diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java index c67fba16..61862dd6 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java @@ -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 pagination = trainSignUpActivityManageService.pageData(pageForm, cnd); - List list = pagination.getList(TrainSignUpActivity.class); - if (list != null && !list.isEmpty()) { - List ids = list.stream().map(TrainSignUpActivity::getId).toList(); - List templateList = dao.query(Sys_home_template.class, Cnd.where("id", "in", ids)); - List 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(); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivity.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivity.java index 37b39285..7165e956 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivity.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivity.java @@ -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) diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java index bab6eaea..6a0bdbb6 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java @@ -59,6 +59,21 @@ public interface TrainSignUpActivityService extends BaseService { + + /** + * 分页查询作品征集活动。 + * + * @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); /** * 校验编辑活动时删除的主题类型、作品类型是否已被投稿引用。 diff --git a/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/impl/ActivityWorksCollectionServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/impl/ActivityWorksCollectionServiceImpl.java index 99962208..61b9fef1 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/impl/ActivityWorksCollectionServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/workscollection/service/impl/ActivityWorksCollectionServiceImpl.java @@ -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 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())) { diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java index 48e80c5f..04404360 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/constant/MemberChangeType.java @@ -17,6 +17,7 @@ import lombok.Getter; public enum MemberChangeType { //变更类型 + PENDING_CONFIRM("PENDING_CONFIRM", "待确认"), NEW("NEW", "新入职"), RESTORE("RESTORE", "入会"), WITHDRAWAL("WITHDRAWAL", "退会"), diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java index 809b5354..f9c472ae 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/change/MemberChangeManageController.java @@ -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 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); } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java index 6bc1cbbd..f37c65d9 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java @@ -441,8 +441,12 @@ public class MemberManageServiceImpl extends BaseServiceImpl implement MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, Cnd.where("userId", "=", userId).desc("applyDateTime")); - List historyList = dao().query(Sys_user_history.class, Cnd.where("loginname", "=", loginName) - .and("changeInfos", "is not", null).desc("changeTime")); + /* + * 待确认人员来自全量数据差异校正,没有常规的字段前后值 changeInfos。 + * 此处保留该人员的全部历史,再在组装时间线时仅接纳普通变更或待确认记录。 + */ + List historyList = dao().query(Sys_user_history.class, + Cnd.where("loginname", "=", loginName).desc("changeTime")); List recordList = historyList.stream().map(Sys_user_history::getRecordId).toList(); @@ -455,11 +459,25 @@ public class MemberManageServiceImpl extends BaseServiceImpl 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 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; diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/controller/PendingSourceChangeController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/controller/PendingSourceChangeController.java new file mode 100644 index 00000000..c93ebc81 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/controller/PendingSourceChangeController.java @@ -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()); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/param/PendingUserConfirmParam.java b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/param/PendingUserConfirmParam.java new file mode 100644 index 00000000..9e13dbcd --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/param/PendingUserConfirmParam.java @@ -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; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/service/PendingUserHistoryService.java b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/service/PendingUserHistoryService.java new file mode 100644 index 00000000..d65981c3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/service/PendingUserHistoryService.java @@ -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 systemUsers, List sourceUsers); +} diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/service/impl/PendingUserHistoryServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/service/impl/PendingUserHistoryServiceImpl.java new file mode 100644 index 00000000..58f31706 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/sourcechange/service/impl/PendingUserHistoryServiceImpl.java @@ -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 systemUsers, List sourceUsers) { + Set sourceLoginNames = sourceUsers.stream() + .map(Sys_user_source::getLoginname) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + List pendingHistories = dao.query(Sys_user_history.class, pendingCondition()); + + // 已重新出现在完整源数据中的人员不再需要人工确认,仅删除尚未处理的待确认记录。 + List recoveredPendingIds = pendingHistories.stream() + .filter(history -> sourceLoginNames.contains(history.getLoginname())) + .map(Sys_user_history::getId) + .toList(); + for (List idBatch : ListUtil.split(recoveredPendingIds, BATCH_SIZE)) { + dao.clear(Sys_user_history.class, Cnd.where("id", "in", idBatch)); + } + + Set existingPendingLoginNames = pendingHistories.stream() + .filter(history -> !sourceLoginNames.contains(history.getLoginname())) + .map(Sys_user_history::getLoginname) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(HashSet::new)); + List 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 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() + "'), '$')")); + } +} diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index 49351962..52398357 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -5,7 +5,7 @@ nutz: ignore: ^(.+[.])(jsp|png|gif|jpg|js|css|jspx|jpeg|html|mp3|mp4|ico|svg|vue)$ exclusions: /favicon/*,/assets/*,/druid/*,/upload/*,/components/* server: - port: 80 + port: 8080 host: 0.0.0.0 jetty: diff --git a/src/main/resources/db/activity_school_add_template_status.sql b/src/main/resources/db/activity_school_add_template_status.sql new file mode 100644 index 00000000..f8a19c77 --- /dev/null +++ b/src/main/resources/db/activity_school_add_template_status.sql @@ -0,0 +1,7 @@ +-- 体育活动增加模板设置状态,并根据现有工作模板回填历史数据。 +ALTER TABLE `activity_school` + ADD COLUMN `templateStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '模板设置状态 0.未设置 1.已设置' AFTER `isSave`; + +UPDATE `activity_school` school +INNER JOIN `sys_home_template` template ON template.`id` = school.`id` +SET school.`templateStatus` = 1; diff --git a/src/main/resources/db/activity_tissue_add_template_status.sql b/src/main/resources/db/activity_tissue_add_template_status.sql new file mode 100644 index 00000000..56daf802 --- /dev/null +++ b/src/main/resources/db/activity_tissue_add_template_status.sql @@ -0,0 +1,8 @@ +-- 文化活动增加模板设置状态,并只回填校工会文化活动的历史模板数据。 +ALTER TABLE `activity_tissue` + ADD COLUMN `templateStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '模板设置状态 0.未设置 1.已设置'; + +UPDATE `activity_tissue` tissue +INNER JOIN `sys_home_template` template ON template.`id` = tissue.`id` +SET tissue.`templateStatus` = 1 +WHERE tissue.`activity_type` = 40001; diff --git a/src/main/resources/db/activity_tissue_backfill_union_template_status.sql b/src/main/resources/db/activity_tissue_backfill_union_template_status.sql new file mode 100644 index 00000000..0110bedb --- /dev/null +++ b/src/main/resources/db/activity_tissue_backfill_union_template_status.sql @@ -0,0 +1,5 @@ +-- 使用现有模板设置状态字段,回填分工会文化活动的历史模板数据。 +UPDATE `activity_tissue` tissue +INNER JOIN `sys_home_template` template ON template.`id` = tissue.`id` +SET tissue.`templateStatus` = 1 +WHERE tissue.`activity_type` = 40002; diff --git a/src/main/resources/db/activity_works_collection_add_template_status.sql b/src/main/resources/db/activity_works_collection_add_template_status.sql new file mode 100644 index 00000000..06813968 --- /dev/null +++ b/src/main/resources/db/activity_works_collection_add_template_status.sql @@ -0,0 +1,7 @@ +-- 作品征集活动增加模板设置状态,并根据现有工作模板回填历史数据。 +ALTER TABLE `activity_works_collection` + ADD COLUMN `templateStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '模板设置状态 0.未设置 1.已设置'; + +UPDATE `activity_works_collection` activity +INNER JOIN `sys_home_template` template ON template.`id` = activity.`id` +SET activity.`templateStatus` = 1; diff --git a/src/main/resources/db/family_activity_add_template_status.sql b/src/main/resources/db/family_activity_add_template_status.sql new file mode 100644 index 00000000..0f67e36c --- /dev/null +++ b/src/main/resources/db/family_activity_add_template_status.sql @@ -0,0 +1,7 @@ +-- 亲子活动增加模板设置状态,并根据现有工作模板回填历史数据。 +ALTER TABLE `family_activity` + ADD COLUMN `templateStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '模板设置状态 0.未设置 1.已设置'; + +UPDATE `family_activity` activity +INNER JOIN `sys_home_template` template ON template.`id` = activity.`id` +SET activity.`templateStatus` = 1; diff --git a/src/main/resources/db/menu/init_pending_source_change_menu.sql b/src/main/resources/db/menu/init_pending_source_change_menu.sql new file mode 100644 index 00000000..d129ece9 --- /dev/null +++ b/src/main/resources/db/menu/init_pending_source_change_menu.sql @@ -0,0 +1,64 @@ +-- 待确认人员记录菜单。以“变更记录”为同级菜单,并复制原变更记录菜单的角色授权。 +INSERT INTO sys_menu ( + id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, + permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, + delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService +) +SELECT + '76a21e7d35df4ffbaecce44b3a659901', + source_menu.parentId, + CONCAT( + LEFT(source_menu.path, CHAR_LENGTH(source_menu.path) - 4), + LPAD( + IFNULL(( + SELECT MAX(CAST(RIGHT(child.path, 4) AS UNSIGNED)) + FROM sys_menu child + WHERE child.parentId = source_menu.parentId + ), 0) + 1, + 4, + '0' + ) + ), + '待确认人员记录', + 'Pending Personnel', + 'menu', + '/platform/sourcechange/pending', + 'data-pjax', + '', + 1, + 0, + 'staff.sourcechange.pending', + '全量人员数据差异待人工确认记录', + source_menu.location + 1, + 0, + '', + UNIX_TIMESTAMP(NOW()) * 1000, + '', + UNIX_TIMESTAMP(NOW()) * 1000, + 0, + 'PC', + source_menu.moduleId, + NULL, + 'd', + 0, + 0 +FROM sys_menu source_menu +WHERE source_menu.permission = 'staff.sourcechange.manage' + AND NOT EXISTS ( + SELECT 1 + FROM (SELECT id FROM sys_menu WHERE permission = 'staff.sourcechange.pending') existing_menu + ); + +-- 原先能够查看“变更记录”的角色默认拥有“待确认人员记录”权限,避免新页面上线后无人可见。 +INSERT INTO sys_role_menu (roleId, menuId) +SELECT source_role.roleId, pending_menu.id +FROM sys_role_menu source_role +JOIN sys_menu source_menu + ON source_menu.id = source_role.menuId + AND source_menu.permission = 'staff.sourcechange.manage' +JOIN sys_menu pending_menu + ON pending_menu.permission = 'staff.sourcechange.pending' +LEFT JOIN sys_role_menu existing_role + ON existing_role.roleId = source_role.roleId + AND existing_role.menuId = pending_menu.id +WHERE existing_role.roleId IS NULL; diff --git a/src/main/resources/db/menu/update_tour_service_unit_menu.sql b/src/main/resources/db/menu/update_tour_service_unit_menu.sql new file mode 100644 index 00000000..ed496c58 --- /dev/null +++ b/src/main/resources/db/menu/update_tour_service_unit_menu.sql @@ -0,0 +1,8 @@ +-- 已初始化环境通过权限标识定位菜单,仅更新展示信息,不改变权限和访问路径。 +UPDATE sys_menu +SET name = '服务单位管理', + aliasName = 'Service Unit', + initialPinyinName = 'f', + updatedAt = UNIX_TIMESTAMP(NOW()) * 1000 +WHERE permission = 'tour.travelAgency' + AND delFlag = 0; diff --git a/src/main/resources/db/sys_user_history_pending_confirm.sql b/src/main/resources/db/sys_user_history_pending_confirm.sql new file mode 100644 index 00000000..99446437 --- /dev/null +++ b/src/main/resources/db/sys_user_history_pending_confirm.sql @@ -0,0 +1,18 @@ +-- 待确认人员人工确认备注字段。已有字段的环境重复执行不会改变表结构。 +SET @pending_remark_column_count = ( + SELECT COUNT(*) + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'sys_user_history' + AND COLUMN_NAME = 'remark' +); + +SET @pending_remark_ddl = IF( + @pending_remark_column_count = 0, + 'ALTER TABLE sys_user_history ADD COLUMN remark TEXT NULL COMMENT ''备注'' AFTER changeReason', + 'SELECT 1' +); + +PREPARE pending_remark_stmt FROM @pending_remark_ddl; +EXECUTE pending_remark_stmt; +DEALLOCATE PREPARE pending_remark_stmt; diff --git a/src/main/resources/db/tour_ledger_add_in_province_check_index.sql b/src/main/resources/db/tour_ledger_add_in_province_check_index.sql new file mode 100644 index 00000000..340f6e4c --- /dev/null +++ b/src/main/resources/db/tour_ledger_add_in_province_check_index.sql @@ -0,0 +1,3 @@ +-- 省内参加间隔按工号、年度、线路类型和参加状态查询,补充联合索引降低报名校验耗时。 +ALTER TABLE `tour_ledger` + ADD KEY `idx_tour_ledger_in_province_check` (`jobNo`, `joined`, `delFlag`, `lineType`, `year`); diff --git a/src/main/resources/db/tour_ledger_add_union_quota_index.sql b/src/main/resources/db/tour_ledger_add_union_quota_index.sql new file mode 100644 index 00000000..dcc1243f --- /dev/null +++ b/src/main/resources/db/tour_ledger_add_union_quota_index.sql @@ -0,0 +1,3 @@ +-- 分工会名额校验按事项、分工会和删除状态统计报名人数,补充联合索引降低抢票时锁内查询耗时。 +ALTER TABLE `tour_ledger` + ADD KEY `idx_tour_ledger_matter_union_del` (`matterId`, `unionId`, `delFlag`); diff --git a/src/main/resources/db/tour_setting_add_in_province_years.sql b/src/main/resources/db/tour_setting_add_in_province_years.sql new file mode 100644 index 00000000..d38c2cd4 --- /dev/null +++ b/src/main/resources/db/tour_setting_add_in_province_years.sql @@ -0,0 +1,3 @@ +-- 疗休养配置增加省内参加间隔年限,历史配置默认不限制。 +ALTER TABLE `tour_setting` + ADD COLUMN `inProvinceYears` int DEFAULT 0 COMMENT '省内几年去一次' AFTER `maxGroupPeople`; diff --git a/src/main/resources/db/train_sign_up_activity_add_template_status.sql b/src/main/resources/db/train_sign_up_activity_add_template_status.sql new file mode 100644 index 00000000..548b70ba --- /dev/null +++ b/src/main/resources/db/train_sign_up_activity_add_template_status.sql @@ -0,0 +1,7 @@ +-- 品牌活动增加模板设置状态,并根据现有工作模板回填历史数据。 +ALTER TABLE `train_sign_up_activity` + ADD COLUMN `templateStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '模板设置状态 0.未设置 1.已设置'; + +UPDATE `train_sign_up_activity` activity +INNER JOIN `sys_home_template` template ON template.`id` = activity.`id` +SET activity.`templateStatus` = 1; diff --git a/src/main/resources/views/platform/zhgh/activity/culture/common/applyActivity.js b/src/main/resources/views/platform/zhgh/activity/culture/common/applyActivity.js index 9d898f1a..54645afd 100644 --- a/src/main/resources/views/platform/zhgh/activity/culture/common/applyActivity.js +++ b/src/main/resources/views/platform/zhgh/activity/culture/common/applyActivity.js @@ -681,6 +681,7 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = { data.taskId = null data.startTaskId = null data.isTemplate = false + data.templateStatus = 0 data.createdBy = null data.createdAt = null data.updatedBy = null diff --git a/src/main/resources/views/platform/zhgh/activity/culture/common/infoMange.js b/src/main/resources/views/platform/zhgh/activity/culture/common/infoMange.js index 0d742030..32855eb1 100644 --- a/src/main/resources/views/platform/zhgh/activity/culture/common/infoMange.js +++ b/src/main/resources/views/platform/zhgh/activity/culture/common/infoMange.js @@ -5,7 +5,8 @@ const ACTIVITY_CULTURE_INFO_MANAGE = { template: /*language=HTML*/`