Compare commits
7
Commits
d18d9bda6d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f51b24686f | ||
|
|
3f7b5dc27a | ||
|
|
e944ebf85f | ||
|
|
a0732fdb08 | ||
|
|
db26813635 | ||
|
|
d5f1c642c4 | ||
|
|
a09cd7b8fd |
@@ -8,7 +8,10 @@ import com.budwk.app.base.result.Result;
|
|||||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.sys.models.*;
|
import com.budwk.app.sys.models.*;
|
||||||
import com.budwk.app.sys.services.SysDictService;
|
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.sys.views.View_user;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
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.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.lang.util.NutMap;
|
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.AdaptBy;
|
||||||
import org.nutz.mvc.annotation.At;
|
import org.nutz.mvc.annotation.At;
|
||||||
import org.nutz.mvc.annotation.Ok;
|
import org.nutz.mvc.annotation.Ok;
|
||||||
@@ -26,9 +32,15 @@ import org.nutz.mvc.upload.UploadAdaptor;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -45,6 +57,10 @@ public class SysUnionCadreImportController {
|
|||||||
private SysDictService sysDictService;
|
private SysDictService sysDictService;
|
||||||
@Inject
|
@Inject
|
||||||
private SysUnionController sysUnionController;
|
private SysUnionController sysUnionController;
|
||||||
|
@Inject
|
||||||
|
private SysRoleService sysRoleService;
|
||||||
|
@Inject
|
||||||
|
private SysUserService sysUserService;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private List<NutMap> roleOptions() {
|
private List<NutMap> roleOptions() {
|
||||||
@@ -72,7 +88,7 @@ public class SysUnionCadreImportController {
|
|||||||
append(notes, "届次编码(选填)", "可留空;填写时使用届次对照表中的编码,与单个添加一致。");
|
append(notes, "届次编码(选填)", "可留空;填写时使用届次对照表中的编码,与单个添加一致。");
|
||||||
append(notes, "所属单位编码(书记必填)", "仅二级党委书记填写,多个单位用英文逗号分隔,必须为当前分工会的二级单位;其他角色留空。");
|
append(notes, "所属单位编码(书记必填)", "仅二级党委书记填写,多个单位用英文逗号分隔,必须为当前分工会的二级单位;其他角色留空。");
|
||||||
append(notes, "重复记录", "普通干部按人员和角色跳过;二级党委书记按人员、角色和工会跳过。禁用的已有关系也跳过,不覆盖。");
|
append(notes, "重复记录", "普通干部按人员和角色跳过;二级党委书记按人员、角色和工会跳过。禁用的已有关系也跳过,不覆盖。");
|
||||||
append(notes, "保存方式", "系统管理员直接授权,写入干部及角色记录并清理权限缓存,不发起审批。逐行保存,失败行不影响其他行。");
|
append(notes, "保存方式", "系统管理员直接授权,批量校验并保存干部及角色记录,统一清理权限缓存,不发起审批。校验失败行不写入;保存异常时拆分定位失败行,其他有效行继续导入。");
|
||||||
append(notes, "已有干部记录", "已有在任或待审核干部记录但未分配角色时跳过,避免重复创建或绕过已有审批。");
|
append(notes, "已有干部记录", "已有在任或待审核干部记录但未分配角色时跳过,避免重复创建或绕过已有审批。");
|
||||||
Sheet unions = createSheet(workbook, "工会对照", "工会编码", "工会名称");
|
Sheet unions = createSheet(workbook, "工会对照", "工会编码", "工会名称");
|
||||||
List<Sys_union> unionList = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode"));
|
List<Sys_union> unionList = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode"));
|
||||||
@@ -145,101 +161,271 @@ public class SysUnionCadreImportController {
|
|||||||
if (rows.isEmpty()) {
|
if (rows.isEmpty()) {
|
||||||
return Result.error("文件中没有需要导入的数据");
|
return Result.error("文件中没有需要导入的数据");
|
||||||
}
|
}
|
||||||
List<String> roleCodes = roleOptions().stream().map(item -> item.getString("code")).toList();
|
Set<String> roleCodes = sysDictService.getSubListByCode("BRANCH_UNION_ROLES").stream()
|
||||||
List<String> terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream()
|
.map(Sys_dict::getCode).collect(Collectors.toSet());
|
||||||
.map(Sys_dict::getCode).toList();
|
roleCodes.add(RoleConstant.UNIT_PARTY_SECRETARY.name());
|
||||||
int success = 0;
|
Set<String> terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream()
|
||||||
int skipped = 0;
|
.map(Sys_dict::getCode).collect(Collectors.toSet());
|
||||||
|
List<String> unionCodes = values(rows, "unionCode");
|
||||||
|
List<String> loginnames = values(rows, "loginname");
|
||||||
|
List<String> inputRoleCodes = values(rows, "roleCode");
|
||||||
|
List<String> unitCodes = rows.stream().flatMap(row -> splitUnitCodes(row.getString("unitCodes")).stream())
|
||||||
|
.distinct().toList();
|
||||||
|
// 各类基础数据及已有关系按表一次查询,逐行校验时不再访问数据库。
|
||||||
|
Map<String, List<Sys_union>> unions = group(unionCodes.isEmpty() ? List.of()
|
||||||
|
: dao.query(Sys_union.class, Cnd.where("unionCode", "in", unionCodes)), Sys_union::getUnionCode);
|
||||||
|
Map<String, List<View_user>> users = group(loginnames.isEmpty() ? List.of()
|
||||||
|
: dao.query(View_user.class, Cnd.where("loginname", "in", loginnames)), View_user::getLoginname);
|
||||||
|
Map<String, List<Sys_role>> roles = group(inputRoleCodes.isEmpty() ? List.of()
|
||||||
|
: dao.query(Sys_role.class, Cnd.where("code", "in", inputRoleCodes)), Sys_role::getCode);
|
||||||
|
Map<String, List<Sys_unit>> units = group(unitCodes.isEmpty() ? List.of()
|
||||||
|
: dao.query(Sys_unit.class, Cnd.where("unitcode", "in", unitCodes)), Sys_unit::getUnitcode);
|
||||||
|
List<String> userIds = users.values().stream().flatMap(List::stream).map(View_user::getId).distinct().toList();
|
||||||
|
List<String> roleIds = roles.values().stream().flatMap(List::stream).map(Sys_role::getId).distinct().toList();
|
||||||
|
Set<List<String>> 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<List<String>> existingCadres = new HashSet<>();
|
||||||
|
if (!userIds.isEmpty() && !inputRoleCodes.isEmpty() && !unionCodes.isEmpty()) {
|
||||||
|
List<String> 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<ImportEntry> entries = new ArrayList<>();
|
||||||
|
Map<List<String>, Integer> fileRoles = new java.util.HashMap<>();
|
||||||
|
String operator = SecurityUtil.getUserId();
|
||||||
for (NutMap row : rows) {
|
for (NutMap row : rows) {
|
||||||
try {
|
ImportEntry entry = prepareRow(row, roleCodes, terms, unions, users, roles, units,
|
||||||
importRow(row, roleCodes, terms);
|
existingRoles, existingCadres, fileRoles, operator);
|
||||||
} catch (Exception e) {
|
if (entry != null) {
|
||||||
log.error("导入分工会干部失败,行号:{}", row.getInt("rowNumber"), e);
|
entries.add(entry);
|
||||||
outcome(row, "失败", "保存失败,请检查该行数据或联系管理员");
|
|
||||||
}
|
|
||||||
if ("成功".equals(row.getString("status"))) {
|
|
||||||
success++;
|
|
||||||
} else if ("跳过".equals(row.getString("status"))) {
|
|
||||||
skipped++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
return Result.success(NutMap.NEW().addv("success", success).addv("skipped", skipped)
|
||||||
.addv("failed", rows.size() - success - skipped).addv("rows", rows));
|
.addv("failed", rows.size() - success - skipped).addv("rows", rows));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void importRow(NutMap row, List<String> roleCodes, List<String> terms) {
|
private List<String> values(List<NutMap> rows, String field) {
|
||||||
|
return rows.stream().map(row -> row.getString(field)).filter(StrUtil::isNotBlank).distinct().toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> splitUnitCodes(String codes) {
|
||||||
|
return Arrays.stream(codes.split("[,,]")).map(String::trim).filter(StrUtil::isNotBlank).distinct().toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Map<String, List<T>> group(List<T> items, Function<T, String> key) {
|
||||||
|
return items.stream().collect(Collectors.groupingBy(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> roleKey(String userId, String roleId, String unionId, boolean secretary) {
|
||||||
|
return Arrays.asList(userId, roleId, secretary ? unionId : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T unique(Map<String, List<T>> records, String code, String label, List<String> errors) {
|
||||||
|
if (StrUtil.isBlank(code)) {
|
||||||
|
errors.add(label + "不能为空");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<T> 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<String> roleCodes, Set<String> terms,
|
||||||
|
Map<String, List<Sys_union>> unions, Map<String, List<View_user>> users,
|
||||||
|
Map<String, List<Sys_role>> roles, Map<String, List<Sys_unit>> units,
|
||||||
|
Set<List<String>> existingRoles, Set<List<String>> existingCadres,
|
||||||
|
Map<List<String>, Integer> fileRoles, String operator) {
|
||||||
String unionCode = row.getString("unionCode");
|
String unionCode = row.getString("unionCode");
|
||||||
String loginname = row.getString("loginname");
|
String loginname = row.getString("loginname");
|
||||||
String roleCode = row.getString("roleCode");
|
String roleCode = row.getString("roleCode");
|
||||||
String j = row.getString("j");
|
String j = row.getString("j");
|
||||||
if (StrUtil.isBlank(unionCode) || StrUtil.isBlank(loginname) || StrUtil.isBlank(roleCode)) {
|
List<String> errors = new ArrayList<>();
|
||||||
outcome(row, "失败", "工会编码、工号、角色编码不能为空");
|
Sys_union union = unique(unions, unionCode, "工会编码", errors);
|
||||||
return;
|
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<Sys_union> unions = dao.query(Sys_union.class, Cnd.where("unionCode", "=", unionCode));
|
if (!errors.isEmpty()) {
|
||||||
List<View_user> users = dao.query(View_user.class, Cnd.where("loginname", "=", loginname));
|
outcome(row, "失败", String.join(";", errors));
|
||||||
List<Sys_role> roles = dao.query(Sys_role.class, Cnd.where("code", "=", roleCode));
|
return null;
|
||||||
if (unions.size() != 1 || users.size() != 1 || roles.size() != 1 || !roleCodes.contains(roleCode)) {
|
|
||||||
outcome(row, "失败", "工会、工号或分工会角色编码不存在或不唯一,请按模板对照表填写");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
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);
|
boolean secretary = RoleConstant.UNIT_PARTY_SECRETARY.name().equals(roleCode);
|
||||||
Cnd existing = Cnd.where("userId", "=", user.getId()).and("roleId", "=", role.getId());
|
List<String> key = roleKey(user.getId(), role.getId(), union.getId(), secretary);
|
||||||
if (secretary) {
|
if (existingRoles.contains(key)) {
|
||||||
existing.and("unionId", "=", union.getId());
|
outcome(row, "跳过", "工号【" + loginname + "】已分配角色【" + roleCode + "】"
|
||||||
}
|
+ (secretary ? "(工会编码【" + unionCode + "】)" : "") + ",保留原有记录(含禁用关系)");
|
||||||
if (dao.count(Sys_user_role.class, existing) > 0) {
|
return null;
|
||||||
outcome(row, "跳过", "已分配该角色,保留原有记录(含禁用关系)");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!union.getId().equals(user.getUnionId())) {
|
if (!union.getId().equals(user.getUnionId())) {
|
||||||
outcome(row, "失败", "所选人员不属于该分工会");
|
errors.add("工号【" + loginname + "】所属工会为【" + StrUtil.blankToDefault(user.getUnionName(), "未分配工会")
|
||||||
return;
|
+ "】,与填写的工会【" + union.getName() + "(" + unionCode + ")】不一致");
|
||||||
}
|
}
|
||||||
if (StrUtil.isNotBlank(j) && !terms.contains(j)) {
|
if (StrUtil.isNotBlank(j) && !terms.contains(j)) {
|
||||||
outcome(row, "失败", "届次编码不存在,请参照届次对照表或留空");
|
errors.add("届次编码【" + j + "】不存在,请参照届次对照表或留空");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (dao.count(Sys_union_cadre.class, Cnd.where("userId", "=", user.getId())
|
if (existingCadres.contains(Arrays.asList(user.getId(), roleCode, union.getId()))) {
|
||||||
.and("roleCode", "=", roleCode).and("unionId", "=", union.getId()).and("isServing", "=", true)) > 0) {
|
outcome(row, "跳过", "工号【" + loginname + "】在工会【" + unionCode + "】已有角色【" + roleCode
|
||||||
outcome(row, "跳过", "已有在任或待审核干部记录,请通过原记录处理");
|
+ "】的在任或待审核干部记录,请通过原记录处理");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
List<String> unitIds = new ArrayList<>();
|
List<String> unitIds = new ArrayList<>();
|
||||||
String unitCodes = row.getString("unitCodes");
|
String unitCodes = row.getString("unitCodes");
|
||||||
if (secretary) {
|
if (secretary) {
|
||||||
List<String> codes = Arrays.stream(unitCodes.split("[,,]"))
|
List<String> codes = splitUnitCodes(unitCodes);
|
||||||
.map(String::trim).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
|
|
||||||
if (codes.isEmpty()) {
|
if (codes.isEmpty()) {
|
||||||
outcome(row, "失败", "二级党委书记必须填写所属单位编码");
|
errors.add("角色【二级党委书记】必须填写所属单位编码,请参照所属单位对照表");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
for (String code : codes) {
|
for (String code : codes) {
|
||||||
List<Sys_unit> units = dao.query(Sys_unit.class, Cnd.where("unitcode", "=", code)
|
List<Sys_unit> matches = units.getOrDefault(code, List.of());
|
||||||
.and("unionId", "=", union.getId()).and("unitLevel", "=", 2));
|
List<Sys_unit> valid = matches.stream().filter(unit -> union.getId().equals(unit.getUnionId())
|
||||||
if (units.size() != 1) {
|
&& Integer.valueOf(2).equals(unit.getUnitLevel())).toList();
|
||||||
outcome(row, "失败", "所属单位编码不存在、不唯一或不是该分工会的二级单位:" + code);
|
if (matches.isEmpty()) {
|
||||||
return;
|
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)) {
|
} 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<Sys_user_role> 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<ImportEntry> entries) {
|
||||||
|
if (entries.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 经由注入的原控制器代理调用,保留单行事务、直接授权及缓存清理逻辑。
|
try {
|
||||||
Result result = secretary
|
// 两张表各批量写入一次,同一事务保证干部记录和角色授权同时生效。
|
||||||
? sysUnionController.insertBranchUnionPartySecretaryRole(user.getId(), union.getId(), unitIds.toArray(new String[0]), j)
|
Trans.exec((Atom) () -> {
|
||||||
: sysUnionController.insertBranchUnionUserRole(user.getId(), roleCode, union.getId(), j);
|
dao.fastInsert(entries.stream().map(entry -> entry.cadre).toList());
|
||||||
if (result.isSuccess()) {
|
dao.fastInsert(entries.stream().flatMap(entry -> entry.relations.stream()).toList());
|
||||||
outcome(row, "成功", "添加成功");
|
});
|
||||||
} else if ("请勿重复添加".equals(result.getMsg()) || "该人员已设置二级党委书记,请先删除后再重新设置".equals(result.getMsg())) {
|
entries.forEach(entry -> outcome(entry.row, "成功", "添加成功"));
|
||||||
outcome(row, "跳过", result.getMsg());
|
} catch (Exception e) {
|
||||||
} else {
|
if (entries.size() > 1) {
|
||||||
outcome(row, "失败", result.getMsg());
|
// 仅保存异常时拆分批次定位坏行,正常导入不产生逐行写入。
|
||||||
|
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<Sys_user_role> relations;
|
||||||
|
|
||||||
|
private ImportEntry(NutMap row, Sys_union_cadre cadre, List<Sys_user_role> relations) {
|
||||||
|
this.row = row;
|
||||||
|
this.cadre = cadre;
|
||||||
|
this.relations = relations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,5 +3,17 @@ package com.budwk.app.sys.services;
|
|||||||
import com.budwk.app.base.service.BaseService;
|
import com.budwk.app.base.service.BaseService;
|
||||||
import com.budwk.app.sys.models.Sys_home_activity;
|
import com.budwk.app.sys.models.Sys_home_activity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface SysHomeActivityService extends BaseService<Sys_home_activity> {
|
public interface SysHomeActivityService extends BaseService<Sys_home_activity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定用户有权查看的已启用首页活动。
|
||||||
|
*
|
||||||
|
* @param userId 当前登录用户ID,用于人员分组及自定义SQL的可见范围校验
|
||||||
|
* @param includeEnded true包含已结束活动并按状态、置顶和开始时间排序;false保持原有过滤和排序
|
||||||
|
* @return 活动实体列表,包含id、name、cover、url、h5Url、startDate、endDate等展示字段,
|
||||||
|
* 不返回classPath和allowUserSql内部配置
|
||||||
|
*/
|
||||||
|
List<Sys_home_activity> listHomeActivity(String userId, boolean includeEnded);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,87 @@
|
|||||||
package com.budwk.app.sys.services.impl;
|
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.base.service.impl.BaseServiceImpl;
|
||||||
import com.budwk.app.sys.models.Sys_home_activity;
|
import com.budwk.app.sys.models.Sys_home_activity;
|
||||||
import com.budwk.app.sys.services.SysHomeActivityService;
|
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.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.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"})
|
@IocBean(args = {"refer:dao"})
|
||||||
public class SysHomeActivityServiceImpl extends BaseServiceImpl<Sys_home_activity> implements SysHomeActivityService {
|
public class SysHomeActivityServiceImpl extends BaseServiceImpl<Sys_home_activity> implements SysHomeActivityService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ActivityBasicScopeService activityBasicScopeService;
|
||||||
|
|
||||||
public SysHomeActivityServiceImpl(Dao dao) {
|
public SysHomeActivityServiceImpl(Dao dao) {
|
||||||
super(dao);
|
super(dao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 沿用首页原有的启用及人员可见范围校验,仅在调用方明确要求时展示已结束活动。
|
||||||
|
* 参数和返回结构见服务接口;查询过程不更新活动配置。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Sys_home_activity> listHomeActivity(String userId, boolean includeEnded) {
|
||||||
|
FieldFilter fieldFilter = FieldFilter.locked(Sys_home_activity.class, "classPath");
|
||||||
|
List<Sys_home_activity> list = Daos.ext(dao(), fieldFilter).query(Sys_home_activity.class,
|
||||||
|
Cnd.where("enable", "=", 1).desc("top"));
|
||||||
|
List<Sys_home_activity> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-2
@@ -54,9 +54,8 @@ public class ActivityBasicSettingsController {
|
|||||||
if (parentId != null) {
|
if (parentId != null) {
|
||||||
parentId.setChild(child(parentId.getId()));
|
parentId.setChild(child(parentId.getId()));
|
||||||
list.add(parentId);
|
list.add(parentId);
|
||||||
return Result.success().addData(list);
|
|
||||||
}
|
}
|
||||||
return Result.success();
|
return Result.success(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ActivityBasicSettings> child(String parentId) {
|
private List<ActivityBasicSettings> child(String parentId) {
|
||||||
@@ -73,6 +72,9 @@ public class ActivityBasicSettingsController {
|
|||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
if (StrUtil.isBlank(parentId)) {
|
if (StrUtil.isBlank(parentId)) {
|
||||||
ActivityBasicSettings rootSetting = dao.fetch(ActivityBasicSettings.class, Cnd.where("parentId", "=", 0));
|
ActivityBasicSettings rootSetting = dao.fetch(ActivityBasicSettings.class, Cnd.where("parentId", "=", 0));
|
||||||
|
if (rootSetting == null) {
|
||||||
|
return Result.success(new Pagination<ActivityBasicSettings>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, new ArrayList<ActivityBasicSettings>()));
|
||||||
|
}
|
||||||
cnd.and("parentId", "=", rootSetting.getId());
|
cnd.and("parentId", "=", rootSetting.getId());
|
||||||
} else {
|
} else {
|
||||||
cnd.and("parentId", "=", parentId);
|
cnd.and("parentId", "=", parentId);
|
||||||
@@ -116,7 +118,13 @@ public class ActivityBasicSettingsController {
|
|||||||
|
|
||||||
@At
|
@At
|
||||||
public Result getActivityTwoLevelType(String code) {
|
public Result getActivityTwoLevelType(String code) {
|
||||||
|
if (StrUtil.isBlank(code)) {
|
||||||
|
return Result.success(new ArrayList<ActivityBasicSettings>());
|
||||||
|
}
|
||||||
ActivityBasicSettings fetch = dao.fetch(ActivityBasicSettings.class, Cnd.where("code", "=", code));
|
ActivityBasicSettings fetch = dao.fetch(ActivityBasicSettings.class, Cnd.where("code", "=", code));
|
||||||
|
if (fetch == null) {
|
||||||
|
return Result.success(new ArrayList<ActivityBasicSettings>());
|
||||||
|
}
|
||||||
List<ActivityBasicSettings> query = dao.query(ActivityBasicSettings.class, Cnd.where("parentId", "=", fetch.getId()).asc("code"));
|
List<ActivityBasicSettings> query = dao.query(ActivityBasicSettings.class, Cnd.where("parentId", "=", fetch.getId()).asc("code"));
|
||||||
return Result.success(query);
|
return Result.success(query);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -649,8 +649,11 @@ public class TrainSignUpActivityServiceImpl extends BaseServiceImpl<TrainSignUpA
|
|||||||
fillCourseResponsibles(courseList);
|
fillCourseResponsibles(courseList);
|
||||||
|
|
||||||
courseList.forEach(c -> {
|
courseList.forEach(c -> {
|
||||||
|
dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime"));
|
||||||
|
if (c.getCourseTimeList() == null) {
|
||||||
|
c.setCourseTimeList(new ArrayList<>());
|
||||||
|
}
|
||||||
if (StrUtil.isNotBlank(c.getCourseType())) {
|
if (StrUtil.isNotBlank(c.getCourseType())) {
|
||||||
dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime"));
|
|
||||||
int courseCount = statisticsService.queryCourseCount(c.getId(), c.getCourseType());
|
int courseCount = statisticsService.queryCourseCount(c.getId(), c.getCourseType());
|
||||||
c.setHasRegisterNum(courseCount);
|
c.setHasRegisterNum(courseCount);
|
||||||
int courseWaitCount = statisticsService.queryCourseWaitCount(c.getId(), c.getCourseType());
|
int courseWaitCount = statisticsService.queryCourseWaitCount(c.getId(), c.getCourseType());
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const branchUnionManage = {
|
|||||||
<div class="el-upload__text" v-if="cadreImportLoading">正在导入,请稍候…</div>
|
<div class="el-upload__text" v-if="cadreImportLoading">正在导入,请稍候…</div>
|
||||||
<div class="el-upload__text" v-else>将文件拖到此处,或<em>点击选择文件</em></div>
|
<div class="el-upload__text" v-else>将文件拖到此处,或<em>点击选择文件</em></div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div class="union-cadre-import-note">选择文件后点击“开始导入”。逐行保存,一行失败不影响其他行。</div>
|
<div class="union-cadre-import-note">选择文件后点击“开始导入”。批量校验并保存,失败行显示具体原因,其他有效行继续导入。</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<section v-if="cadreImportResult" class="union-cadre-import-results">
|
<section v-if="cadreImportResult" class="union-cadre-import-results">
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ layout("/layouts/platform.html"){
|
|||||||
currentTreeNode: null,
|
currentTreeNode: null,
|
||||||
currentTreeData: null,
|
currentTreeData: null,
|
||||||
|
|
||||||
checkData: {},
|
checkData: { id: "0", name: "无(新建根节点)" },
|
||||||
tableData: [],
|
tableData: [],
|
||||||
|
|
||||||
basicTypeDialog: false,
|
basicTypeDialog: false,
|
||||||
@@ -146,10 +146,8 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
getTreeData() {
|
getTreeData() {
|
||||||
this.$axios.post(loc() + "/tree").then((res) => {
|
this.$axios.post(loc() + "/tree").then((res) => {
|
||||||
this.treeData = res.data
|
this.treeData = res.data || []
|
||||||
if (this.treeData) {
|
this.checkData = this.treeData.length ? this.treeData[0] : { id: "0", name: "无(新建根节点)" }
|
||||||
this.checkData = this.treeData[0]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -370,12 +370,14 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
|
<!--
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="报名表单" prop="formConfig"
|
<el-form-item label="报名表单" prop="formConfig"
|
||||||
v-if="formData.isEnrollSystem&&formData.signUpMethod===1">
|
v-if="formData.isEnrollSystem&&formData.signUpMethod===1">
|
||||||
<custom-form-field v-model="formData.formConfig"></custom-form-field>
|
<custom-form-field v-model="formData.formConfig"></custom-form-field>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
-->
|
||||||
|
|
||||||
<el-col :span="24" v-if="formData.signUpMethod!=null&&formData.isEnrollSystem">
|
<el-col :span="24" v-if="formData.signUpMethod!=null&&formData.isEnrollSystem">
|
||||||
<el-form-item label="封面图" prop="cover">
|
<el-form-item label="封面图" prop="cover">
|
||||||
@@ -592,6 +594,7 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
|
|||||||
name: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
name: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||||
type: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
type: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||||
projectTypeCode: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
projectTypeCode: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||||
|
mobile: this.activity_type === 40001 ? [{pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号码", trigger: ["blur", "change"]}] : [],
|
||||||
address: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
address: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||||
plannedDate: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
plannedDate: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||||
time: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
time: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||||
@@ -725,7 +728,15 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
|
|||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
// 保存
|
// 保存
|
||||||
onSave() {
|
async onSave() {
|
||||||
|
if (this.activity_type === 40001) {
|
||||||
|
const mobileValid = await new Promise(resolve => {
|
||||||
|
this.$refs["addForm"].validateField("mobile", error => resolve(!error))
|
||||||
|
})
|
||||||
|
if (!mobileValid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!this.formData.projectTypeCode) {
|
if (!this.formData.projectTypeCode) {
|
||||||
this.$message.error("请选择活动项目类型")
|
this.$message.error("请选择活动项目类型")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -585,11 +585,13 @@ const basicForm = {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const courseValid = this.formData.courseList.some((v, i) => {
|
const courseValid = this.formData.courseList.some((v, i) => {
|
||||||
// 新活动通过多选关系设置负责人;未重新设置的旧活动仍允许保留历史联系人。
|
const missingFields = []
|
||||||
const hasResponsible = Array.isArray(v.responsibleList)
|
if (!v.courseName) missingFields.push(this.trainType + "名称")
|
||||||
? v.responsibleList.length > 0 : !!v.courseInstructor
|
if (!v.coursePeopleNumber) missingFields.push(this.trainType + "人数(不能为空或为0)")
|
||||||
const basicValid = v.courseName && v.coursePeopleNumber && v.courseLocation && hasResponsible && v.courseType
|
if (!v.courseLocation) missingFields.push(this.trainType + "地点")
|
||||||
|
if (!v.courseType) missingFields.push("类型")
|
||||||
const timeValid =
|
const timeValid =
|
||||||
|
Array.isArray(v.courseTimeList) &&
|
||||||
v.courseTimeList.length > 0 &&
|
v.courseTimeList.length > 0 &&
|
||||||
v.courseTimeList.every((x) => {
|
v.courseTimeList.every((x) => {
|
||||||
return x.courseStartTime && x.courseEndTime && x.courseStartTime < x.courseEndTime
|
return x.courseStartTime && x.courseEndTime && x.courseStartTime < x.courseEndTime
|
||||||
@@ -598,8 +600,8 @@ const basicForm = {
|
|||||||
this.$message.warning("第" + (i + 1) + "行时间填写有误,请核查")
|
this.$message.warning("第" + (i + 1) + "行时间填写有误,请核查")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (!basicValid) {
|
if (missingFields.length > 0) {
|
||||||
this.$message.warning("第" + (i + 1) + "行信息填写有误,请核查")
|
this.$message.warning("第" + (i + 1) + "行请补充:" + missingFields.join("、"))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// 联系方式允许手机号或办公电话,逐人校验,不能只检查兼容展示的第一位。
|
// 联系方式允许手机号或办公电话,逐人校验,不能只检查兼容展示的第一位。
|
||||||
|
|||||||
Reference in New Issue
Block a user