diff --git a/src/main/java/com/budwk/app/sys/controller/SysUnionCadreImportController.java b/src/main/java/com/budwk/app/sys/controller/SysUnionCadreImportController.java index 59df764..575e1e9 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysUnionCadreImportController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysUnionCadreImportController.java @@ -8,7 +8,10 @@ import com.budwk.app.base.result.Result; import com.budwk.app.base.utils.CommonDownloadUtil; import com.budwk.app.sys.models.*; import com.budwk.app.sys.services.SysDictService; +import com.budwk.app.sys.services.SysRoleService; +import com.budwk.app.sys.services.SysUserService; import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; @@ -17,6 +20,9 @@ import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.util.NutMap; +import org.nutz.lang.random.R; +import org.nutz.trans.Atom; +import org.nutz.trans.Trans; import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; @@ -26,9 +32,15 @@ import org.nutz.mvc.upload.UploadAdaptor; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @@ -45,6 +57,10 @@ public class SysUnionCadreImportController { private SysDictService sysDictService; @Inject private SysUnionController sysUnionController; + @Inject + private SysRoleService sysRoleService; + @Inject + private SysUserService sysUserService; @SuppressWarnings("unchecked") private List roleOptions() { @@ -72,7 +88,7 @@ public class SysUnionCadreImportController { append(notes, "届次编码(选填)", "可留空;填写时使用届次对照表中的编码,与单个添加一致。"); append(notes, "所属单位编码(书记必填)", "仅二级党委书记填写,多个单位用英文逗号分隔,必须为当前分工会的二级单位;其他角色留空。"); append(notes, "重复记录", "普通干部按人员和角色跳过;二级党委书记按人员、角色和工会跳过。禁用的已有关系也跳过,不覆盖。"); - append(notes, "保存方式", "系统管理员直接授权,写入干部及角色记录并清理权限缓存,不发起审批。逐行保存,失败行不影响其他行。"); + append(notes, "保存方式", "系统管理员直接授权,批量校验并保存干部及角色记录,统一清理权限缓存,不发起审批。校验失败行不写入;保存异常时拆分定位失败行,其他有效行继续导入。"); append(notes, "已有干部记录", "已有在任或待审核干部记录但未分配角色时跳过,避免重复创建或绕过已有审批。"); Sheet unions = createSheet(workbook, "工会对照", "工会编码", "工会名称"); List unionList = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode")); @@ -145,101 +161,271 @@ public class SysUnionCadreImportController { if (rows.isEmpty()) { return Result.error("文件中没有需要导入的数据"); } - List roleCodes = roleOptions().stream().map(item -> item.getString("code")).toList(); - List terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream() - .map(Sys_dict::getCode).toList(); - int success = 0; - int skipped = 0; + Set roleCodes = sysDictService.getSubListByCode("BRANCH_UNION_ROLES").stream() + .map(Sys_dict::getCode).collect(Collectors.toSet()); + roleCodes.add(RoleConstant.UNIT_PARTY_SECRETARY.name()); + Set terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream() + .map(Sys_dict::getCode).collect(Collectors.toSet()); + List unionCodes = values(rows, "unionCode"); + List loginnames = values(rows, "loginname"); + List inputRoleCodes = values(rows, "roleCode"); + List unitCodes = rows.stream().flatMap(row -> splitUnitCodes(row.getString("unitCodes")).stream()) + .distinct().toList(); + // 各类基础数据及已有关系按表一次查询,逐行校验时不再访问数据库。 + Map> unions = group(unionCodes.isEmpty() ? List.of() + : dao.query(Sys_union.class, Cnd.where("unionCode", "in", unionCodes)), Sys_union::getUnionCode); + Map> users = group(loginnames.isEmpty() ? List.of() + : dao.query(View_user.class, Cnd.where("loginname", "in", loginnames)), View_user::getLoginname); + Map> roles = group(inputRoleCodes.isEmpty() ? List.of() + : dao.query(Sys_role.class, Cnd.where("code", "in", inputRoleCodes)), Sys_role::getCode); + Map> units = group(unitCodes.isEmpty() ? List.of() + : dao.query(Sys_unit.class, Cnd.where("unitcode", "in", unitCodes)), Sys_unit::getUnitcode); + List userIds = users.values().stream().flatMap(List::stream).map(View_user::getId).distinct().toList(); + List roleIds = roles.values().stream().flatMap(List::stream).map(Sys_role::getId).distinct().toList(); + Set> existingRoles = new HashSet<>(); + if (!userIds.isEmpty() && !roleIds.isEmpty()) { + for (Sys_user_role relation : dao.query(Sys_user_role.class, + Cnd.where("userId", "in", userIds).and("roleId", "in", roleIds))) { + existingRoles.add(roleKey(relation.getUserId(), relation.getRoleId(), relation.getUnionId(), + roles.getOrDefault(RoleConstant.UNIT_PARTY_SECRETARY.name(), List.of()).stream() + .anyMatch(role -> role.getId().equals(relation.getRoleId())))); + } + } + Set> existingCadres = new HashSet<>(); + if (!userIds.isEmpty() && !inputRoleCodes.isEmpty() && !unionCodes.isEmpty()) { + List unionIds = unions.values().stream().flatMap(List::stream).map(Sys_union::getId).distinct().toList(); + if (!unionIds.isEmpty()) { + for (Sys_union_cadre cadre : dao.query(Sys_union_cadre.class, Cnd.where("userId", "in", userIds) + .and("roleCode", "in", inputRoleCodes).and("unionId", "in", unionIds).and("isServing", "=", true))) { + existingCadres.add(Arrays.asList(cadre.getUserId(), cadre.getRoleCode(), cadre.getUnionId())); + } + } + } + List entries = new ArrayList<>(); + Map, Integer> fileRoles = new java.util.HashMap<>(); + String operator = SecurityUtil.getUserId(); for (NutMap row : rows) { - try { - importRow(row, roleCodes, terms); - } catch (Exception e) { - log.error("导入分工会干部失败,行号:{}", row.getInt("rowNumber"), e); - outcome(row, "失败", "保存失败,请检查该行数据或联系管理员"); - } - if ("成功".equals(row.getString("status"))) { - success++; - } else if ("跳过".equals(row.getString("status"))) { - skipped++; + ImportEntry entry = prepareRow(row, roleCodes, terms, unions, users, roles, units, + existingRoles, existingCadres, fileRoles, operator); + if (entry != null) { + entries.add(entry); } } + saveBatch(entries); + int success = (int) rows.stream().filter(row -> "成功".equals(row.getString("status"))).count(); + int skipped = (int) rows.stream().filter(row -> "跳过".equals(row.getString("status"))).count(); + if (success > 0) { + sysRoleService.clearCache(); + sysUserService.clearCache(); + } return Result.success(NutMap.NEW().addv("success", success).addv("skipped", skipped) .addv("failed", rows.size() - success - skipped).addv("rows", rows)); } - private void importRow(NutMap row, List roleCodes, List terms) { + private List values(List rows, String field) { + return rows.stream().map(row -> row.getString(field)).filter(StrUtil::isNotBlank).distinct().toList(); + } + + private List splitUnitCodes(String codes) { + return Arrays.stream(codes.split("[,,]")).map(String::trim).filter(StrUtil::isNotBlank).distinct().toList(); + } + + private Map> group(List items, Function key) { + return items.stream().collect(Collectors.groupingBy(key)); + } + + private List roleKey(String userId, String roleId, String unionId, boolean secretary) { + return Arrays.asList(userId, roleId, secretary ? unionId : ""); + } + + private T unique(Map> records, String code, String label, List errors) { + if (StrUtil.isBlank(code)) { + errors.add(label + "不能为空"); + return null; + } + List matches = records.getOrDefault(code, List.of()); + if (matches.isEmpty()) { + errors.add(label + "【" + code + "】不存在"); + return null; + } + if (matches.size() > 1) { + errors.add(label + "【" + code + "】匹配到" + matches.size() + "条记录,需先处理系统中的重复编码"); + return null; + } + return matches.get(0); + } + + private ImportEntry prepareRow(NutMap row, Set roleCodes, Set terms, + Map> unions, Map> users, + Map> roles, Map> units, + Set> existingRoles, Set> existingCadres, + Map, Integer> fileRoles, String operator) { String unionCode = row.getString("unionCode"); String loginname = row.getString("loginname"); String roleCode = row.getString("roleCode"); String j = row.getString("j"); - if (StrUtil.isBlank(unionCode) || StrUtil.isBlank(loginname) || StrUtil.isBlank(roleCode)) { - outcome(row, "失败", "工会编码、工号、角色编码不能为空"); - return; + List errors = new ArrayList<>(); + Sys_union union = unique(unions, unionCode, "工会编码", errors); + View_user user = unique(users, loginname, "工号", errors); + Sys_role role = unique(roles, roleCode, "角色编码", errors); + if (StrUtil.isNotBlank(roleCode) && !roleCodes.contains(roleCode)) { + errors.add("角色编码【" + roleCode + "】不在允许导入的分工会干部角色范围内,请参照角色对照表"); } - List unions = dao.query(Sys_union.class, Cnd.where("unionCode", "=", unionCode)); - List users = dao.query(View_user.class, Cnd.where("loginname", "=", loginname)); - List roles = dao.query(Sys_role.class, Cnd.where("code", "=", roleCode)); - if (unions.size() != 1 || users.size() != 1 || roles.size() != 1 || !roleCodes.contains(roleCode)) { - outcome(row, "失败", "工会、工号或分工会角色编码不存在或不唯一,请按模板对照表填写"); - return; + if (!errors.isEmpty()) { + outcome(row, "失败", String.join(";", errors)); + return null; } - Sys_union union = unions.get(0); - View_user user = users.get(0); - Sys_role role = roles.get(0); boolean secretary = RoleConstant.UNIT_PARTY_SECRETARY.name().equals(roleCode); - Cnd existing = Cnd.where("userId", "=", user.getId()).and("roleId", "=", role.getId()); - if (secretary) { - existing.and("unionId", "=", union.getId()); - } - if (dao.count(Sys_user_role.class, existing) > 0) { - outcome(row, "跳过", "已分配该角色,保留原有记录(含禁用关系)"); - return; + List key = roleKey(user.getId(), role.getId(), union.getId(), secretary); + if (existingRoles.contains(key)) { + outcome(row, "跳过", "工号【" + loginname + "】已分配角色【" + roleCode + "】" + + (secretary ? "(工会编码【" + unionCode + "】)" : "") + ",保留原有记录(含禁用关系)"); + return null; } if (!union.getId().equals(user.getUnionId())) { - outcome(row, "失败", "所选人员不属于该分工会"); - return; + errors.add("工号【" + loginname + "】所属工会为【" + StrUtil.blankToDefault(user.getUnionName(), "未分配工会") + + "】,与填写的工会【" + union.getName() + "(" + unionCode + ")】不一致"); } if (StrUtil.isNotBlank(j) && !terms.contains(j)) { - outcome(row, "失败", "届次编码不存在,请参照届次对照表或留空"); - return; + errors.add("届次编码【" + j + "】不存在,请参照届次对照表或留空"); } - if (dao.count(Sys_union_cadre.class, Cnd.where("userId", "=", user.getId()) - .and("roleCode", "=", roleCode).and("unionId", "=", union.getId()).and("isServing", "=", true)) > 0) { - outcome(row, "跳过", "已有在任或待审核干部记录,请通过原记录处理"); - return; + if (existingCadres.contains(Arrays.asList(user.getId(), roleCode, union.getId()))) { + outcome(row, "跳过", "工号【" + loginname + "】在工会【" + unionCode + "】已有角色【" + roleCode + + "】的在任或待审核干部记录,请通过原记录处理"); + return null; } List unitIds = new ArrayList<>(); String unitCodes = row.getString("unitCodes"); if (secretary) { - List codes = Arrays.stream(unitCodes.split("[,,]")) - .map(String::trim).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList()); + List codes = splitUnitCodes(unitCodes); if (codes.isEmpty()) { - outcome(row, "失败", "二级党委书记必须填写所属单位编码"); - return; + errors.add("角色【二级党委书记】必须填写所属单位编码,请参照所属单位对照表"); } for (String code : codes) { - List units = dao.query(Sys_unit.class, Cnd.where("unitcode", "=", code) - .and("unionId", "=", union.getId()).and("unitLevel", "=", 2)); - if (units.size() != 1) { - outcome(row, "失败", "所属单位编码不存在、不唯一或不是该分工会的二级单位:" + code); - return; + List matches = units.getOrDefault(code, List.of()); + List valid = matches.stream().filter(unit -> union.getId().equals(unit.getUnionId()) + && Integer.valueOf(2).equals(unit.getUnitLevel())).toList(); + if (matches.isEmpty()) { + errors.add("所属单位编码【" + code + "】不存在"); + } else if (valid.isEmpty()) { + boolean inUnion = matches.stream().anyMatch(unit -> union.getId().equals(unit.getUnionId())); + errors.add(inUnion ? "所属单位编码【" + code + "】属于工会【" + unionCode + "】,但单位级别不是二级" + : "所属单位编码【" + code + "】不属于填写的工会【" + union.getName() + "(" + unionCode + ")】"); + } else if (valid.size() > 1) { + errors.add("所属单位编码【" + code + "】在工会【" + unionCode + "】下匹配到" + valid.size() + "个二级单位,编码不唯一"); + } else { + unitIds.add(valid.get(0).getId()); } - unitIds.add(units.get(0).getId()); } } else if (StrUtil.isNotBlank(unitCodes)) { - outcome(row, "失败", "普通干部角色的所属单位编码应留空"); + errors.add("角色【" + roleCode + "】不是二级党委书记,所属单位编码【" + unitCodes + "】应留空"); + } + if (!errors.isEmpty()) { + outcome(row, "失败", String.join(";", errors)); + return null; + } + Integer previousRow = fileRoles.putIfAbsent(key, row.getInt("rowNumber")); + if (previousRow != null) { + outcome(row, "跳过", "与本文件第" + previousRow + "行的人员角色授权重复"); + return null; + } + Sys_union_cadre cadre = new Sys_union_cadre(); + cadre.setId(R.UU32()); + cadre.setUserId(user.getId()); + cadre.setUnionId(union.getId()); + cadre.setMobile(user.getMobile()); + cadre.setUnionName(user.getUnionName()); + cadre.setLoginName(user.getLoginname()); + cadre.setUserName(user.getUsername()); + cadre.setRoleCode(roleCode); + cadre.setJ(j); + cadre.setApplyDate(new Date()); + cadre.setIsServing(true); + cadre.setIsJoin(true); + // fastInsert不执行实体插入拦截器,显式补齐主键及审计字段。 + cadre.setCreatedBy(operator); + cadre.setUpdatedBy(operator); + cadre.setCreatedAt(System.currentTimeMillis()); + cadre.setUpdatedAt(cadre.getCreatedAt()); + cadre.setDelFlag(false); + List relations = new ArrayList<>(); + for (String unitId : secretary ? unitIds : java.util.Collections.singletonList((String) null)) { + Sys_user_role relation = new Sys_user_role(); + relation.setUserId(user.getId()); + relation.setRoleId(role.getId()); + relation.setUnionId(union.getId()); + relation.setUnitId(unitId); + relations.add(relation); + } + return new ImportEntry(row, cadre, relations); + } + + private void saveBatch(List entries) { + if (entries.isEmpty()) { return; } - // 经由注入的原控制器代理调用,保留单行事务、直接授权及缓存清理逻辑。 - Result result = secretary - ? sysUnionController.insertBranchUnionPartySecretaryRole(user.getId(), union.getId(), unitIds.toArray(new String[0]), j) - : sysUnionController.insertBranchUnionUserRole(user.getId(), roleCode, union.getId(), j); - if (result.isSuccess()) { - outcome(row, "成功", "添加成功"); - } else if ("请勿重复添加".equals(result.getMsg()) || "该人员已设置二级党委书记,请先删除后再重新设置".equals(result.getMsg())) { - outcome(row, "跳过", result.getMsg()); - } else { - outcome(row, "失败", result.getMsg()); + try { + // 两张表各批量写入一次,同一事务保证干部记录和角色授权同时生效。 + Trans.exec((Atom) () -> { + dao.fastInsert(entries.stream().map(entry -> entry.cadre).toList()); + dao.fastInsert(entries.stream().flatMap(entry -> entry.relations.stream()).toList()); + }); + entries.forEach(entry -> outcome(entry.row, "成功", "添加成功")); + } catch (Exception e) { + if (entries.size() > 1) { + // 仅保存异常时拆分批次定位坏行,正常导入不产生逐行写入。 + int middle = entries.size() / 2; + saveBatch(entries.subList(0, middle)); + saveBatch(entries.subList(middle, entries.size())); + } else { + NutMap row = entries.get(0).row; + log.error("导入分工会干部保存失败,行号:{},工号:{},角色编码:{}", + row.getInt("rowNumber"), row.getString("loginname"), row.getString("roleCode"), e); + outcome(row, "失败", saveFailure(e)); + } + } + } + + private String saveFailure(Exception error) { + for (Throwable cause = error; cause != null; cause = cause.getCause()) { + if (cause instanceof SQLException) { + SQLException sql = (SQLException) cause; + String state = sql.getSQLState(); + if ("23505".equals(state) || sql.getErrorCode() == 1062) { + return "保存时发生唯一键冲突,可能已有相同干部或角色授权记录;本行已回滚"; + } + if ("22001".equals(state) || sql.getErrorCode() == 1406) { + return "干部信息字段超出数据库长度限制,请检查工号、姓名、手机号、工会名称及届次长度;本行已回滚"; + } + if ("23502".equals(state) || sql.getErrorCode() == 1048 || sql.getErrorCode() == 1364) { + return "干部记录或角色授权缺少数据库要求的必填值,请检查该人员的基础信息及干部表必填字段;本行已回滚"; + } + if ("23503".equals(state) || sql.getErrorCode() == 1452) { + return "人员、工会、角色或所属单位的关联记录已不存在,请核对对应系统数据;本行已回滚"; + } + if (state != null && state.startsWith("23")) { + return "干部记录或角色授权违反数据库必填、关联或唯一性约束,请核对人员、工会和角色数据;本行已回滚"; + } + if (state != null && state.startsWith("08")) { + return "保存干部及角色授权时数据库连接异常,本行未完成导入,可稍后重新导入"; + } + if (state != null && state.startsWith("40")) { + return "保存干部及角色授权时发生事务冲突,本行已回滚,可重新导入"; + } + } + } + return "干部记录或角色授权写入异常,本行未完成导入;请管理员按Excel行号、工号及角色编码查看导入日志"; + } + + private static class ImportEntry { + private final NutMap row; + private final Sys_union_cadre cadre; + private final List relations; + + private ImportEntry(NutMap row, Sys_union_cadre cadre, List relations) { + this.row = row; + this.cadre = cadre; + this.relations = relations; } } diff --git a/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java b/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java index 5341ac7..dad534c 100644 --- a/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java +++ b/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java @@ -3,5 +3,17 @@ package com.budwk.app.sys.services; import com.budwk.app.base.service.BaseService; import com.budwk.app.sys.models.Sys_home_activity; +import java.util.List; + public interface SysHomeActivityService extends BaseService { + + /** + * 获取指定用户有权查看的已启用首页活动。 + * + * @param userId 当前登录用户ID,用于人员分组及自定义SQL的可见范围校验 + * @param includeEnded true包含已结束活动并按状态、置顶和开始时间排序;false保持原有过滤和排序 + * @return 活动实体列表,包含id、name、cover、url、h5Url、startDate、endDate等展示字段, + * 不返回classPath和allowUserSql内部配置 + */ + List listHomeActivity(String userId, boolean includeEnded); } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java index 9553fd5..0e73dae 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java @@ -1,15 +1,87 @@ package com.budwk.app.sys.services.impl; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.sys.services.SysHomeActivityService; +import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService; +import org.nutz.dao.Cnd; import org.nutz.dao.Dao; +import org.nutz.dao.FieldFilter; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.Daos; +import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; @IocBean(args = {"refer:dao"}) public class SysHomeActivityServiceImpl extends BaseServiceImpl implements SysHomeActivityService { + @Inject + private ActivityBasicScopeService activityBasicScopeService; + public SysHomeActivityServiceImpl(Dao dao) { super(dao); } + + /** + * 沿用首页原有的启用及人员可见范围校验,仅在调用方明确要求时展示已结束活动。 + * 参数和返回结构见服务接口;查询过程不更新活动配置。 + */ + @Override + public List listHomeActivity(String userId, boolean includeEnded) { + FieldFilter fieldFilter = FieldFilter.locked(Sys_home_activity.class, "classPath"); + List list = Daos.ext(dao(), fieldFilter).query(Sys_home_activity.class, + Cnd.where("enable", "=", 1).desc("top")); + List allowActivityList = new ArrayList<>(); + // 同一次请求使用同一个时间点,保证过滤与排序对活动是否结束的判断一致。 + Date today = DateUtil.date(); + for (Sys_home_activity activity : list) { + // 未传includeEnded的既有调用继续过滤已结束活动,保留原来的日期比较口径。 + if (!includeEnded && DateUtil.compare(today, activity.getEndDate()) > 0) { + continue; + } + Integer allowUserGroupId = activity.getAllowUserGroupId(); + String allowUserSql = activity.getAllowUserSql(); + // 自定义SQL仅用于服务端判断可见范围,禁止随活动列表返回前端。 + activity.setAllowUserSql(null); + if (allowUserGroupId == null && StrUtil.isBlank(allowUserSql)) { + allowActivityList.add(activity); + continue; + } + + if (allowUserGroupId != null) { + if (activityBasicScopeService.isUserInGroup(allowUserGroupId, userId)) { + allowActivityList.add(activity); + continue; + } + } + + if (StrUtil.isNotBlank(allowUserSql)) { + Sql sql = Sqls.create(allowUserSql).setParam("userId", userId); + sql.setCallback(Sqls.callback.map()); + dao().execute(sql); + NutMap nutMap = (NutMap) sql.getResult(); + if (Lang.isNotEmpty(nutMap) && StrUtil.isNotBlank(nutMap.getString("userId"))) { + allowActivityList.add(activity); + } + } + } + if (includeEnded) { + // 未结束活动整体在前,已结束置顶活动也不能越组;组内置顶优先,再按开始时间倒序,空开始时间排后。 + allowActivityList.sort(Comparator + .comparing((Sys_home_activity activity) -> DateUtil.compare(today, activity.getEndDate()) > 0) + .thenComparing(activity -> Boolean.TRUE.equals(activity.getTop()), Comparator.reverseOrder()) + .thenComparing(Sys_home_activity::getStartDate, Comparator.nullsLast(Comparator.reverseOrder()))); + } + return allowActivityList; + } } diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index 5f69385..ea7aa76 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -42,8 +42,8 @@ sdk: client-call-back-url: /platform/sso/login validation-type: cas minio: - accessKey: o1MwuzixNqAXh5zqEfMH - secretKey: RVnZum91JmGO79qtzWy2gKMBsF6OxAaibGrr7ets + accessKey: minioadmin + secretKey: Minio@123#admin endPoint: http://localhost:9000 bucket: zjnu diff --git a/src/main/resources/views/platform/sys/union/branchUnionManage.js b/src/main/resources/views/platform/sys/union/branchUnionManage.js index 1a57b09..a0ecc2e 100644 --- a/src/main/resources/views/platform/sys/union/branchUnionManage.js +++ b/src/main/resources/views/platform/sys/union/branchUnionManage.js @@ -71,7 +71,7 @@ const branchUnionManage = {
正在导入,请稍候…
将文件拖到此处,或点击选择文件
-
选择文件后点击“开始导入”。逐行保存,一行失败不影响其他行。
+
选择文件后点击“开始导入”。批量校验并保存,失败行显示具体原因,其他有效行继续导入。