Compare commits

18 Commits
Author SHA1 Message Date
c-chenxs1 f51b24686f Merge branch 'feat_可同步长江大学的优化_fix' 2026-11-02 11:30:17 +08:00
c-chenxs1 3f7b5dc27a feat: 优化活动相关模块 2026-10-29 09:43:43 +08:00
c-chenxs1 e944ebf85f Merge branch 'feat_本工会单独业务' 2026-10-28 17:58:29 +08:00
c-chenxs1 a0732fdb08 Merge branch 'feat_可同步长江大学的优化_fix' into feat_本工会单独业务 2026-10-28 15:26:58 +08:00
c-chenxs1 db26813635 feat: move 2026-10-28 15:22:43 +08:00
c-chenxs1 d5f1c642c4 Merge branch 'feat_可同步长江大学的优化_fix' 2026-10-28 15:21:46 +08:00
c-chenxs1 a09cd7b8fd feat: 优化批量导入人员角色 2026-10-28 15:21:27 +08:00
c-chenxs1 d18d9bda6d Merge branch 'feat_可同步长江大学的优化_fix'
# Conflicts:
#	.gitignore
2026-10-28 13:54:48 +08:00
c-chenxs1 919f8c9dec feat: 同步地大代码-打开密码sso验证 2026-10-28 13:53:45 +08:00
c-chenxs1 0fb779ff5a feat: v3版疗休养优化9 2026-10-27 11:59:57 +08:00
c-chenxs1 55e94de004 feat: v3版疗休养优化8 2026-10-27 09:12:52 +08:00
c-chenxs1 d452d4ad92 feat: v3版疗休养优化7 2026-10-26 18:19:28 +08:00
c-chenxs1 6ea864cb64 feat: v3版疗休养优化6 2026-10-26 17:33:07 +08:00
c-chenxs1 56cc3fee91 feat: v3版疗休养优化6 2026-10-26 16:50:49 +08:00
c-chenxs1 4c03b389d4 feat: v3版疗休养优化5 2026-10-26 15:27:53 +08:00
c-chenxs1 fcb6ba7e2d feat: v3版疗休养优化4 2026-10-26 14:28:19 +08:00
c-chenxs1 65fac78cfb feat: v3版疗休养优化3 2026-10-26 13:35:39 +08:00
c-chenxs1 2d20959355 feat: v3版疗休养优化2 2026-10-26 09:49:06 +08:00
107 changed files with 4244 additions and 1798 deletions
+1
View File
@@ -49,3 +49,4 @@ Thumbs.db
.trae/pr-creator/SKILL.md
.trae/update-docs/SKILL.md
.trae/webapp-testing/SKILL.md
outputs
@@ -1,34 +1,29 @@
package com.budwk.app.sys.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONObject;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.result.Result;
import com.budwk.app.sys.models.Sys_home_activity;
import com.budwk.app.sys.models.Sys_home_template;
import com.budwk.app.sys.models.Sys_menu;
import com.budwk.app.sys.services.SysHomeActivityService;
import com.budwk.app.sys.services.SysHomeNewsService;
import com.budwk.app.sys.services.SysMenuService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
import io.swagger.annotations.ApiOperation;
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.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
@@ -52,7 +47,7 @@ public class SysHomeController {
@Inject
private SysUserService sysUserService;
@Inject
private ActivityBasicScopeService activityBasicScopeService;
private SysHomeActivityService sysHomeActivityService;
@Inject
private SysHomeNewsService sysHomeNewsService;
@@ -201,71 +196,16 @@ public class SysHomeController {
}
/**
* includeEnded可选:true供PC首页展示已结束活动,缺省false保持既有调用行为。
* 返回Result,data为当前登录用户可见的活动实体列表,含名称、封面、链接及起止时间,不含内部SQL和类路径。
*/
@At
@SaCheckLogin
@ApiOperation("首页推送活动")
@Ok("json")
public Result listHomeActivity() {
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"));
String userId = SecurityUtil.getUserId();
List<Sys_home_activity> allowActivityList = new ArrayList<>();
// 今天的时间
Date today = DateUtil.date();
for (Sys_home_activity activity : list) {
// 该活动的时间范围
Date startDate = activity.getStartDate();
Date endDate = activity.getEndDate();
// 判断当前时间是否在活动范围内,不在就过滤掉
// if (!DateUtil.isIn(today, startDate, endDate)) {
// continue;
// }
// 只过滤结束的
if (DateUtil.compare(today, endDate) > 0) {
continue;
}
Integer allowUserGroupId = activity.getAllowUserGroupId();
String allowUserSql = activity.getAllowUserSql();
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);
}
}
}
return Result.success(allowActivityList);
//
//
//
//
// FieldFilter fieldFilter = FieldFilter.locked(Sys_home_activity.class, "allowUserSql|classPath");
// List<Sys_home_activity> list = Daos.ext(dao, fieldFilter).query(Sys_home_activity.class, Cnd.where("enable", "=", 1).desc("top"));
//
// List<Sys_menu> menus = sysUserService.getMenus(SecurityUtil.getUserId());
// Set<String> hrefs = menus.stream().map(Sys_menu::getHref).collect(Collectors.toSet());
//
// List<Sys_home_activity> hasPermisiionList = list.stream().filter(activity -> {
// String url = activity.getUrl();
// String h5Url = activity.getH5Url();
// return hrefs.contains(url) || hrefs.contains(h5Url);
// }).toList().stream().toList();
// return Result.success(hasPermisiionList);
public Result listHomeActivity(@Param(value = "includeEnded", df = "false") boolean includeEnded) {
return Result.success(sysHomeActivityService.listHomeActivity(SecurityUtil.getUserId(), includeEnded));
}
@At
@@ -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<NutMap> 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<Sys_union> unionList = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode"));
@@ -145,101 +161,271 @@ public class SysUnionCadreImportController {
if (rows.isEmpty()) {
return Result.error("文件中没有需要导入的数据");
}
List<String> roleCodes = roleOptions().stream().map(item -> item.getString("code")).toList();
List<String> terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream()
.map(Sys_dict::getCode).toList();
int success = 0;
int skipped = 0;
Set<String> roleCodes = sysDictService.getSubListByCode("BRANCH_UNION_ROLES").stream()
.map(Sys_dict::getCode).collect(Collectors.toSet());
roleCodes.add(RoleConstant.UNIT_PARTY_SECRETARY.name());
Set<String> terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream()
.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) {
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<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 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<String> 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<Sys_union> unions = dao.query(Sys_union.class, Cnd.where("unionCode", "=", unionCode));
List<View_user> users = dao.query(View_user.class, Cnd.where("loginname", "=", loginname));
List<Sys_role> 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<String> 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<String> unitIds = new ArrayList<>();
String unitCodes = row.getString("unitCodes");
if (secretary) {
List<String> codes = Arrays.stream(unitCodes.split("[,,]"))
.map(String::trim).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
List<String> codes = splitUnitCodes(unitCodes);
if (codes.isEmpty()) {
outcome(row, "失败", "二级党委书记必须填写所属单位编码");
return;
errors.add("角色【二级党委书记】必须填写所属单位编码,请参照所属单位对照表");
}
for (String code : codes) {
List<Sys_unit> 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<Sys_unit> matches = units.getOrDefault(code, List.of());
List<Sys_unit> 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<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;
}
// 经由注入的原控制器代理调用,保留单行事务、直接授权及缓存清理逻辑。
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<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;
}
}
@@ -22,7 +22,6 @@ import com.budwk.app.sys.services.SysDictService;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.sys.services.SysUnitService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.sys.utils.DataCenterUtil;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
@@ -215,9 +214,9 @@ public class SysUnitController {
if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId());
cnd.and("parentId", "=", "").or("parentId", "is", null);
} else {
cnd.and("parentId", "=", pid).and("id", "<>", pid);
cnd.and("parentId", "=", pid);
}
cnd.asc("location").asc("path");
list = sysUnitService.query(cnd);
@@ -228,9 +227,9 @@ public class SysUnitController {
} else {
Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId());
cnd.and("parentId", "=", "").or("parentId", "is", null);
} else {
cnd.and("parentId", "=", pid).and("id", "<>", pid);
cnd.and("parentId", "=", pid);
}
cnd.asc("location").asc("path");
list = sysUnitService.query(cnd);
@@ -259,9 +258,9 @@ public class SysUnitController {
if (StpUtil.hasRole("SYSADMIN")) {
Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId());
cnd.and("parentId", "=", "").or("parentId", "is", null);
} else {
cnd.and("parentId", "=", pid).and("id", "<>", pid);
cnd.and("parentId", "=", pid);
}
cnd.asc("location").asc("path");
list = sysUnitService.query(cnd);
@@ -272,9 +271,9 @@ public class SysUnitController {
} else {
Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId());
cnd.and("parentId", "=", "").or("parentId", "is", null);
} else {
cnd.and("parentId", "=", pid).and("id", "<>", pid);
cnd.and("parentId", "=", pid);
}
cnd.asc("location").asc("path");
list = sysUnitService.query(cnd);
@@ -296,27 +295,37 @@ public class SysUnitController {
}
}
/**
* 获取以指定单位为根的单位树。
*
* @param pid 根单位 ID;未传时使用系统根单位 0
* @param req 当前 HTTP 请求
* @return Result 对象;code 为 0 时 data 为树数组,节点包含 id、parentId、name、children、unitTypeCode;
* unitTypeCode 为 0 表示其他类、1 表示部门类,历史空值仅在返回时按 0 展示
*/
@At("/tree")
@Ok("json")
@SaCheckLogin
public Object tree(@Param("pid") String pid, HttpServletRequest req) {
try {
String rootId = StrUtil.blankToDefault(pid, "0");
String virtualRootId = "root";
Cnd cnd = Cnd.NEW();
cnd.asc("unitcode");
List<Sys_unit> list = sysUnitService.query(cnd);
String rootId = StrUtil.isBlank(pid) ? DataCenterUtil.findRootUnit(list).getId() : pid;
List<TreeNode<String>> nodeList = CollUtil.newArrayList();
for (int i = 0; i < list.size(); i++) {
Sys_unit unit = list.get(i);
/*
* 动态查询根挂到虚拟根下,兼容根节点父级为空或指向自身的数据。
* 单位根节点存在 id 与 parentId 都为 0 的自引用数据。
* 构建树时把当前查询根挂到虚拟根下,避免“中国地质大学”和 parentId=0 的学院被构造成同级。
*/
String parentId = rootId.equals(unit.getId()) ? virtualRootId : unit.getParentId();
nodeList.add(new TreeNode<>(unit.getId(), parentId, unit.getName(), i)
.setExtra(
Map.of(
// 历史手工新建单位可能未设置类型,展示时按其他类处理,避免空值使整棵树加载失败。
"unitTypeCode", unit.getUnitTypeCode() == null ? 0 : unit.getUnitTypeCode()
)
));
@@ -324,23 +333,37 @@ public class SysUnitController {
List<Tree<String>> treeList = TreeUtil.build(nodeList, virtualRootId);
return Result.success(treeList);
} catch (Exception e) {
log.error("加载单位树失败", e);
return Result.error();
}
}
/**
* 新建当前单位的下设单位。
*
* @param unit 表单数据;name 为单位名称,unitcode 为唯一编码,unitLevel 为单位等级,unionId 为所属工会;
* unitTypeCode 为部门类别,0 表示其他类、1 表示部门类,未传时由 service 按其他类保存
* @param parentId 当前选中上级单位的 ID,必须对应已存在的单位
* @param req 当前 HTTP 请求
* @return Result 对象;code 为 0 表示保存成功,非 0 表示失败,msg 为提示信息,data 为空
*/
@At
@Ok("json")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("sys.manager.unit.add")
@SLog(tag = "新建单位", msg = "单位名称:${args[0].name}")
public Object addDo(@Param("..") Sys_unit unit, @Param("parentId") String parentId, HttpServletRequest req) {
try {
if ("root".equals(parentId)) {
parentId = "";
if (Strings.isBlank(unit.getName()) || Strings.isBlank(unit.getUnitcode()) || Strings.isBlank(parentId) || "root".equals(parentId)) {
return Result.error("单位名称、单位编码和上级单位不能为空");
}
unit.setCreatedBy(SecurityUtil.getUserId());
sysUnitService.save(unit, parentId);
return Result.success();
} catch (BaseException e) {
return Result.error(e.getMessage());
} catch (Exception e) {
log.error("新建单位失败", e);
return Result.error();
}
}
@@ -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<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;
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<Sys_home_activity> implements SysHomeActivityService {
@Inject
private ActivityBasicScopeService activityBasicScopeService;
public SysHomeActivityServiceImpl(Dao 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,7 +10,6 @@ import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.plugins.mvc.websocket.AbstractWsEndpoint;
import org.nutz.plugins.mvc.websocket.NutWsConfigurator;
import org.nutz.plugins.mvc.websocket.WsHandler;
import redis.clients.jedis.*;
@@ -21,7 +20,7 @@ import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.List;
@ServerEndpoint(value = "/websocket", configurator = NutWsConfigurator.class)
@ServerEndpoint(value = "/websocket", configurator = WkWsConfigurator.class)
@IocBean(create = "init") // 使用NutWsConfigurator的必备条件
public class WkWebSocket extends AbstractWsEndpoint implements PubSub {
protected static final Log log = Logs.get();
@@ -0,0 +1,20 @@
package com.budwk.app.web.commons.ext.websocket;
import org.nutz.plugins.mvc.websocket.NutWsConfigurator;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
public class WkWsConfigurator extends NutWsConfigurator {
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
// WebSocket升级不一定经过Nutz请求链,只使用当前握手的会话,避免读取已回收的MVC请求。
Object session = request.getHttpSession();
if (session == null) {
config.getUserProperties().remove("HttpSession");
} else {
config.getUserProperties().put("HttpSession", session);
}
}
}
@@ -54,9 +54,8 @@ public class ActivityBasicSettingsController {
if (parentId != null) {
parentId.setChild(child(parentId.getId()));
list.add(parentId);
return Result.success().addData(list);
}
return Result.success();
return Result.success(list);
}
private List<ActivityBasicSettings> child(String parentId) {
@@ -73,6 +72,9 @@ public class ActivityBasicSettingsController {
Cnd cnd = Cnd.NEW();
if (StrUtil.isBlank(parentId)) {
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());
} else {
cnd.and("parentId", "=", parentId);
@@ -116,7 +118,13 @@ public class ActivityBasicSettingsController {
@At
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));
if (fetch == null) {
return Result.success(new ArrayList<ActivityBasicSettings>());
}
List<ActivityBasicSettings> query = dao.query(ActivityBasicSettings.class, Cnd.where("parentId", "=", fetch.getId()).asc("code"));
return Result.success(query);
}
@@ -0,0 +1,35 @@
package com.budwk.app.zhgh.activity.basic.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
import org.nutz.lang.util.NutMap;
/**
* 活动工会资料同步及组成单位维护,保留活动模块独立维护的临时分工会。
*/
public interface ActivityBasicUnionService extends BaseService<ActivityBasicUnion> {
/**
* 无请求参数,按 sys_union.id 新增缺少的活动工会,仅更新已有非临时工会的名称,不删除记录。
*
* @return NutMap;insertCount 为新增工会数,updateCount 为名称实际变更的工会数
*/
NutMap syncUnions();
/**
* 获取全部二级活动单位,不按现有分工会归属过滤候选项。
*
* @param unionId 当前活动分工会ID,用于回显已选组成单位
* @return NutMap;allUnits 为二级单位列表,selectUnitIds 为当前分工会已选二级单位ID列表
*/
NutMap getPartUnitTransferData(String unionId);
/**
* 设置当前活动分工会的组成单位,选中单位允许从其他活动分工会转入。
*
* @param unionId 当前活动分工会ID
* @param unitIds 二级活动单位ID数组,传空数组或 null 表示清空当前工会组成单位
* @return 无返回值;包含不存在或非二级单位的ID时抛出异常,不修改归属
*/
void setPartUnits(String unionId, String[] unitIds);
}
@@ -0,0 +1,19 @@
package com.budwk.app.zhgh.activity.basic.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
import org.nutz.lang.util.NutMap;
/**
* 活动单位基础资料同步,活动工会归属仍由活动模块独立维护。
*/
public interface ActivityBasicUnitService extends BaseService<ActivityBasicUnit> {
/**
* 将系统单位同步到活动单位,不删除活动单位,不覆盖已有活动单位的工会归属。
*
* @return NutMap;insertCount 为新增单位数,updateCount 为更新基础资料的已有单位数,
* pendingUnionCount 为新增单位中未能匹配活动工会、需要配置归属的数量
*/
NutMap syncUnits();
}
@@ -0,0 +1,115 @@
package com.budwk.app.zhgh.activity.basic.service.impl;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicUnionService;
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.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@IocBean(args = {"refer:dao"})
public class ActivityBasicUnionServiceImpl extends BaseServiceImpl<ActivityBasicUnion> implements ActivityBasicUnionService {
public ActivityBasicUnionServiceImpl(Dao dao) {
super(dao);
}
/**
* 无请求参数,按来源工会ID同步全部工会组织;返回新增数和名称实际变更数。
* 已有工会只更新名称及修改审计信息,不覆盖编码、联系方式、校区、组成单位和管理员关系。
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public NutMap syncUnions() {
List<Sys_union> sourceUnions = dao().query(Sys_union.class, Cnd.NEW());
Map<String, ActivityBasicUnion> existingUnions = dao().query(ActivityBasicUnion.class, Cnd.NEW()).stream()
.collect(Collectors.toMap(ActivityBasicUnion::getId, union -> union));
String operatorId = SecurityUtil.getUserId();
long updateTime = System.currentTimeMillis();
int insertCount = 0;
int updateCount = 0;
for (Sys_union sourceUnion : sourceUnions) {
if (StrUtil.isBlank(sourceUnion.getId())) {
throw new BaseException("工会组织存在空ID,本次同步已取消,请先检查工会组织资料");
}
ActivityBasicUnion existingUnion = existingUnions.get(sourceUnion.getId());
if (existingUnion == null) {
// 按列插入以避开实体UUID生成拦截器,保留来源ID,保证重复同步不会重复新增。
dao().insert(ActivityBasicUnion.class, Chain.make("id", sourceUnion.getId())
.add("name", sourceUnion.getName()).add("unionCode", sourceUnion.getUnionCode())
.add("telephone", sourceUnion.getTelephone()).add("campus", sourceUnion.getCampus())
.add("source", "sys").add("createdBy", operatorId).add("createdAt", updateTime)
.add("updatedBy", operatorId).add("updatedAt", updateTime).add("delFlag", false));
insertCount++;
} else if (!"activity".equals(existingUnion.getSource())
&& !Objects.equals(existingUnion.getName(), sourceUnion.getName())) {
// 临时分工会即使与来源ID意外相同也不覆盖;来源中已不存在的工会自然保留。
dao().update(ActivityBasicUnion.class, Chain.make("name", sourceUnion.getName())
.add("updatedBy", operatorId).add("updatedAt", updateTime),
Cnd.where("id", "=", sourceUnion.getId()));
updateCount++;
}
}
return NutMap.NEW().addv("insertCount", insertCount).addv("updateCount", updateCount);
}
/**
* 按单位层级查询全部二级活动单位,单位类别和现有工会归属不影响候选范围。
*
* @param unionId 当前活动分工会ID,仅用于计算回显的选中项
* @return NutMap;allUnits 为候选单位实体列表,selectUnitIds 为当前工会已选二级单位ID列表
*/
@Override
public NutMap getPartUnitTransferData(String unionId) {
List<ActivityBasicUnit> units = dao().query(ActivityBasicUnit.class,
Cnd.where("unitLevel", "=", 2).asc("unitcode"));
List<String> selectUnitIds = units.stream()
.filter(unit -> Objects.equals(unit.getUnionId(), unionId))
.map(ActivityBasicUnit::getId).toList();
return NutMap.NEW().addv("selectUnitIds", selectUnitIds).addv("allUnits", units);
}
/**
* 校验全部选中单位均为二级单位后,替换当前活动分工会的组成单位关系。
*
* @param unionId 当前活动分工会ID
* @param unitIds 二级活动单位ID数组,空数组或 null 表示清空组成单位
* @return 无返回值;无效单位参数在修改归属之前抛出异常
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public void setPartUnits(String unionId, String[] unitIds) {
List<String> selectedIds = unitIds == null ? List.of() : Arrays.stream(unitIds).distinct().toList();
if (!selectedIds.isEmpty()) {
// 必须先完整校验再解除原归属,防止提交三级、空ID或不存在的单位时丢失已有组成单位。
if (selectedIds.stream().anyMatch(StrUtil::isBlank)
|| dao().count(ActivityBasicUnit.class,
Cnd.where("id", "in", selectedIds).and("unitLevel", "=", 2)) != selectedIds.size()) {
throw new BaseException("组成单位只能选择有效的二级单位,请刷新后重新选择");
}
}
// 保存时替换当前组成单位,历史误选的三级单位也随本次重新设置解除关联。
dao().update(ActivityBasicUnit.class, Chain.make("unionId", null), Cnd.where("unionId", "=", unionId));
if (!selectedIds.isEmpty()) {
// 允许将已属于其他活动分工会的二级单位转入,不增加原工会归属限制。
dao().update(ActivityBasicUnit.class, Chain.make("unionId", unionId),
Cnd.where("id", "in", selectedIds).and("unitLevel", "=", 2));
}
}
}
@@ -0,0 +1,93 @@
package com.budwk.app.zhgh.activity.basic.service.impl;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicUnitService;
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.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@IocBean(args = {"refer:dao"})
public class ActivityBasicUnitServiceImpl extends BaseServiceImpl<ActivityBasicUnit> implements ActivityBasicUnitService {
public ActivityBasicUnitServiceImpl(Dao dao) {
super(dao);
}
/**
* 无请求参数,按 sys_unit.id 同步全部系统单位;返回新增数、更新数和新增单位待配置活动工会数。
* 已有记录只更新基础字段,连原有的空工会归属也保留,避免覆盖活动模块人工维护的组成单位关系。
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public NutMap syncUnits() {
List<Sys_unit> sourceUnits = dao().query(Sys_unit.class, Cnd.NEW());
Set<String> existingIds = dao().query(ActivityBasicUnit.class, Cnd.NEW()).stream()
.map(ActivityBasicUnit::getId).collect(Collectors.toSet());
Set<String> activityUnionIds = dao().query(ActivityBasicUnion.class, Cnd.NEW()).stream()
.map(ActivityBasicUnion::getId).collect(Collectors.toSet());
int insertCount = 0;
int updateCount = 0;
int pendingUnionCount = 0;
String operatorId = SecurityUtil.getUserId();
long updateTime = System.currentTimeMillis();
for (Sys_unit sourceUnit : sourceUnits) {
if (StrUtil.isBlank(sourceUnit.getId())) {
throw new BaseException("系统单位存在空ID,本次同步已取消,请先检查系统单位资料");
}
Chain fields = buildBasicFields(sourceUnit)
.add("updatedBy", operatorId).add("updatedAt", updateTime);
if (existingIds.contains(sourceUnit.getId())) {
// 更新列中不包含 unionId、unionGroupId 和 id,保留现有归属及报名记录使用的单位ID。
dao().update(ActivityBasicUnit.class, fields, Cnd.where("id", "=", sourceUnit.getId()));
updateCount++;
} else {
// 新单位仅继承已存在于活动工会表的归属,不能将普通工会ID直接当作有效活动工会。
String unionId = StrUtil.isNotBlank(sourceUnit.getUnionId()) && activityUnionIds.contains(sourceUnit.getUnionId())
? sourceUnit.getUnionId() : null;
if (unionId == null) {
pendingUnionCount++;
}
fields.add("id", sourceUnit.getId()).add("unionId", unionId)
.add("createdBy", operatorId).add("createdAt", updateTime).add("delFlag", false);
// 按列插入避开实体的 UUID 生成拦截器,确保活动单位ID始终等于系统单位ID。
dao().insert(ActivityBasicUnit.class, fields);
existingIds.add(sourceUnit.getId());
insertCount++;
}
}
return NutMap.NEW().addv("insertCount", insertCount).addv("updateCount", updateCount)
.addv("pendingUnionCount", pendingUnionCount);
}
/**
* 只列出允许从系统单位更新的基础资料;工会、小组归属和审计创建信息不属于基础同步字段。
* 父级、路径与层级沿用源值,树展示需要的根节点适配在接口内存中完成,不改写单位关系。
*
* @param unit sys_unit 中的完整单位记录
* @return 可供 DAO 按列新增或更新的 Chain,不含单位ID和工会归属
*/
private Chain buildBasicFields(Sys_unit unit) {
return Chain.make("parentId", unit.getParentId()).add("path", unit.getPath())
.add("name", unit.getName()).add("aliasName", unit.getAliasName()).add("unitcode", unit.getUnitcode())
.add("note", unit.getNote()).add("address", unit.getAddress()).add("telephone", unit.getTelephone())
.add("email", unit.getEmail()).add("website", unit.getWebsite()).add("location", unit.getLocation())
.add("hasChildren", unit.isHasChildren()).add("logo", unit.getLogo()).add("unitLevel", unit.getUnitLevel())
.add("divisionCollegeCode", unit.getDivisionCollegeCode()).add("institutionType", unit.getInstitutionType())
.add("unitType", unit.getUnitType()).add("unitTypeCode", unit.getUnitTypeCode());
}
}
@@ -0,0 +1,40 @@
package com.budwk.app.zhgh.activity.sports.models;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import java.math.BigDecimal;
/** 一条获奖成绩的奖品人数归属,与积分分配独立;一人一次获奖对应一份奖品。 */
@Data
@EqualsAndHashCode(callSuper = true)
@Table("activity_results_prize")
@Comment("活动成绩奖品人数分配")
@TableIndexes({@Index(name = "ARP_RESULT_UNION", fields = {"resultId", "prizeUnionId"}, unique = true)})
public class ActivityResultsPrize extends BaseModel {
@Name
@ColDefine(type = ColType.VARCHAR, width = 32)
private String id;
@Column
@Comment("成绩主记录ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String resultId;
@Column
@Comment("领取奖品的正式分工会ID,对应sys_union")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String prizeUnionId;
@Column
@Comment("奖品领取工会名称快照")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String prizeUnionName;
@Column
@Comment("实际获奖人数,个人成绩合计为1,团体成绩合计等于获奖总人数")
@ColDefine(type = ColType.INT)
// 接收时保留原始数值精度,避免JSON直接绑定Integer时把3.5截断为3;保存前严格转为int范围整数。
private BigDecimal numberOfPeople;
}
@@ -0,0 +1,40 @@
package com.budwk.app.zhgh.activity.sports.models;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import java.math.BigDecimal;
/** 一次团体获奖在正式分工会之间的积分分配,不代表新增获奖或人数分配。 */
@Data
@EqualsAndHashCode(callSuper = true)
@Table("activity_results_score")
@Comment("活动成绩积分分配")
@TableIndexes({@Index(name = "ARS_RESULT_UNION", fields = {"resultId", "scoreUnionId"}, unique = true)})
public class ActivityResultsScore extends BaseModel {
@Name
@ColDefine(type = ColType.VARCHAR, width = 32)
private String id;
@Column
@Comment("成绩主记录ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String resultId;
@Column
@Comment("正式计分工会ID,对应sys_union")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String scoreUnionId;
@Column
@Comment("计分工会名称快照")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String scoreUnionName;
@Column
@Comment("分配积分,合计必须等于主成绩总积分")
@ColDefine(customType = "decimal(10,2)")
private BigDecimal integral;
}
@@ -649,8 +649,11 @@ public class TrainSignUpActivityServiceImpl extends BaseServiceImpl<TrainSignUpA
fillCourseResponsibles(courseList);
courseList.forEach(c -> {
dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime"));
if (c.getCourseTimeList() == null) {
c.setCourseTimeList(new ArrayList<>());
}
if (StrUtil.isNotBlank(c.getCourseType())) {
dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime"));
int courseCount = statisticsService.queryCourseCount(c.getId(), c.getCourseType());
c.setHasRegisterNum(courseCount);
int courseWaitCount = statisticsService.queryCourseWaitCount(c.getId(), c.getCourseType());
@@ -0,0 +1,104 @@
package com.budwk.app.zhgh.club.controller.statistics;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
import com.budwk.app.zhgh.club.service.SysClubService;
import com.budwk.app.zhgh.club.service.impl.SysClubUserServiceImpl;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
import java.util.List;
@IocBean
@Ok("json")
@At("/platform/club/statistics/member")
public class ClubMemberStatisticsController {
@Inject
private SysClubService sysClubService;
@At("")
@Ok("beetl:/platform/zhgh/club/statistics/member.html")
@SaCheckPermission("club.statistics.member")
public void index() {
}
@At
@SaCheckPermission("club.statistics.member")
public Result pageData(@Valid PageForm pageForm, String clubId, String userId, String keyWord, String unitName, String userState, String sex) {
Sql sql = generateSql(false, clubId, userId, keyWord, unitName, userState, sex);
Pagination pagination = sysClubService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
List<NutMap> members = pagination.getList(NutMap.class);
for (NutMap member : members) {
List<String> roles = StrUtil.isBlank(member.getString("roleCode"))
? List.of() : Json.fromJsonAsList(String.class, member.getString("roleCode"));
member.put("roleName", SysClubUserServiceImpl.convertRoleName(roles));
member.put("roleCode", roles);
}
pagination.setList(members);
return Result.success(pagination);
}
@At
@SaCheckPermission("club.statistics.member")
public Result clubOptions() {
return Result.success(sysClubService.listMap(generateSql(true, null, null, null, null, null, null)));
}
private Sql generateSql(boolean options, String clubId, String userId, String keyWord, String unitName, String userState, String sex) {
String fields = options ? "DISTINCT club.id, club.clubCode, club.clubName" : """
c.id, c.userId, club.clubCode, club.clubName,
COALESCE(NULLIF(u.username, ''), c.userName) AS userName,
COALESCE(NULLIF(u.loginname, ''), c.loginName) AS loginName,
u.sex, COALESCE(NULLIF(u.mobile, ''), c.mobile) AS mobile,
u.unitname AS unitName, u.userState, c.roleCode, c.joinTime
""";
Sql sql = Sqls.create("SELECT " + fields + "\n" + """
FROM sys_club club
INNER JOIN club_user c ON c.clubId = club.id
LEFT JOIN vw_user u ON u.id = c.userId
$condition
AND EXISTS (
SELECT 1 FROM wf_process_instance registerInstance
INNER JOIN wf_process_define registerDefine
ON registerDefine.id = registerInstance.processDefineId
WHERE registerInstance.businessNo = club.id
AND registerInstance.state = @finishedState
AND registerInstance.delFlag = 0
AND registerDefine.name = @registerProcessKey
AND registerDefine.delFlag = 0
)
ORDER BY club.clubCode, club.id
""" + (options ? "" : ", c.id"));
Cnd cnd = Cnd.where("club.dismiss", "=", false);
cnd.and("club.delFlag", "=", false);
cnd.and("c.delFlag", "=", false);
cnd.andEX("club.id", "=", clubId);
cnd.andEX("c.userId", "=", userId);
cnd.andEX("u.userState", "=", userState);
cnd.andEX("u.sex", "=", sex);
if (StrUtil.isNotBlank(unitName)) {
cnd.and("u.unitname", "=", unitName);
}
if (StrUtil.isNotBlank(keyWord)) {
cnd.and(Cnd.exps("COALESCE(NULLIF(u.username, ''), c.userName)", "like", "%" + keyWord + "%")
.or("COALESCE(NULLIF(u.loginname, ''), c.loginName)", "like", "%" + keyWord + "%"));
}
sql.setCondition(cnd);
sql.setParam("finishedState", ProcessInstanceStateEnum.FINISHED.getCode());
sql.setParam("registerProcessKey", "XHZC");
return sql;
}
}
@@ -129,7 +129,21 @@ public class ClubStatisticsController {
u.mobile,
u.unitname as unitName,
u.userState,
c.*
c.id,
c.clubId,
c.userId,
c.roleCode,
c.clubPosition,
c.email,
c.avatar,
c.sameTimeJoinOtherClubSituation,
c.awardsExperience,
c.joinTime,
c.createdBy,
c.createdAt,
c.updatedBy,
c.updatedAt,
c.delFlag
FROM
club_user c
LEFT JOIN `vw_user` u ON u.id = c.userId
@@ -24,20 +24,23 @@ public class TherapyRecuperationModule {
{"base", "目的地管理", "/baseManagement", "TheBaseManagement"},
{"branchSelect", "分工会选择线路", "/lineFghSelect?mode=1", "lineFghSelect"},
{"schoolSelect", "校工会选择线路", "/lineXghSelect?mode=2", "lineXghSelect"},
{"overview", "线路选择总览", "/lineSelectionOverview", "lineSelectionOverview"},
{"overview", "线路选择查询", "/lineSelectionOverview", "lineSelectionOverview"},
{"cluster", "线路组团", "/lineCluster", "lineCluster"},
{"adjustment", "线路调剂", "/lineAdjustment", "line.adjustment"},
{"import", "参加人员导入", "/joinUserImport", "joinUser.import"},
{"branchAudit", "分工会审核", "/TheRapyAudit", "TheRapyAudit"},
{"travelAudit", "自由组团审核", "/TheRapyTravelAudit", "TheRapyTravelAudit"},
{"schoolAudit", "校工会审核", "/TheRapyXghAudit", "TheRapyXghAudit"},
{"branchQuery", "分工会查询", "/query", "TheRapyQuery"},
{"userQuery", "报名人员查询", "/user/query", "TheRapyUserQuery"},
{"queryStatistics", "查询统计", "/query/statics", "queryStatics"},
{"lineStatistics", "线路统计", "/statistics", "statistics"},
{"agencyStatistics", "旅行社月度统计", "/travelAgencyMonthlyStatistics", "travelAgencyMonthlyStatistics"},
{"unionStatistics", "分工会线路数量统计", "/statistics/unionLineNumberStatistics", "unionLineNumberStatistics"}
{"branchQuery", "分工会信息查询", "/query", "TheRapyQuery"},
{"userQuery", "校工会信息查询", "/user/query", "TheRapyUserQuery"},
{"queryStatistics", "满意度统计", "/query/statics", "queryStatics"},
{"lineStatistics", "成团结果通知", "/statistics", "statistics"},
{"agencyStatistics", "人数统计", "/travelAgencyMonthlyStatistics", "travelAgencyMonthlyStatistics"},
{"unionStatistics", "分工会线路选择统计", "/statistics/unionLineNumberStatistics", "unionLineNumberStatistics"}
};
public static final List<String> MENU_SCREENS = List.of("agency", "line", "branchSelect", "schoolSelect",
"queryStatistics", "branchQuery", "userQuery", "overview", "lineStatistics", "config",
"unionStatistics", "agencyStatistics");
@Inject
private Dao dao;
@@ -49,7 +52,6 @@ public class TherapyRecuperationModule {
private SysUserService sysUserService;
public void init() {
renameLegacyTables();
Class<?>[] tables = {TheRapyRecuperationBaseManagement.class, TheRapyRecuperationCluster.class,
TheRapyRecuperationClusterMember.class, TheRapyRecuperationConfig.class,
TheRapyRecuperationEnroll.class, TheRapyRecuperationEnrollBed.class,
@@ -58,7 +60,6 @@ public class TherapyRecuperationModule {
TheRapyRecuperationLot.class, TheRapyRecuperationTravelAgency.class,
TherapyAudit.class, TherapyAuditState.class};
for (Class<?> table : tables) dao.create(table, false);
widenLineImageAddress();
createView("inclusive_therapy_v3_user", "SELECT u.*, u.arrivalAtSchoolDate AS schoolTime FROM vw_user u");
createView("inclusive_therapy_v3_union", "SELECT u.*, u.name AS unionname FROM sys_union u");
createView("inclusive_therapy_v3_unit", "SELECT u.* FROM sys_unit u");
@@ -97,14 +98,14 @@ public class TherapyRecuperationModule {
Sys_config setting = new Sys_config();
setting.setConfigKey("staffTherapyRecuperationVersion");
setting.setConfigValue("zjnu");
setting.setNote("普惠疗休养V3独立子模块报名规则版本");
setting.setNote("普惠疗休养独立子模块报名规则版本");
dao.insert(setting);
}
private void seedConfig() {
if (dao.count(TheRapyRecuperationConfig.class) != 0) return;
TheRapyRecuperationConfig config = new TheRapyRecuperationConfig();
config.setConfigName("普惠疗休养V3配置");
config.setConfigName("普惠疗休养配置");
config.setIsSnLine(false);
config.setIsSwLine(false);
config.setTravelAudit(false);
@@ -116,7 +117,6 @@ public class TherapyRecuperationModule {
}
private void seedMenus() {
migrateLegacyMenuIdentifiers();
Sys_menu existing = dao.fetch(Sys_menu.class, Cnd.where("href", "like", "/platform/recuperation%").and("platform", "=", "pc"));
Sys_module module = existing == null ? null : dao.fetch(Sys_module.class, existing.getModuleId());
if (module == null) module = dao.fetch(Sys_module.class, Cnd.where("name", "=", "职工福利").and("platform", "=", "pc"));
@@ -128,11 +128,14 @@ public class TherapyRecuperationModule {
module.setFaIcon("fa fa-heart");
dao.insert(module);
}
Sys_menu root = addMenu(module.getId(), "", "普惠疗休养V3", ROOT, "inclusiveTherapyV3", "pc");
Sys_menu root = addMenu(module.getId(), "", "普惠疗休养", ROOT, "inclusiveTherapyV3", "pc");
List<Sys_role> roles = dao.query(Sys_role.class, Cnd.where("disabled", "=", false));
for (String[] screen : SCREENS) {
Sys_menu menu = addMenu(module.getId(), root.getId(), screen[1], ROOT + "?screen=" + screen[0],
Sys_menu menu = addMenu(module.getId(), root.getId(), screen[1], ROOT + screen[2],
"inclusiveTherapyV3." + screen[3], "pc");
int position = MENU_SCREENS.indexOf(screen[0]);
dao.update(Sys_menu.class, Chain.make("showit", position >= 0)
.add("location", position >= 0 ? position + 1 : MENU_SCREENS.size() + 1), Cnd.where("id", "=", menu.getId()));
for (Sys_role role : roles) {
String code = role.getCode();
boolean school = List.of("sysadmin", "superadmin", "A06", "SchoolUnionMemberAdmin", "SYSADMIN", "SCHOOL_UNION_ADMIN", "SCHOOL_UNION_WELFARE_ADMIN", "SCHOOL_UNION_MEMBER_ADMIN").contains(code);
@@ -144,7 +147,8 @@ public class TherapyRecuperationModule {
}
}
}
Sys_menu signup = addMenu(module.getId(), root.getId(), "疗休养报名", ROOT + "?screen=signup", "inclusiveTherapyV3.signup", "pc");
Sys_menu signup = addMenu(module.getId(), root.getId(), "疗休养报名", ROOT + "/mobile/index", "inclusiveTherapyV3.signup", "pc");
dao.update(Sys_menu.class, Chain.make("showit", false), Cnd.where("id", "=", signup.getId()));
Sys_module h5Module = dao.fetch(Sys_module.class, Cnd.where("name", "=", module.getName()).and("platform", "=", "h5"));
if (h5Module == null) {
h5Module = new Sys_module();
@@ -154,7 +158,7 @@ public class TherapyRecuperationModule {
h5Module.setFaIcon("fa fa-heart");
dao.insert(h5Module);
}
Sys_menu mobile = addMenu(h5Module.getId(), "", "普惠疗休养V3", ROOT + "/mobile/index", "inclusiveTherapyV3.mobile", "h5");
Sys_menu mobile = addMenu(h5Module.getId(), "", "普惠疗休养", ROOT + "/mobile/index", "inclusiveTherapyV3.mobile", "h5");
for (Sys_role role : roles) {
if (List.of("public", "PUBLIC", "MEMBER", "sysadmin", "superadmin", "SYSADMIN").contains(role.getCode())) {
grant(role.getId(), root.getId());
@@ -51,7 +51,8 @@ public class TherapyCommonController {
@At({"/unions", "/getUnion"})
@SaCheckLogin
public Result unions(Boolean isPermission) {
Cnd cnd = Cnd.NEW().asc("unionname");
Cnd cnd = Cnd.NEW();
cnd.asc("unionCode");
if (Boolean.TRUE.equals(isPermission) && !TherapyContext.hasAnyRoles("sysadmin,A06")) {
cnd.and("id", "=", TherapyContext.getUnionId());
}
@@ -93,7 +94,11 @@ public class TherapyCommonController {
private NutMap fileInfo(Sys_file file) {
return NutMap.NEW().addv("id", file.getId()).addv("filename", file.getName())
.addv("filepath", file.getDownloadPath()).addv("url", file.getDownloadPath());
.addv("filepath", file.getDownloadPath()).addv("url", file.getDownloadPath())
.addv("name", file.getName()).addv("downloadPath", file.getDownloadPath())
.addv("engine", file.getEngine()).addv("bucket", file.getBucket())
.addv("objName", file.getObjName()).addv("storagePath", file.getStoragePath())
.addv("suffix", file.getSuffix()).addv("sizeKb", file.getSizeKb()).addv("sizeInfo", file.getSizeInfo());
}
@At
@@ -111,8 +116,10 @@ public class TherapyCommonController {
@SaCheckLogin
@POST
public Result deleteFile(String id) {
if (Strings.isBlank(id)) return Result.error("缺少文件ID");
Sys_file file = sysFileService.fetch(id);
if (file != null && !Objects.equals(file.getCreatedBy(), TherapyContext.getUserId())
if (file == null) return Result.success();
if (!Objects.equals(file.getCreatedBy(), TherapyContext.getUserId())
&& !TherapyContext.hasAnyRoles("sysadmin,A06")) return Result.error("无权删除此文件");
sysFileService.delete(Collections.singletonList(id));
return Result.success();
@@ -5,15 +5,27 @@ import cn.dev33.satoken.stp.StpUtil;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.TherapyRecuperationModule;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@IocBean
@At("/platform/inclusiveTherapyV3")
public class TherapyWorkspaceController {
@At("")
@SaCheckLogin
@Ok("beetl:/platform/zhgh/staffbenefit/therapyRecuperation/index.html")
public void index(String screen, HttpServletRequest request) {
@Ok("void")
public void index(String screen, HttpServletResponse response) throws IOException {
if (screen == null) {
for (String key : TherapyRecuperationModule.MENU_SCREENS) {
for (String[] candidate : TherapyRecuperationModule.SCREENS) {
if (candidate[0].equals(key) && StpUtil.hasPermission("inclusiveTherapyV3." + candidate[3])) {
screen = key;
break;
}
}
if (screen != null) break;
}
}
String url = TherapyRecuperationModule.ROOT + "/mobile/index";
if (screen != null && !"signup".equals(screen)) {
boolean found = false;
@@ -25,8 +37,8 @@ public class TherapyWorkspaceController {
break;
}
}
if (!found) throw new IllegalArgumentException("未知的普惠疗休养V3页面");
if (!found) throw new IllegalArgumentException("未知的普惠疗休养页面");
}
request.setAttribute("therapyPageUrl", url);
response.sendRedirect(url);
}
}
@@ -65,11 +65,11 @@ public class TheRapyRecuperationTravelAuditController {
@At
@ViReturn
public Object pageData(PageForm pageForm,
@Param(value = "agencyId", required = false) String agencyId,
@Param(value = "year", required = false) String year,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "isAudit", required = false) String isAudit){
@Param(value = "agencyId") String agencyId,
@Param(value = "year") String year,
@Param(value = "unionId") String unionId,
@Param(value = "unitId") String unitId,
@Param(value = "isAudit") String isAudit){
Sql sql = Sqls.create("""
SELECT
enroll.*,
@@ -309,11 +309,11 @@ public class TheRapyRecuperationXghAuditController {
@ViReturn
@SaCheckLogin
public Object getLinePlayTimeByLineId(String lineId,
@Param(value = "signUpMode",required = false) Integer signUpMode,
@Param(value = "year",required = false) Integer year,
@Param(value = "startYear",required = false)Integer startYear,
@Param(value = "endYear",required = false)Integer endYear,
@Param(value = "flag",required = false) Boolean flag) {
@Param(value = "signUpMode") Integer signUpMode,
@Param(value = "year") Integer year,
@Param(value = "startYear")Integer startYear,
@Param(value = "endYear")Integer endYear,
@Param(value = "flag") Boolean flag) {
Cnd cnd = Cnd.NEW();
cnd.and("lineId", "=", lineId);
if (flag == null || !flag){
@@ -70,7 +70,7 @@ public class TheRapyRecuperationBaseManagerController {
@At("")
@Ok("beetl:/platform/zhgh/staffbenefit/therapyRecuperation/baseManage/baseManagement.html")
@SaCheckPermission("inclusiveTherapyV3.line")
@SaCheckPermission("inclusiveTherapyV3.TheBaseManagement")
public void index() {
}
@@ -10,6 +10,8 @@ import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
import com.budwk.app.sys.models.Sys_office_template;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.ViReturn;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext;
import com.budwk.app.base.param.PageForm;
@@ -66,6 +68,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
@@ -93,17 +96,34 @@ public class TheRapyRecuperationLineController {
/**
* 新线路导入模板中“联系方式”列下标,设置为文本格式避免手机号被Excel转成科学计数法。
*/
private static final int LINE_IMPORT_CONTACT_PHONE_COLUMN_INDEX = 10;
private static final int LINE_IMPORT_CONTACT_PHONE_COLUMN_INDEX = 12;
/**
* 新线路导入模板中“移动端缩略图”列下标,用于定位Excel内嵌图片。
*/
private static final int LINE_IMPORT_THUMBNAIL_COLUMN_INDEX = 13;
private static final int LINE_IMPORT_THUMBNAIL_COLUMN_INDEX = 15;
@Inject
private TheRapyRecuperationLineService lineService;
@Inject
private Dao dao;
@Inject
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
@At
@Ok("void")
@SaCheckPermission("inclusiveTherapyV3.line")
public void downloadTemplate(HttpServletResponse response) throws IOException {
String templateCode = "inclusive_therapy_v3_line_import";
try (InputStream in = sysOfficeTemplateUtil.getTemplate(templateCode)) {
Sys_office_template template = dao.fetch(Sys_office_template.class, Cnd.where("templateCode", "=", templateCode));
TherapyDownload.excelResponse(response, template.getTemplateName());
if (template.getTemplateName().toLowerCase(Locale.ROOT).endsWith(".xls")) {
response.setContentType("application/vnd.ms-excel");
}
in.transferTo(response.getOutputStream());
}
}
@At("")
@Ok("beetl:/platform/zhgh/staffbenefit/therapyRecuperation/basicManage/line.html")
@@ -438,7 +458,7 @@ public class TheRapyRecuperationLineController {
List<String> excelLots = lots.stream().map(v -> v.getLotName() + "_" + v.getId()).collect(Collectors.toList());
List<Field> needAddReplaceFields = Arrays.stream(TheRapyLineImportExcelMode.class.getDeclaredFields())
.filter(v -> List.of("lotId", "regionalNature", "signUpMode", "isEnabled").contains(v.getName()))
.filter(v -> List.of("lotId", "regionalNature", "signUpMode", "isEnabled", "familySignUp").contains(v.getName()))
.collect(Collectors.toList());
for (Field field : needAddReplaceFields) {
Excel excelAnnotation = field.getAnnotation(Excel.class);
@@ -456,7 +476,7 @@ public class TheRapyRecuperationLineController {
e.put("replace", buildRegionalNatureExcelOptions());
} else if (field.getName().equals("signUpMode")) {
e.put("replace", buildSignUpModeExcelOptions());
} else if (field.getName().equals("isEnabled")) {
} else if (field.getName().equals("isEnabled") || field.getName().equals("familySignUp")) {
e.put("replace", new String[]{"是_是", "否_否"});
}
}
@@ -1,10 +1,11 @@
package com.budwk.app.zhgh.staffbenefit.therapyRecuperation.controller.basicManage;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
import com.budwk.app.sys.models.Sys_office_template;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyDownload;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.ViReturn;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.PageUtil;
import com.budwk.app.base.param.PageForm;
@@ -14,13 +15,11 @@ import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.service.TheRapyRecupe
import lombok.extern.slf4j.Slf4j;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
@@ -32,7 +31,20 @@ import org.nutz.mvc.upload.UploadAdaptor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.nutz.trans.Trans;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import java.math.BigDecimal;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.http.HttpServletResponse;
/**
@@ -51,6 +63,8 @@ public class TheRapyRecuperationTravelAgencyController {
private TheRapyRecuperationTravelAgencyService travelAgencyService;
@Inject
private Dao dao;
@Inject
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
@At("")
@Ok("beetl:/platform/zhgh/staffbenefit/therapyRecuperation/basicManage/travelAgency.html")
@@ -58,6 +72,21 @@ public class TheRapyRecuperationTravelAgencyController {
public void index() {
}
@At
@Ok("void")
@SaCheckPermission("inclusiveTherapyV3.travelAgency")
public void downloadTemplate(HttpServletResponse response) throws IOException {
String templateCode = "inclusive_therapy_v3_travel_agency_import";
try (InputStream in = sysOfficeTemplateUtil.getTemplate(templateCode)) {
Sys_office_template template = dao.fetch(Sys_office_template.class, Cnd.where("templateCode", "=", templateCode));
TherapyDownload.excelResponse(response, template.getTemplateName());
if (template.getTemplateName().toLowerCase(java.util.Locale.ROOT).endsWith(".xls")) {
response.setContentType("application/vnd.ms-excel");
}
in.transferTo(response.getOutputStream());
}
}
/**
* 页面数据
*
@@ -211,9 +240,8 @@ public class TheRapyRecuperationTravelAgencyController {
*/
@At
@ViReturn
@SaCheckLogin
@SaCheckPermission("inclusiveTherapyV3.travelAgency")
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
@Aop(TransAop.READ_COMMITTED)
public Object travelAgencyImport(TempFile file) {
if (Lang.isEmpty(file)) {
return Result.error("上传的文件不能为空");
@@ -222,58 +250,146 @@ public class TheRapyRecuperationTravelAgencyController {
if (!List.of("xls", "xlsx").contains(extName.toLowerCase())) {
return Result.error("请上传xls,xlsx文件");
}
List<TheRapyTravelAgencyExcelMode> excelList;
List<TheRapyTravelAgencyExcelMode> excelList = new ArrayList<>();
List<Integer> excelRowNumbers = new ArrayList<>();
try {
ImportParams importParams = new ImportParams();
// importParams.setTitleRows(1);
excelList = ExcelImportUtil.importExcel(file.getFile(), TheRapyTravelAgencyExcelMode.class, importParams);
try (Workbook workbook = WorkbookFactory.create(file.getFile())) {
Sheet sheet = workbook.getSheetAt(0);
Row header = sheet.getRow(0);
if (header == null) return Result.error("第一行必须是模板表头");
DataFormatter formatter = new DataFormatter();
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
Map<String, Integer> headers = new java.util.LinkedHashMap<>();
for (Cell cell : header) {
String name = formatter.formatCellValue(cell).trim().replace("(可填)", "").replace("(可填)", "");
if ("编号".equals(name)) name = "排序编号";
if ("是否启用".equals(name)) name = "是否启用(是/否)";
if (StrUtil.isBlank(name)) continue;
if (headers.putIfAbsent(name, cell.getColumnIndex()) != null) return Result.error("模板表头重复:" + name);
}
for (String name : List.of("年度", "排序编号", "旅行社名称", "是否自由组团(是/否)", "旅行社联系人", "联系电话")) {
if (!headers.containsKey(name)) return Result.error("模板缺少必填列:" + name);
}
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
Row dataRow = sheet.getRow(rowIndex);
if (dataRow == null) continue;
Map<String, String> values = new java.util.HashMap<>();
for (Map.Entry<String, Integer> column : headers.entrySet()) {
Cell cell = dataRow.getCell(column.getValue());
String value = formatter.formatCellValue(cell, evaluator).trim();
if (cell != null && ("年度".equals(column.getKey()) || "最多承担人数".equals(column.getKey()))) {
CellValue evaluated = evaluator.evaluate(cell);
if (evaluated != null && evaluated.getCellType() == CellType.NUMERIC) {
value = BigDecimal.valueOf(evaluated.getNumberValue()).toPlainString();
}
}
values.put(column.getKey(), value);
}
if (values.values().stream().allMatch(StrUtil::isBlank)) continue;
TheRapyTravelAgencyExcelMode travel = new TheRapyTravelAgencyExcelMode();
try {
if (StrUtil.isNotBlank(values.get("年度"))) {
travel.setYear(new BigDecimal(values.get("年度")).intValueExact());
}
} catch (NumberFormatException | ArithmeticException e) {
return Result.error("第" + (rowIndex + 1) + "行:年度须填写4位整数");
}
try {
if (StrUtil.isNotBlank(values.get("最多承担人数"))) {
travel.setMaxUndertakeNumber(new BigDecimal(values.get("最多承担人数")).intValueExact());
}
} catch (NumberFormatException | ArithmeticException e) {
return Result.error("第" + (rowIndex + 1) + "行:最多承担人数须填写有效整数");
}
travel.setSerialNumber(values.get("排序编号"));
travel.setTravelAgencyName(values.get("旅行社名称"));
travel.setSignUpTravelAgency(values.get("是否自由组团(是/否)"));
travel.setContact(values.get("旅行社联系人"));
travel.setContactMobileNumber(values.get("联系电话"));
travel.setEmail(values.get("邮箱"));
travel.setOfficialWebsite(values.get("官网"));
travel.setNote(values.get("备注"));
travel.setIsDisabled(values.get("是否启用(是/否)"));
excelList.add(travel);
excelRowNumbers.add(rowIndex + 1);
}
} catch (Exception e) {
log.error(e.getMessage());
return Result.error("读取不到数据,请检查excel文件格式");
log.error("读取旅行社导入文件失败", e);
return Result.error("读取失败,请使用新模板;年度和最多承担人数须填写整数");
}
if (Lang.isEmpty(excelList)) {
return Result.error("读取不到数据,请检查excel文件格式");
}
List<TheRapyRecuperationTravelAgency> list = new ArrayList<>();
Map<String, Integer> importedNumbers = new java.util.HashMap<>();
for (int index = 0; index < excelList.size(); index++) {
TheRapyTravelAgencyExcelMode travel = excelList.get(index);
String row = "第" + excelRowNumbers.get(index) + "行:";
travel.setSerialNumber(StrUtil.trim(travel.getSerialNumber()));
travel.setTravelAgencyName(StrUtil.trim(travel.getTravelAgencyName()));
travel.setContact(StrUtil.trim(travel.getContact()));
travel.setContactMobileNumber(StrUtil.trim(travel.getContactMobileNumber()));
travel.setSignUpTravelAgency(StrUtil.trim(travel.getSignUpTravelAgency()));
travel.setIsDisabled(StrUtil.trim(travel.getIsDisabled()));
travel.setEmail(StrUtil.trim(travel.getEmail()));
travel.setOfficialWebsite(StrUtil.trim(travel.getOfficialWebsite()));
if (travel.getYear() == null || travel.getYear() < 1000 || travel.getYear() > 9999) {
return Result.error(row + "年度须填写4位整数");
}
if (StrUtil.isBlank(travel.getSerialNumber()) || StrUtil.isBlank(travel.getTravelAgencyName())
|| StrUtil.isBlank(travel.getContact()) || StrUtil.isBlank(travel.getContactMobileNumber())) {
return Result.error(row + "编号、旅行社名称、旅行社联系人和联系电话不能为空");
}
if (!List.of("是", "否").contains(travel.getSignUpTravelAgency() == null ? "" : travel.getSignUpTravelAgency())) {
return Result.error(row + "是否自由组团须填写是或否");
}
if (StrUtil.isBlank(travel.getIsDisabled())) travel.setIsDisabled("是");
if (!List.of("是", "否").contains(travel.getIsDisabled())) return Result.error(row + "是否启用须填写是或否");
if (!travel.getContactMobileNumber().matches("^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$")) {
return Result.error(row + "联系电话格式不正确");
}
if (travel.getSerialNumber().length() > 50 || travel.getTravelAgencyName().length() > 50
|| travel.getContact().length() > 10 || StrUtil.length(travel.getEmail()) > 50
|| StrUtil.length(travel.getOfficialWebsite()) > 100 || StrUtil.length(travel.getNote()) > 100) {
return Result.error(row + "字段长度超限:编号/名称/邮箱最多50字,联系人10字,官网/备注100字");
}
if (StrUtil.isNotBlank(travel.getEmail()) && !cn.hutool.core.lang.Validator.isEmail(travel.getEmail())) {
return Result.error(row + "邮箱格式不正确");
}
if (StrUtil.isNotBlank(travel.getOfficialWebsite()) && !cn.hutool.core.lang.Validator.isUrl(travel.getOfficialWebsite())) {
return Result.error(row + "官网须填写完整网址");
}
if (travel.getMaxUndertakeNumber() != null && travel.getMaxUndertakeNumber() < 0) {
return Result.error(row + "最多承担人数不能小于0");
}
Integer previousRow = importedNumbers.putIfAbsent(travel.getSerialNumber(), excelRowNumbers.get(index));
if (previousRow != null) return Result.error(row + "编号与第" + previousRow + "行重复");
List<TheRapyRecuperationTravelAgency> existing = dao.query(TheRapyRecuperationTravelAgency.class,
Cnd.where("serialNumber", "=", travel.getSerialNumber()));
if (existing.size() > 1) return Result.error(row + "数据库中该编号对应多条旅行社记录");
TheRapyRecuperationTravelAgency agency = existing.isEmpty() ? new TheRapyRecuperationTravelAgency() : existing.get(0);
agency.setDisabled("否".equals(travel.getIsDisabled()));
agency.setSignUpTravelAgency("是".equals(travel.getSignUpTravelAgency()));
agency.setContact(travel.getContact());
agency.setTravelAgencyName(travel.getTravelAgencyName());
agency.setSerialNumber(travel.getSerialNumber());
agency.setEmail(travel.getEmail());
agency.setMaxUndertakeNumber(travel.getMaxUndertakeNumber());
agency.setContactMobileNumber(travel.getContactMobileNumber());
agency.setNote(travel.getNote());
agency.setYear(travel.getYear());
agency.setOfficialWebsite(travel.getOfficialWebsite());
list.add(agency);
}
try {
if (excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getYear().toString())) || excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getTravelAgencyName()))) {
return Result.error("年度和旅行社名称不能为空");
}
List<TheRapyTravelAgencyExcelMode> travelAgency = ExcelImportUtil.importExcel(file.getFile(), TheRapyTravelAgencyExcelMode.class, new ImportParams());
List<TheRapyRecuperationTravelAgency> travelAgencyList = dao.query(TheRapyRecuperationTravelAgency.class, Cnd.NEW().desc("id"));
Map<String, String> map = travelAgencyList.stream().collect(Collectors.toMap(v -> v.getTravelAgencyName(), v -> v.getId()));
List<TheRapyRecuperationTravelAgency> list = new ArrayList<>();
for (TheRapyTravelAgencyExcelMode travel : travelAgency) {
TheRapyRecuperationTravelAgency agency = new TheRapyRecuperationTravelAgency();
if (Strings.isNotBlank(map.get(travel.getTravelAgencyName()))){
agency.setId(map.get(travel.getTravelAgencyName()));
}
if (travel.getIsDisabled().equals("是")) {
agency.setDisabled(false);
} else if (travel.getIsDisabled().equals("否")) {
agency.setDisabled(true);
}
agency.setContact(travel.getContact());
agency.setTravelAgencyName(travel.getTravelAgencyName());
agency.setSerialNumber(travel.getSerialNumber());
agency.setEmail(travel.getEmail());
agency.setMaxUndertakeNumber(travel.getMaxUndertakeNumber());
agency.setContactMobileNumber(travel.getContactMobileNumber());
agency.setNote(travel.getNote());
agency.setYear(travel.getYear());
agency.setOfficialWebsite(travel.getOfficialWebsite());
list.add(agency);
}
dao.insertOrUpdate(list);
Trans.exec(() -> dao.insertOrUpdate(list));
} catch (Exception e) {
log.error(e.getMessage());
log.error("导入旅行社失败", e);
return Result.error("导入旅行社失败");
}
return null;
return Result.success("成功导入" + list.size() + "条旅行社");
}
}
@@ -88,12 +88,12 @@ public class TheRapyRecuperationLineSelectionOverviewController {
@ViReturn
@SaCheckPermission("inclusiveTherapyV3.lineSelectionOverview")
public Object pageData(PageForm pageForm,
@Param(value = "year", required = false) Integer year,
@Param(value = "keywords", required = false) String keywords,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "lotId", required = false) String lotId,
@Param(value = "travelAgencyId", required = false) String travelAgencyId,
@Param(value = "regionalNature", required = false) String regionalNature) {
@Param(value = "year") Integer year,
@Param(value = "keywords") String keywords,
@Param(value = "unionId") String unionId,
@Param(value = "lotId") String lotId,
@Param(value = "travelAgencyId") String travelAgencyId,
@Param(value = "regionalNature") String regionalNature) {
Sql listSql = buildSelectionOverviewSql(pageForm, year, keywords, unionId, lotId, travelAgencyId, regionalNature);
Pagination pagination = lineUnionSelectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), listSql);
List<NutMap> rowList = pagination.getList();
@@ -136,12 +136,12 @@ public class TheRapyRecuperationLineSelectionOverviewController {
@Ok("void")
@SaCheckPermission("inclusiveTherapyV3.lineSelectionOverview")
public void doExportExcel(PageForm pageForm,
@Param(value = "year", required = false) Integer year,
@Param(value = "keywords", required = false) String keywords,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "lotId", required = false) String lotId,
@Param(value = "travelAgencyId", required = false) String travelAgencyId,
@Param(value = "regionalNature", required = false) String regionalNature,
@Param(value = "year") Integer year,
@Param(value = "keywords") String keywords,
@Param(value = "unionId") String unionId,
@Param(value = "lotId") String lotId,
@Param(value = "travelAgencyId") String travelAgencyId,
@Param(value = "regionalNature") String regionalNature,
HttpServletResponse response) throws IOException {
Sql listSql = buildSelectionOverviewSql(pageForm, year, keywords, unionId, lotId, travelAgencyId, regionalNature);
List<NutMap> list = queryMapList(listSql);
@@ -175,7 +175,7 @@ public class TheRapyRecuperationLineSelectionOverviewController {
@SaCheckPermission("inclusiveTherapyV3.lineSelectionOverview")
public Object timeSlots(@Param("lineId") String lineId,
@Param("unionId") String unionId,
@Param(value = "year", required = false) Integer year) {
@Param(value = "year") Integer year) {
Assert.notBlank(lineId, "请选择线路");
Assert.notBlank(unionId, "请选择分工会");
Sql sql = Sqls.create("""
@@ -255,7 +255,7 @@ public class TheRapyRecuperationLineSelectionOverviewController {
public Object saveTimeSlots(@Param("lineUnionSelects") TheRapyRecuperationLineUnionSelect[] lineUnionSelects,
@Param("lineId") String lineId,
@Param("unionId") String unionId,
@Param(value = "year", required = false) Integer year) {
@Param(value = "year") Integer year) {
Assert.notBlank(lineId, "请选择线路");
Assert.notBlank(unionId, "请选择分工会");
lineUnionSelectService.adminSaveLineTimes(lineUnionSelects, lineId, unionId, year);
@@ -277,7 +277,7 @@ public class TheRapyRecuperationLineSelectionOverviewController {
@Aop(TransAop.READ_COMMITTED)
public Object cancelLine(@Param("lineId") String lineId,
@Param("unionId") String unionId,
@Param(value = "year", required = false) Integer year) {
@Param(value = "year") Integer year) {
Assert.notBlank(lineId, "请选择线路");
Assert.notBlank(unionId, "请选择分工会");
Integer queryYear = year == null ? DateUtil.thisYear() : year;
@@ -336,7 +336,7 @@ public class TheRapyRecuperationLineSelectionOverviewController {
@At
@ViReturn
@SaCheckPermission("inclusiveTherapyV3.lineSelectionOverview")
public Object travelAgencyOptions(@Param(value = "year", required = false) Integer year) {
public Object travelAgencyOptions(@Param(value = "year") Integer year) {
// 旅行社按年度维护,管理员查看页切换年度时下拉框只展示该年度可选旅行社。
return dao.query(TheRapyRecuperationTravelAgency.class,
Cnd.where("year", "=", year == null ? DateUtil.thisYear() : year).asc("serialNumber"));
@@ -488,20 +488,20 @@ public class TheRapyRecuperationUserQueryController {
@Ok("void")
@ViReturn
@SaCheckLogin
public void doExportViewExcel(@Param(value = "regionalNature", required = false) String regionalNature,
@Param(value = "state", required = false) Integer state,
@Param(value = "searchName", required = false) String searchName,
@Param(value = "searchKeyword", required = false) String searchKeyword,
@Param(value = "startYear", required = false) Integer startYear,
@Param(value = "endYear", required = false) Integer endYear,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "takePartInLineId", required = false) String takePartInLineId,
@Param(value = "agencyId", required = false) String agencyId,
@Param(value = "lotId", required = false) String lotId,
@Param(value = "takePartInBaseManagementId", required = false) String takePartInBaseManagementId,
@Param(value = "signUpMode", required = false) String signUpMode,
@Param(value = "isTakePartIn", required = false) Integer isTakePartIn,
public void doExportViewExcel(@Param(value = "regionalNature") String regionalNature,
@Param(value = "state") Integer state,
@Param(value = "searchName") String searchName,
@Param(value = "searchKeyword") String searchKeyword,
@Param(value = "startYear") Integer startYear,
@Param(value = "endYear") Integer endYear,
@Param(value = "unionId") String unionId,
@Param(value = "unitId") String unitId,
@Param(value = "takePartInLineId") String takePartInLineId,
@Param(value = "agencyId") String agencyId,
@Param(value = "lotId") String lotId,
@Param(value = "takePartInBaseManagementId") String takePartInBaseManagementId,
@Param(value = "signUpMode") String signUpMode,
@Param(value = "isTakePartIn") Integer isTakePartIn,
HttpServletResponse response) throws IOException {
Cnd cnd = Cnd.NEW();
@@ -720,21 +720,21 @@ public class TheRapyRecuperationUserQueryController {
@Ok("void")
@ViReturn
@SaCheckLogin
public void doExportExcel(@Param(value = "regionalNature", required = false) String regionalNature,
@Param(value = "state", required = false) Integer state,
@Param(value = "searchName", required = false) String searchName,
@Param(value = "searchKeyword", required = false) String searchKeyword,
@Param(value = "startYear", required = false) Integer startYear,
@Param(value = "endYear", required = false) Integer endYear,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "takePartInLineId", required = false) String takePartInLineId,
@Param(value = "agencyId", required = false) String agencyId,
@Param(value = "lotId", required = false) String lotId,
@Param(value = "takePartInBaseManagementId", required = false) String takePartInBaseManagementId,
@Param(value = "signUpMode", required = false) String signUpMode,
@Param(value = "types", required = false) String[] types,
@Param(value = "satisfyPeople", required = false) Boolean satisfyPeople,
public void doExportExcel(@Param(value = "regionalNature") String regionalNature,
@Param(value = "state") Integer state,
@Param(value = "searchName") String searchName,
@Param(value = "searchKeyword") String searchKeyword,
@Param(value = "startYear") Integer startYear,
@Param(value = "endYear") Integer endYear,
@Param(value = "unionId") String unionId,
@Param(value = "unitId") String unitId,
@Param(value = "takePartInLineId") String takePartInLineId,
@Param(value = "agencyId") String agencyId,
@Param(value = "lotId") String lotId,
@Param(value = "takePartInBaseManagementId") String takePartInBaseManagementId,
@Param(value = "signUpMode") String signUpMode,
@Param(value = "types") String[] types,
@Param(value = "satisfyPeople") Boolean satisfyPeople,
HttpServletResponse response) throws IOException {
Cnd commonCnd = Cnd.NEW();
@@ -891,22 +891,22 @@ public class TheRapyRecuperationUserQueryController {
@Ok("void")
@ViReturn
@SaCheckLogin
public void doExport(@Param(value = "regionalNature", required = false) String regionalNature,
@Param(value = "state", required = false) Integer state,
@Param(value = "searchName", required = false) String searchName,
@Param(value = "searchKeyword", required = false) String searchKeyword,
@Param(value = "startYear", required = false) Integer startYear,
@Param(value = "endYear", required = false) Integer endYear,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "takePartInLineId", required = false) String takePartInLineId,
@Param(value = "agencyId", required = false) String agencyId,
@Param(value = "lotId", required = false) String lotId,
@Param(value = "takePartInBaseManagementId", required = false) String takePartInBaseManagementId,
@Param(value = "signUpMode", required = false) String signUpMode,
@Param(value = "isTakePartIn", required = false) Integer isTakePartIn,
@Param(value = "types", required = false) String[] types,
@Param(value = "satisfyPeople", required = false) Boolean satisfyPeople,
public void doExport(@Param(value = "regionalNature") String regionalNature,
@Param(value = "state") Integer state,
@Param(value = "searchName") String searchName,
@Param(value = "searchKeyword") String searchKeyword,
@Param(value = "startYear") Integer startYear,
@Param(value = "endYear") Integer endYear,
@Param(value = "unionId") String unionId,
@Param(value = "unitId") String unitId,
@Param(value = "takePartInLineId") String takePartInLineId,
@Param(value = "agencyId") String agencyId,
@Param(value = "lotId") String lotId,
@Param(value = "takePartInBaseManagementId") String takePartInBaseManagementId,
@Param(value = "signUpMode") String signUpMode,
@Param(value = "isTakePartIn") Integer isTakePartIn,
@Param(value = "types") String[] types,
@Param(value = "satisfyPeople") Boolean satisfyPeople,
HttpServletResponse response) throws IOException {
response.setContentType("application/octet-stream");
@@ -86,7 +86,7 @@ public class TheRapyRecuperationLineStatisticsController {
@At("/unionLineNumberStatistics/pageData")
@ViReturn
@SaCheckPermission("inclusiveTherapyV3.unionLineNumberStatistics")
public Object unionLineNumberStatisticsPageData(@Param(value = "unionId", required = false) String unionId) {
public Object unionLineNumberStatisticsPageData(@Param(value = "unionId") String unionId) {
TheRapyRecuperationConfig config = dao.fetch(TheRapyRecuperationConfig.class, Cnd.NEW());
List<NutMap> lineNumberConfigs = Optional.ofNullable(config)
.map(TheRapyRecuperationConfig::getUnionLineNumberConfigs)
@@ -177,16 +177,16 @@ public class TheRapyRecuperationLineStatisticsController {
@ViReturn
@SaCheckPermission("inclusiveTherapyV3.statistics")
public Object pageData(PageForm pageForm,
@Param(value = "startYear", required = false) Integer startYear,
@Param(value = "endYear", required = false) Integer endYear,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "startYear") Integer startYear,
@Param(value = "endYear") Integer endYear,
@Param(value = "unionId") String unionId,
@Param("takePartInLineId") String takePartInLineId,
@Param(value = "lotId", required = false) String lotId,
@Param(value = "signUpMode", required = false) String signUpMode,
@Param(value = "selectId", required = false) String selectId,
@Param(value = "playMonth", required = false) String playMonth,
@Param(value = "regionalNature", required = false) String regionalNature,
@Param(value = "travelAgencyId", required = false) String travelAgencyId) {
@Param(value = "lotId") String lotId,
@Param(value = "signUpMode") String signUpMode,
@Param(value = "selectId") String selectId,
@Param(value = "playMonth") String playMonth,
@Param(value = "regionalNature") String regionalNature,
@Param(value = "travelAgencyId") String travelAgencyId) {
Sql sql = Sqls.create("""
SELECT
line.id,
@@ -317,10 +317,10 @@ public class TheRapyRecuperationLineStatisticsController {
@ViReturn
@SaCheckPermission("inclusiveTherapyV3.statistics")
public Object getUserDateByLine(PageForm pageForm,
@Param(value = "takePartLineId", required = false) String takePartLineId,
@Param(value = "searchKeyword", required = false) String searchKeyword,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "unitId", required = false) String unitId) {
@Param(value = "takePartLineId") String takePartLineId,
@Param(value = "searchKeyword") String searchKeyword,
@Param(value = "unionId") String unionId,
@Param(value = "unitId") String unitId) {
Sql sql = Sqls.create("""
SELECT
enroll.*,
@@ -52,7 +52,7 @@ public class TheRapyRecuperationTravelAgencyMonthlyStatisticsController {
@At("/getChartData")
@ViReturn
@SaCheckPermission("inclusiveTherapyV3.travelAgencyMonthlyStatistics")
public Object getChartData(@Param(value = "year", required = false) Integer year) {
public Object getChartData(@Param(value = "year") Integer year) {
Integer queryYear = year == null ? DateUtil.thisYear() : year;
return enrollService.getTravelAgencyMonthlyEnrollStatistics(queryYear);
}
@@ -68,7 +68,7 @@ public class TheRapyRecuperationTravelAgencyMonthlyStatisticsController {
@At("/getUnionChartData")
@ViReturn
@SaCheckPermission("inclusiveTherapyV3.travelAgencyMonthlyStatistics")
public Object getUnionChartData(@Param(value = "year", required = false) Integer year) {
public Object getUnionChartData(@Param(value = "year") Integer year) {
Integer queryYear = year == null ? DateUtil.thisYear() : year;
List<UnionEnrollStatisticsVo> list = enrollService.getUnionEnrollStatistics(queryYear);
return list;
@@ -85,7 +85,7 @@ public class TheRapyRecuperationTravelAgencyMonthlyStatisticsController {
@At("/doExportExcel")
@Ok("void")
@SaCheckPermission("inclusiveTherapyV3.travelAgencyMonthlyStatistics")
public void doExportExcel(@Param(value = "year", required = false) Integer year,
public void doExportExcel(@Param(value = "year") Integer year,
HttpServletResponse response) throws IOException {
Integer queryYear = year == null ? DateUtil.thisYear() : year;
NutMap exportData = enrollService.getTravelAgencyMonthlyEnrollExportData(queryYear);
@@ -113,7 +113,7 @@ public class TheRapyRecuperationTravelAgencyMonthlyStatisticsController {
@At("/doExportUnionExcel")
@Ok("void")
@SaCheckPermission("inclusiveTherapyV3.travelAgencyMonthlyStatistics")
public void doExportUnionExcel(@Param(value = "year", required = false) Integer year,
public void doExportUnionExcel(@Param(value = "year") Integer year,
HttpServletResponse response) throws IOException {
Integer queryYear = year == null ? DateUtil.thisYear() : year;
NutMap exportData = enrollService.getUnionEnrollExportData(queryYear);
@@ -62,7 +62,13 @@ public class TheRapyRecuperationConfigController {
@ViReturn
@SaCheckLogin
@Aop(TransAop.READ_COMMITTED)
public Object operation(TheRapyRecuperationConfig config, String[] lotDeleteList, String unionLineNumberConfigs) {
public Object operation(TheRapyRecuperationConfig config, String[] lotDeleteList, String unionLineNumberConfigs, String lots) {
if (Strings.isNotBlank(lots)) {
config.setLots(Json.fromJsonAsList(TheRapyRecuperationLot.class, lots));
}
if (config.getLots() == null) {
config.setLots(new ArrayList<>());
}
// unionLineNumberConfigs 为前端分工会线路数量配置 JSON 数组,返回保存后的配置对象仍由 findOne 接口按实体结构回显。
config.setUnionLineNumberConfigs(Strings.isBlank(unionLineNumberConfigs)
? new ArrayList<>()
@@ -76,7 +82,9 @@ public class TheRapyRecuperationConfigController {
for (TheRapyRecuperationLot obj : collect) {
obj.setConfigId(config.getId());
}
dao.insert(collect);
if (!collect.isEmpty()) {
dao.insert(collect);
}
} else {
dao.insertWith(config, "lots");
}
@@ -24,6 +24,9 @@ public class TheRapyLineImportExcelMode {
@Excel(name = "线路类型")
private String regionalNature;
@Excel(name = "旅行社名称")
private String travelAgencyName;
@Excel(name = "交通工具")
private String trafficTools;
@@ -33,6 +36,9 @@ public class TheRapyLineImportExcelMode {
@Excel(name = "预计费用(元/人次)")
private String estimatedCost;
@Excel(name = "家属报名")
private String familySignUp;
@Excel(name = "组织形式")
private String signUpMode;
@@ -16,6 +16,9 @@ public class TheRapyTravelAgencyExcelMode {
@Excel(name = "旅行社名称")
private String travelAgencyName;
@Excel(name = "是否自由组团(是/否)")
private String signUpTravelAgency;
@Excel(name = "旅行社联系人")
private String contact;
@@ -1790,7 +1790,7 @@ public class TheRapyRecuperationEnrollServiceImpl extends TherapyServiceImpl<The
cnd.and("loginName", "=", loginName);
cnd.and("isNormal", "=", true);
cnd.and("stateId", "not in", Lang.array(TheRapyRecuperationState.UNITFAIL, TheRapyRecuperationState.LINEUNITFAIL, TheRapyRecuperationState.SCHOOLFAIL));
cnd.and("YEAR(signingUptime)", "=", com.budwk.app.base.utils.DateUtil.thisYear());
cnd.and("YEAR(signingUptime)", "=", DateUtil.thisYear());
int joinCount = dao().count(TheRapyRecuperationEnroll.class, cnd);
if (joinCount >= travelFrequency) {
@@ -1803,27 +1803,27 @@ public class TheRapyRecuperationEnrollServiceImpl extends TherapyServiceImpl<The
.and("takePartInLineId", "in", unionInSelects.stream().map(TheRapyRecuperationLineUnionSelect::getId).collect(Collectors.toList()))
.and("isNormal", "=", true)
.and("stateId", "not in", Lang.array(TheRapyRecuperationState.UNITFAIL, TheRapyRecuperationState.LINEUNITFAIL, TheRapyRecuperationState.SCHOOLFAIL))
.and("YEAR(signingUptime)", "=", com.budwk.app.base.utils.DateUtil.thisYear()));
.and("YEAR(signingUptime)", "=", DateUtil.thisYear()));
//是否报省外
int outCount = dao().count("inclusive_therapy_v3_enroll", Cnd.where("loginName", "=", loginName)
.and("takePartInLineId", "in", unionOutSelects.stream().map(TheRapyRecuperationLineUnionSelect::getId).collect(Collectors.toList()))
.and("isNormal", "=", true)
.and("stateId", "not in", Lang.array(TheRapyRecuperationState.UNITFAIL, TheRapyRecuperationState.LINEUNITFAIL, TheRapyRecuperationState.SCHOOLFAIL))
.and("YEAR(signingUptime)", "=", com.budwk.app.base.utils.DateUtil.thisYear()));
.and("YEAR(signingUptime)", "=", DateUtil.thisYear()));
//是否报旅行社
int travelCount = dao().count("inclusive_therapy_v3_enroll", Cnd.where("loginName", "=", loginName)
.and(Cnd.exps("takePartInLineId", "is", null).or("takePartInLineId", "=", ""))
.and("isNormal", "=", true)
.and("stateId", "not in", Lang.array(TheRapyRecuperationState.UNITFAIL, TheRapyRecuperationState.LINEUNITFAIL, TheRapyRecuperationState.SCHOOLFAIL))
.and("takePartInTravelAgencyId", "is not", null)
.and("YEAR(signingUptime)", "=", com.budwk.app.base.utils.DateUtil.thisYear()));
.and("YEAR(signingUptime)", "=", DateUtil.thisYear()));
//是否报酒店
int hotelCount = dao().count("inclusive_therapy_v3_enroll", Cnd.where("loginName", "=", loginName)
.and("takePartInLineId", "is", null)
.and("isNormal", "=", true)
.and("stateId", "not in", Lang.array(TheRapyRecuperationState.UNITFAIL, TheRapyRecuperationState.LINEUNITFAIL, TheRapyRecuperationState.SCHOOLFAIL))
.and("takePartInBaseManagementId", "is not", null)
.and("YEAR(signingUptime)", "=", com.budwk.app.base.utils.DateUtil.thisYear()));
.and("YEAR(signingUptime)", "=", DateUtil.thisYear()));
String str = "";
if (inCount > 0) {
str = "省内线路";
@@ -1855,8 +1855,8 @@ public class TheRapyRecuperationEnrollServiceImpl extends TherapyServiceImpl<The
lineCnd.and("loginName", "=", loginName);
lineCnd.and("isNormal", "=", true);
lineCnd.and("takePartInLineId", "IS NOT", null);
lineCnd.and("YEAR ( signingUptime )", ">=", com.budwk.app.base.utils.DateUtil.thisYear() - outsideNumber);
lineCnd.and("YEAR ( signingUptime )", "<=", com.budwk.app.base.utils.DateUtil.thisYear() - 1);
lineCnd.and("YEAR ( signingUptime )", ">=", DateUtil.thisYear() - outsideNumber);
lineCnd.and("YEAR ( signingUptime )", "<=", DateUtil.thisYear() - 1);
lineCnd.and("regionalNature", "=", TheRapyRecuperationType.provinceOutLine.getValue());
lineJoinSql.setCondition(lineCnd);
@@ -16,6 +16,7 @@ import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.model.TheRapyRecupera
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.model.TheRapyRecuperationLine;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.model.TheRapyRecuperationLineUnionSelect;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.model.TheRapyRecuperationLot;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.model.TheRapyRecuperationTravelAgency;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.service.TheRapyRecuperationLineService;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
@@ -229,6 +230,8 @@ public class TheRapyRecuperationLineServiceImpl extends TherapyServiceImpl<TheRa
&& StrUtil.isBlank(mode.getLineContactPhone())
&& StrUtil.isBlank(mode.getContent())
&& StrUtil.isBlank(mode.getIsEnabled())
&& StrUtil.isBlank(mode.getTravelAgencyName())
&& StrUtil.isBlank(mode.getFamilySignUp())
&& StrUtil.isBlank(mode.getFiles()));
}
@@ -239,6 +242,12 @@ public class TheRapyRecuperationLineServiceImpl extends TherapyServiceImpl<TheRa
* @param rowNumber Excel行号
*/
private void validImportRequired(TheRapyLineImportExcelMode mode, int rowNumber) {
if (StrUtil.isBlank(mode.getTravelAgencyName())) {
throw new IllegalArgumentException("第" + rowNumber + "行旅行社名称不能为空");
}
if (!StrUtil.equalsAny(StrUtil.trim(mode.getFamilySignUp()), "是", "否")) {
throw new IllegalArgumentException("第" + rowNumber + "行家属报名必填,请填写是或否");
}
if (mode.getYear() == null) {
throw new IllegalArgumentException("第" + rowNumber + "行年度不能为空");
}
@@ -268,7 +277,17 @@ public class TheRapyRecuperationLineServiceImpl extends TherapyServiceImpl<TheRa
* @return 线路实体
*/
private TheRapyRecuperationLine buildLineByImportMode(TheRapyLineImportExcelMode mode, TheRapyLineImportImageMode imageMode, int rowNumber) {
List<TheRapyRecuperationTravelAgency> agencies = dao().query(TheRapyRecuperationTravelAgency.class,
Cnd.where("year", "=", mode.getYear()).and("travelAgencyName", "=", StrUtil.trim(mode.getTravelAgencyName())));
if (agencies.isEmpty()) {
throw new IllegalArgumentException("第" + rowNumber + "行旅行社名称在该年度不存在");
}
if (agencies.size() > 1) {
throw new IllegalArgumentException("第" + rowNumber + "行旅行社名称在该年度存在重名,无法确定旅行社");
}
TheRapyRecuperationLine line = new TheRapyRecuperationLine();
line.setTravelAgencyId(agencies.get(0).getId());
line.setIsFamilySignUp("是".equals(StrUtil.trim(mode.getFamilySignUp())));
line.setYear(mode.getYear());
line.setSerialNumber(mode.getSerialNumber());
line.setLineName(mode.getLineName());
@@ -71,7 +71,7 @@ public class TheRapyRecuperationLineUnionSelectServiceImpl extends TherapyServic
us.playEndTime,
us.changeEndTime,
us.isOpen,
us.signUpMode,
IFNULL(us.signUpMode, line.signUpMode) AS signUpMode,
line.createMode,
gh.unionname AS createUnionName,
u.username AS createUserName,
@@ -1,6 +1,7 @@
package com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support;
import cn.dev33.satoken.stp.StpUtil;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -12,6 +13,15 @@ import java.util.Collection;
@IocBean
public class TherapyContext {
public static boolean isEmbeddedPage() {
return "1".equals(Mvcs.getReq().getParameter("therapyEmbedded"));
}
public static String getEmbeddedPageUrl() {
String query = Mvcs.getReq().getQueryString();
return Mvcs.getReq().getRequestURI() + (Strings.isBlank(query) ? "?" : "?" + query + "&") + "therapyEmbedded=1";
}
public static String getUserId() {
return SecurityUtil.getUserId();
}
@@ -20,6 +30,10 @@ public class TherapyContext {
return getUserId();
}
public static String getPlatformLoginname() {
return SecurityUtil.getUserLoginname();
}
public static String getUnionId() {
String unionId = SecurityUtil.getUnionId();
if (Strings.isNotBlank(unionId)) return unionId;
@@ -57,7 +71,8 @@ public class TherapyContext {
}
public static String getRoleCodesJson() {
java.util.List<String> roles = new java.util.ArrayList<>(StpUtil.getRoleList());
SysUserService userService = Mvcs.getIoc().get(SysUserService.class, "sysUserServiceImpl");
java.util.List<String> roles = new java.util.ArrayList<>(userService.getRoleCodeList(userService.fetch(getUserId())));
for (String role : Arrays.asList("sysadmin", "A06", "H03", "H04", "H06", "SchoolUnionMemberAdmin")) {
if (hasRole(role) && !roles.contains(role)) roles.add(role);
}
@@ -29,7 +29,7 @@ public class TherapyEmail {
String user = setting("user");
String password = setting("password");
if (host == null || from == null || user == null || password == null) {
throw new IllegalStateException("普惠疗休养V3邮件发送配置不完整");
throw new IllegalStateException("普惠疗休养邮件发送配置不完整");
}
String portSetting = setting("port");
int port = portSetting == null ? 465 : Integer.parseInt(portSetting);
+2 -2
View File
@@ -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
+1
View File
@@ -13,6 +13,7 @@
port: 6379
database: 4
mode: normal
password: dd3s@Redis#2026
jdbc:
url: jdbc:mysql://127.0.0.1:3306/zhgh_zjnu_v4?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
@@ -0,0 +1,58 @@
-- 1. 将现有“社团统计”移到新父级下面,保留原权限和角色关联。
UPDATE sys_menu
SET parentId = 'f2b61f72eab34e139bc150a2d907c385',
path = '001100060001',
updatedAt = UNIX_TIMESTAMP(NOW()) * 1000,
permission = 'club.statistics.group'
WHERE id = 'b8817cce3ae34d49844a7ea8d8b15f3f'
AND permission = 'club.statistics';
-- 2. 新增“社团统计”父级菜单。
INSERT INTO sys_menu (
id, parentId, path, name, aliasName, type, href, target,
icon, showit, disabled, permission, location, hasChildren,
createdBy, createdAt, updatedBy, updatedAt, delFlag,
platform, moduleId, initialPinyinName, isRecommendApp, isRecommendService
) VALUES (
'f2b61f72eab34e139bc150a2d907c385',
'',
'00110006',
'社团统计', '', 'menu',
'', '',
'', 1, 0, 'club.statistics', 411, 1,
'', UNIX_TIMESTAMP(NOW()) * 1000,
'', UNIX_TIMESTAMP(NOW()) * 1000, 0,
'PC', '4cfc8977507c40b3acee8443c7c5a8a3', 's', 0, 0
);
-- 3. 新增“成员统计”子菜单。
INSERT INTO sys_menu (
id, parentId, path, name, aliasName, type, href, target,
icon, showit, disabled, permission, location, hasChildren,
createdBy, createdAt, updatedBy, updatedAt, delFlag,
platform, moduleId, initialPinyinName, isRecommendApp, isRecommendService
) VALUES (
'a914ce82f0764e9c8f1b35a6d2270b41',
'f2b61f72eab34e139bc150a2d907c385',
'001100060002',
'成员统计', '', 'menu',
'/platform/club/statistics/member', 'data-pjax',
'', 1, 0, 'club.statistics.member', 412, 0,
'', UNIX_TIMESTAMP(NOW()) * 1000,
'', UNIX_TIMESTAMP(NOW()) * 1000, 0,
'PC', '4cfc8977507c40b3acee8443c7c5a8a3', 'c', 0, 0
);
-- 成员统计可查询所有社团,仅给系统管理员和校工会管理员授权。
-- 社团统计父级
INSERT INTO sys_role_menu (roleId, menuId) VALUES
('419844ad90f34ca58807e84224905f27', 'f2b61f72eab34e139bc150a2d907c385'),
('6aece46b946e4fb9ac4cb15c0cd8c3e6', 'f2b61f72eab34e139bc150a2d907c385'),
('722d454171ac49f1bba60b7672e500ff', 'f2b61f72eab34e139bc150a2d907c385'),
('72e17abb91cb48b4820474904e189182', 'f2b61f72eab34e139bc150a2d907c385'),
('7f4a820d5a394bb8a0a92d6699afe7c8', 'f2b61f72eab34e139bc150a2d907c385');
-- 成员统计
INSERT INTO sys_role_menu (roleId, menuId) VALUES
('722d454171ac49f1bba60b7672e500ff', 'a914ce82f0764e9c8f1b35a6d2270b41'),
('7f4a820d5a394bb8a0a92d6699afe7c8', 'a914ce82f0764e9c8f1b35a6d2270b41');
@@ -8,6 +8,7 @@
"""
import argparse
from datetime import datetime
import getpass
import hashlib
import json
@@ -17,6 +18,7 @@ import re
import subprocess
import sys
import tempfile
import time
from urllib.parse import unquote, urlsplit
import zipfile
@@ -31,6 +33,11 @@ SUFFIXES = (
AUDIT_FIELDS = ("selfUnionAuditId", "joinLineUnionAuditId", "schoolUnionAuditId")
def log(message, error=False):
print("[%s] %s" % (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message),
file=sys.stderr if error else sys.stdout, flush=True)
def identifier(value):
if not re.fullmatch(r"[A-Za-z0-9_]+", value):
raise ValueError("数据库标识符只允许英文字母、数字、下划线")
@@ -148,6 +155,8 @@ def main():
output = args.output.resolve()
if output.exists():
raise ValueError("导出文件已存在,不覆盖:" + str(output))
log("开始导出普惠疗休养;源数据库:" + args.database)
log("[1/4] 连接数据库并检查源表结构")
client = MySQL(args)
tables = {suffix: "the_rapy_recuperation_" + suffix for suffix in SUFFIXES}
schemas = client.schema(list(tables.values()) + [args.audit_table, "activity_user_scope",
@@ -192,24 +201,40 @@ def main():
archive = zipfile.ZipFile(output, "x", compression=zipfile.ZIP_DEFLATED, allowZip64=True)
finished = False
try:
log("[2/4] 从一致性快照读取数据并写入导出包")
current_label = None
total_records = 0
with archive.open("data.jsonl", "w", force_zip64=True) as data:
for line in client.lines(sql):
record = json.loads(line)
record["row"] = decode_row(record)
if record["table"] != current_label:
if current_label is not None:
log("数据类别 %s 已导出 %s 条" % (current_label, counts[current_label]))
current_label = record["table"]
log("正在导出数据类别:" + current_label)
counts[record["table"]] += 1
if record["table"] == "_file":
file_rows.append(record["row"])
encoded = (json.dumps(record, ensure_ascii=False, separators=(",", ":")) + "\n").encode("utf-8")
digest.update(encoded)
data.write(encoded)
total_records += 1
if total_records % 1000 == 0:
log("已写入 %s 条记录" % total_records)
if current_label is not None:
log("数据类别 %s 已导出 %s 条" % (current_label, counts[current_label]))
log("数据库读取完成,共 %s 条记录" % total_records)
log("[3/4] 打包实际附件并计算 SHA-256,共 %s 个" % len(file_rows))
assets = {}
if file_rows and args.files_root is None:
raise ValueError("数据包含附件,必须提供 --files-root,不能只导出文件地址")
storage = args.files_root.resolve() if args.files_root else None
for row in file_rows:
for index, row in enumerate(file_rows, 1):
old_id, old_path = get(row, "id"), get(row, "filepath")
if not old_id or not old_path:
raise ValueError("关联附件记录缺少 ID 或存储路径")
log("附件 [%s/%s] 开始打包,文件ID:%s" % (index, len(file_rows), old_id))
relative = unquote(urlsplit(old_path.replace("\\", "/")).path).lstrip("/")
source = (storage / relative).resolve()
if not source.is_relative_to(storage) or not source.is_file():
@@ -223,6 +248,10 @@ def main():
size += len(chunk)
writer.write(chunk)
assets[old_id] = {"member": member, "sha256": file_hash.hexdigest(), "size": size}
log("附件 [%s/%s] 打包完成(%s 字节),SHA-256 已记录" % (index, len(file_rows), size))
if not file_rows:
log("没有关联附件,跳过附件打包")
log("[4/4] 写入清单并关闭导出包")
manifest = {"format": FORMAT, "source_database": args.database, "source_prefix": "the_rapy_recuperation_",
"target_prefix": PREFIX, "counts": counts, "data_sha256": digest.hexdigest(), "files": assets}
archive.writestr("manifest.json", json.dumps(manifest, ensure_ascii=False, indent=2).encode("utf-8"))
@@ -231,14 +260,20 @@ def main():
archive.close()
if not finished:
output.unlink()
print("导出完成:" + str(output))
print("业务记录:%s;审核记录:%s;附件:%s" %
(sum(counts.get(name, 0) for name in SUFFIXES), counts.get("_audit", 0), len(file_rows)))
log("导出完成:" + str(output))
log("业务记录:%s;审核记录:%s;附件:%s" %
(sum(counts.get(name, 0) for name in SUFFIXES), counts.get("_audit", 0), len(file_rows)))
if __name__ == "__main__":
started = time.monotonic()
try:
main()
log("【成功结束】导出成功,总耗时 %.1f 秒,退出码 0" % (time.monotonic() - started))
except KeyboardInterrupt:
log("【中断结束】用户中断导出,总耗时 %.1f 秒,退出码 130" % (time.monotonic() - started), error=True)
sys.exit(130)
except (OSError, ValueError, RuntimeError, KeyError) as error:
print("导出失败:" + str(error), file=sys.stderr)
log("导出失败:" + str(error), error=True)
log("【失败结束】导出未成功,总耗时 %.1f 秒,退出码 1" % (time.monotonic() - started), error=True)
sys.exit(1)
@@ -2,23 +2,34 @@
两个 Python 脚本应放在同一目录;使用 Python 3.9+ 标准库及已有 mysql 客户端。
参数:--database v4目标库 --input 导出.zip --login-path 连接名。
有附件时 --target-files-dir 必须是 v4 服务器可直接访问的本地/共享存储目录。
有附件时通过 MinIO S3 API 上传,不复制到本地目录或 MinIO 底层存储目录。
--minio-endpoint、--minio-bucket、--minio-access-key 分别对应 v4 的 MinIO 端点、桶和访问密钥。
也可使用 MINIO_ENDPOINT、MINIO_BUCKET、MINIO_ACCESS_KEY 环境变量;MINIO_SECRET_KEY 未设置时交互输入。
自定义区域使用 --minio-region / MINIO_REGION;临时凭证可设置 MINIO_SESSION_TOKEN。
先使用本目录初始化 SQL 直接创建 inclusive_therapy_v3_* 表及菜单。
仅支持首次导入:目标子模块必须为空,或仅包含未使用的自动生成默认配置。
可用 --mapping 提供 JSON:{"user":{"旧ID":"新ID"},"unit":{},"union":{}}。
不覆盖 v4 原有疗休养、人员、组织或附件;导入期间不要向目标库写入业务数据。
失败时数据库事务回滚;已复制的附件保留在独立目录,避免提交状态不明时误删文件。
附件逐个上传并回读校验后才写入数据库;失败时保留独立对象前缀,避免提交状态不明时误删附件。
"""
import argparse
from collections import defaultdict
from datetime import datetime, timezone
import getpass
import hashlib
import hmac
import http.client
import json
import mimetypes
import os
from pathlib import Path
import re
import sys
import tempfile
import time
import uuid
from urllib.parse import parse_qs, unquote, urlsplit
from urllib.parse import parse_qs, quote, unquote, urlsplit
import zipfile
from export_inclusive_therapy_v3 import (
@@ -27,6 +38,11 @@ from export_inclusive_therapy_v3 import (
)
def log(message, error=False):
print("[%s] %s" % (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message),
file=sys.stderr if error else sys.stdout, flush=True)
def rows(client, table, columns):
from export_inclusive_therapy_v3 import row_query, decode_row
return [decode_row(json.loads(line)) for line in client.lines(row_query(table, table, columns))]
@@ -129,7 +145,7 @@ class IdentityMap:
def default_config(row):
permitted = {"id": None, "configName": {"智慧工会疗休养配置", "普惠疗休养V3配置"},
permitted = {"id": None, "configName": {"智慧工会疗休养配置", "普惠疗休养配置"},
"isSnLine": {"0"}, "isSwLine": {"0"}, "travelAudit": {"0"}, "bedInfo": {"1"},
"familyInfo": {"1"}, "outsideQuotaProportion": {"0", "0.00", "0.0"},
"unionLineNumberConfigs": {"[]"}, "lots": {"[]"}}
@@ -142,18 +158,129 @@ def default_config(row):
return True
class MinIO:
"""使用标准库签名并调用 S3 API,不依赖额外 Python 包。
签名格式:https://docs.aws.amazon.com/AmazonS3/latest/developerguide/sig-v4-header-based-auth.html
"""
def __init__(self, args):
if not args.minio_endpoint or not args.minio_bucket or not args.minio_access_key:
raise ValueError("有附件时必须提供与 v4 一致的 MinIO 端点、桶和访问密钥")
self.endpoint = urlsplit(args.minio_endpoint)
if (self.endpoint.scheme not in ("http", "https") or not self.endpoint.hostname
or self.endpoint.username or self.endpoint.password or self.endpoint.query or self.endpoint.fragment):
raise ValueError("MinIO 端点必须是 http/https S3 API 地址,不能包含账号、查询参数或片段")
self.port = self.endpoint.port
self.bucket = args.minio_bucket
self.access_key = args.minio_access_key
self.region = args.minio_region
self.session_token = os.environ.get("MINIO_SESSION_TOKEN")
self.secret_key = os.environ.get("MINIO_SECRET_KEY") or getpass.getpass("MinIO secret key: ")
if not self.secret_key or not self.region or "/" in self.bucket:
raise ValueError("MinIO 桶、区域或密钥配置不正确")
for value in (self.bucket, self.access_key, self.region, self.session_token or ""):
if re.search(r"[\x00-\x20\x7f]", value):
raise ValueError("MinIO 连接参数包含不合法的空白或控制字符")
def request(self, method, key=None, body=None, size=0, digest=None, content_type=None):
uri = self.endpoint.path.rstrip("/") + "/" + quote(self.bucket, safe="-_.~")
if key is not None:
uri += "/" + quote(key, safe="/-_.~")
# 对 URI 只编码对象名,不改变对象路径;不自动跟随重定向转发凭证。
now = datetime.now(timezone.utc)
timestamp, date = now.strftime("%Y%m%dT%H%M%SZ"), now.strftime("%Y%m%d")
payload_hash = digest if digest is not None else hashlib.sha256(b"").hexdigest()
headers = {"host": self.endpoint.netloc, "x-amz-date": timestamp,
"x-amz-content-sha256": payload_hash}
if self.session_token:
headers["x-amz-security-token"] = self.session_token
if method == "PUT":
headers.update({"content-length": str(size), "content-type": content_type,
"x-amz-meta-sha256": payload_hash, "if-none-match": "*"})
signed_headers = ";".join(sorted(headers))
canonical_headers = "".join(name + ":" + headers[name].strip() + "\n" for name in sorted(headers))
canonical_request = "\n".join((method, uri, "", canonical_headers, signed_headers, payload_hash))
scope = date + "/" + self.region + "/s3/aws4_request"
string_to_sign = "\n".join(("AWS4-HMAC-SHA256", timestamp, scope,
hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()))
signing_key = ("AWS4" + self.secret_key).encode("utf-8")
for value in (date, self.region, "s3", "aws4_request"):
signing_key = hmac.new(signing_key, value.encode("utf-8"), hashlib.sha256).digest()
signature = hmac.new(signing_key, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
headers["authorization"] = ("AWS4-HMAC-SHA256 Credential=" + self.access_key + "/" + scope +
", SignedHeaders=" + signed_headers + ", Signature=" + signature)
connection_type = http.client.HTTPSConnection if self.endpoint.scheme == "https" else http.client.HTTPConnection
connection = connection_type(self.endpoint.hostname, self.port, timeout=120)
try:
connection.request(method, uri, body=body, headers=headers)
response = connection.getresponse()
if not 200 <= response.status < 300:
status = response.status
response.close()
raise RuntimeError("MinIO %s 请求失败(HTTP %s),数据库尚未写入" % (method, status))
return connection, response
except (OSError, http.client.HTTPException) as error:
connection.close()
raise RuntimeError("MinIO 网络请求失败,数据库尚未写入") from error
except BaseException:
connection.close()
raise
def check_bucket(self):
connection, response = self.request("HEAD")
try:
response.read()
finally:
response.close()
connection.close()
def upload_and_verify(self, key, body, size, digest, content_type):
connection, response = self.request("PUT", key, body, size, digest, content_type)
try:
response.read()
except (OSError, http.client.HTTPException) as error:
raise RuntimeError("MinIO 上传响应读取失败,数据库尚未写入") from error
finally:
response.close()
connection.close()
connection, response = self.request("GET", key)
try:
actual_hash, actual_size = hashlib.sha256(), 0
for chunk in iter(lambda: response.read(1024 * 1024), b""):
actual_size += len(chunk)
actual_hash.update(chunk)
if actual_size > size:
raise RuntimeError("MinIO 回读对象的文件大小与导出附件不一致")
if actual_size != size or actual_hash.hexdigest() != digest:
raise RuntimeError("MinIO 回读对象的大小或 SHA-256 与导出附件不一致")
except (OSError, http.client.HTTPException) as error:
raise RuntimeError("MinIO 对象回读失败,数据库尚未写入") from error
finally:
response.close()
connection.close()
def main():
parser = argparse.ArgumentParser(description=__doc__)
connection_args(parser)
parser.add_argument("--input", type=Path, required=True)
parser.add_argument("--target-files-dir", type=Path)
parser.add_argument("--minio-endpoint", default=os.environ.get("MINIO_ENDPOINT"))
parser.add_argument("--minio-bucket", default=os.environ.get("MINIO_BUCKET"))
parser.add_argument("--minio-access-key", default=os.environ.get("MINIO_ACCESS_KEY"))
parser.add_argument("--minio-region", default=os.environ.get("MINIO_REGION", "us-east-1"))
parser.add_argument("--mapping", type=Path)
args = parser.parse_args()
log("开始导入普惠疗休养;目标数据库:" + args.database)
log("[1/5] 读取导出包并校验数据:" + str(args.input))
overrides = json.loads(args.mapping.read_text(encoding="utf-8-sig")) if args.mapping else {}
copied_directory = None
uploaded_location = None
with zipfile.ZipFile(args.input) as archive:
manifest, records = load_bundle(archive)
check_relations(records)
log("导出包校验通过:业务记录 %s 条,审核记录 %s 条,附件 %s 个" %
(sum(len(records[name]) for name in SUFFIXES), len(records["_audit"]), len(records["_file"])))
log("[2/5] 连接数据库,检查表结构、目标数据和人员组织映射")
client = MySQL(args)
tables = {suffix: PREFIX + suffix for suffix in SUFFIXES}
tables["_audit"] = PREFIX + "audit"
@@ -178,6 +305,14 @@ def main():
initial = rows(client, tables["config"], schemas[tables["config"]])
if len(initial) > 1 or initial and not default_config(initial[0]):
raise ValueError("目标配置已有业务设置,不覆盖;仅允许空的新子模块首次导入")
for label, table in tables.items():
if label != "config":
count = client.objects("SELECT JSON_OBJECT('n',COUNT(*)) FROM " + identifier(table) + ";")[0]["n"]
if count:
raise ValueError("目标子模块已有业务数据,不覆盖:" + table)
log("[3/5] 转换业务数据和附件引用")
minio = MinIO(args) if records["_file"] else None
object_prefix = "inclusive_therapy_v3/" + uuid.uuid4().hex
file_info = {}
paths = {}
for row in records["_file"]:
@@ -185,9 +320,20 @@ def main():
asset = manifest["files"].get(old_id)
if not asset or asset["member"] not in archive.namelist():
raise ValueError("附件内容缺失,ID:" + old_id)
if type(asset.get("size")) is not int or asset["size"] < 0 or not re.fullmatch(r"[0-9a-f]{64}", asset.get("sha256", "")):
raise ValueError("附件大小或 SHA-256 信息不正确,ID:" + old_id)
new_id = uuid.uuid4().hex
name = get(row, "filename") or old_id
suffix = Path(name).suffix.lower().lstrip(".")
if not re.fullmatch(r"[a-z0-9]{1,12}", suffix):
suffix = "bin"
object_name = new_id + "." + suffix
file_info[old_id] = {"id": new_id, "name": get(row, "filename") or old_id,
"engine": "LOCAL", "bucket": "", "downloadPath": "/platform/sys/file/download?id=" + new_id}
"engine": "MINIO", "bucket": minio.bucket,
"storagePath": object_prefix + "/" + object_name, "objName": object_name,
"suffix": suffix, "sizeKb": str(round(asset["size"] / 1024, 2)),
"sizeInfo": str(asset["size"]) + " B", "delFlag": "0",
"downloadPath": "/platform/sys/file/download?id=" + new_id}
path = get(row, "filepath")
if path in paths and paths[path] != old_id:
raise ValueError("源附件路径对应多个文件 ID,请先消除歧义")
@@ -269,37 +415,42 @@ def main():
for row in source:
user = get(row, "userId")
prepared["activity_user_scope"].append({
"groupId": new_group, "groupName": "普惠疗休养V3 / " + (get(row, "groupName") or "参加人员"),
"groupId": new_group, "groupName": "普惠疗休养 / " + (get(row, "groupName") or "参加人员"),
"userId": identities["user"].resolve(user, "user") if user else "",
"groupType": "1", "groupSql": None,
"creator": identities["user"].resolve(get(row, "creator"), "user", required=False), "delFlag": "0"})
version = get(records["_version"][0], "configValue") if records["_version"] else "zjnu"
if version not in ("zjnu", "zjxu", "zjiet"):
raise ValueError("无法识别 v3 的疗休养规则版本")
log("[4/5] 上传附件到 MinIO 并回读校验,共 %s 个" % len(file_info))
if file_info:
if args.target_files_dir is None:
raise ValueError("有附件时必须提供 --target-files-dir,不能只迁移数据库地址")
storage = args.target_files_dir.resolve()
storage.mkdir(parents=True, exist_ok=True)
copied_directory = storage / ("inclusive_therapy_v3_" + uuid.uuid4().hex)
copied_directory.mkdir()
for old_id, info in file_info.items():
asset = manifest["files"][old_id]
suffix = Path(info["name"]).suffix.lower().lstrip(".")
if not re.fullmatch(r"[a-z0-9]{1,12}", suffix):
suffix = "bin"
path = copied_directory / (info["id"] + "." + suffix)
digest, size = hashlib.sha256(), 0
with archive.open(asset["member"]) as source, path.open("xb") as destination:
for chunk in iter(lambda: source.read(1024 * 1024), b""):
digest.update(chunk)
size += len(chunk)
destination.write(chunk)
if digest.hexdigest() != asset["sha256"] or size != asset["size"]:
raise ValueError("附件内容不完整,ID:" + old_id)
info.update(suffix=suffix, storagePath=str(path), objName=path.name,
sizeKb=str(round(size / 1024, 2)), sizeInfo=str(size) + " B", delFlag="0")
prepared["sys_file"].append(info)
minio.check_bucket()
log("MinIO 桶连接成功:" + minio.bucket)
try:
for index, (old_id, info) in enumerate(file_info.items(), 1):
log("附件 [%s/%s] 开始上传及校验,源文件ID:%s" % (index, len(file_info), old_id))
asset = manifest["files"][old_id]
digest, size = hashlib.sha256(), 0
with tempfile.SpooledTemporaryFile(max_size=8 * 1024 * 1024, mode="w+b") as body:
with archive.open(asset["member"]) as source:
for chunk in iter(lambda: source.read(1024 * 1024), b""):
digest.update(chunk)
size += len(chunk)
body.write(chunk)
if digest.hexdigest() != asset["sha256"] or size != asset["size"]:
raise ValueError("附件内容不完整,ID:" + old_id)
body.seek(0)
content_type = mimetypes.guess_type(info["objName"])[0] or "application/octet-stream"
uploaded_location = "s3://" + minio.bucket + "/" + object_prefix + "/"
minio.upload_and_verify(info["storagePath"], body, size, asset["sha256"], content_type)
prepared["sys_file"].append(info)
log("附件 [%s/%s] 上传及 SHA-256 回读校验通过(%s 字节)" % (index, len(file_info), size))
except (OSError, ValueError, RuntimeError, KeyError, zipfile.BadZipFile):
if uploaded_location:
print("MinIO 附件对象前缀(可能已有上传):" + uploaded_location, file=sys.stderr)
raise
else:
log("导出包没有附件,跳过 MinIO 上传")
sql = ["SET SESSION time_zone='+00:00';", "SET SESSION sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';",
"CREATE TEMPORARY TABLE inclusive_therapy_v3_import_guard (ok INT NOT NULL, CONSTRAINT inclusive_therapy_v3_import_requirement CHECK(ok=1)) ENGINE=InnoDB;",
"START TRANSACTION;"]
@@ -327,27 +478,36 @@ def main():
",".join(literal(value) for value in row.values()) + ");")
sql.append("UPDATE sys_config SET configValue=" + literal(version) + " WHERE configKey='staffTherapyRecuperationVersion';")
sql.append("INSERT INTO sys_config(configKey,configValue,note,delFlag) SELECT 'staffTherapyRecuperationVersion'," +
literal(version) + "," + literal("普惠疗休养V3报名规则版本") + ",0 WHERE NOT EXISTS "
literal(version) + "," + literal("普惠疗休养报名规则版本") + ",0 WHERE NOT EXISTS "
"(SELECT 1 FROM sys_config WHERE configKey='staffTherapyRecuperationVersion');")
sql.append("COMMIT;")
log("[5/5] 开始数据库事务,写入 %s 条记录;数据量较大时请等待事务提交" %
sum(len(table_rows) for table_rows in prepared.values()))
try:
# mysql 批处理遇错即停止;连接关闭回滚未提交事务,不启用 --force。
for _ in client.lines("\n".join(sql)):
pass
except (OSError, RuntimeError):
if copied_directory:
print("附件暂存目录保留:" + str(copied_directory), file=sys.stderr)
if uploaded_location:
print("已上传附件保留在 MinIO 前缀:" + uploaded_location, file=sys.stderr)
raise
print("导入完成:普惠疗休养V3,表前缀 " + PREFIX)
print("业务记录:%s;审核记录:%s;附件:%s" %
(sum(len(records[name]) for name in SUFFIXES), len(records["_audit"]), len(file_info)))
if copied_directory:
print("附件目录:" + str(copied_directory))
log("数据库事务提交成功")
log("导入完成:普惠疗休养,表前缀 " + PREFIX)
log("业务记录:%s;审核记录:%s;附件:%s" %
(sum(len(records[name]) for name in SUFFIXES), len(records["_audit"]), len(file_info)))
if uploaded_location:
log("MinIO 附件对象前缀:" + uploaded_location)
if __name__ == "__main__":
started = time.monotonic()
try:
main()
log("【成功结束】导入成功,总耗时 %.1f 秒,退出码 0" % (time.monotonic() - started))
except KeyboardInterrupt:
log("【中断结束】用户中断导入,退出码 130;事务提交状态需确认,已上传的 MinIO 对象予以保留", error=True)
sys.exit(130)
except (OSError, ValueError, RuntimeError, KeyError, zipfile.BadZipFile) as error:
print("导入失败:" + str(error), file=sys.stderr)
log("导入失败:" + str(error), error=True)
log("【失败结束】导入未成功,总耗时 %.1f 秒,退出码 1" % (time.monotonic() - started), error=True)
sys.exit(1)
@@ -0,0 +1,13 @@
-- 仅清理普惠疗休养菜单及角色菜单关联,保留职工权益模块和业务数据。
START TRANSACTION;
DELETE rm FROM sys_role_menu rm
INNER JOIN sys_menu m ON m.id = rm.menuId
WHERE m.permission = 'inclusiveTherapyV3'
OR m.permission LIKE 'inclusiveTherapyV3.%';
DELETE FROM sys_menu
WHERE permission = 'inclusiveTherapyV3'
OR permission LIKE 'inclusiveTherapyV3.%';
COMMIT;
@@ -0,0 +1,155 @@
-- 普惠疗休养:PC父菜单及12个子菜单、移动端入口,归属职工权益模块。
-- 角色菜单关系暂时只授予本项目超级管理员角色 SYSADMIN。
SET NAMES utf8mb4;
START TRANSACTION;
-- 普惠疗休养
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000000', '',
(SELECT LPAD(COALESCE(MAX(CAST(path AS UNSIGNED)),0)+1,4,'0') FROM sys_menu WHERE CHAR_LENGTH(path)=4),
'普惠疗休养', 'menu', '/platform/inclusiveTherapyV3', '_self', 'fa fa-heart', 1, 0,
'inclusiveTherapyV3', 50, 1, 'pc', id, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_module WHERE name='职工权益' AND platform='pc' LIMIT 1;
-- 旅行社管理
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000001', id, CONCAT(path, '0001'),
'旅行社管理', 'menu', '/platform/inclusiveTherapyV3/travelAgency', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.travelAgency', 1, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 线路管理
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000002', id, CONCAT(path, '0002'),
'线路管理', 'menu', '/platform/inclusiveTherapyV3/line', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.line', 2, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 分工会选择线路
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000003', id, CONCAT(path, '0003'),
'分工会选择线路', 'menu', '/platform/inclusiveTherapyV3/lineFghSelect?mode=1', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.lineFghSelect', 3, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 校工会选择线路
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000004', id, CONCAT(path, '0004'),
'校工会选择线路', 'menu', '/platform/inclusiveTherapyV3/lineXghSelect?mode=2', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.lineXghSelect', 4, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 满意度统计
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000005', id, CONCAT(path, '0005'),
'满意度统计', 'menu', '/platform/inclusiveTherapyV3/query/statics', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.queryStatics', 5, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 分工会信息查询
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000006', id, CONCAT(path, '0006'),
'分工会信息查询', 'menu', '/platform/inclusiveTherapyV3/query', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.TheRapyQuery', 6, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 校工会信息查询
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000007', id, CONCAT(path, '0007'),
'校工会信息查询', 'menu', '/platform/inclusiveTherapyV3/user/query', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.TheRapyUserQuery', 7, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 线路选择查询
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000008', id, CONCAT(path, '0008'),
'线路选择查询', 'menu', '/platform/inclusiveTherapyV3/statistics/unionLineNumberStatistics', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.unionLineNumberStatistics', 8, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 成团结果通知
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea90000000000000000000000000009', id, CONCAT(path, '0009'),
'成团结果通知', 'menu', '/platform/inclusiveTherapyV3/statistics', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.statistics', 9, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 基础设置
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea9000000000000000000000000000a', id, CONCAT(path, '0010'),
'基础设置', 'menu', '/platform/inclusiveTherapyV3/TheRapyConfig', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.TheRapyConfig', 10, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 分工会线路选择统计
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea9000000000000000000000000000b', id, CONCAT(path, '0011'),
'分工会线路选择统计', 'menu', '/platform/inclusiveTherapyV3/lineSelectionOverview', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.lineSelectionOverview', 11, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 人数统计
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag)
SELECT '7ea9000000000000000000000000000c', id, CONCAT(path, '0012'),
'人数统计', 'menu', '/platform/inclusiveTherapyV3/travelAgencyMonthlyStatistics', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.travelAgencyMonthlyStatistics', 12, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3';
-- 仅授予超级管理员角色
INSERT INTO sys_role_menu (roleId, menuId)
SELECT r.id, m.id FROM sys_role r CROSS JOIN sys_menu m
WHERE r.code='SYSADMIN' AND r.disabled=0 AND COALESCE(r.delFlag,0)=0
AND m.permission IN (
'inclusiveTherapyV3',
'inclusiveTherapyV3.travelAgency',
'inclusiveTherapyV3.line',
'inclusiveTherapyV3.lineFghSelect',
'inclusiveTherapyV3.lineXghSelect',
'inclusiveTherapyV3.queryStatics',
'inclusiveTherapyV3.TheRapyQuery',
'inclusiveTherapyV3.TheRapyUserQuery',
'inclusiveTherapyV3.lineSelectionOverview',
'inclusiveTherapyV3.statistics',
'inclusiveTherapyV3.TheRapyConfig',
'inclusiveTherapyV3.unionLineNumberStatistics',
'inclusiveTherapyV3.travelAgencyMonthlyStatistics');
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note,
location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, processKey, platform,
moduleId, isQuickEntry, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
VALUES ('e08d3515ed2f4ce28591f30703b68f1a', '', '0179', '普惠疗休养', null, 'menu', null, null, null, true, false,
'inclusiveTherapyV3.mobile', null, 1025, true, '17a7f8ad3ee947b4a26175049a9c253d', 1793064184942,
'17a7f8ad3ee947b4a26175049a9c253d', 1793064184942, false, null, 'H5', '586fffaeddc94a7493c81b6d69e546ab', false,
'/platform/sys/file/download?id=5j67fh5qaij5mr4p3q91peu46r', 'p', false, false);
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note,
location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, processKey, platform,
moduleId, isQuickEntry, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
VALUES ('a57fbc8998d04acdb9d694841e1d572c', 'e08d3515ed2f4ce28591f30703b68f1a', '01790001', '疗休养报名', null, 'menu',
'/platform/inclusiveTherapyV3/mobile/index', null, null, true, false, 'inclusiveTherapyV3.mobile.signup', null,
1026, false, '17a7f8ad3ee947b4a26175049a9c253d', 1793064222219, '17a7f8ad3ee947b4a26175049a9c253d',
1793064310249, false, null, 'H5', '586fffaeddc94a7493c81b6d69e546ab', false,
'/platform/sys/file/download?id=6llemukl0ugaeqdgh7ud7g31ll', 'l', false, false);
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note,
location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, processKey, platform,
moduleId, isQuickEntry, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
VALUES ('30f0cfd45c60406aaea5b44da88f828a', 'e08d3515ed2f4ce28591f30703b68f1a', '01790002', '我的报名', null, 'menu',
'/platform/inclusiveTherapyV3/mobile/myRecuperation', null, null, true, false,
'inclusiveTherapyV3.mobile.mySignup', null, 1027, false, '17a7f8ad3ee947b4a26175049a9c253d', 1793064293963,
'17a7f8ad3ee947b4a26175049a9c253d', 1793064317183, false, null, 'H5', '586fffaeddc94a7493c81b6d69e546ab', false,
'/platform/sys/file/download?id=v9phasf6roh33ocmnej2h2qbj1', 'w', false, false);
-- 移动端三个菜单授予超级管理员角色。
INSERT INTO sys_role_menu (roleId, menuId)
SELECT r.id, m.id FROM sys_role r CROSS JOIN sys_menu m
WHERE r.code IN ('SYSADMIN', 'superadmin') AND r.disabled=0 AND COALESCE(r.delFlag,0)=0
AND m.platform='H5'
AND m.id IN (
'e08d3515ed2f4ce28591f30703b68f1a',
'a57fbc8998d04acdb9d694841e1d572c',
'30f0cfd45c60406aaea5b44da88f828a')
AND NOT EXISTS (
SELECT 1 FROM sys_role_menu rm WHERE rm.roleId=r.id AND rm.menuId=m.id);
COMMIT;
@@ -1,9 +1,9 @@
-- v4 职工福利 / 普惠疗休养V3独立子模块初始化脚本(MySQL 8)。
-- v4 职工福利 / 普惠疗休养独立子模块初始化脚本(MySQL 8)。
-- 在 v4 目标数据库中执行;表结构依据 therapyRecuperation 模块实体定义。
-- v3 the_rapy_recuperation_* 对应本模块 inclusive_therapy_v3_*,不覆盖 v4 其他疗休养表。
-- 仅新增表、视图、默认配置、菜单及角色权限关联,不迁移 v3 历史业务数据。
-- 已存在的表、视图、配置和菜单保留原值;脚本不修订已有表结构。
-- 依赖 v4 已有 vw_user、sys_union、sys_unit、sys_config、sys_module、sys_menu、sys_role、sys_role_menu。
-- 仅新增表、视图和默认配置,不迁移 v3 历史业务数据。
-- 已存在的表、视图和配置保留原值;脚本不修订已有表结构。
-- 依赖 v4 已有 vw_user、sys_union、sys_unit、sys_config。
-- DDL 存在 MySQL 隐式提交;后续初始化记录使用单独事务。
SET NAMES utf8mb4;
@@ -353,335 +353,12 @@ SELECT 2750,'审核通过','#67c23a'
WHERE NOT EXISTS (SELECT 1 FROM `inclusive_therapy_v3_audit_state` WHERE `stateId`=2750);
INSERT INTO `sys_config` (`configKey`,`configValue`,`note`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT 'staffTherapyRecuperationVersion','zjnu','普惠疗休养V3独立子模块报名规则版本','',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
SELECT 'staffTherapyRecuperationVersion','zjnu','普惠疗休养独立子模块报名规则版本','',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `configKey`='staffTherapyRecuperationVersion');
INSERT INTO `inclusive_therapy_v3_config`
(`id`,`configName`,`isSnLine`,`isSwLine`,`travelAudit`,`bedInfo`,`familyInfo`,`outsideQuotaProportion`,`unionLineNumberConfigs`)
SELECT REPLACE(UUID(),'-',''),'普惠疗休养V3配置',0,0,0,1,1,0,JSON_ARRAY()
SELECT REPLACE(UUID(),'-',''),'普惠疗休养配置',0,0,0,1,1,0,JSON_ARRAY()
WHERE NOT EXISTS (SELECT 1 FROM `inclusive_therapy_v3_config`);
SET @inclusive_therapy_v3_pc_module = COALESCE(
(SELECT m.`moduleId` FROM `sys_menu` m INNER JOIN `sys_module` s ON s.`id`=m.`moduleId`
WHERE m.`href` LIKE '/platform/recuperation%' AND m.`platform`='pc' ORDER BY m.`id` LIMIT 1),
(SELECT `id` FROM `sys_module` WHERE `name`='职工福利' AND `platform`='pc' ORDER BY `id` LIMIT 1),
REPLACE(UUID(),'-','')
);
INSERT INTO `sys_module` (`id`,`name`,`platform`,`sortNum`,`faIcon`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_pc_module,'职工福利','pc',50,'fa fa-heart','',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_module` WHERE `id`=@inclusive_therapy_v3_pc_module);
SET @inclusive_therapy_v3_module_name = (SELECT `name` FROM `sys_module` WHERE `id`=@inclusive_therapy_v3_pc_module);
SET @inclusive_therapy_v3_module_sort = (SELECT `sortNum` FROM `sys_module` WHERE `id`=@inclusive_therapy_v3_pc_module);
SET @inclusive_therapy_v3_h5_module = COALESCE(
(SELECT `id` FROM `sys_module` WHERE `name`=@inclusive_therapy_v3_module_name AND `platform`='h5' ORDER BY `id` LIMIT 1),
REPLACE(UUID(),'-','')
);
INSERT INTO `sys_module` (`id`,`name`,`platform`,`sortNum`,`faIcon`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_h5_module,@inclusive_therapy_v3_module_name,'h5',@inclusive_therapy_v3_module_sort,'fa fa-heart','',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_module` WHERE `id`=@inclusive_therapy_v3_h5_module);
SET @inclusive_therapy_v3_menu_root = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT('',LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=4
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_root,'',@inclusive_therapy_v3_next_path,'普惠疗休养V3','menu','/platform/inclusiveTherapyV3','_self','fa fa-heart',1,0,'inclusiveTherapyV3',
@inclusive_therapy_v3_next_location,1,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3');
SET @inclusive_therapy_v3_root_path = (SELECT `path` FROM `sys_menu` WHERE `id`=@inclusive_therapy_v3_menu_root);
-- 基础设置
SET @inclusive_therapy_v3_menu_config = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyConfig' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_config,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'基础设置','menu','/platform/inclusiveTherapyV3?screen=config','_self','fa fa-heart',1,0,'inclusiveTherapyV3.TheRapyConfig',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyConfig');
-- 旅行社管理
SET @inclusive_therapy_v3_menu_agency = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.travelAgency' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_agency,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'旅行社管理','menu','/platform/inclusiveTherapyV3?screen=agency','_self','fa fa-heart',1,0,'inclusiveTherapyV3.travelAgency',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.travelAgency');
-- 线路管理
SET @inclusive_therapy_v3_menu_line = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.line' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_line,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'线路管理','menu','/platform/inclusiveTherapyV3?screen=line','_self','fa fa-heart',1,0,'inclusiveTherapyV3.line',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.line');
-- 目的地管理
SET @inclusive_therapy_v3_menu_base = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheBaseManagement' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_base,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'目的地管理','menu','/platform/inclusiveTherapyV3?screen=base','_self','fa fa-heart',1,0,'inclusiveTherapyV3.TheBaseManagement',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheBaseManagement');
-- 分工会选择线路
SET @inclusive_therapy_v3_menu_branchSelect = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineFghSelect' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_branchSelect,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'分工会选择线路','menu','/platform/inclusiveTherapyV3?screen=branchSelect','_self','fa fa-heart',1,0,'inclusiveTherapyV3.lineFghSelect',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineFghSelect');
-- 校工会选择线路
SET @inclusive_therapy_v3_menu_schoolSelect = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineXghSelect' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_schoolSelect,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'校工会选择线路','menu','/platform/inclusiveTherapyV3?screen=schoolSelect','_self','fa fa-heart',1,0,'inclusiveTherapyV3.lineXghSelect',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineXghSelect');
-- 线路选择总览
SET @inclusive_therapy_v3_menu_overview = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineSelectionOverview' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_overview,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'线路选择总览','menu','/platform/inclusiveTherapyV3?screen=overview','_self','fa fa-heart',1,0,'inclusiveTherapyV3.lineSelectionOverview',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineSelectionOverview');
-- 线路组团
SET @inclusive_therapy_v3_menu_cluster = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineCluster' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_cluster,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'线路组团','menu','/platform/inclusiveTherapyV3?screen=cluster','_self','fa fa-heart',1,0,'inclusiveTherapyV3.lineCluster',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.lineCluster');
-- 线路调剂
SET @inclusive_therapy_v3_menu_adjustment = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.line.adjustment' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_adjustment,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'线路调剂','menu','/platform/inclusiveTherapyV3?screen=adjustment','_self','fa fa-heart',1,0,'inclusiveTherapyV3.line.adjustment',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.line.adjustment');
-- 参加人员导入
SET @inclusive_therapy_v3_menu_import = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.joinUser.import' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_import,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'参加人员导入','menu','/platform/inclusiveTherapyV3?screen=import','_self','fa fa-heart',1,0,'inclusiveTherapyV3.joinUser.import',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.joinUser.import');
-- 分工会审核
SET @inclusive_therapy_v3_menu_branchAudit = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyAudit' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_branchAudit,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'分工会审核','menu','/platform/inclusiveTherapyV3?screen=branchAudit','_self','fa fa-heart',1,0,'inclusiveTherapyV3.TheRapyAudit',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyAudit');
-- 自由组团审核
SET @inclusive_therapy_v3_menu_travelAudit = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyTravelAudit' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_travelAudit,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'自由组团审核','menu','/platform/inclusiveTherapyV3?screen=travelAudit','_self','fa fa-heart',1,0,'inclusiveTherapyV3.TheRapyTravelAudit',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyTravelAudit');
-- 校工会审核
SET @inclusive_therapy_v3_menu_schoolAudit = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyXghAudit' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_schoolAudit,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'校工会审核','menu','/platform/inclusiveTherapyV3?screen=schoolAudit','_self','fa fa-heart',1,0,'inclusiveTherapyV3.TheRapyXghAudit',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyXghAudit');
-- 分工会查询
SET @inclusive_therapy_v3_menu_branchQuery = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyQuery' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_branchQuery,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'分工会查询','menu','/platform/inclusiveTherapyV3?screen=branchQuery','_self','fa fa-heart',1,0,'inclusiveTherapyV3.TheRapyQuery',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyQuery');
-- 报名人员查询
SET @inclusive_therapy_v3_menu_userQuery = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyUserQuery' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_userQuery,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'报名人员查询','menu','/platform/inclusiveTherapyV3?screen=userQuery','_self','fa fa-heart',1,0,'inclusiveTherapyV3.TheRapyUserQuery',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.TheRapyUserQuery');
-- 查询统计
SET @inclusive_therapy_v3_menu_queryStatistics = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.queryStatics' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_queryStatistics,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'查询统计','menu','/platform/inclusiveTherapyV3?screen=queryStatistics','_self','fa fa-heart',1,0,'inclusiveTherapyV3.queryStatics',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.queryStatics');
-- 线路统计
SET @inclusive_therapy_v3_menu_lineStatistics = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.statistics' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_lineStatistics,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'线路统计','menu','/platform/inclusiveTherapyV3?screen=lineStatistics','_self','fa fa-heart',1,0,'inclusiveTherapyV3.statistics',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.statistics');
-- 旅行社月度统计
SET @inclusive_therapy_v3_menu_agencyStatistics = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.travelAgencyMonthlyStatistics' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_agencyStatistics,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'旅行社月度统计','menu','/platform/inclusiveTherapyV3?screen=agencyStatistics','_self','fa fa-heart',1,0,'inclusiveTherapyV3.travelAgencyMonthlyStatistics',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.travelAgencyMonthlyStatistics');
-- 分工会线路数量统计
SET @inclusive_therapy_v3_menu_unionStatistics = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.unionLineNumberStatistics' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_unionStatistics,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'分工会线路数量统计','menu','/platform/inclusiveTherapyV3?screen=unionStatistics','_self','fa fa-heart',1,0,'inclusiveTherapyV3.unionLineNumberStatistics',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.unionLineNumberStatistics');
SET @inclusive_therapy_v3_menu_signup = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.signup' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT(@inclusive_therapy_v3_root_path,LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=CHAR_LENGTH(@inclusive_therapy_v3_root_path)+4 AND LEFT(`path`,CHAR_LENGTH(@inclusive_therapy_v3_root_path))=@inclusive_therapy_v3_root_path
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_signup,@inclusive_therapy_v3_menu_root,@inclusive_therapy_v3_next_path,'疗休养报名','menu','/platform/inclusiveTherapyV3?screen=signup','_self','fa fa-heart',1,0,'inclusiveTherapyV3.signup',
@inclusive_therapy_v3_next_location,0,'pc',@inclusive_therapy_v3_pc_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.signup');
SET @inclusive_therapy_v3_menu_mobile = COALESCE((SELECT `id` FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.mobile' LIMIT 1),REPLACE(UUID(),'-',''));
SET @inclusive_therapy_v3_next_path = (
SELECT CONCAT('',LPAD(COALESCE(MAX(CAST(RIGHT(`path`,4) AS UNSIGNED)),0)+1,4,'0'))
FROM `sys_menu` WHERE CHAR_LENGTH(`path`)=4
);
SET @inclusive_therapy_v3_next_location = (SELECT COALESCE(MAX(`location`),0)+1 FROM `sys_menu`);
INSERT INTO `sys_menu`
(`id`,`parentId`,`path`,`name`,`type`,`href`,`target`,`icon`,`showit`,`disabled`,`permission`,`location`,`hasChildren`,`platform`,`moduleId`,`createdBy`,`createdAt`,`updatedBy`,`updatedAt`,`delFlag`)
SELECT @inclusive_therapy_v3_menu_mobile,'',@inclusive_therapy_v3_next_path,'普惠疗休养V3','menu','/platform/inclusiveTherapyV3/mobile/index','_self','fa fa-heart',1,0,'inclusiveTherapyV3.mobile',
@inclusive_therapy_v3_next_location,0,'h5',@inclusive_therapy_v3_h5_module,'',@inclusive_therapy_v3_now,'',@inclusive_therapy_v3_now,0
WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission`='inclusiveTherapyV3.mobile');
INSERT INTO `sys_role_menu` (`roleId`,`menuId`)
SELECT r.`id`,m.`id` FROM `sys_role` r CROSS JOIN `sys_menu` m
WHERE r.`disabled`=0 AND r.`code` IN ('sysadmin','superadmin','A06','SchoolUnionMemberAdmin','SYSADMIN','SCHOOL_UNION_ADMIN','SCHOOL_UNION_WELFARE_ADMIN','SCHOOL_UNION_MEMBER_ADMIN')
AND m.`permission` IN ('inclusiveTherapyV3','inclusiveTherapyV3.TheRapyConfig','inclusiveTherapyV3.travelAgency','inclusiveTherapyV3.line','inclusiveTherapyV3.TheBaseManagement','inclusiveTherapyV3.lineFghSelect','inclusiveTherapyV3.lineXghSelect','inclusiveTherapyV3.lineSelectionOverview','inclusiveTherapyV3.lineCluster','inclusiveTherapyV3.line.adjustment','inclusiveTherapyV3.joinUser.import','inclusiveTherapyV3.TheRapyAudit','inclusiveTherapyV3.TheRapyTravelAudit','inclusiveTherapyV3.TheRapyXghAudit','inclusiveTherapyV3.TheRapyQuery','inclusiveTherapyV3.TheRapyUserQuery','inclusiveTherapyV3.queryStatics','inclusiveTherapyV3.statistics','inclusiveTherapyV3.travelAgencyMonthlyStatistics','inclusiveTherapyV3.unionLineNumberStatistics')
AND NOT EXISTS (SELECT 1 FROM `sys_role_menu` rel WHERE rel.`roleId`=r.`id` AND rel.`menuId`=m.`id`);
INSERT INTO `sys_role_menu` (`roleId`,`menuId`)
SELECT r.`id`,m.`id` FROM `sys_role` r CROSS JOIN `sys_menu` m
WHERE r.`disabled`=0 AND r.`code` IN ('H03','H04','H06','BRANCH_UNION_ADMIN','BRANCH_UNION_CHAIRMAN')
AND m.`permission` IN ('inclusiveTherapyV3','inclusiveTherapyV3.line','inclusiveTherapyV3.TheBaseManagement','inclusiveTherapyV3.lineFghSelect','inclusiveTherapyV3.lineSelectionOverview','inclusiveTherapyV3.lineCluster','inclusiveTherapyV3.line.adjustment','inclusiveTherapyV3.TheRapyAudit','inclusiveTherapyV3.TheRapyTravelAudit','inclusiveTherapyV3.TheRapyQuery')
AND NOT EXISTS (SELECT 1 FROM `sys_role_menu` rel WHERE rel.`roleId`=r.`id` AND rel.`menuId`=m.`id`);
INSERT INTO `sys_role_menu` (`roleId`,`menuId`)
SELECT r.`id`,m.`id` FROM `sys_role` r CROSS JOIN `sys_menu` m
WHERE r.`disabled`=0 AND r.`code` IN ('public','PUBLIC','MEMBER','sysadmin','superadmin','SYSADMIN')
AND m.`permission` IN ('inclusiveTherapyV3','inclusiveTherapyV3.signup','inclusiveTherapyV3.mobile')
AND NOT EXISTS (SELECT 1 FROM `sys_role_menu` rel WHERE rel.`roleId`=r.`id` AND rel.`menuId`=m.`id`);
COMMIT;
@@ -1,58 +0,0 @@
;(function (a) {
;(jQuery.browser = jQuery.browser || {}).mobile =
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(
a
) ||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
a.substr(0, 4)
)
})(navigator.userAgent || navigator.vendor || window.opera)
$.ajaxSetup({
contentType: "application/x-www-form-urlencoded;charset=utf-8",
success: function (response, textStatus, jqXHR) {
if (response.code !== 0) {
// AJAX全局回调没有Vue实例上下文,使用Element全局消息组件展示业务错误。
if (window.ELEMENT && ELEMENT.Message) {
ELEMENT.Message.error(response.msg)
}
} else {
return response
}
},
error: function (v1) {
this.$message.error(v1.status + " " + v1.statusText)
},
complete: function (XMLHttpRequest, textStatus) {
var sessionstatus = XMLHttpRequest.getResponseHeader("loginStatus") //通过XMLHttpRequest取得响应头,sessionstatus,
if (sessionstatus == "accessDenied") {
this.$message({
message: "\u767b\u5f55\u5931\u6548\uff0c\u8bf7\u5237\u65b0\u9875\u9762\u91cd\u65b0\u767b\u5f55",
type: "error"
})
}
if (sessionstatus == "unauthorized") {
this.$message({
message: "\u6ca1\u6709\u6743\u9650",
type: "error"
})
}
}
})
function pjaxReplace(url, data = {}) {
const { pathname, search } = location
if (url === pathname + search) {
return
}
$.pjax({
url: url,
container: "#sub-app-container-main-content-body",
maxCacheLength: 0,
push: false,
replace: true,
fragment: "#sub-app-container-main-content-body",
timeout: 8000,
data
})
}
@@ -105,11 +105,11 @@ const nation = [
'基诺族'
];
const loc = () => {
function loc() {
return location.href.replace(location.search, "").replace(location.hash, "")
}
const clone = (obj) => {
function clone(obj) {
return JSON.parse(JSON.stringify(obj))
}
@@ -1,21 +1,83 @@
const sublime = {
showLoadingbar() {
if (!document.getElementById('therapy-loading')) {
const bar = document.createElement('div');
bar.id = 'therapy-loading';
document.body.appendChild(bar);
}
},
closeLoadingbar() {
const bar = document.getElementById('therapy-loading');
if (bar) bar.remove();
jumpPagePjax(url) {
window.location.href = url;
}
};
Vue.prototype.$validateForm = function(form) {
return new Promise(resolve => {
if (!form) {
this.$message.error('表单尚未加载完成');
resolve(false);
return;
}
const uploading = component => {
if (Array.isArray(component.uploadFiles) && component.uploadFiles.some(file => file.status === 'uploading')) return true;
return (component.$children || []).some(uploading);
};
if (uploading(form)) {
this.$message.warning('请等待图片或附件上传完成后再提交');
resolve(false);
return;
}
form.validate((valid, fields) => {
if (!valid) {
const errors = Object.values(fields || {}).flat();
this.$message.warning(errors.length ? errors[0].message : '请检查必填项和填写格式');
}
resolve(valid);
});
});
};
Vue.prototype.$confirmAction = async function(...args) {
try {
return await this.$confirm(...args);
} catch (error) {
if (error === 'cancel' || error === 'close') return false;
throw error;
}
};
Vue.prototype.$actionError = function(error) {
if (error === 'cancel' || error === 'close') return;
const message = error && (error.responseJSON && error.responseJSON.msg || error.msg || error.message);
this.$message.error(message || '操作失败,请稍后重试');
};
Vue.prototype.$downloadFile = function(url) {
window.location.href = url;
};
Vue.prototype.$importExcel = function(url, files) {
const data = new FormData();
files.forEach(file => data.append('file', file.raw, file.raw.name));
return $.ajax({url: url, type: 'POST', data: data, processData: false, contentType: false});
};
Vue.directive('throttle', {
bind(el) {
let lastClick = 0;
el.therapyThrottleHandler = event => {
const now = Date.now();
if (now - lastClick < 1000) {
event.preventDefault();
event.stopImmediatePropagation();
return;
}
lastClick = now;
};
el.addEventListener('click', el.therapyThrottleHandler, true);
},
unbind(el) {
el.removeEventListener('click', el.therapyThrottleHandler, true);
delete el.therapyThrottleHandler;
}
});
$.ajaxSetup({
traditional: true,
error(xhr) {
sublime.closeLoadingbar();
const message = xhr.responseJSON && xhr.responseJSON.msg || '请求失败,请稍后重试';
if (window.ELEMENT) ELEMENT.Message.error(message);
else if (window.vant) vant.Toast.fail(message);
@@ -40,3 +102,14 @@ window.therapyPreview = function(value) {
return /^(https?:|data:|blob:|\/)/.test(value) ? value :
'/platform/inclusiveTherapyV3/common/preview?id=' + encodeURIComponent(value);
};
if (window.vant) {
window.preview = function(filename, id) {
const address = therapyPreview(id);
if (/\.(jpe?g|png|gif|bmp|webp|svg)$/i.test(filename || '')) {
vant.ImagePreview([address]);
} else {
window.open(address);
}
};
}
@@ -1,8 +1,8 @@
Vue.component('vi-title', {
props: ['title'],
template: `
<div style="display: flex;flex-direction:row;color: #1867b0;font-weight: bolder;margin-bottom: 20px">
<div style="width: 5px;height: 24px;background-color: #1867b0;border-radius: 2px"></div>
<div style="display: flex;flex-direction:row;color: var(--color-primary);font-weight: bolder;margin-bottom: 20px">
<div style="width: 5px;height: 24px;background-color: var(--color-primary);border-radius: 2px"></div>
<div style="margin-left: 20px;line-height: 24px;font-size: 15px;letter-spacing: 1px">
{{ title }}
</div>
@@ -109,7 +109,7 @@ Vue.component('table-tool', {
<div>
<el-checkbox-group v-model="checkedFields" @change="columnChange">
<el-checkbox v-for="field in columns" :label="field.prop" style="display: block">{{
<el-checkbox v-for="field in columns" :key="field.prop" :label="field.prop" style="display: block">{{
field.label
}}
</el-checkbox>
@@ -126,4 +126,4 @@ Vue.component('table-tool', {
</div>
</el-row>
`,
})
})
@@ -61,7 +61,7 @@
}
.search .search-item-label {
color: rgb(100, 100, 100);
color: var(--color-text-regular);
margin-right: 10px;
width: 80px;
min-width: 80px;
@@ -97,18 +97,18 @@
.table-tool-group {
margin-left: 15px;
overflow: hidden;
border-radius: 20px;
border-radius: 2px;
display: flex;
}
.table-tool-group .table-tool-group-item {
width: 40px;
height: 40px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
background-color: rgba(240, 240, 240, .7);
background-color: var(--background-color-base);
font-weight: bolder;
transition: all 250ms;
}
@@ -119,7 +119,7 @@
.table-tool-group .table-tool-group-item:hover {
color: white;
background-color: rgb(64, 158, 255);
background-color: var(--color-primary);
}
.width-100 {
@@ -176,11 +176,11 @@
.w-e-toolbar {
background-color: white !important;
border-color: #DCDFE6 !important;
border-color: var(--border-color-base) !important;
}
.w-e-text-container {
border-color: #DCDFE6 !important;
border-color: var(--border-color-base) !important;
}
.el-radio-group label {
@@ -195,4 +195,4 @@
.main-navigation {
border-right: 3px solid rgb(240, 240, 240);
}
}
@@ -16,15 +16,16 @@
}
.el-pagination {
height: 50px;
overflow: hidden;
min-height: 32px;
flex-wrap: wrap;
row-gap: 8px;
display: flex;
align-items: center;
}
.el-pagination button, .el-pagination span:not([class*=suffix]) {
line-height: 50px;
height: 50px;
line-height: 28px;
height: 28px;
}
a .collapsed {
@@ -128,7 +129,7 @@ a .expanded {
.el-upload__tip {
margin-top: 0px;
color: #c33714;
color: var(--color-danger);
}
.el-dialog {
@@ -137,16 +138,12 @@ a .expanded {
.el-table__empty-block {
width: 100% !important;
min-height: 300px;
background: url("/none.png") no-repeat center center;
background-size: 360px 260px;
min-height: 120px;
}
.el-table__empty-text {
display: block;
position: absolute;
bottom: 80px;
height: 40px;
line-height: 40px;
position: static;
line-height: 24px;
/*display: none !important;*/
}
@@ -54,7 +54,7 @@ const initTableMixins = {
removeFile()
}
if (size && !file.size < size) {
if (size && file.size > size) {
this.notifyWarning(`文件大小不能超过 ${size / 1024 / 1024}MB!`)
removeFile()
}
@@ -93,10 +93,8 @@ const initTableMixins = {
},
pageData(url) {
const address = url ? url : loc() + "/pageData"
sublime.showLoadingbar();
this.tableLoading = true
$.post(address, this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code == 0) {
this.tableData = data.data.list;
@@ -104,7 +102,9 @@ const initTableMixins = {
} else {
this.$message.error(data.msg);
}
}, "json");
}, "json").always(() => {
this.tableLoading = false;
});
},
notifySuccess(msg) {
this.$notify({
@@ -0,0 +1,101 @@
#app.therapy-mobile {
--color-primary: #1867b0;
--therapy-primary-light: #eef5fc;
box-sizing: border-box;
min-height: 100vh;
padding-bottom: calc(16px + env(safe-area-inset-bottom));
background: #f7f8fa !important;
color: #323233;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", sans-serif !important;
font-size: 14px;
}
#app.therapy-mobile .van-nav-bar--fixed {
left: 50%;
width: 100%;
max-width: 640px;
transform: translateX(-50%);
}
#app.therapy-mobile .van-nav-bar__title {
color: #323233;
font-size: 16px;
font-weight: 600;
}
#app.therapy-mobile .van-nav-bar .van-icon,
#app.therapy-mobile .van-dropdown-menu__title--active,
#app.therapy-mobile .van-dropdown-item__option--active,
#app.therapy-mobile .van-dropdown-item__option--active .van-icon,
#app.therapy-mobile .van-search__action,
#app.therapy-mobile .union-popup-action {
color: var(--color-primary);
}
#app.therapy-mobile .van-doc-card,
#app.therapy-mobile .list-card {
margin: 12px;
border: 1px solid #ebedf0;
border-radius: 10px;
background: #fff;
box-shadow: none;
}
#app.therapy-mobile .van-doc-card { padding: 16px; }
#app.therapy-mobile .van-grid-item__content { padding: 12px 6px; border-radius: 8px; }
#app.therapy-mobile .van-grid-item__content:active,
#app.therapy-mobile .type-icon.active-icon,
#app.therapy-mobile .union-item.active-union { background: var(--therapy-primary-light); }
#app.therapy-mobile .type-icon.active-icon { border-color: var(--color-primary); }
#app.therapy-mobile .active,
#app.therapy-mobile .cus_button,
#app.therapy-mobile .sign_button .van-button {
background: var(--color-primary);
border-color: var(--color-primary);
color: #fff;
}
#app.therapy-mobile .choose_button .button_text { margin-top: 8px; font-size: 14px; line-height: 22px; }
#app.therapy-mobile .van-dropdown-menu__item { flex: 1; min-width: 0; }
#app.therapy-mobile .van-dropdown-menu__title { max-width: 100%; font-size: 14px; }
#app.therapy-mobile .list-card { overflow: hidden; }
#app.therapy-mobile .list-card > .content { padding: 14px; max-height: none; align-items: flex-start; }
#app.therapy-mobile .list-card > .content > .van-image {
flex: 0 0 96px;
width: 96px !important;
height: 80px !important;
}
#app.therapy-mobile .list-card > .content > .van-image img { object-fit: cover; }
#app.therapy-mobile .content-right { flex: 1; width: auto; max-width: none; min-width: 0; padding-left: 12px; }
#app.therapy-mobile .cr-title { margin-bottom: 6px; font-size: 15px; line-height: 22px; color: #323233; }
#app.therapy-mobile .concat,
#app.therapy-mobile .mobile,
#app.therapy-mobile .union { font-size: 12px; line-height: 21px; color: #646566; }
#app.therapy-mobile .operateDiv {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
padding: 12px 14px;
border-top: 1px solid #f2f3f5;
}
#app.therapy-mobile .operateDiv .van-button {
min-width: 64px;
height: 32px;
margin: 0;
border-radius: 6px;
font-size: 13px;
}
#app.therapy-mobile .pop_footer {
box-sizing: border-box;
height: auto;
padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #ebedf0;
}
#app.therapy-mobile .pop_footer .van-button { width: 100%; height: 40px; }
#app.therapy-mobile .cus_content {
box-sizing: border-box;
height: calc(100% - 46px);
padding-bottom: calc(80px + env(safe-area-inset-bottom));
}
#app.therapy-mobile .van-list__finished-text { color: #969799; font-size: 13px; }
@@ -11,7 +11,7 @@
<el-table-column label="总分" prop="totalScore" header-align="center"
align="center" show-overflow-tooltip></el-table-column>
<el-table-column align="center" header-align="center" type="index" :index="indexMethod" label="名次"
<el-table-column align="center" header-align="center" prop="rank" label="名次"
width="80px"></el-table-column>
</el-table>
@@ -47,7 +47,21 @@ module.exports = {
this.tableData = []
const {data} = await this.$axios.post(loc() + "/isScoreTopEight", this.Form)
const table = data.score.sort(this.compare("totalScore"))
this.tableData = table.slice(0, 8)
// 按竞赛名次规则取前八:同分并列同名次,并列后名次不跳号(dense rank);
// 名次大于 8 的舍弃。不能直接 slice(0, 8),否则同分并列的工会会被切掉。
const ranked = []
let rank = 0
let prevScore = null
table.forEach(v => {
// 总分带 0.5 折半小数,比较用容差,避免浮点误差误判并列
if (prevScore === null || Math.abs(v.totalScore - prevScore) > 0.000001) {
// 每遇到一个新的分值,名次 +1;同分者沿用同一名次
rank += 1
prevScore = v.totalScore
}
ranked.push(Object.assign({}, v, {rank: rank}))
})
this.tableData = ranked.filter(v => v.rank <= 8)
} catch (e) {
this.$message.error(e.msg)
} finally {
@@ -280,9 +280,11 @@ module.exports = {
if (v.data && v.data.code === 0) {
insertImgFn(v.data.data)
} else {
this.$message.error("图片上传失败")
_this.$message.error(v.data && v.data.msg || "图片上传失败")
}
})
}).catch(() => {
_this.$message.error("图片上传失败,请重试")
})
}
this.editor.config.pasteFilterStyle = false
@@ -1,10 +1,28 @@
<template>
<el-drawer title="参加人员范围设置" :visible.sync="userScopeDialog" size="90%" :append-to-body="true" @closed="$emit('group_change')">
<iframe v-if="userScopeDialog" src="/platform/activity/basic/scope" title="参加人员范围设置" style="width:100%;height:calc(100vh - 90px);border:0"></iframe>
<el-drawer title="参加人员范围设置" :visible.sync="userScopeDialog" size="40%" :append-to-body="true" @closed="loadGroups">
<div style="padding:0 20px 10px">
<el-select :value="group_id" placeholder="选择疗休养参加人员分组" filterable clearable style="width:100%" @change="$emit('update:group_id', $event)">
<el-option v-for="group in groups" :key="group.groupId" :label="group.groupName" :value="group.groupId"></el-option>
</el-select>
<el-button type="text" @click="loadGroups">刷新分组</el-button>
</div>
<div style="padding:0 20px;text-align:right">
<el-button type="primary" @click="userScopeDialog = false">确定</el-button>
</div>
</el-drawer>
</template>
<script>
module.exports = {
data() { return {userScopeDialog: false}; }
props: {group_id: {type: [String, Number], default: null}},
data() { return {userScopeDialog: false, groups: []}; },
watch: {userScopeDialog(value) { if (value) this.loadGroups(); }},
methods: {
async loadGroups() {
const result = await $.get('/platform/activity/basic/scope/getActivityUserScopeGroup');
if (result.code !== 0) { this.$message.error(result.msg); return; }
this.groups = result.data || [];
this.$emit('group_change');
}
}
};
</script>
@@ -74,17 +74,17 @@
<el-table-column label="身份证号" prop="idCard"></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.otherSleepUser ? row.bedInfo?.otherSleepUser : '暂无' }}
</template>
</el-table-column>
@@ -1,11 +1,11 @@
<template>
<div>
<div v-if="view">
<a v-for="file in files" :key="file.id || file.filepath" :href="file.filepath || preview(file.id)" target="_blank" style="display:block">{{ file.filename || file.name }}</a>
<a v-for="file in files" :key="file.id || file.filepath" :href="file.downloadPath || file.filepath || preview(file.id)" target="_blank" style="display:block">{{ file.name || file.filename }}</a>
</div>
<el-upload v-else action="/platform/inclusiveTherapyV3/common/uploadFile" name="file"
<el-upload v-else action="/platform/sys/file/uploadDynamicReturnUrl" name="file"
:limit="max" :multiple="max > 1" :file-list="fileList" :drag="card"
:before-upload="beforeUpload" :on-success="success" :on-remove="remove" :on-preview="open">
:before-upload="beforeUpload" :on-success="success" :on-error="error" :on-remove="remove" :on-preview="open">
<el-button size="small" type="primary">选择文件</el-button>
<div slot="tip"><slot></slot></div>
</el-upload>
@@ -17,7 +17,7 @@ module.exports = {
max: {type: Number, default: 10}, type: Array, max_size: Number},
data() { return {fileList: []}; },
watch: {files: {immediate: true, deep: true, handler(files) {
this.fileList = (files || []).map(file => ({name: file.filename || file.name, url: file.filepath || therapyPreview(file.id), rawInfo: file}));
this.fileList = (files || []).map(file => ({name: file.name || file.filename, url: file.downloadPath || file.filepath || therapyPreview(file.id), rawInfo: file}));
}}},
methods: {
preview: therapyPreview,
@@ -28,15 +28,26 @@ module.exports = {
return true;
},
success(result, file, list) {
if (result.code !== 0) { this.$message.error(result.msg); return; }
file.rawInfo = result.data;
if (result.code !== 0) {
list.splice(list.indexOf(file), 1);
this.$message.error(result.msg); return;
}
if (typeof result.data !== 'string' || !result.data) {
list.splice(list.indexOf(file), 1);
this.$message.error('上传未返回文件地址'); return;
}
const id = new URL(result.data, window.location.origin).searchParams.get('id');
file.rawInfo = {id: id, name: file.name, filename: file.name,
downloadPath: result.data, filepath: result.data, url: result.data};
file.url = result.data;
this.emit(list);
},
error() { this.$message.error('文件上传失败,请重试'); },
remove(file, list) { this.emit(list); },
emit(list) {
this.$emit('update:files', list.map(file => file.rawInfo || file.response && file.response.data).filter(Boolean));
},
open(file) { window.open(file.url || file.rawInfo && file.rawInfo.filepath); }
open(file) { window.open(file.url || file.rawInfo && (file.rawInfo.downloadPath || file.rawInfo.filepath)); }
}
};
</script>
@@ -1,18 +1,19 @@
<template>
<el-upload action="/platform/inclusiveTherapyV3/common/uploadFile" name="file" list-type="picture-card"
<el-upload action="/platform/sys/file/uploadDynamicReturnUrl" name="file" list-type="picture-card"
:file-list="fileList" :limit="limit" :before-upload="beforeUpload"
:on-success="success" :on-remove="remove" :on-preview="open"
:on-success="success" :on-error="error" :on-exceed="exceed" :on-remove="remove" :on-preview="open"
:style="{'--therapy-width': width + 'px', '--therapy-height': height + 'px'}">
<i class="el-icon-plus"></i>
</el-upload>
</template>
<script>
module.exports = {
props: {value: {type: Array, default: () => []}, limit: {type: Number, default: 1},
props: {value: {type: [String, Array], default: ''}, limit: {type: Number, default: 1},
width: {type: Number, default: 100}, height: {type: Number, default: 100}, fileType: Array, fileSize: Number},
data() { return {fileList: []}; },
watch: {value: {immediate: true, deep: true, handler(values) {
this.fileList = (values || []).map((value, index) => ({name: '图片' + (index + 1), url: therapyPreview(value)}));
const items = Array.isArray(values) ? values : values ? [values] : [];
this.fileList = items.map((value, index) => ({name: '图片' + (index + 1), url: therapyPreview(value), storedValue: value}));
}}},
methods: {
beforeUpload(file) {
@@ -25,13 +26,31 @@ module.exports = {
return true;
},
success(result, file, list) {
if (result.code !== 0) { this.$message.error(result.msg); return; }
file.url = result.data.filepath;
if (result.code !== 0) {
list.splice(list.indexOf(file), 1);
this.$message.error(result.msg); return;
}
if (typeof result.data !== 'string' || !result.data) {
list.splice(list.indexOf(file), 1);
this.$message.error('上传未返回图片地址'); return;
}
file.url = result.data;
file.storedValue = result.data;
this.emit(list);
},
error() { this.$message.error('图片上传失败,请重试'); },
exceed() { this.$message.warning('最多上传' + this.limit + '张图片'); },
remove(file, list) { this.emit(list); },
emit(list) { this.$emit('input', list.map(file => file.response ? file.response.data.filepath : file.url)); },
open(file) { window.open(file.url); }
emit(list) {
const values = list.map(file => file.storedValue).filter(Boolean);
this.$emit('input', Array.isArray(this.value) ? values : values[0] || '');
},
open(file) {
const img = new Image();
img.src = file.url;
const viewer = new Viewer(img, {hidden() { viewer.destroy(); }});
viewer.show();
}
}
};
</script>
@@ -67,17 +67,17 @@
<el-table-column label="身份证号" prop="idCard"></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.otherSleepUser ? row.bedInfo?.otherSleepUser : '暂无' }}
</template>
</el-table-column>
@@ -448,10 +448,11 @@ module.exports = {
methods: {
// 返回布尔值
beforeRead(file) {
if (Array.isArray(file)) return file.every(item => this.beforeRead(item));
const lastIndexOf = file.name.lastIndexOf(".")
const type = this.type.map(v => v.toLowerCase()).includes(file.name.substr(lastIndexOf + 1).toLowerCase())
if (!type) {
this.$message.warning(`上传文件只能是 ${this.type.map(v => v.toLowerCase()).join("/")} 格式!`);
this.$toast(`上传文件只能是 ${this.type.map(v => v.toLowerCase()).join("/")} 格式!`);
return false;
}
return true;
@@ -466,13 +467,11 @@ module.exports = {
* 查看资源
*/
showSource(showItem) {
const show = this.resolvingShowByFileName(showItem.filepath)
const show = this.resolvingShowByFileName(showItem.name || showItem.filename || '')
if (show == 1 || show == 2 || show == 3) {
$('.viewFile').viewer({
url: 'src',
});
window.open(showItem.downloadPath || showItem.filepath || therapyPreview(showItem.id));
} else if (show == 4 || show == 5 || show == 7) {
preview(showItem.filepath, showItem.id)
preview(showItem.name || showItem.filename, showItem.id)
}
},
/**
@@ -596,9 +595,13 @@ module.exports = {
return FILE_DOMAIN + fileItem;
},
change(fileList) {
this.$emit("update:files", fileList.map(v => v.data))
this.$emit("update:files", fileList.map(v => v.data).filter(Boolean))
},
afterRead(file) {
if (Array.isArray(file)) {
file.forEach(item => this.afterRead(item));
return;
}
file.status = 'uploading';
file.message = '上传中...';
@@ -616,7 +619,12 @@ module.exports = {
if (code === 0) {
file.status = 'success';
file.data = data
file.url = data.downloadPath || data.filepath || therapyPreview(data.id)
this.change(this.fileList)
} else {
file.status = 'failed';
file.message = res.msg || '上传失败';
this.$toast.fail(file.message);
}
},
error: (err) => {
@@ -627,18 +635,19 @@ module.exports = {
},
doDelete(file) {
if (file.data) {
const {filename, filepath} = file.data
if (this.del) {
$.post(FILE_DELETE_ADDRESS, {filepath})
const {id} = file.data
if (this.del && id) {
$.post(FILE_DELETE_ADDRESS, {id})
}
this.change(this.fileList)
}
},
clickPreview(file) {
const {filepath, id} = file.data
const show = this.resolvingShowByFileName(filepath)
if (!file.data) return;
const {filename, name, id} = file.data
const show = this.resolvingShowByFileName(name || filename || '')
if (show == 4 || show == 5 || show == 7) {
preview(filepath, id)
preview(name || filename, id)
}
},
updateFileList(val) {
@@ -647,15 +656,15 @@ module.exports = {
return
}
const pending = this.fileList.filter(file => !file.data);
this.fileList = val.map(v => {
let url = ''
if (this.resolvingShowByFileName(v.filename) == 1) {
url = APP_DOMAIN + '/platform/inclusiveTherapyV3/common/preview?id=' + v.id
console.log(url)
return {data: v, url, isImage: true, file: {name: v.filename}, status: 'success'}
const name = v.name || v.filename || ''
const url = v.downloadPath || v.filepath || therapyPreview(v.id)
if (this.resolvingShowByFileName(name) == 1) {
return {data: v, url, isImage: true, file: {name}, status: 'success'}
}
return {data: v, url, file: {name: v.filename}, status: 'success'}
})
return {data: v, url, file: {name}, status: 'success'}
}).concat(pending)
},
},
created() {
@@ -668,4 +677,4 @@ module.exports = {
.van-image-preview .van-image-preview__close-icon--top-right {
font-size: 50px !important;
}
</style>
</style>
@@ -384,7 +384,7 @@ layout("/layouts/v4/baseLayout.html"){
return search(menus, []);
}
const result = findMenuPath(this.menus, targetHref)
const result = findMenuPath(this.menus, this.getMenuOwnerFullPath()) || findMenuPath(this.menus, targetHref)
if(result){
this.activeMenuIndex = result[result.length-1]['id']
this.openedMenus = result.map(v=>v.id)
@@ -399,6 +399,10 @@ layout("/layouts/v4/baseLayout.html"){
// 默认选中
getMenuOwnerPath() {
const pathname = window.location.pathname
if (pathname === "/platform/inclusiveTherapyV3") {
const screen = new URLSearchParams(window.location.search).get("screen")
if (screen) return pathname + "?screen=" + encodeURIComponent(screen)
}
// API配置表单不是独立菜单,直接刷新表单地址时仍归属API配置菜单。
if (pathname === "/platform/personGovernance/apiConfig/form") {
return "/platform/personGovernance/apiConfig"
@@ -283,6 +283,11 @@
})()
function pjaxReplace(url, data = null) {
// 普惠疗休养移动端使用独立布局,没有公共 PJAX 容器,需整页跳转以保留应用中心样式。
if (url && url.indexOf("/platform/inclusiveTherapyV3/mobile/") === 0) {
window.location.href = url
return
}
showH5PageSkeleton(url)
// 疗休养报名页面使用独立 H5 布局,其中包含图片懒加载等专用初始化逻辑。
// 禁止通过公共 PJAX 只替换页面片段,否则专用布局脚本不会执行,首次进入会出现图片懒加载指令未注册。
@@ -15,7 +15,7 @@ const act = {
<el-image :src="activity.cover" fit="cover" :alt="activity.name">
<div slot="error" class="portal-cover-empty"><i class="fa fa-picture-o" aria-hidden="true"></i><span>暂无图片</span></div>
</el-image>
<span class="status" :class="{'status-ended': getStatusText(activity) === '已结束', 'status-upcoming': getStatusText(activity) === '未开始'}">
<span class="status" :class="{'status-ended': getStatusText(activity) === '报名已结束', 'status-upcoming': getStatusText(activity) === '未开始'}">
{{getStatusText(activity)}}
</span>
</div>
@@ -76,9 +76,9 @@ const act = {
if (!this.swiper) return
this.swiper.isEnd ? this.swiper.slideTo(0) : this.swiper.slideNext()
},
/*查询活动*/
// PC首页包含已结束活动;接口data为按未结束在前、已结束在后排列的活动实体数组。
listAct() {
this.$axios.post("/platform/home/listHomeActivity").then((res) => {
this.$axios.post("/platform/home/listHomeActivity", {includeEnded: true}).then((res) => {
if (res.code === 0) {
// for (let i = 0; i < 10; i++) {
// this.actList = this.actList.concat(res.data)
@@ -149,7 +149,7 @@ const act = {
// 活动状态
getStatusText(item) {
if (this.$moment().unix() > this.$moment(item.endDate).unix()) {
return "已结束"
return "报名已结束"
} else if (this.$moment().unix() < this.$moment(item.startDate).unix()) {
return "未开始"
} else {
@@ -40,7 +40,7 @@ const branchUnionGroupManage = {
</el-card>
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogFormVisible" width="600px"
:close-on-click-modal="false">
:close-on-click-modal="false" @close="clearUserOptions">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="小组编码" prop="code">
<el-input v-model="formData.code" placeholder="小组编码" maxlength="10"
@@ -103,6 +103,7 @@ const branchUnionGroupManage = {
unitIds: [{ required: true, message: "请选择组成单位", trigger: "change" }],
},
userOptions: [],
userOptionsRequestId: 0,
units: [],
}
},
@@ -173,13 +174,21 @@ const branchUnionGroupManage = {
})
},
clearUserOptions() {
this.userOptions = []
// 关闭后使未完成的搜索失效,防止旧结果回填到下一次打开的弹窗。
this.userOptionsRequestId++
},
getUserOptions(keyword, userIds = null) {
if (!this.dialogFormVisible && !userIds) return
const requestId = ++this.userOptionsRequestId
$.get("/platform/sys/unionGroup/listUser", {
keyword,
unionId: this.union_id,
userIds: JSON.stringify(userIds)
}).then((res) => {
if (res.code === 0) {
if (res.code === 0 && this.dialogFormVisible && requestId === this.userOptionsRequestId) {
this.userOptions = res.data
}
})
@@ -71,7 +71,7 @@ const branchUnionManage = {
<div class="el-upload__text" v-if="cadreImportLoading">正在导入,请稍候…</div>
<div class="el-upload__text" v-else>将文件拖到此处,或<em>点击选择文件</em></div>
</el-upload>
<div class="union-cadre-import-note">选择文件后点击“开始导入”。逐行保存,一行失败不影响其他行。</div>
<div class="union-cadre-import-note">选择文件后点击“开始导入”。批量校验并保存,失败行显示具体原因,其他有效行继续导入。</div>
</section>
</div>
<section v-if="cadreImportResult" class="union-cadre-import-results">
@@ -77,6 +77,7 @@ layout("/layouts/platform.html"){
<el-input placeholder="输入关键字进行查找" v-model="filterText" clearable></el-input>
<div style="max-height: calc(100vh - 200px); overflow-y: auto">
<el-tree
v-loading="treeLoading"
:data="treeData"
ref="treeRef"
:expand-on-click-node="false"
@@ -151,13 +152,14 @@ layout("/layouts/platform.html"){
<!--#include("unitLeader.js"){}#-->
new Vue({
el: "#app",
data: function () {
data() {
return {
unitTabActive: "threeUnitManage",
filterText: null,
currentTreeNode: null,
currentTreeData: null,
defaultExpandedKeys: [],
treeLoading: false,
treeData: []
}
},
@@ -173,26 +175,45 @@ layout("/layouts/platform.html"){
},
methods: {
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.currentTreeData = this.treeData[0]
this.defaultExpandedKeys = this.treeData.length > 0 ? [this.treeData[0].id] : []
this.$set(this, "treeLoading", true)
// tree 返回单位树数组;失败时保留现有内容,成功后按 ID 恢复当前单位。
return this.$axios.post(loc() + "/tree").then((res) => {
if (res.code !== 0 || !Array.isArray(res.data)) return
const selectedId = this.currentTreeData?.id
this.$set(this, "treeData", res.data)
this.$set(this, "defaultExpandedKeys", res.data.length > 0 ? [res.data[0].id] : [])
if (res.data.length === 0) {
this.$set(this, "currentTreeData", null)
this.$set(this, "currentTreeNode", null)
return
}
this.$nextTick(() => {
const tree = this.$refs.treeRef
const node = (selectedId && tree.getNode(selectedId)) || tree.getNode(res.data[0].id)
// 将选中节点的祖先展开,避免刷新后当前单位隐藏在折叠的分支中。
let parent = node.parent
while (parent && parent.level > 0) {
parent.expanded = true
parent = parent.parent
}
tree.setCurrentKey(node.data.id)
tree.filter(this.filterText)
this.treeNodeClick(node.data, node)
})
}).finally(() => {
this.$set(this, "treeLoading", false)
})
},
treeNodeClick(data, node) {
this.currentTreeData = data
this.currentTreeNode = node
this.$nextTick(()=>{
if (data.unitTypeCode==1) {
this.$refs.bmlRef.pageData()
this.$refs.userRef.pageData()
this.$refs.leaderRef.pageData()
} else {
this.$refs.bzlRef.pageData()
}
})
this.$set(this, "currentTreeData", data)
this.$set(this, "currentTreeNode", node)
// 单位列表由 currentData 监听刷新,部门类另外更新人员和干部页签。
this.$nextTick(() => {
if (data.unitTypeCode == 1) {
this.$refs.userRef.pageData()
this.$refs.leaderRef.pageData()
}
})
},
filterNode(value, data, node) {
if (!value) return true
@@ -11,7 +11,7 @@ const UNIT_MANAGE_TEMPLATE = {
<table-tool label="单位列表">
<el-button @click="openAdd" type="primary" size="small">新建单位</el-button>
</table-tool>
<el-table :data="tableData" size="mini">
<el-table :data="tableData" v-loading="tableLoading" size="mini">
<el-table-column label="序号" type="index" width="60">
<template v-slot="scope">{{scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</template>
</el-table-column>
@@ -75,8 +75,8 @@ const UNIT_MANAGE_TEMPLATE = {
<!-- </el-form-item>-->
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doHandle">确 定</el-button>
<el-button :disabled="formLoading" @click="closeDialog">取 消</el-button>
<el-button type="primary" :loading="formLoading" @click="doHandle">确 定</el-button>
</span>
</el-dialog>
</div>
@@ -110,6 +110,8 @@ const UNIT_MANAGE_TEMPLATE = {
audit: false
},
tableData: [],
tableLoading: false,
formLoading: false,
dialogVisible: false,
formData: {},
formRules: {
@@ -128,96 +130,130 @@ const UNIT_MANAGE_TEMPLATE = {
}
},
computed: {},
watch: {
// 首次进入、切换节点以及刷新树后,均按最新上级单位从第一页重新查询。
currentData: {
immediate: true,
handler() {
this.doSearch()
}
}
},
methods: {
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
this.$set(this.pageForm, "pageNumber", 1)
return this.pageData()
},
openAdd() {
this.dialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
this.parentUnit = []
this.options = []
// 上级关系取当前单位 ID,与用户是否点击过树节点无关;手工新增默认其他类。
this.$set(this, "formData", {
parentId: this.currentData.id,
unitLevel: this.unitLevel,
unitTypeCode: 0
})
this.$set(this, "parentUnit", [])
this.$set(this, "options", [])
this.$set(this, "dialogVisible", true)
this.$nextTick(() => {
this.$refs.form.clearValidate()
})
},
closeDialog() {
// 提交过程中保留表单,等待请求完成后再允许取消。
if (!this.formLoading) {
this.$set(this, "dialogVisible", false)
}
},
doHandle() {
this.$confirm("确定要提交吗?", "提示", {
if (this.formLoading) return
this.$refs.form.validate((valid) => {
if (!valid) return
return this.$confirm("确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
if (this.formLoading) return
const url = this.formData.id ? "/platform/sys/unit/editDo" : "/platform/sys/unit/addDo"
// 新建始终携带当前上级;编辑沿用回显的原上级,不在保存时意外变更层级。
if (!this.formData.id) {
this.$set(this.formData, "parentId", this.currentData.id)
}
this.$set(this, "formLoading", true)
return this.$axios.post(url, this.formData).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$set(this, "dialogVisible", false)
// 父页面刷新并恢复当前树节点,currentData 监听统一刷新列表,避免重复查询。
this.$emit("refresh", null)
} else {
this.$message.warning(resp.msg)
}
}).finally(() => {
this.$set(this, "formLoading", false)
})
}).catch(() => {
// 取消确认直接结束;请求错误由全局 axios 拦截器提示,保留表单供重试。
})
})
},
// id 为待编辑单位 ID,接口 data 为单位实体;保留已有部门类别及原上级关系。
openEdit(id) {
return this.$axios.post("/platform/sys/unit/edit/" + id).then((resp) => {
if (resp.code === 0) {
this.$set(this, "formData", resp.data)
this.$set(this, "dialogVisible", true)
this.$nextTick(() => {
this.$refs.form.clearValidate()
})
} else {
this.$message.warning(resp.msg)
}
})
},
doDelete(id) {
return this.$confirm("此操作将永久删除, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const self = this
const url = this.formData.id ? "/platform/sys/unit/editDo" : "/platform/sys/unit/addDo"
this.$refs["form"].validate(async function (valid) {
if (valid) {
if (self.currentNode) {
self.formData.parentId = self.currentData.id
}
const resp = await self.$axios.post(url, self.formData)
if (resp.code === 0) {
self.$message.success(resp.msg)
self.doSearch()
self.dialogVisible = false
self.$emit("refresh", null)
} else {
self.$message.warning(resp.msg)
}
return this.$axios.post("/platform/sys/unit/delete/" + id).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$emit("refresh", null)
} else {
this.$message.warning(resp.msg)
}
})
})
},
async openEdit(id) {
console.log(this.currentData)
const resp = await this.$axios.post("/platform/sys/unit/edit/" + id)
if (resp.code === 0) {
this.formData = resp.data
this.dialogVisible = true
} else {
this.$message.warning(resp.msg)
}
},
async doDelete(id) {
const confirm = await this.$confirm("此操作将永久删除, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post("/platform/sys/unit/delete/" + id)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
this.$emit("refresh", null)
} else {
this.$message.warning(resp.msg)
}
}
},
pageNumberChange(val) {
this.pageForm.pageNumber = val
this.$set(this.pageForm, "pageNumber", val)
this.pageData()
},
pageSizeChange(val) {
this.pageForm.pageSize = val
this.$set(this.pageForm, "pageSize", val)
this.pageData()
},
pageData() {
this.pageForm.unitId = this.currentData.id
// this.pageForm.unitLevel = this.unitLevel
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (!this.currentData || !this.currentData.id) return
// unitId 限定当前上级,返回 data.list 为下设单位,data.totalCount 为分页总数。
this.$set(this.pageForm, "unitId", this.currentData.id)
this.$set(this, "tableLoading", true)
return this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
this.$set(this, "tableData", res.data.list)
this.$set(this.pageForm, "totalCount", res.data.totalCount)
}
}).finally(() => {
this.$set(this, "tableLoading", false)
})
}
},
async created() {
this.pageData()
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')) {
this.unions = await this.$businessTool.listUnion()
} else {
this.unions = await this.$businessTool.listUnion(this.store.state.user.union.id)
}
created() {
const unionId = this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN') ? null : this.store.state.user.union.id
this.$businessTool.listUnion(unionId).then((unions) => {
this.$set(this, "unions", unions)
})
}
}
@@ -119,7 +119,7 @@ layout("/layouts/platform.html"){
currentTreeNode: null,
currentTreeData: null,
checkData: {},
checkData: { id: "0", name: "无(新建根节点)" },
tableData: [],
basicTypeDialog: false,
@@ -146,10 +146,8 @@ layout("/layouts/platform.html"){
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.checkData = this.treeData[0]
}
this.treeData = res.data || []
this.checkData = this.treeData.length ? this.treeData[0] : { id: "0", name: "无(新建根节点)" }
})
},
@@ -14,6 +14,7 @@ const ACTIVITY_BASIC_BRANCH_UNION_MANAGE = {
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<table-tool>
<el-button @click="openAdd" icon="ti-plus" type="primary" style="margin-left: auto" size="small">新建临时分工会</el-button>
<el-button @click="updateUnions" :loading="formLoading" :disabled="formLoading" icon="el-icon-refresh" type="primary" size="small">更新工会</el-button>
</table-tool>
<el-table :data="tableData" border size="small" height="calc(100vh - 375px)">
<el-table-column label="序号" type="index" :index="indexMethod" width="100px"></el-table-column>
@@ -79,6 +80,7 @@ const ACTIVITY_BASIC_BRANCH_UNION_MANAGE = {
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/activity/basic/union/pageData",
dialogFormVisible: false,
dialogGlyFormVisible: false,
formData: {},
@@ -88,10 +90,25 @@ const ACTIVITY_BASIC_BRANCH_UNION_MANAGE = {
}
},
methods: {
pageData() {
this.$axios.post("/platform/activity/basic/union/pageData", this.pageForm).then((res) => {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
// 同步新增工会和已有工会名称;复用表格查询及父页面刷新事件,保留现有查询和分页逻辑。
updateUnions() {
if (this.formLoading) {
return
}
this.$set(this, "formLoading", true)
return this.$axios.post("/platform/activity/basic/union/updateUnions").then((res) => {
if (res.code !== 0) {
this.notifyWarning(res.msg)
return
}
const result = res.data
this.notifySuccess("工会更新完成:新增 " + result.insertCount + " 个,更新名称 " + result.updateCount + " 个。")
this.$emit("refresh", null)
return this.pageData()
}).catch(() => {
this.notifyError("工会更新或刷新失败,请刷新页面后核对结果")
}).finally(() => {
this.$set(this, "formLoading", false)
})
},
openAdd() {
@@ -9,10 +9,10 @@ layout("/layouts/platform.html"){
<div style="max-height: calc(100vh - 160px); overflow-y: auto">
<el-tree
:data="treeData"
:default-expanded-keys="['1']"
:default-expanded-keys="pageForm.parentId ? [pageForm.parentId] : []"
:expand-on-click-node="false"
:props="{
children: 'child',
children: 'children',
label: 'name'
}"
@node-click="treeNodeClick"
@@ -52,6 +52,7 @@ layout("/layouts/platform.html"){
</div>
<div class="search-item">
<el-button @click="doSearch" icon="el-icon-search" type="primary">搜索</el-button>
<el-button @click="updateUnits" :loading="formLoading" :disabled="formLoading" icon="el-icon-refresh" type="primary">更新单位</el-button>
</div>
</div>
</el-card>
@@ -104,6 +105,36 @@ layout("/layouts/platform.html"){
},
components: {},
methods: {
// 点击后同步一次系统单位;已有活动工会归属由后端保留,完成后刷新树和当前单位列表。
updateUnits() {
if (this.formLoading) {
return
}
this.$set(this, "formLoading", true)
this.$axios.post(loc() + "/updateUnits").then((res) => {
if (res.code !== 0) {
this.notifyWarning(res.msg)
return
}
const result = res.data
let message = "单位更新完成:新增 " + result.insertCount + " 个,更新 " + result.updateCount + " 个。"
if (result.pendingUnionCount > 0) {
message += "新增单位中有 " + result.pendingUnionCount + " 个待配置活动工会,请到活动工会的组成单位中维护。"
this.notifyWarning(message)
} else {
this.notifySuccess(message)
}
return this.getTreeData().then((loaded) => {
if (loaded) {
this.doSearch()
}
})
}).catch(() => {
this.notifyError("单位更新或刷新失败,请刷新页面后核对结果")
}).finally(() => {
this.$set(this, "formLoading", false)
})
},
async doDelete(id) {
const confirm = await this.$confirm("确定要删除该单位吗?", "提示", {
confirmButtonText: "确定",
@@ -122,24 +153,42 @@ layout("/layouts/platform.html"){
}
},
treeNodeClick(data, node) {
this.currentTreeData = data
this.currentTreeNode = node
this.pageForm.parentId = data.id
this.$set(this, "currentTreeData", data)
this.$set(this, "currentTreeNode", node)
this.$set(this.pageForm, "parentId", data.id)
this.doSearch()
},
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.currentTreeData = this.treeData[0]
return this.$axios.post(loc() + "/tree").then((res) => {
if (res.code !== 0) {
this.notifyWarning(res.msg)
return false
}
this.$set(this, "treeData", res.data || [])
// 同步后沿用当前选择,首次进入按真实树根查询,不再依赖旧的根单位ID常量。
if (!this.pageForm.parentId && this.treeData.length > 0) {
this.$set(this.pageForm, "parentId", this.treeData[0].id)
}
this.$nextTick(() => {
const tree = this.$refs.treeRef
const node = tree.getNode(this.pageForm.parentId)
this.$set(this, "currentTreeNode", node || null)
this.$set(this, "currentTreeData", node ? node.data : null)
tree.setCurrentKey(this.pageForm.parentId)
})
return true
})
},
openUnit() {}
},
created() {
this.pageData()
this.getTreeData()
this.getTreeData().then((loaded) => {
if (loaded) {
this.doSearch()
}
}).catch(() => {
this.notifyError("加载单位失败,请稍后重试")
})
}
})
</script>
@@ -370,12 +370,14 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
</el-form-item>
</el-col>
<!--
<el-col :span="24">
<el-form-item label="报名表单" prop="formConfig"
v-if="formData.isEnrollSystem&&formData.signUpMethod===1">
<custom-form-field v-model="formData.formConfig"></custom-form-field>
</el-form-item>
</el-col>
-->
<el-col :span="24" v-if="formData.signUpMethod!=null&&formData.isEnrollSystem">
<el-form-item label="封面图" prop="cover">
@@ -592,6 +594,7 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
name: [{required: true, message: "必填", trigger: ["blur", "change"]}],
type: [{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"]}],
plannedDate: [{required: true, message: "必填", trigger: ["blur", "change"]}],
time: [{required: true, message: "必填", trigger: ["blur", "change"]}],
@@ -725,7 +728,15 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
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) {
this.$message.error("请选择活动项目类型")
return
@@ -6,18 +6,19 @@ layout("/layouts/platform.html"){
<template>
<el-card shadow="never">
<search @search="doSearch" :is-search-button="false">
<search @search="refreshPrizes" :is-search-button="false">
<search-item label="年度">
<el-date-picker
:clearable="false"
:disabled="tableLoading"
@change="getActivitys"
placeholder="选择年"
style="width: 100%" type="year"
v-model="pageForm.year" value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="活动名称" v-if="!pageForm.status">
<el-select :clearable="false" @change="actChange(pageForm.activityId)"
<search-item label="活动名称" v-if="pageForm.status!=='1'">
<el-select :clearable="false" :disabled="tableLoading" @change="actChange(pageForm.activityId)"
filterable
placeholder="请选择活动名称"
style="width: 100%" v-model="pageForm.activityId">
@@ -30,7 +31,7 @@ layout("/layouts/platform.html"){
</el-select>
</search-item>
<search-item label="工会名称" v-if="!pageForm.status">
<el-select :clearable="false" @change="unionChange(pageForm.unionId)"
<el-select :clearable="false" :disabled="tableLoading" @change="unionChange(pageForm.unionId)"
filterable
placeholder="请选择工会"
style="width: 100%" v-model="pageForm.unionId">
@@ -43,9 +44,9 @@ layout("/layouts/platform.html"){
</el-select>
</search-item>
<search-item label="性别" v-if="pageForm.status==='1'||!pageForm.status">
<el-select filterable
<el-select filterable :disabled="tableLoading"
placeholder="请选择性别"
style="width: 100%" v-model="pageForm.sex">
style="width: 100%" v-model="pageForm.sex" @change="sexChange">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
@@ -56,7 +57,7 @@ layout("/layouts/platform.html"){
<el-card class="mt10" shadow="never">
<table-tool
:label="pageForm.status==='2'?('浙江师范大学'+pageForm.year+'年教职工运动会获奖个数汇总表'):'奖品名单'">
:label="pageForm.status==='2'?('中国地质大学(武汉)'+pageForm.year+'年教职工运动会获奖个数汇总表'):'奖品名单'">
<el-tag
:effect="pageForm.status===item.code?'dark':'plain'"
:key="item.code"
@@ -66,17 +67,32 @@ layout("/layouts/platform.html"){
v-for="item in statusOptions">
{{ item.name }}
</el-tag>
<el-button @click="print" icon="el-icon-printer" type="primary" size="small">打 印</el-button>
<el-button @click="print" :disabled="tableLoading || queryFailed" icon="el-icon-printer" type="primary" size="small">打 印</el-button>
</table-tool>
<div id=print>
<template v-if="pageForm.activityId!=null">
<!-- 未分配记录同时进入打印内容,避免将部分已确认数量当作最终发放总数。 -->
<div v-if="isSummary!==3" class="mb10">
<p>{{ isSummary===2 ? '当前活动' : '当前工会' }}已确认奖品:{{ confirmedTotal }}份;当前活动待确认成绩:{{ pendingResults.length }}条。</p>
<el-alert v-if="pendingResults.length" type="warning" :closable="false" title="当前数量尚未包含以下待确认成绩,请补充分配后再作为最终发放依据。"></el-alert>
<table v-if="pendingResults.length" class="table table-bordered">
<tr><th>项目</th><th>参赛工会/人员</th><th>名次</th><th>获奖总人数</th><th>操作</th></tr>
<tr v-for="item in pendingResults" :key="item.id">
<td>{{ item.allName }}</td>
<td>{{ item.username || item.participantUnionName }}</td>
<td>第{{ item.ranking }}名</td>
<td>{{ item.totalNumberOfPeople == null ? '待确认' : item.totalNumberOfPeople }}</td>
<td><a :href="resultsInputUrl(item)">补充分配</a></td>
</tr>
</table>
</div>
<template v-if="isSummary!==3">
<table class="table table-bordered" v-if="isSummary==1" v-loading="tableLoading">
<tr>
<td class="text-center" colspan="11">
<span v-if="activityList.find(v=>v.id === pageForm.activityId)">
浙江师范大学{{ activityList.find(v=>v.id === pageForm.activityId).name }}
中国地质大学(武汉){{ activityList.find(v=>v.id === pageForm.activityId).name }}
({{unionName}})获奖名单
</span>
</td>
@@ -97,10 +113,10 @@ layout("/layouts/platform.html"){
<td>{{k}}</td>
<td v-for="i in 8">
<span v-if="o.filter(f=>f.ranking==i && f.numberOfPeople!=null) && o.filter(f=>f.ranking==i && f.numberOfPeople!=null).length>0">
{{o.filter(f=>f.ranking==i && f.numberOfPeople!=null).map(g=>g.numberOfPeople).reduce((a,b)=>a+b)}}
{{o.filter(f=>f.ranking==i && f.numberOfPeople!=null).map(g=>Number(g.numberOfPeople)).reduce((a,b)=>a+b,0)}}
</span>
</td>
<td></td>
<td>{{ prizeSourceText(o) }}</td>
</tr>
<tr v-for="(o,k,index) in tableDataUnionPrize['男子项目']">
<td :rowspan="Object.keys(tableDataUnionPrize['男子项目']).length"
@@ -111,7 +127,7 @@ layout("/layouts/platform.html"){
<td v-for="i in 8">
{{o.filter(f=>f.ranking==i).map(g=>g.username).join('、')}}
</td>
<td></td>
<td>{{ prizeSourceText(o) }}</td>
</tr>
<tr v-for="(o,k,index) in tableDataUnionPrize['女子项目']">
<td :rowspan="Object.keys(tableDataUnionPrize['女子项目']).length" dd
@@ -122,7 +138,13 @@ layout("/layouts/platform.html"){
<td v-for="i in 8">
{{o.filter(f=>f.ranking==i).map(g=>g.username).join('、')}}
</td>
<td></td>
<td>{{ prizeSourceText(o) }}</td>
</tr>
<tr v-for="(o,k,index) in tableDataUnionPrize['其他']">
<td :rowspan="Object.keys(tableDataUnionPrize['其他']).length" v-if="index===0">其他项目</td>
<td>{{ k }}</td>
<td v-for="i in 8">{{ o.filter(item=>item.ranking===i).map(item=>item.username).join('、') }}</td>
<td>{{ prizeSourceText(o) }}</td>
</tr>
<tr>
<td>合计</td>
@@ -283,200 +305,161 @@ layout("/layouts/platform.html"){
],
tableDataUnionPrize: {},
lastSum: {},
tableDataPrize: [],
tableDataPrize: {},
confirmedTotal: 0,
pendingResults: [],
queryFailed: false,
statusOptions: [{code: "1", name: "分组汇总年度前八"}, {code: "2", name: "奖品个数年度汇总表"}]
}
},
components: {},
methods: {
async statusType(state) {
this.tableLoading = true
if (state === "1") {
const data = await this.summaryYearPrizes()
if (!data) {
this.tableLoading = false
return
}
} else if (state === "2") {
this.pageForm.sex = null
await this.summary()
statusType(state) {
if (this.tableLoading) return
const next = this.pageForm.status === state ? null : state
if (next === '1' && !this.pageForm.sex) {
this.$message.warning('请选择性别')
return
}
if (this.pageForm.status === state) {
this.pageForm.status = null
this.pageForm.sex = null
this.pageForm.activityId = this.activityList[0].id
this.pageForm.unionId = this.unionList[0].id
this.unionChange(this.unionList[0].id)
} else {
this.pageForm.status = state
}
this.tableLoading = false
this.$set(this.pageForm, 'status', next)
this.$set(this, 'isSummary', next === '1' ? 3 : (next === '2' ? 2 : 1))
return this.refreshPrizes()
},
getSummaryByYear(o, i, type) {
if (type === "集体项目") {
const datas = o.filter(o => o.ranking === i).map(o => o.unionname)
if (datas) {
return datas.join(",")
} else {
return ""
}
} else {
//甲组里面有可能有团体项目,所以说如果这个没有username就代表是团体
return o.filter(f => f.ranking === i).map(g => g.username ? g.username : g.unionname).join('、')
}
// 三种展示分别刷新,沿用mixins的分页能力,不另写公共表格分页方法。
refreshPrizes() {
if (this.isSummary === 3) return this.summaryYearPrizes()
if (this.isSummary === 2) return this.summary()
return this.getPrizes()
},
async summaryYearPrizes() {
try {
if (!this.pageForm.sex) {
this.$message.warning("请选择性别")
return false
}
this.$set(this.pageForm, "unionId", null)
this.$set(this.pageForm, "activityId", null)
this.isSummary = 3
const {data} = await this.$axios.post(loc() + "/getSummaryYearPrizes", this.pageForm)
this.tableDataPrize = data
return true
} catch (e) {
this.$message.error(e.msg)
return false
}
sexChange() {
if (this.isSummary === 3) return this.summaryYearPrizes()
},
getTableTdContent(d, i) {
return d.filter(v => {
if (v.isteampersonal === 1) {
if (v.ranking == i) {
console.log(v, i)
return v.username
}
} else {
if (v.ranking == i) {
return v.numberofpeople
}
}
}).map(v => {
return v.isteampersonal === 1 ? v.username : v.numberofpeople
}).toString()
getSummaryByYear(rows, ranking, type) {
return rows.filter(item => item.ranking === ranking).map(item => type === '集体项目' ? item.unionname : (item.username || item.unionname)).join('、')
},
async summary() {
try {
if (this.activityList.length === 0) {
return
}
if (!this.pageForm.activityId) {
this.pageForm.activityId = this.activityList[0].id
}
this.$set(this.pageForm, "unionId", null)
this.isSummary = 2
this.tableData = []
const {data} = await this.$axios.post(loc() + "/summary", this.pageForm)
this.$set(this, "tableData", data.score)
this.unionName = "汇总"
} catch (e) {
this.$message.error(e.msg)
prizeSourceText(rows) {
return [...new Set(rows.map(item => item.participantUnionName).filter(Boolean))].join('、')
},
resultsInputUrl(item) {
return '/platform/activity/results/input?activityId=' + encodeURIComponent(item.activityId)
+ '&eventId=' + encodeURIComponent(item.eventId) + '&year=' + encodeURIComponent(this.pageForm.year)
},
acceptPrizeStatistics(data) {
this.$set(this, 'confirmedTotal', Number(data.confirmedTotal) || 0)
this.$set(this, 'pendingResults', data.pendingResults || [])
},
clearPrizeStatistics() {
this.$set(this, 'confirmedTotal', 0)
this.$set(this, 'pendingResults', [])
this.$set(this, 'lastSum', {})
this.$set(this, 'tableDataUnionPrize', {})
this.$set(this, 'tableData', [])
},
summaryYearPrizes() {
if (!this.pageForm.sex) {
this.$message.warning('请选择性别')
return Promise.resolve()
}
this.$set(this, 'tableLoading', true)
this.$set(this, 'queryFailed', false)
this.$set(this, 'tableDataPrize', {})
return this.$axios.post(loc() + '/getSummaryYearPrizes', this.pageForm).then((resp) => {
if (resp.code !== 0) throw new Error(resp.msg || '年度名次查询失败')
this.$set(this, 'tableDataPrize', resp.data)
}).catch((error) => {
this.$set(this, 'queryFailed', true)
this.$message.error(error.message || error.msg || '年度名次查询失败')
}).finally(() => {
this.$set(this, 'tableLoading', false)
})
},
summary() {
this.clearPrizeStatistics()
this.$set(this, 'tableLoading', true)
this.$set(this, 'queryFailed', false)
return this.$axios.post(loc() + '/summary', {activityId: this.pageForm.activityId}).then((resp) => {
if (resp.code !== 0) throw new Error(resp.msg || '奖品汇总查询失败')
this.$set(this, 'tableData', resp.data.score || [])
this.acceptPrizeStatistics(resp.data)
}).catch((error) => {
this.$set(this, 'queryFailed', true)
this.$message.error(error.message || error.msg || '奖品汇总查询失败')
}).finally(() => {
this.$set(this, 'tableLoading', false)
})
},
print() {
let subOutputRankPrint = document.getElementById('print');
let newContent = subOutputRankPrint.innerHTML;
let oldContent = document.body.innerHTML;
document.body.innerHTML = newContent;
window.print();
window.location.reload();
document.body.innerHTML = oldContent;
return false;
if (this.tableLoading || this.queryFailed) return
let newContent = document.getElementById('print').innerHTML
let oldContent = document.body.innerHTML
document.body.innerHTML = newContent
window.print()
window.location.reload()
document.body.innerHTML = oldContent
return false
},
actChange(activityId) {
this.tableColumns = []
this.tableData = []
this.pageForm.activityId = ""
const activityData = this.activityList.find(v => v.id == activityId)
this.pageForm.activityId = activityData.id
this.getPrizes()
this.$set(this.pageForm, 'activityId', activityId)
return this.refreshPrizes()
},
unionChange(unionId) {
this.tableColumns = []
this.tableData = []
this.pageForm.unionId = ""
this.isSummary = 1
const unionData = this.unionList.find(v => v.id == unionId)
this.pageForm.unionId = unionData.id
this.unionName = unionData.name
this.getPrizes()
this.$set(this.pageForm, 'unionId', unionId)
const union = this.unionList.find(item => item.id === unionId)
this.$set(this, 'unionName', union ? union.name : '')
return this.getPrizes()
},
async getActivitys() {
this.tableData = []
const {data} = await this.$axios.post("/platform/activity/score/statistics/getActivitys", {year: this.pageForm.year})
this.pageForm.activityId = ""
this.activityList = data
if (data && data.length > 0) {
this.pageForm.activityId = data[0].id
}
await this.getPrizes()
},
async getPrizes() {
try {
this.tableLoading = true
const {data} = await this.$axios.post(loc() + "/getPrizes", this.pageForm)
this.tableDataUnionPrize = data
const lastSum = {}
for (let i = 1; i <= 8; i++) {
let sum = 0
if (!$.isEmptyObject(data['男子项目'])) {
let xm = []
for (let key in data['男子项目']) {
xm = xm.concat(data['男子项目'][key])
}
sum += xm.filter(v => v.ranking === i).length
}
if (!$.isEmptyObject(data['女子项目'])) {
let xm = []
for (let key in data['女子项目']) {
xm = xm.concat(data['女子项目'][key])
}
sum += xm.filter(v => v.ranking === i).length
}
if (!$.isEmptyObject(data['团体项目'])) {
let xm = []
for (let key in data['团体项目']) {
xm = xm.concat(data['团体项目'][key])
}
const teams = xm.filter(v => v.ranking === i).map(v => Number(v.numberOfPeople))
if (teams && teams.length > 0) {
sum += teams.reduce((a, b) => a + b)
}
}
lastSum[i] = sum
getActivitys() {
this.clearPrizeStatistics()
this.$set(this, 'tableDataPrize', {})
this.$set(this, 'tableLoading', true)
this.$set(this, 'queryFailed', false)
return this.$axios.post('/platform/activity/score/statistics/getActivitys', {year: this.pageForm.year}).then((resp) => {
if (resp.code !== 0) throw new Error(resp.msg || '活动查询失败')
const activities = resp.data || []
this.$set(this, 'activityList', activities)
if (!activities.some(item => item.id === this.pageForm.activityId)) {
this.$set(this.pageForm, 'activityId', activities.length ? activities[0].id : '')
}
lastSum[9] = Object.values(lastSum).reduce((a, b) => a + b)
this.lastSum = lastSum
} catch (e) {
this.$message.error(e.msg)
} finally {
this.tableLoading = false
}
return this.refreshPrizes()
}).catch((error) => {
this.$set(this, 'queryFailed', true)
this.$message.error(error.message || error.msg || '活动查询失败')
}).finally(() => {
this.$set(this, 'tableLoading', false)
})
},
getPrizes() {
this.clearPrizeStatistics()
this.$set(this, 'tableLoading', true)
this.$set(this, 'queryFailed', false)
return this.$axios.post(loc() + '/getPrizes', this.pageForm).then((resp) => {
if (resp.code !== 0) throw new Error(resp.msg || '奖品名单查询失败')
this.$set(this, 'tableDataUnionPrize', resp.data)
// 名单与汇总共用后端人数统计,前端不再用积分或整队人数另算一套合计。
this.$set(this, 'lastSum', resp.data.lastSum || {})
this.acceptPrizeStatistics(resp.data)
}).catch((error) => {
this.$set(this, 'queryFailed', true)
this.$message.error(error.message || error.msg || '奖品名单查询失败')
}).finally(() => {
this.$set(this, 'tableLoading', false)
})
},
},
async created() {
await this.getActivitys()
this.unionList = await this.$businessTool.listUnion()
if (this.unionList.length > 0) {
this.pageForm.unionId = this.unionList[0].id
this.unionName = this.unionList[0].unionname
}
await this.getPrizes()
created() {
this.$set(this, 'tableLoading', true)
this.$businessTool.listUnion().then((unions) => {
this.$set(this, 'unionList', unions || [])
this.$set(this.pageForm, 'unionId', unions.length ? unions[0].id : '')
this.$set(this, 'unionName', unions.length ? unions[0].name : '')
return this.getActivitys()
}).catch((error) => {
this.$set(this, 'queryFailed', true)
this.$message.error(error.message || error.msg || '工会查询失败')
}).finally(() => {
this.$set(this, 'tableLoading', false)
})
}
})
</script>
File diff suppressed because it is too large Load Diff
@@ -73,7 +73,8 @@ layout("/layouts/platform.html"){
</el-select>
</search-item>
<search-item>
<el-button @click="doExcelCj" icon="el-icon-printer" type="primary">导出成绩excel
<el-button @click="doExcelCj" icon="el-icon-printer" type="primary"
:disabled="!pageForm.activityId">导出成绩excel
</el-button>
</search-item>
</search>
@@ -301,10 +302,18 @@ layout("/layouts/platform.html"){
},
doExcelCj() {
const {activityId, unionname} = this.pageForm
// 年度统计视图下 activityId 已被清空,此处导出会查不到数据
if (!activityId) {
this.$message.warning("当前为年度统计视图,无法导出单个活动的成绩明细,请先选择「运动会成绩统计」中的任一维度")
return
}
let unionId = ''
if (unionname) {
const unionlist = clone(this.unionList)
unionId = unionlist.find(v => v.unionname === unionname).id
const target = unionlist.find(v => v.name === unionname)
if (target) {
unionId = target.id
}
}
this.$downLoad(loc() + "/doExcelCj", {activityId: activityId, unionId: unionId})
@@ -585,11 +585,13 @@ const basicForm = {
return
}
const courseValid = this.formData.courseList.some((v, i) => {
// 新活动通过多选关系设置负责人;未重新设置的旧活动仍允许保留历史联系人。
const hasResponsible = Array.isArray(v.responsibleList)
? v.responsibleList.length > 0 : !!v.courseInstructor
const basicValid = v.courseName && v.coursePeopleNumber && v.courseLocation && hasResponsible && v.courseType
const missingFields = []
if (!v.courseName) missingFields.push(this.trainType + "名称")
if (!v.coursePeopleNumber) missingFields.push(this.trainType + "人数(不能为空或为0)")
if (!v.courseLocation) missingFields.push(this.trainType + "地点")
if (!v.courseType) missingFields.push("类型")
const timeValid =
Array.isArray(v.courseTimeList) &&
v.courseTimeList.length > 0 &&
v.courseTimeList.every((x) => {
return x.courseStartTime && x.courseEndTime && x.courseStartTime < x.courseEndTime
@@ -598,8 +600,8 @@ const basicForm = {
this.$message.warning("第" + (i + 1) + "行时间填写有误,请核查")
return true
}
if (!basicValid) {
this.$message.warning("第" + (i + 1) + "行信息填写有误,请核查")
if (missingFields.length > 0) {
this.$message.warning("第" + (i + 1) + "行请补充:" + missingFields.join("、"))
return true
}
// 联系方式允许手机号或办公电话,逐人校验,不能只检查兼容展示的第一位。
@@ -0,0 +1,126 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search :is-search-button="false" @search="doSearch">
<search-item label="社团名称:">
<el-select v-model="pageForm.clubId" placeholder="请选择社团" clearable filterable>
<el-option v-for="item in clubList" :key="item.id" :label="item.clubName" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号:">
<user-select
v-model="pageForm.userId"
placeholder="请输入姓名或工号选择人员"
api_input_key_name="query"
:option_label_func="(item) => item.username + '(' + item.loginname + ')'"
></user-select>
</search-item>
<search-item label="所属单位:">
<el-select v-model="pageForm.unitName" placeholder="请选择所属单位" clearable filterable>
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.name"></el-option>
</el-select>
</search-item>
<search-item label="人员状态:">
<el-select v-model="pageForm.userState" placeholder="请选择人员状态" clearable>
<el-option label="在职" value="在职"></el-option>
<el-option label="在岗" value="在岗"></el-option>
<el-option label="退休" value="退休"></el-option>
<el-option label="不在岗" value="不在岗"></el-option>
</el-select>
</search-item>
<search-item label="性别:">
<el-select v-model="pageForm.sex" placeholder="请选择性别" clearable>
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</search-item>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetSearch">重置</el-button>
</div>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="成员统计">
<span>成员记录数:{{ pageForm.totalCount }}(同一人员加入多个社团分别统计)</span>
</table-tool>
<el-table :data="tableData">
<el-table-column label="社团名称" prop="clubName" show-overflow-tooltip></el-table-column>
<el-table-column label="姓名" prop="userName" show-overflow-tooltip></el-table-column>
<el-table-column label="工号" prop="loginName" show-overflow-tooltip></el-table-column>
<el-table-column label="性别" prop="sex" show-overflow-tooltip></el-table-column>
<el-table-column label="联系方式" prop="mobile" show-overflow-tooltip></el-table-column>
<el-table-column label="所属单位" prop="unitName" show-overflow-tooltip></el-table-column>
<el-table-column label="在职状态" prop="userState" show-overflow-tooltip></el-table-column>
<el-table-column label="职务" prop="roleName" show-overflow-tooltip></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
clubList: [],
unitList: [],
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
clubId: "",
userId: "",
unitName: "",
userState: "",
sex: ""
}
}
},
methods: {
resetSearch() {
this.pageForm.clubId = ""
this.pageForm.userId = ""
this.pageForm.unitName = ""
this.pageForm.userState = ""
this.pageForm.sex = ""
this.doSearch()
},
async getUnit() {
const resp = await this.$axios.post("/open/common/unitOptions")
if (resp.code === 0) {
this.unitList = resp.data
} else {
this.$message.warning(resp.msg)
}
},
async pageData() {
const resp = await this.$axios.post("/platform/club/statistics/member/pageData", this.pageForm)
if (resp.code === 0) {
this.tableData = resp.data.list
this.pageForm.totalCount = resp.data.totalCount
} else {
this.$message.warning(resp.msg)
}
},
async getClub() {
const resp = await this.$axios.post("/platform/club/statistics/member/clubOptions")
if (resp.code === 0) {
this.clubList = resp.data
} else {
this.$message.warning(resp.msg)
}
}
},
async created() {
await this.getClub()
await this.getUnit()
await this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -818,6 +818,10 @@ layout("/layouts/platform.html"){
paymentWay: [{required: true, message: "请选择支付方式", trigger: ["change", "blur"]}],
reimburseProject: [{required: true, message: "请选择报销项目", trigger: ["change", "blur"]}],
reimburseFundSource: [{required: true, message: "请选择经费来源", trigger: ["change", "blur"]}],
// 报销事由仅在慰问项目显示,提交和重新提交时拒绝空值及纯空白。
paymentNotes: [{required: true, whitespace: true, message: "请填写报销事由", trigger: ["change", "blur"]}],
// 所属协会仅在协会经费显示,候选范围由后端当前会员关系确定。
clubId: [{required: true, message: "请选择所属协会", trigger: ["change", "blur"]}],
bankUserName: [{
required: true,
whitespace: true,
@@ -1890,10 +1894,14 @@ layout("/layouts/platform.html"){
this.normalizeFundBalance()
resolve(true)
} else {
// 支付信息已移至发票信息页,支付明细校验失败时跳转到对应页签。
// 新增必填项属于基本信息;同时存在支付错误时优先展示这两个字段的校验提示。
const basicInfoInvalid = Object.keys(invalidFields || {})
.some((field) => ["paymentNotes", "clubId"].includes(field))
const paymentDetailInvalid = Object.keys(invalidFields || {})
.some((field) => field.indexOf("paymentDetails.") === 0)
if (paymentDetailInvalid) {
if (basicInfoInvalid) {
this.$set(this, "activeTabName", "basic")
} else if (paymentDetailInvalid) {
this.$set(this, "activeTabName", "invoice")
}
this.$message.warning("请完善必填信息")
@@ -243,22 +243,22 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop=='isTransferIn'">
<template slot-scope="{row}" v-if="column.prop=='isTransferIn'">
<sapn v-if="row.takePartInUnionId!=unionId">转出</sapn>
<sapn v-else-if="row.selfUnionId!=unionId">转入</sapn>
<sapn v-else>否</sapn>
</template>
<template scope="{row}" v-else-if="column.prop=='lineName'">
<template slot-scope="{row}" v-else-if="column.prop=='lineName'">
<el-link type="primary" @click="openLine(row)">{{row.lineName}}
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='isFamily'">
<template slot-scope="{row}" v-else-if="column.prop=='isFamily'">
<el-link v-if="!row.familyNumber" type="primary" @click="openView(row)">
{{row.isFamily?'携带':'未携带'}}({{row.isFamily}})
</el-link>
@@ -266,18 +266,19 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.familyNumber?'携带':'未携带'}}({{row.familyNumber}})
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='num'">
<template slot-scope="{row}" v-else-if="column.prop=='num'">
{{1+row.num}}
</template>
<template scope="{row}" v-else-if="column.prop=='stateId'">
<template slot-scope="{row}" v-else-if="column.prop=='stateId'">
<span v-if="row.stateId">
<vi-table-state :state="row"></vi-table-state>
</span>
<sapn v-else style="color: #67C23A">暂无</sapn>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="180px">
<template scope="{row}">
<template slot-scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button plain size="mini">
<i class="ti-settings"></i>
@@ -474,17 +475,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="身份证号" prop="idCard" show-overflow-tooltip></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.otherSleepUser ?
row.bedInfo?.otherSleepUser : '暂无' }}
</template>
@@ -647,7 +648,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doDelete(row) {
this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doDelete')) return
this._therapyActions.add('doDelete')
try {
await this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
dangerouslyUseHTMLString: true,
@@ -665,6 +670,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doDelete')
}
},
async openModify(row) {
this.getUnionSelectLine(row.takePartInLineId)
@@ -689,8 +699,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.editVisible = true
},
async doEdit() {
this.$refs['editForm'].validate().then(async () => {
const confirm = await this.$confirm('您确定要修改这位老师的报名信息吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doEdit')) return
this._therapyActions.add('doEdit')
try {
return await this.$validateForm(this.$refs['editForm']).then(async valid => {
if (!valid) return
const confirm = await this.$confirmAction('您确定要修改这位老师的报名信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -710,6 +725,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doEdit')
}
},
async lineChange(val) {
this.pageForm.selectId = '';
@@ -727,6 +747,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doOnekeyAudit(flag, adjustment) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doOnekeyAudit')) return
this._therapyActions.add('doOnekeyAudit')
try {
let msg = '';
if (adjustment && !flag) {
msg = '您确定要一键【调整】您所勾选的报名信息吗,调整后该报名信息将不会在审核列表中展示, 是否继续?'
@@ -735,7 +759,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else if (!adjustment && flag) {
msg = '您确定要一键【通过】您所勾选的报名信息吗,是否继续?'
}
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -756,6 +780,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.dialogVisible = false
}
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doOnekeyAudit')
}
},
async openOnekeyAudit() {
if (this.tableSelection.length === 0) {
@@ -798,7 +827,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doRecall(row) {
const confirm = await this.$confirm('您确定要撤回吗, 是否继续?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doRecall')) return
this._therapyActions.add('doRecall')
try {
const confirm = await this.$confirmAction('您确定要撤回吗, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -812,8 +845,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$notify.warning({title: '失败', message: resp.msg});
}
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doRecall')
}
},
async doAudit(flag, adjustment) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doAudit')) return
this._therapyActions.add('doAudit')
try {
let msg = '';
if (adjustment && !flag) {
msg = '您确定要【调整】该报名信息吗,调整后该报名信息将不会在审核列表中展示, 是否继续?'
@@ -822,7 +864,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else if (!adjustment && flag) {
msg = '您确定要【通过】该报名信息吗,是否继续?'
}
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -845,6 +887,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doAudit')
}
},
openLine(row) {
this.$refs.guava.public()
@@ -907,14 +954,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return data
},
pageData() {
sublime.showLoadingbar();
this.tableLoading = true
const pageForm = clone(this.pageForm)
pageForm.states = JSON.stringify(pageForm.states)
$.post(loc() + "/pageData", pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -171,18 +171,18 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop=='isTransferIn'">
<template slot-scope="{row}" v-if="column.prop=='isTransferIn'">
<sapn v-if="row.takePartInUnionId!=unionId">转出</sapn>
<sapn v-else-if="row.selfUnionId!=unionId">转入</sapn>
<sapn v-else>否</sapn>
</template>
<template scope="{row}" v-else-if="column.prop=='isFamily'">
<template slot-scope="{row}" v-else-if="column.prop=='isFamily'">
<el-link v-if="!row.familyNumber" type="primary" @click="openUser(row)">
{{row.isFamily?'携带':'未携带'}}({{row.isFamily}})
</el-link>
@@ -190,18 +190,19 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.familyNumber?'携带':'未携带'}}({{row.familyNumber}})
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='num'">
<template slot-scope="{row}" v-else-if="column.prop=='num'">
{{1+row.num}}
</template>
<template scope="{row}" v-else-if="column.prop=='stateId'">
<template slot-scope="{row}" v-else-if="column.prop=='stateId'">
<span v-if="row.stateId">
<vi-table-state :state="row"></vi-table-state>
</span>
<sapn v-else style="color: #67C23A">暂无</sapn>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="180px">
<template scope="{row}">
<template slot-scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button plain size="mini">
<i class="ti-settings"></i>
@@ -383,17 +384,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="身份证号" prop="idCard" show-overflow-tooltip></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo.otherSleepUser ?
row.bedInfo.otherSleepUser : '暂无' }}
</template>
@@ -520,7 +521,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doDelete(row) {
this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doDelete')) return
this._therapyActions.add('doDelete')
try {
await this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
dangerouslyUseHTMLString: true,
@@ -538,6 +543,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doDelete')
}
},
async openModify(row) {
this.editFormData = {};
@@ -561,8 +571,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.editVisible = true
},
async doEdit() {
this.$refs['editForm'].validate().then(async () => {
const confirm = await this.$confirm('您确定要修改这位老师的报名信息吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doEdit')) return
this._therapyActions.add('doEdit')
try {
return await this.$validateForm(this.$refs['editForm']).then(async valid => {
if (!valid) return
const confirm = await this.$confirmAction('您确定要修改这位老师的报名信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -582,8 +597,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doEdit')
}
},
async doOnekeyAudit(flag, adjustment) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doOnekeyAudit')) return
this._therapyActions.add('doOnekeyAudit')
try {
let msg = '';
if (adjustment && !flag) {
msg = '您确定要一键【调整】您所勾选的报名信息吗,调整后该报名信息将不会在审核列表中展示, 是否继续?'
@@ -592,7 +616,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else if (!adjustment && flag) {
msg = '您确定要一键【通过】您所勾选的报名信息吗,是否继续?'
}
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -613,6 +637,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.dialogVisible = false
}
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doOnekeyAudit')
}
},
async openOnekeyAudit() {
if (this.tableSelection.length === 0) {
@@ -655,7 +684,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doRecall(row) {
const confirm = await this.$confirm('您确定要撤回吗, 是否继续?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doRecall')) return
this._therapyActions.add('doRecall')
try {
const confirm = await this.$confirmAction('您确定要撤回吗, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -669,8 +702,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$notify.warning({title: '失败', message: resp.msg});
}
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doRecall')
}
},
async doAudit(flag, adjustment) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doAudit')) return
this._therapyActions.add('doAudit')
try {
let msg = '';
if (adjustment && !flag) {
msg = '您确定要【调整】该报名信息吗,调整后该报名信息将不会在审核列表中展示, 是否继续?'
@@ -679,7 +721,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else if (!adjustment && flag) {
msg = '您确定要【通过】该报名信息吗,是否继续?'
}
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -702,6 +744,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doAudit')
}
},
openEdit(row) {
this.$set(this.formData, "isTransferIn", row.isTransferIn)
@@ -750,14 +797,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.unionOptions = data
},
pageData() {
sublime.showLoadingbar();
this.tableLoading = true
const pageForm = clone(this.pageForm)
pageForm.states = JSON.stringify(pageForm.states)
$.post(loc() + "/pageData", pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -201,8 +201,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
(pageForm.regionalNature==='省内'&&modifyConfig.isSnLine)||
(pageForm.regionalNature==='省外'&&modifyConfig.isSwLine)">
<el-button size="small"
style="background-color: #fff;border-color: #b3d8ff;color: #1867b0;font-size: 15px"
<el-button size="small" type="primary" plain
>{{selectLine.lineName?selectLine.lineName:'全部'}}线路的人数:{{lineSignNumber}}人
</el-button>
@@ -237,22 +236,22 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop=='isTransferIn'">
<template slot-scope="{row}" v-if="column.prop=='isTransferIn'">
<sapn v-if="row.takePartInUnionId!=unionId">转出</sapn>
<sapn v-else-if="row.selfUnionId!=unionId">转入</sapn>
<sapn v-else>否</sapn>
</template>
<template scope="{row}" v-else-if="column.prop=='lineName'">
<template slot-scope="{row}" v-else-if="column.prop=='lineName'">
<el-link type="primary" @click="openLine(row)">{{row.lineName}}
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='isFamily'">
<template slot-scope="{row}" v-else-if="column.prop=='isFamily'">
<el-link v-if="!row.familyNumber" type="primary" @click="openView(row)">
{{row.isFamily?'携带':'未携带'}}({{row.isFamily}})
</el-link>
@@ -260,18 +259,19 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.familyNumber?'携带':'未携带'}}({{row.familyNumber}})
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='num'">
<template slot-scope="{row}" v-else-if="column.prop=='num'">
{{1+row.num}}
</template>
<template scope="{row}" v-else-if="column.prop=='stateId'">
<template slot-scope="{row}" v-else-if="column.prop=='stateId'">
<span v-if="row.stateId">
<vi-table-state :state="row"></vi-table-state>
</span>
<sapn v-else style="color: #67C23A">暂无</sapn>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="180px">
<template scope="{row}">
<template slot-scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button plain size="mini">
<i class="ti-settings"></i>
@@ -468,17 +468,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="身份证号" prop="idCard" show-overflow-tooltip></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.otherSleepUser ?
row.bedInfo?.otherSleepUser : '暂无' }}
</template>
@@ -642,8 +642,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.doDelete(data)
}
},
async doDelete(row){
this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
async doDelete(row) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doDelete')) return
this._therapyActions.add('doDelete')
try {
await this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
dangerouslyUseHTMLString: true,
@@ -661,6 +665,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doDelete')
}
},
async openModify(row) {
this.getUnionSelectLine(row.takePartInLineId)
@@ -685,8 +694,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.editVisible = true
},
async doEdit() {
this.$refs['editForm'].validate().then(async () => {
const confirm = await this.$confirm('您确定要修改这位老师的报名信息吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doEdit')) return
this._therapyActions.add('doEdit')
try {
return await this.$validateForm(this.$refs['editForm']).then(async valid => {
if (!valid) return
const confirm = await this.$confirmAction('您确定要修改这位老师的报名信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -707,6 +721,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doEdit')
}
},
async lineChange(val) {
console.log(val)
@@ -739,6 +758,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.lineSignNumber = resp.data
},
async doOnekeyAudit(flag, adjustment) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doOnekeyAudit')) return
this._therapyActions.add('doOnekeyAudit')
try {
let msg = '';
if (adjustment && !flag) {
msg = '您确定要一键【调整】您所勾选的报名信息吗,调整后该报名信息将不会在审核列表中展示, 是否继续?'
@@ -747,7 +770,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else if (!adjustment && flag) {
msg = '您确定要一键【通过】您所勾选的报名信息吗,是否继续?'
}
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -768,6 +791,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.dialogVisible = false
}
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doOnekeyAudit')
}
},
async openOnekeyAudit() {
if (this.tableSelection.length === 0) {
@@ -801,7 +829,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doRecall(row) {
const confirm = await this.$confirm('您确定要撤回吗, 是否继续?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doRecall')) return
this._therapyActions.add('doRecall')
try {
const confirm = await this.$confirmAction('您确定要撤回吗, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -816,8 +848,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doRecall')
}
},
async doAudit(flag, adjustment) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doAudit')) return
this._therapyActions.add('doAudit')
try {
let msg = '';
if (adjustment && !flag) {
msg = '您确定要【调整】该报名信息吗,调整后该报名信息将不会在审核列表中展示, 是否继续?'
@@ -826,7 +867,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else if (!adjustment && flag) {
msg = '您确定要【通过】该报名信息吗,是否继续?'
}
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -848,6 +889,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doAudit')
}
},
openLine(row) {
this.$refs.guava.public()
@@ -910,14 +956,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return data
},
pageData() {
sublime.showLoadingbar();
this.tableLoading = true
const pageForm = clone(this.pageForm)
pageForm.states = JSON.stringify(pageForm.states)
$.post(loc() + "/pageData", pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -92,9 +92,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
>
<template scope="{row}" v-if="column.prop==='isDisabled'">
<template slot-scope="{row}" v-if="column.prop==='isDisabled'">
<el-switch
:active-value="false"
:inactive-value="true"
@@ -104,20 +104,21 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-model="row.isDisabled">
</el-switch>
</template>
<template scope="{row}" v-else-if="column.prop==='lotId'">
<template slot-scope="{row}" v-else-if="column.prop==='lotId'">
<div v-for="item in modifyBdList">
<span v-if="row.lotId===item.id">{{item.lotName}}</span>
</div>
</template>
<template scope="{row}" v-else-if="column.prop==='activityTime'">
<template slot-scope="{row}" v-else-if="column.prop==='activityTime'">
<span>
{{row.activityStartTime + '至' + row.activityEndTime}}
</span>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column label="操作" width="250px">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="openView(row.id)" size="mini" type="primary">查看</el-button>
<el-button @click="openEdit(row.id)" size="mini" type="primary">编辑</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
@@ -356,7 +357,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" type=""
@click="location.href='/platform/inclusiveTherapyV3/baseManagement/exportTemplate'"
@click="$downloadFile('/platform/inclusiveTherapyV3/baseManagement/exportTemplate')"
icon="el-icon-download">下载模板
</el-button>
@@ -366,6 +367,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-card>
<el-form>
<el-upload
action="/platform/inclusiveTherapyV3/baseManagement/importBaseManager"
name="file"
ref="upload"
:on-remove="(file, fileList) => {importData.fileList = fileHandleRemove(file, fileList)}"
@@ -556,15 +558,28 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async baseStatusChange(id) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('baseStatusChange')) return
this._therapyActions.add('baseStatusChange')
try {
const resp = await $.post(loc() + '/openClosedBase/' + id)
if (resp.code === 0) {
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('baseStatusChange')
}
},
async doDelete(id) {
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doDelete')) return
this._therapyActions.add('doDelete')
try {
const confirm = await this.$confirmAction('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -578,12 +593,22 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doDelete')
}
},
async doSubmit() {
const valid = await this.$refs['form'].validate()
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doSubmit')) return
this._therapyActions.add('doSubmit')
let loading = null
try {
const valid = await this.$validateForm(this.$refs['form'])
if (!valid) return
const loading = this.$loading({
loading = this.$loading({
lock: true,
text: '提交中',
spinner: 'el-icon-loading',
@@ -591,7 +616,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
});
const resp = await $.post(loc() + '/doSubmit', {base: JSON.stringify(this.formData)})
loading.close()
if (resp.code === 0) {
this.$refs.guava.index()
this.notifySuccess(resp.msg)
@@ -599,6 +623,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
if (loading) loading.close()
this._therapyActions.delete('doSubmit')
}
},
yearChange() {
this.formData.travelAgencyId = null
@@ -649,37 +679,28 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
this.importVisible = true;
},
doImport() {
if (this.importData.fileList.length === 0) {
this.notifyWarning("请选择文件!")
async doImport() {
if (this.importLoading) return
const files = this.importData.fileList || []
if (!files.length || files.some(file => !file.raw)) {
this.notifyWarning('请选择要导入的Excel文件')
return
}
const data = new FormData();
this.importData.fileList.forEach((val) => {
data.append("file", val.raw, val.raw.name);
});
this.importLoading = true
$.ajax({
url: loc() + "/importBaseManager",
type: "post",
data: data,
processData: false,
contentType: false,
success: (data) => {
if (data.code === 0){
this.$message.success(data.msg)
this.pageData();
this.importVisible = false
this.importLoading = false
}else {
this.importVisible = false
}
},
error: (data) => {
this.notifyWarning("导入失败")
this.importLoading = false
try {
const resp = await this.$importExcel('/platform/inclusiveTherapyV3/baseManagement/importBaseManager', files)
if (resp.code === 0) {
this.notifySuccess(resp.msg || '导入成功')
this.pageData()
this.importVisible = false
} else {
this.notifyWarning(resp.msg || '导入失败')
}
});
} catch (error) {
this.$actionError(error)
} finally {
this.importLoading = false
}
},
},
async created() {
@@ -22,24 +22,24 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="search">
<div class="search-item">
<div class="search-item-label">年度范围:</div>
<div class="search-item-option">
<div class="search-item-option" style="display:flex;align-items:center;gap:10px">
<el-date-picker
v-model="pageForm.startYear"
type="year"
class="picker-year"
format="yyyy"
style="width: 46%"
style="flex:1;width:0;min-width:0"
value-format="yyyy"
@change="handleChangeYear"
>
</el-date-picker>
<span>至</span>
<span style="flex-shrink:0">至</span>
<el-date-picker
v-model="pageForm.endYear"
type="year"
class="picker-year"
format="yyyy"
style="width: 46%"
style="flex:1;width:0;min-width:0"
value-format="yyyy"
@change="handleChangeYear"
>
@@ -153,9 +153,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
:key="column.prop"
>
<template scope="{row}" v-if="column.prop==='isDisabled'">
<template slot-scope="{row}">
<el-switch
v-if="column.prop==='isDisabled'"
:active-value="false"
:inactive-value="true"
@change="(val)=>{lineStatusChange(row.id)}"
@@ -163,21 +165,20 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
inactive-color="#ff4949"
v-model="row.isDisabled">
</el-switch>
</template>
<template scope="{row:{signUpMode}}" v-else-if="column.prop==='signUpMode'">
{{signUpModeName(signUpMode)}}
</template>
<template scope="{row:{createMode}}" v-else-if="column.prop==='createMode'">
{{createModeName(createMode)}}
</template>
<template scope="{row}" v-else-if="column.prop==='createUserName'">
<span v-else-if="column.prop==='signUpMode'">
{{signUpModeName(row.signUpMode)}}
</span>
<span v-else-if="column.prop==='createMode'">
{{createModeName(row.createMode)}}
</span>
<span v-else-if="column.prop==='createUserName'">
{{row.createUserName + '(' + row.createUnionName + ')'}}
</template>
<template scope="{row}" v-else-if="column.prop==='playTime'">
<el-button @click="viewUnionSelectTimeInfo(row.id)"
</span>
<el-button v-else-if="column.prop==='playTime'" @click="viewUnionSelectTimeInfo(row.id)"
type="text">
查看详情
</el-button>
<span v-else>{{row[column.prop]}}</span>
<!-- v-if="row.createMode===2 && row.signUpMode===1"-->
<!--<span v-else>
{{row.playStartTime + '至' + row.playEndTime}}
@@ -185,7 +186,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="操作" width="250px">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="openView(row.id)" size="mini" type="primary">查看</el-button>
<el-button @click="openEdit(row.id)" size="mini" type="primary">编辑</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
@@ -242,6 +243,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :md="12" :sm="24" :xs="24">
<el-form-item label="旅行社名称" prop="travelAgencyId">
<el-select clearable filterable style="width: 100%" v-model="formData.travelAgencyId">
@@ -271,11 +274,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-col :md="12" :sm="24" :xs="24">
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="24">
<el-form-item label="线路类型" prop="regionalNature">
<el-radio-group class="mr0-radio" size="small" v-model="formData.regionalNature">
<el-radio :label="item.value"
border v-for="item in regionalNatureList">
border v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio>
</el-radio-group>
@@ -283,6 +286,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-col>
</el-row>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :md="12" :sm="24" :xs="24">
<el-form-item label="交通工具" prop="trafficTools">
<el-input clearable maxlength="50" v-model="formData.trafficTools"></el-input>
@@ -311,6 +316,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-col>
</el-row>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :md="12" :sm="24" :xs="24">
<el-form-item label="预计费用(元/人次)" prop="estimatedCost">
<el-input clearable maxlength="50" v-model="formData.estimatedCost"></el-input>
@@ -332,7 +339,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-radio-group class="mr0-radio" size="small" v-model="formData.signUpMode">
<el-radio :label="item.value" v-if="isShow(item.roles)"
size="small"
border v-for="item in signUpModeList">
border v-for="(item, therapyIndex) in signUpModeList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio>
</el-radio-group>
@@ -502,7 +509,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" type=""
@click="location.href='/platform/inclusiveTherapyV3/line/exportTemplate'"
@click="downloadLegacyTemplate"
icon="el-icon-download">下载模板
</el-button>
@@ -512,6 +519,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-card>
<el-form>
<el-upload
action="/platform/inclusiveTherapyV3/line/travelLineImport"
name="file"
ref="upload"
:on-remove="(file, fileList) => {
@@ -551,7 +559,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" type=""
@click="location.href='/platform/inclusiveTherapyV3/line/exportPageFieldsTemplate'"
@click="downloadTemplate"
icon="el-icon-download">下载模板
</el-button>
</el-card>
@@ -560,6 +568,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-card>
<el-form>
<el-upload
action="/platform/inclusiveTherapyV3/line/importLineByPageFields"
name="file"
ref="lineImportUpload"
:on-remove="(file, fileList) => {
@@ -715,7 +724,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
signUpStartTime: null,
signUpEndTime: null,
changeEndTime: null,
files: [],
files: '',
signUpMode: null,
createMode: null,
playStartTime: null,
@@ -810,10 +819,22 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doSubmit() {
const valid = await this.$refs['form'].validate()
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doSubmit')) return
this._therapyActions.add('doSubmit')
let loading = null
try {
const valid = await this.$validateForm(this.$refs['form'])
if (!valid) return
const loading = this.$loading({
const confirm = await this.$confirmAction('确定保存该线路吗?', '保存确认', {
confirmButtonText: '确认保存',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm !== 'confirm') return
loading = this.$loading({
lock: true,
text: '提交中',
spinner: 'el-icon-loading',
@@ -822,18 +843,15 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
delete this.formData.travelAgency
const resp = await $.post(loc() + '/doSubmit', this.formData)
loading.close()
loading = null
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$confirm('需要将该线路设置为出行线路吗?', '提示', {
await this.$confirm('需要将该线路设置为出行线路吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
if ("${@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.hasRole('sysadmin')||@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.hasRole('A06')}" === 'true') {
sublime.jumpPagePjax('/platform/inclusiveTherapyV3/lineXghSelect?mode=2')
} else {
sublime.jumpPagePjax('/platform/inclusiveTherapyV3/lineFghSelect?mode=1')
}
window.top.location.href = '/platform/inclusiveTherapyV3/lineXghSelect?mode=2'
}).catch(() => {
this.$refs.guava.index()
this.pageData()
@@ -841,17 +859,36 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.$message.warning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
if (loading) loading.close()
this._therapyActions.delete('doSubmit')
}
},
async lineStatusChange(id) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('lineStatusChange')) return
this._therapyActions.add('lineStatusChange')
try {
const resp = await $.post(loc() + '/openClosedLine/' + id)
if (resp.code === 0) {
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('lineStatusChange')
}
},
async doDelete(id) {
const confirm = await this.$confirm('可能会导致数据不完整,您确定要删除吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doDelete')) return
this._therapyActions.add('doDelete')
try {
const confirm = await this.$confirmAction('可能会导致数据不完整,您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -865,6 +902,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doDelete')
}
},
async openView(id) {
this.$refs.guava.view()
@@ -977,6 +1019,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
this.lineImportVisible = true
},
downloadTemplate() {
window.location.href = '/platform/inclusiveTherapyV3/line/downloadTemplate';
},
downloadLegacyTemplate() {
window.location.href = '/platform/inclusiveTherapyV3/line/exportTemplate';
},
async doLineImport() {
if (this.lineImportData.fileList.length === 0) {
this.notifyWarning("请选择文件")
@@ -64,9 +64,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
:key="column.prop"
>
<template scope="{row}" v-if="column.prop==='isDisabled'">
<template slot-scope="{row}">
<el-switch
v-if="column.prop==='isDisabled'"
:active-value="false"
:inactive-value="true"
@change="(val)=>{travelAgencyStatusChange(row.id)}"
@@ -74,15 +76,14 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
inactive-color="#ff4949"
v-model="row.isDisabled">
</el-switch>
</template>
<template scope="{row:{officialWebsite}}" v-else-if="column.prop==='officialWebsite'">
<a :href="officialWebsite" class="text-primary" target="_blank">
{{officialWebsite}}
<a v-else-if="column.prop==='officialWebsite'" :href="row.officialWebsite" class="text-primary" target="_blank">
{{row.officialWebsite}}
</a>
<span v-else>{{row[column.prop]}}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="250px">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="openEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
@@ -234,7 +235,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" type=""
@click="location.href='/platform/inclusiveTherapyV3/common/downloadTemplate?filePath=travel/TravelAgencyImport.xlsx&fileName=旅行社导入模板.xls'"
@click="downloadTemplate"
icon="el-icon-download">下载模板
</el-button>
@@ -244,6 +245,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-card>
<el-form>
<el-upload
action="/platform/inclusiveTherapyV3/travelAgency/travelAgencyImport"
name="file"
ref="upload"
:on-remove="(file, fileList) => {
@@ -353,6 +355,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
methods: {
downloadTemplate() {
window.location.href = '/platform/inclusiveTherapyV3/travelAgency/downloadTemplate';
},
openAdd() {
this.editDialogVisible = true
this.$nextTick(() => {
@@ -382,7 +387,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.editDialogVisible = true
},
async doSubmit() {
const valid = await this.$refs['form'].validate()
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doSubmit')) return
this._therapyActions.add('doSubmit')
try {
const valid = await this.$validateForm(this.$refs['form'])
if (!valid) return
const resp = await $.post(loc() + '/doSubmit', {travelAgency: JSON.stringify(this.formData)})
if (resp.code === 0) {
@@ -392,17 +401,35 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doSubmit')
}
},
async travelAgencyStatusChange(id) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('travelAgencyStatusChange')) return
this._therapyActions.add('travelAgencyStatusChange')
try {
const resp = await $.post(loc() + '/openClosedTravelAgency/' + id)
if (resp.code === 0) {
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('travelAgencyStatusChange')
}
},
async doDelete(id) {
const confirm = await this.$confirm('可能会导致数据不完整,您确定要删除吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doDelete')) return
this._therapyActions.add('doDelete')
try {
const confirm = await this.$confirmAction('可能会导致数据不完整,您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -416,6 +443,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doDelete')
}
},
async openView(row) {
@@ -442,20 +474,24 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
});
this.importLoading = true
const resp = await $.ajax({
url: loc() + '/travelAgencyImport',
type: 'POST',
data: data,
processData: false,
contentType: false
})
if (resp.code===0){
this.$message.success(resp.msg)
this.pageData();
this.importVisible = false
this.importLoading = false
}else {
this.notifyWarning("导入失败")
try {
const resp = await $.ajax({
url: loc() + '/travelAgencyImport',
type: 'POST',
data: data,
processData: false,
contentType: false
})
if (resp.code===0){
this.$message.success(resp.msg)
this.pageData();
this.importVisible = false
}else {
this.notifyWarning(resp.msg || "导入失败")
}
} catch (error) {
this.notifyWarning("导入请求失败,请重试")
} finally {
this.importLoading = false
}
},
@@ -1,5 +1,5 @@
<!--#
layout("/layouts/platform.html"){
#-->
<iframe src="${therapyPageUrl,escape}" title="普惠疗休养V3" style="width:100%;height:calc(100vh - 100px);border:0;background:#fff"></iframe>
<iframe src="${therapyPageUrl,escape}" title="普惠疗休养" style="width:100%;height:calc(100vh - 100px);border:0;background:#fff"></iframe>
<!--# } #-->
@@ -1,23 +1,36 @@
<!doctype html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>?????</title>
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.js"></script>
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<script>const APP_DOMAIN = location.origin; const FILE_DOMAIN = location.origin;</script>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vant/index.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/theme.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/main.css">
<script src="${base!}/assets/platform/plugins/vant/index.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/basic.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/v.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/mobileMixins.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/compat.js"></script>
<link rel="stylesheet" href="${base!}/assets/platform/css/pdf/pdfh5.css">
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.js"></script>
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.worker.js"></script>
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdfh5.js"></script>
<style>[v-cloak]{display:none}body{margin:0}</style>
</head><body>${layoutContent}</body></html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>普惠疗休养</title>
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.js"></script>
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<script>const APP_DOMAIN = location.origin;
const FILE_DOMAIN = location.origin;</script>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vant/index.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/theme.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/main.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/pages.css">
<script src="${base!}/assets/platform/plugins/vant/index.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/basic.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/v.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/mobileMixins.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/compat.js"></script>
<link rel="stylesheet" href="${base!}/assets/platform/css/pdf/pdfh5.css">
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.js"></script>
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.worker.js"></script>
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdfh5.js"></script>
<style>[v-cloak] {
display: none !important;
}
body {
margin: 0
}</style>
</head>
<body>${layoutContent}</body>
</html>
@@ -1,20 +1,38 @@
<!--# if(!@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.isEmbeddedPage()){ #-->
<!--# layout("/layouts/platform.html"){ #-->
<iframe src="${@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.getEmbeddedPageUrl(),escape}" title="普惠疗休养" style="width:100%;height:calc(100vh - 100px);border:0;background:#fff"></iframe>
<!--# } } else { #-->
<!doctype html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>?????</title>
<title>普惠疗休养</title>
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.js"></script>
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<script>const APP_DOMAIN = location.origin; const FILE_DOMAIN = location.origin;</script>
<link rel="stylesheet" href="${base!}/assets/platform/css/root.css">
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css">
<link rel="stylesheet" href="${base!}/assets/platform/fonts/font-awesome.min.css">
<link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css">
<link rel="stylesheet" href="${base!}/assets/platform/plugins/viewerjs/viewer.css">
<script src="${base!}/assets/platform/plugins/viewerjs/viewer.js"></script>
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/css/common.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/css/main.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/css/elmain.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/css/panel.css">
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index_custom.css">
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css">
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css">
<script src="${base!}/assets/platform/plugins/element-ui/lib/index.js"></script>
<script>
ELEMENT.Dialog.props.closeOnClickModal.default = false;
ELEMENT.Dialog.props.top.default = '50px';
ELEMENT.Table.props.border.default = true;
ELEMENT.TableColumn.props.headerAlign.default = 'center';
ELEMENT.TableColumn.props.align.default = 'center';
Vue.use(ELEMENT, {zIndex: 20000});
</script>
<script src="${base!}/assets/platform/plugins/wangEditor4/wangEditor.js"></script>
<script src="${base!}/assets/platform/plugins/sortablejs/sortable.min.js"></script>
<script src="${base!}/assets/platform/plugins/vuedraggable/vuedraggable.umd.min.js"></script>
@@ -25,7 +43,14 @@
<script src="${base!}/assets/staffbenefit/therapyRecuperation/component.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/initTableMixins.js"></script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/compat.js"></script>
<script src="${base!}/assets/platform/js/util/commonUtil.js"></script>
<script src="${base!}/assets/platform/js/tool/businessTool.js"></script>
<script>
Vue.prototype.$axios = commonUtil.axiosService();
Vue.prototype.$businessTool = businessTool;
Vue.prototype.$downLoad = commonUtil.downLoadService;
Vue.prototype.$download = commonUtil.downLoadService;
Vue.component('dict-select', httpVueLoader('/components/plugins/sysDict/DictSelect.vue'));
Vue.component('guava', httpVueLoader('/components/staffbenefit/therapyRecuperation/Guava.vue'));
Vue.component('text-editor', httpVueLoader('/components/plugins/sysTextEditor/index.vue'));
Vue.component('file-upload', httpVueLoader('/components/staffbenefit/therapyRecuperation/FileUpload.vue'));
@@ -38,5 +63,6 @@ Vue.directive('auth', {inserted(el, binding) {
if (!requested.some(role => roles.includes(role))) el.parentNode.removeChild(el);
}});
</script>
<style>body{margin:0;padding:12px;box-sizing:border-box;background:#f6f6f6} [v-cloak]{display:none} #therapy-loading{position:fixed;top:0;left:0;height:3px;width:100%;background:#409eff;z-index:99999}</style>
<style>body{margin:0;padding:12px;box-sizing:border-box;background:#f6f6f6} [v-cloak]{display:none}</style>
</head><body>${layoutContent}</body></html>
<!--# } #-->
@@ -280,18 +280,18 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<!-- <el-button icon="el-icon-s-promotion" @click="openImport" size="small"
type="primary">参加人员导入
</el-button>-->
<!--# if(@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.hasRole('H04')){ #-->
<!--# if(@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.hasAnyRoles('H04,superadmin')){ #-->
<template>
<el-button icon="el-icon-s-promotion"
@click="location.href='/platform/inclusiveTherapyV3/query/exportDeclareForm'"
@click="$downloadFile('/platform/inclusiveTherapyV3/query/exportDeclareForm')"
size="small" type="primary">申报表导出
</el-button>
<el-button icon="el-icon-s-promotion"
@click="location.href='/platform/inclusiveTherapyV3/query/exportTravelers?year=' + pageForm.year"
@click="$downloadFile('/platform/inclusiveTherapyV3/query/exportTravelers?year=' + pageForm.year)"
size="small" type="primary">出行人员导出
</el-button>
<el-button icon="el-icon-s-promotion"
@click="location.href='/platform/inclusiveTherapyV3/query/exportSignUser?year=' + pageForm.year"
@click="$downloadFile('/platform/inclusiveTherapyV3/query/exportSignUser?year=' + pageForm.year)"
size="small" type="primary">本分工会报名人员导出
</el-button>
</template>
@@ -346,7 +346,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column align="center" header-align="center" type="index" label="序号"
width="80px" key="#index">
<template scope="scope">
<template slot-scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}} </span>
</template>
</el-table-column>
@@ -354,17 +354,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop=='lineName'">
<template slot-scope="{row}" v-if="column.prop=='lineName'">
<el-link type="primary" @click="openLine(row)">{{row.lineName}}
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='isFamily'">
<template slot-scope="{row}" v-else-if="column.prop=='isFamily'">
<el-link v-if="!row.familyNumber" type="primary" @click="openView(row)">
{{row.isFamily?'携带':'未携带'}}({{row.isFamily}})
</el-link>
@@ -372,7 +372,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.familyNumber?'携带':'未携带'}}({{row.familyNumber}})
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='lineNum'">
<template slot-scope="{row}" v-else-if="column.prop=='lineNum'">
<span v-if="!row.familyNumber" >
{{row.lineNum}}({{row.signUpUserFamilyNum}})
@@ -383,21 +383,21 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
<template scope="{row}" v-else-if="column.prop=='signUpMode'">
<template slot-scope="{row}" v-else-if="column.prop=='signUpMode'">
{{signUpModeName(row.signUpMode)}}
</template>
<template scope="{row}" v-else-if="column.prop=='agencyNum'">
<template slot-scope="{row}" v-else-if="column.prop=='agencyNum'">
<el-link type="primary" @click="openApplyUser(row)">{{row.agencyNum}}
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='times'">
<template slot-scope="{row}" v-else-if="column.prop=='times'">
<div v-if="row.playStartTime">{{row.playStartTime}}</div>
<div v-else>{{row.playStartTime1}}</div>
</template>
<template scope="{row}" v-else-if="column.prop=='isTakePartIn'">
<template slot-scope="{row}" v-else-if="column.prop=='isTakePartIn'">
{{row.isTakePartIn?'已参加':'未参加'}}
</template>
<template scope="{row}" v-else-if="column.prop=='stateId'">
<template slot-scope="{row}" v-else-if="column.prop=='stateId'">
<span v-if="row.stateId">
<vi-table-state :state="row"></vi-table-state>
</span>-->
@@ -409,21 +409,22 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.travelAgencyName}}
</el-link>
</template>-->
<template scope="{row}" v-else-if="column.prop=='lineOrMaName'">
<template slot-scope="{row}" v-else-if="column.prop=='lineOrMaName'">
{{row.lineName?row.lineName:row.baseName?row.baseName:row.travelAgencyName}}
</template>
<template scope="{row:{officialWebsite}}"
<template slot-scope="{row:{officialWebsite}}"
v-else-if="column.prop==='officialWebsite'">
<a :href="officialWebsite" class="text-primary" target="_blank">
{{officialWebsite}}
</a>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<!-- <el-table-column label="家属信息" type="expand" width="100px"
v-if="pageForm.lb==='ry'">
<template scope="{row}">
<el-card shadow="never">
<h4 slot="header" style="color: #1867b0">
<h4 slot="header" style="color: var(--color-primary)">
家属信息
</h4>
<el-table :data="row.companionList">
@@ -458,13 +459,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
header-align="center"
label="标段"
sortable>
<template scope="{row}">
<template slot-scope="{row}">
{{row.lotName}}
</template>
</el-table-column>
<el-table-column label="操作" width="250px"
v-if="pageForm.lb==='ry'||pageForm.lb===''||pageForm.lb==='xl'">
<template scope="{row}">
<template slot-scope="{row}">
<template v-if="pageForm.lb==='xl'">
<el-button @click="openApplyUser(row)" size="mini" type="primary">
查看
@@ -494,7 +495,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-table-column>
<el-table-column label="操作" width="250px" v-if="pageForm.lb==='lxs'">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="doEmail(row)" size="mini" type="primary">发送
</el-button>
</template>
@@ -525,9 +526,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
row-key="id" @sort-change="pageOrder"
v-loading="tableLoading">
<el-table-column label="家属信息" type="expand" width="150px">
<template scope="{row}">
<template slot-scope="{row}">
<el-card shadow="never">
<h4 slot="header" style="color: #1867b0">
<h4 slot="header" style="color: var(--color-primary)">
家属信息
</h4>
<el-table :data="row.companionList">
@@ -536,17 +537,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="身份证号" prop="idCard"></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.otherSleepUser ?
row.bedInfo?.otherSleepUser : '暂无' }}
</template>
@@ -558,26 +559,27 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-table-column>
<el-table-column align="center" header-align="center" type="index" label="序号"
width="80px">
<template scope="scope">
<template slot-scope="scope">
<span>{{scope.$index+(pageFormUser.pageNumber - 1) * pageFormUser.pageSize + 1}} </span>
</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumnUsers"
v-for="(column, therapyIndex) in tableColumnUsers"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
:key="column.id || column.code || therapyIndex">
<template scope="{row}" v-if="column.prop=='isFamily'">
<template slot-scope="{row}" v-if="column.prop=='isFamily'">
{{row.isFamily?'携带':'未携带'}}
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column label="操作" width="250px">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看
</el-button>
</template>
@@ -706,7 +708,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="small" type=""
@click="location.href='/platform/inclusiveTherapyV3/common/downloadTemplate?filePath=travel/TravelEnrollImport.xlsx&fileName=参加人员导入模板.xls'"
@click="$downloadFile('/platform/inclusiveTherapyV3/common/downloadTemplate?filePath=travel/TravelEnrollImport.xlsx&fileName=参加人员导入模板.xls')"
icon="el-icon-download">下载模板
</el-button>
</el-card>
@@ -715,6 +717,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-card>
<el-form>
<el-upload
action="/platform/inclusiveTherapyV3/user/query/enrollImport"
name="file"
ref="upload"
:on-remove="(file, fileList) => {
@@ -749,7 +752,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
title="家属信息"
:visible.sync="familyDrawer"
direction="rtl">
<h4 slot="header" style="color: #1867b0">
<h4 slot="header" style="color: var(--color-primary)">
家属信息
</h4>
<el-table :data="companionList">
@@ -758,17 +761,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="身份证号" prop="idCard"></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo.otherSleepUser ?
row.bedInfo.otherSleepUser : '暂无' }}
</template>
@@ -834,17 +837,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="身份证号" prop="idCard" show-overflow-tooltip></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.otherSleepUser ?
row.bedInfo?.otherSleepUser : '暂无' }}
</template>
@@ -1029,7 +1032,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
})
},
async doReimbursement(){
async doReimbursement() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doReimbursement')) return
this._therapyActions.add('doReimbursement')
try {
if (this.multipleSelection && this.multipleSelection.length > 0){
const enrollIds = this.multipleSelection.filter(v=>v.isTakePartIn).map(v=>v.id)
@@ -1046,7 +1053,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return
}
console.log(enrollIds)
this.$confirm(msg, '提示', {
await this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
dangerouslyUseHTMLString: true,
@@ -1072,6 +1079,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.$message.warning('请勾选需要报销的报名信息')
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doReimbursement')
}
},
async lineChange(val) {
this.pageForm.selectId = '';
@@ -1097,7 +1109,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doDelete(row) {
this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doDelete')) return
this._therapyActions.add('doDelete')
try {
await this.$confirm("您确定要删除【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
dangerouslyUseHTMLString: true,
@@ -1115,6 +1131,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doDelete')
}
},
async doSearch() {
this.pageForm.pageNumber = 1;
@@ -1123,8 +1144,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
await this.getXlByUnion()
},
async doEdit() {
this.$refs['editForm'].validate().then(async () => {
const confirm = await this.$confirm('您确定要修改这位老师的报名信息吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doEdit')) return
this._therapyActions.add('doEdit')
try {
return await this.$validateForm(this.$refs['editForm']).then(async valid => {
if (!valid) return
const confirm = await this.$confirmAction('您确定要修改这位老师的报名信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -1144,6 +1170,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doEdit')
}
},
async openEdit(row) {
this.editFormData = {};
@@ -1224,6 +1255,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.multipleSelection = val;
},
async doAttend() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doAttend')) return
this._therapyActions.add('doAttend')
try {
let arr = []
this.multipleSelection.forEach((v, index) => {
if (!v.lotId || !v.takePartInTime) {
@@ -1245,6 +1280,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.notifyWarning(refs.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doAttend')
}
},
async checkState2(type) {
this.pageForm.state2 = type
@@ -1269,7 +1309,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
await this.doSearch()
},
async doEmail(row) {
const confirm = await this.$confirm('您将发送文件到旅行社邮箱!, 是否继续?', '提示', {
const confirm = await this.$confirmAction('您将发送文件到旅行社邮箱!, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -1284,7 +1324,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doRemind(row) {
const confirm = await this.$confirm('您将发送提醒!, 是否继续?', '提示', {
const confirm = await this.$confirmAction('您将发送提醒!, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -1312,7 +1352,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
linePlayTime,
} = this.pageForm
let types = this.pageForm.state == 1 ? JSON.stringify(['line']) : JSON.stringify(['travel'])
window.open("/platform/inclusiveTherapyV3/user/query/doExport?" +
this.$downloadFile("/platform/inclusiveTherapyV3/user/query/doExport?" +
"searchName=" + searchName +
"&searchKeyword=" + searchKeyword +
"&startYear=" + year +
@@ -1341,7 +1381,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
linePlayTime,
} = this.pageForm
let types = this.pageForm.state == 1 ? JSON.stringify(['line']) : JSON.stringify(['travel'])
window.open("/platform/inclusiveTherapyV3/user/query/doExportExcel?" +
this.$downloadFile("/platform/inclusiveTherapyV3/user/query/doExportExcel?" +
"searchName=" + searchName +
"&searchKeyword=" + searchKeyword +
"&startYear=" + year +
@@ -1410,7 +1450,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$message.warning('请先选择需要查看的记录');
return
}
sublime.showLoadingbar();
this.tableLoading = true
const pageForm = clone(this.pageFormUser)
pageForm.id = this.applyUserRow.id
@@ -1426,7 +1465,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
})
.always(() => {
sublime.closeLoadingbar();
this.tableLoading = false
});
this.$refs.guava.view()
@@ -1465,7 +1503,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true
this.tableData = []
$.post(loc() + "/getSelfUnionUser", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -1600,7 +1637,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true
this.tableData = []
$.post(loc() + "/getLxsData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -1614,7 +1650,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true
this.tableData = []
$.post(loc() + "/getJdData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -1628,7 +1663,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true
this.tableData = []
$.post(loc() + "/getXlData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -1642,7 +1676,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true
this.tableData = []
$.post(loc() + "/getRyData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false
if (data.code === 0) {
this.tableData = data.data.list;
@@ -1703,23 +1736,25 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.importVisible = true;
},
async doImport() {
if (this.importData.fileList.length === 0) {
this.notifyWarning("请选择文件!")
if (this.importLoading) return
const files = this.importData.fileList || []
if (!files.length || files.some(file => !file.raw)) {
this.notifyWarning('请选择要导入的Excel文件')
return
}
const data = new FormData();
this.importData.fileList.forEach((val) => {
data.append("file", val.raw, val.raw.name);
});
this.importLoading = true
const resp = await $.post('/platform/inclusiveTherapyV3/user/query/enrollImport', data)
if (resp.code === 0) {
await this.pageData();
this.importVisible = false
} else {
this.notifyWarning("导入失败")
try {
const resp = await this.$importExcel('/platform/inclusiveTherapyV3/user/query/enrollImport', files)
if (resp.code === 0) {
this.notifySuccess(resp.msg || '导入成功')
this.pageData()
this.importVisible = false
} else {
this.notifyWarning(resp.msg || '导入失败')
}
} catch (error) {
this.$actionError(error)
} finally {
this.importLoading = false
}
},
@@ -260,18 +260,18 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop=='lineName'">
<template slot-scope="{row}" v-if="column.prop=='lineName'">
{{row.baseName?row.baseName:row.lineName}}
<!-- <el-link type="primary" @click="openLine(row)">{{row.lineName}}
</el-link>-->
</template>
<template scope="{row}" v-else-if="column.prop=='isFamily'">
<template slot-scope="{row}" v-else-if="column.prop=='isFamily'">
<el-link v-if="!row.familyNumber" type="primary" @click="openView(row)">
{{row.isFamily?'携带':'未携带'}}({{row.isFamily}})
</el-link>
@@ -279,17 +279,18 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.familyNumber?'携带':'未携带'}}({{row.familyNumber}})
</el-link>
</template>
<template scope="{row}" v-else-if="column.prop=='isTakePartIn'">
<template slot-scope="{row}" v-else-if="column.prop=='isTakePartIn'">
{{row.isTakePartIn?'已参加':'未参加'}}
</template>
<template scope="{row}" v-else-if="column.prop=='lotName'">
<template slot-scope="{row}" v-else-if="column.prop=='lotName'">
<span v-if="row.lotName"> {{row.lotName}}</span>
<span v-else>暂无</span>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column label="操作" width="250px">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看
</el-button>
<el-button
@@ -392,7 +393,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" type=""
@click="location.href='/platform/inclusiveTherapyV3/common/downloadTemplate?filePath=travel/TravelEnrollImport.xlsx&fileName=参加人员导入模板.xls'"
@click="$downloadFile('/platform/inclusiveTherapyV3/common/downloadTemplate?filePath=travel/TravelEnrollImport.xlsx&fileName=参加人员导入模板.xls')"
icon="el-icon-download">下载模板
</el-button>
</el-card>
@@ -401,6 +402,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-card>
<el-form>
<el-upload
action="/platform/inclusiveTherapyV3/user/query/enrollImport"
name="file"
ref="upload"
:on-remove="(file, fileList) => {
@@ -487,17 +489,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
show-overflow-tooltip></el-table-column>
<el-table-column label="年龄" prop="age"></el-table-column>
<el-table-column label="床型" prop="bedType">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedType }}
</template>
</el-table-column>
<el-table-column label="床位" prop="bedNum">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.bedNum }}
</template>
</el-table-column>
<el-table-column label="意向拼床人" prop="otherSleepUser">
<template scope="{row}">
<template slot-scope="{row}">
{{ row.bedInfo?.otherSleepUser ?
row.bedInfo?.otherSleepUser : '暂无' }}
</template>
@@ -602,12 +604,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-button type="primary" size="mini" @click="addProxyCompanion">添加家属</el-button>
<el-table :data="proxySignUpForm.companionList" class="mt10" border>
<el-table-column label="姓名" min-width="110">
<template scope="{row}">
<template slot-scope="{row}">
<el-input v-model="row.userName" placeholder="姓名"></el-input>
</template>
</el-table-column>
<el-table-column label="性别" width="100">
<template scope="{row}">
<template slot-scope="{row}">
<el-select v-model="row.sex" placeholder="性别">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
@@ -615,23 +617,23 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="年龄" width="110">
<template scope="{row}">
<template slot-scope="{row}">
<el-input-number v-model="row.age" :min="0" :max="120" controls-position="right"
style="width: 90px"></el-input-number>
</template>
</el-table-column>
<el-table-column label="身份证件" min-width="170">
<template scope="{row}">
<template slot-scope="{row}">
<el-input v-model="row.idCard" placeholder="身份证号、护照等"></el-input>
</template>
</el-table-column>
<el-table-column label="手机号" min-width="140">
<template scope="{row}">
<template slot-scope="{row}">
<el-input v-model="row.mobile" placeholder="手机号"></el-input>
</template>
</el-table-column>
<el-table-column label="关系" min-width="110">
<template scope="{row}">
<template slot-scope="{row}">
<el-select v-model="row.relation" placeholder="关系">
<el-option v-for="item in proxyCompanionRelationOptions"
:key="item"
@@ -642,7 +644,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="房间" min-width="120">
<template scope="{row}">
<template slot-scope="{row}">
<el-select v-model="row.bedInfo.bedType" clearable placeholder="请选择">
<el-option v-for="item in proxyRoomOptions"
:key="item"
@@ -653,7 +655,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="床位" width="100">
<template scope="{row}">
<template slot-scope="{row}">
<el-select v-if="row.bedInfo.bedType == '标准间'" v-model="row.bedInfo.bedNum" clearable
placeholder="床位">
<el-option v-for="item in proxyBedOptions"
@@ -665,7 +667,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="是否拼房" width="130">
<template scope="{row}">
<template slot-scope="{row}">
<el-radio-group v-if="row.bedInfo.bedType == '标准间'"
v-model="row.bedInfo.isSleepTogether">
<el-radio :label="true">是</el-radio>
@@ -674,14 +676,14 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="意向拼房人" min-width="150">
<template scope="{row}">
<template slot-scope="{row}">
<el-input v-if="row.bedInfo.bedType == '标准间' && row.bedInfo.isSleepTogether == true"
v-model="row.bedInfo.otherSleepUser"
placeholder="多个拼房人请用,隔开"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template scope="scope">
<template slot-scope="scope">
<el-button type="text" @click="removeProxyCompanion(scope.$index)">删除</el-button>
</template>
</el-table-column>
@@ -969,6 +971,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
})
},
async doReimbursement() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doReimbursement')) return
this._therapyActions.add('doReimbursement')
try {
if (this.multipleSelection && this.multipleSelection.length > 0) {
const enrollIds = this.multipleSelection.filter(v => v.isTakePartIn).map(v => v.id)
@@ -985,7 +991,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return
}
console.log(enrollIds)
this.$confirm(msg, '提示', {
await this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
dangerouslyUseHTMLString: true,
@@ -1011,6 +1017,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.$message.warning('请勾选需要报销的报名信息')
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doReimbursement')
}
},
doModify(row) {
this.$confirm("您确定要调整【<span style='color: red'>" + row.userName + "</span>】的此条报名信息吗?", '提示', {
@@ -1047,7 +1058,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
isTakePartIn,
} = this.pageForm
let types = this.pageForm.state == 1 ? JSON.stringify(['line']) : JSON.stringify(['travel'])
window.open(loc() + "/doExport?takePartInBaseManagementId=" + takePartInBaseManagementId +
this.$downloadFile(loc() + "/doExport?takePartInBaseManagementId=" + takePartInBaseManagementId +
"&searchName=" + searchName +
"&searchKeyword=" + searchKeyword +
"&startYear=" + startYear +
@@ -1083,7 +1094,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
linePlayTime,
isTakePartIn,
} = this.pageForm
window.open(loc() + "/doExportViewExcel?takePartInBaseManagementId=" + takePartInBaseManagementId +
this.$downloadFile(loc() + "/doExportViewExcel?takePartInBaseManagementId=" + takePartInBaseManagementId +
"&searchName=" + searchName +
"&searchKeyword=" + searchKeyword +
"&startYear=" + startYear +
@@ -1109,8 +1120,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doEdit() {
this.$refs['editForm'].validate().then(async () => {
const confirm = await this.$confirm('您确定要修改这位老师的报名信息吗?', '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doEdit')) return
this._therapyActions.add('doEdit')
try {
return await this.$validateForm(this.$refs['editForm']).then(async valid => {
if (!valid) return
const confirm = await this.$confirmAction('您确定要修改这位老师的报名信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -1130,6 +1146,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doEdit')
}
},
async openEdit(row) {
this.getUnionSelectLine(row.takePartInLineId)
@@ -1230,6 +1251,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.multipleSelection = val;
},
async doAttend() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doAttend')) return
this._therapyActions.add('doAttend')
try {
let arr = []
this.multipleSelection.forEach((v, index) => {
if (!v.lotId || !v.takePartInTime) {
@@ -1250,6 +1275,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.notifyWarning(refs.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doAttend')
}
},
checkboxT(v) {
if (v.isTakePartIn) {
@@ -1428,36 +1458,28 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
this.importVisible = true;
},
doImport() {
if (this.importData.fileList.length === 0) {
this.notifyWarning("请选择文件!")
async doImport() {
if (this.importLoading) return
const files = this.importData.fileList || []
if (!files.length || files.some(file => !file.raw)) {
this.notifyWarning('请选择要导入的Excel文件')
return
}
const data = new FormData();
this.importData.fileList.forEach((val) => {
data.append("file", val.raw, val.raw.name);
});
this.importLoading = true
$.ajax({
url: loc() + "/enrollImport",
type: "post",
data: data,
processData: false,
contentType: false,
success: (data) => {
if (data.code === 0) {
this.pageData();
this.importVisible = false
} else {
this.importLoading = false
}
},
error: (data) => {
this.notifyWarning("导入失败")
this.importLoading = false
try {
const resp = await this.$importExcel('/platform/inclusiveTherapyV3/user/query/enrollImport', files)
if (resp.code === 0) {
this.notifySuccess(resp.msg || '导入成功')
this.pageData()
this.importVisible = false
} else {
this.notifyWarning(resp.msg || '导入失败')
}
});
} catch (error) {
this.$actionError(error)
} finally {
this.importLoading = false
}
},
importVisibleClose() {
this.importVisible = false;
@@ -35,7 +35,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div id="app">
<el-card class="m10" shadow="never" style="height: calc(100% - 20px)">
<template #header>
<h3 style="color: #1867b0">导入参加人员</h3>
<h3 style="color: var(--color-primary)">导入参加人员</h3>
</template>
<el-steps :active="stepActive">
@@ -70,7 +70,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="panel-body">
<el-radio-group @change="travelId=''" size="small" v-model="lineId">
<el-radio :label="item.id"
border v-for="item in lines">{{item.label}}
border v-for="(item, therapyIndex) in lines" :key="item.id || item.code || therapyIndex">{{item.label}}
</el-radio>
</el-radio-group>
</div>
@@ -86,7 +86,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="panel-body">
<el-radio-group @change="lineId=''" size="small" v-model="travelId">
<el-radio :label="item.id"
border v-for="item in travels">{{item.label}}
border v-for="(item, therapyIndex) in travels" :key="item.id || item.code || therapyIndex">{{item.label}}
</el-radio>
</el-radio-group>
</div>
@@ -101,7 +101,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-button @click="downloadTemplate" size="small" type="primary">下载模板</el-button>
<el-upload
:action="loc()+'/readExcel'"
action="/platform/inclusiveTherapyV3/joinUserImport/readExcel"
:auto-upload="false"
:data="{lineId:lineId,travelAgencyId:travelId}"
:file-list="fileList"
@@ -109,7 +109,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
:on-error="(err)=>{this.notifyWarning(err)}"
:on-exceed="()=>{this.notifyWarning('最多只能选择一个文件')}"
:on-success="fileHandleSuccess"
accept="xls,xlsx"
accept=".xls,.xlsx"
drag
ref="upload"
style="text-align: center"
@@ -204,6 +204,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.stepActive--
},
async next() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('next')) return
this._therapyActions.add('next')
try {
const i = this.stepActive
if (i === 0) {
if (this.lineId === '' && this.travelId === '') {
@@ -243,6 +247,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return
}
this.stepActive++
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('next')
}
},
yearChange() {
this.selectLineOrTravelAgency()
@@ -255,7 +264,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
downloadTemplate() {
window.open(loc() + '/downloadTemplate')
this.$downloadFile(loc() + '/downloadTemplate')
}
},
updated() {
@@ -4,7 +4,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<style>
.companion_card {
border: 1px #1867b0 solid;
border: 1px var(--color-primary) solid;
}
.row-expand-cover .el-table__expand-icon {
@@ -44,7 +44,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-model="pageForm.lineId">
<el-option :label="item.lineName"
:value="item.id"
v-for="item in schoolFreeLineList"></el-option>
v-for="(item, therapyIndex) in schoolFreeLineList" :key="item.id || item.code || therapyIndex"></el-option>
</el-select>
</div>
</div>
@@ -81,7 +81,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-radio-group class="mr0-radio"
v-model="pageForm.regionalNature">
<el-radio-button :label="item.value"
border v-for="item in regionalNatureList">
border v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio-button>
</el-radio-group>
@@ -128,15 +128,15 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
header-align="center"
show-overflow-tooltip
:width="column.width"
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
>
<template scope="{row:{signUpMode}}" v-if="column.prop==='signUpMode'">
<template slot-scope="{row:{signUpMode}}" v-if="column.prop==='signUpMode'">
{{signUpModeName(signUpMode)}}
</template>
<template scope="{row:{createMode}}" v-else-if="column.prop==='createMode'">
<template slot-scope="{row:{createMode}}" v-else-if="column.prop==='createMode'">
{{createModeName(createMode)}}
</template>
<template scope="{row}" v-else-if="column.prop==='isDisabled'">
<template slot-scope="{row}" v-else-if="column.prop==='isDisabled'">
<el-switch
:active-value="false"
:inactive-value="true"
@@ -146,7 +146,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-model="row.isDisabled">
</el-switch>
</template>
<template scope="{row}" v-else-if="column.prop==='signUpUserAndFamilyNum'">
<template slot-scope="{row}" v-else-if="column.prop==='signUpUserAndFamilyNum'">
<span class="text-primary" v-if="configData.familyInfo == 2">
{{row.signUpUserNum + row.signUpUserFamilyNum}}
</span>
@@ -154,14 +154,15 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.signUpUserNum + row.familyNumber}}
</span>
</template>
<template scope="{row}" v-else-if="column.prop==='playTime'">
<template slot-scope="{row}" v-else-if="column.prop==='playTime'">
<template v-if="row.playStartTime">{{row.playStartTime + '至' + row.playEndTime}}</template>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column label="操作" width="100px">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="openViewSignUpUsers(row.usId,row.unionId)" size="mini" type="primary">调整
</el-button>
</template>
@@ -186,9 +187,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
:data="schoolFreeSignUpUserList" ref="adjustTable">
<el-table-column selectable="" type="selection"></el-table-column>
<el-table-column label="序号" type="expand" width="150px">
<template scope="{row}">
<template slot-scope="{row}">
<el-card class="companion_card" shadow="never">
<h4 slot="header" style="color: #1867b0">
<h4 slot="header" style="color: var(--color-primary)">
家属信息
</h4>
<el-table :data="row.companionList">
@@ -208,7 +209,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="工会" prop="unionName" show-overflow-tooltip sortable></el-table-column>
<el-table-column label="报名时间" prop="signingUptime"></el-table-column>
<el-table-column label="家属人数" prop="companionCount">
<template scope="{row}">
<template slot-scope="{row}">
<span v-if="configData.familyInfo === 2" class="text-primary">
{{row.companionCount}}
</span>
@@ -218,7 +219,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="是否调整" prop="isNormal">
<template scope="{row}">
<template slot-scope="{row}">
<span class="text-success" v-if="row.isNormal">
未调整
</span>
@@ -228,7 +229,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="操作">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="adjustmentUser(row.loginName,row.isNormal)" size="mini" type="primary"
v-if="row.isNormal">调整
</el-button>
@@ -316,17 +317,20 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return d ? d.label : null
},
async pageData() {
sublime.showLoadingbar()
this.tableLoading = true
try {
const resp = await $.post(loc() + '/pageData', this.pageForm)
sublime.closeLoadingbar()
this.tableLoading = false
if (resp.code === 0) {
this.tableData = resp.data.list
this.pageForm.totalCount = resp.data.totalCount
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this.tableLoading = false
}
},
async openViewSignUpUsers(lineId, unionId) {
this.currentLineId = lineId
@@ -343,8 +347,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
},
//调整人员
async adjustmentUser(loginName, isNormal) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('adjustmentUser')) return
this._therapyActions.add('adjustmentUser')
try {
const msg = isNormal ? '确定要调整吗?' : '确定要恢复吗?'
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -358,14 +366,23 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('adjustmentUser')
}
},
async aKeyToAdjust() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('aKeyToAdjust')) return
this._therapyActions.add('aKeyToAdjust')
try {
if (this.$refs.adjustTable.selection.length === 0) {
this.notifyWarning('请选择需要调整的人员')
return
}
const confirm = await this.$confirm('您确定要一键调整吗', '提示', {
const confirm = await this.$confirmAction('您确定要一键调整吗', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -388,13 +405,22 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('aKeyToAdjust')
}
},
async smsAlerts() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('smsAlerts')) return
this._therapyActions.add('smsAlerts')
try {
if (this.$refs.adjustTable.selection.length === 0) {
this.notifyWarning('请选择需要发送短信通知的人员')
return
}
const confirm = await this.$confirm('此操作会向已调整的人员发送短信,您确定要发送短信提醒吗?', '提示', {
const confirm = await this.$confirmAction('此操作会向已调整的人员发送短信,您确定要发送短信提醒吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -418,14 +444,28 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('smsAlerts')
}
},
async lineStatusChange(id) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('lineStatusChange')) return
this._therapyActions.add('lineStatusChange')
try {
const resp = await $.post('/platform/inclusiveTherapyV3/line/openClosedLine/' + id)
if (resp.code === 0) {
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('lineStatusChange')
}
},
async getConfigData() {
const resp = await $.get('/platform/inclusiveTherapyV3/TheRapyConfig/findOne')
@@ -110,20 +110,21 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
>
<template scope="{row:{signUpMode}}" v-if="column.prop==='signUpMode'">
<template slot-scope="{row:{signUpMode}}" v-if="column.prop==='signUpMode'">
{{signUpModeName(signUpMode)}}
</template>
<template scope="{row:{createMode}}" v-else-if="column.prop==='createMode'">
<template slot-scope="{row:{createMode}}" v-else-if="column.prop==='createMode'">
{{createModeName(createMode)}}
</template>
<template scope="{row}" v-if="column.prop==='times'">
<template slot-scope="{row}" v-else-if="column.prop==='times'">
{{row.playStartTime.substr(0,10)}}至{{row.playEndTime.substr(0,10)}}
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column label="操作" width="200px">
<template scope="{row}">
<template slot-scope="{row}">
<el-button @click="openViewClusterInfo(row.id)" size="mini" type="primary">查看</el-button>
<el-button @click="openCluster(row.id,row.ascriptionUnionId)" size="mini" type="primary">组团
</el-button>
@@ -238,7 +239,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="性别" prop="sex"></el-table-column>
<el-table-column label="工会" prop="unionName"></el-table-column>
<el-table-column label="身份" prop="isLeader">
<template scope="{row}">
<template slot-scope="{row}">
<span class="text-primary" v-if="row.isLeader">团长</span>
<span v-else>成员</span>
</template>
@@ -255,7 +256,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-radio-group size="small" v-model="batchMoveData.originalGroup">
<el-radio :label="item"
border
v-for="(item,key) in clusterData">{{item.clusterName}}
v-for="(item,key) in clusterData" :key="item.id || item.code || key">{{item.clusterName}}
</el-radio>
</el-radio-group>
@@ -295,7 +296,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-radio :disabled="item.clusterName == batchMoveData.originalGroup.clusterName"
:label="item"
border
v-for="(item,key) in clusterData">{{item.clusterName}}
v-for="(item,key) in clusterData" :key="item.id || item.code || key">{{item.clusterName}}
</el-radio>
</el-radio-group>
</div>
@@ -425,6 +426,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
},
async setClusterMembers() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('setClusterMembers')) return
this._therapyActions.add('setClusterMembers')
try {
const emptyCluster = Object.values(vue.clusterData).filter(v => v.clusterName !== '线路未分配人员').find(v => v.members.length === 0)
if (emptyCluster) {
this.notifyWarning(emptyCluster.clusterName + '未分配成员,请分配后再提交!')
@@ -443,6 +448,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('setClusterMembers')
}
},
setMemberRole(key, loginName, isLeader) {
const i = this.clusterData[key].members.findIndex(v => v.loginName === loginName)
@@ -46,7 +46,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-model="pageForm.regionalNature">
<el-radio-button :label="item.value"
border
v-for="item in regionalNatureList">
v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio-button>
</el-radio-group>
@@ -134,7 +134,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop === 'playTimes' || column.prop === 'signUpTimes'">
<template slot-scope="{row}" v-if="column.prop === 'playTimes' || column.prop === 'signUpTimes'">
<template v-if="row[column.prop]">
<template slot="content">
<div :class="[index === row[column.prop].split(',').length - 1 ? '' : 'mb10']"
@@ -149,18 +149,18 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</template>
<span v-else>暂未设置</span>
</template>
<template scope="{row}" v-else-if="column.prop === 'signUpMode'">
<template slot-scope="{row}" v-else-if="column.prop === 'signUpMode'">
{{signUpModeName(row.signUpMode)}}
</template>
<template scope="{row}" v-else-if="column.prop === 'isOpen'">
<template slot-scope="{row}" v-else-if="column.prop === 'isOpen'">
{{row.isOpen ? '是' : '否'}}
</template>
<template scope="{row}" v-else>
<template slot-scope="{row}" v-else>
{{row[column.prop]}}
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="120px">
<template scope="{row}">
<template slot-scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
@@ -212,7 +212,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="最少成团人数(包括家属)" prop="estimatedFamilyNumbers" width="170"></el-table-column>
<el-table-column label="最多人数" prop="maxPeopleNumber" width="100"></el-table-column>
<el-table-column label="是否开启" width="80">
<template scope="{row}">
<template slot-scope="{row}">
{{row.enable ? '是' : '否'}}
</template>
</el-table-column>
@@ -494,7 +494,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
url += this.buildExportParam('regionalNature', this.pageForm.regionalNature)
url += this.buildExportParam('pageOrderName', this.pageForm.pageOrderName)
url += this.buildExportParam('pageOrderBy', this.pageForm.pageOrderBy)
window.open(url)
this.$downloadFile(url)
},
buildExportParam(name, value) {
return '&' + name + '=' + encodeURIComponent(value == null ? '' : value)
@@ -579,13 +579,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$set(row, 'contactPhone', item.contactMobileNumber)
}
},
saveEditTimeSlots() {
this.$refs.editTimeSlotsForm.validate((valid) => {
if (!valid) {
return
}
async saveEditTimeSlots() {
if (this.editTimeSlotsLoading || !await this.$validateForm(this.$refs.editTimeSlotsForm)) return
try {
this.$set(this, 'editTimeSlotsLoading', true)
$.post(loc() + '/saveTimeSlots', {
await $.post(loc() + '/saveTimeSlots', {
lineId: this.editTimeSlotsForm.lineId,
unionId: this.editTimeSlotsForm.unionId,
year: this.pageForm.year,
@@ -601,7 +599,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}).always(() => {
this.$set(this, 'editTimeSlotsLoading', false)
})
})
} catch (error) {
this.$actionError(error)
}
},
cancelLine(row) {
const msg = '确认取消该分工会选择的线路吗?取消后将删除该线路下已有报名、床位、同伴和变更记录。'
@@ -62,7 +62,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
@change="doSearch"
v-model="pageForm.regionalNature">
<el-radio-button :label="item.value"
border v-for="item in regionalNatureList">
border v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio-button>
</el-radio-group>
@@ -145,16 +145,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-model="row.isDisabled">
</el-switch>
</template>-->
<template scope="{row:{signUpMode}}" v-if="column.prop==='signUpMode'">
{{signUpModeName(signUpMode)}}
<template slot-scope="{row}">
<template v-if="column.prop==='signUpMode'">
{{signUpModeName(row.signUpMode)}}
</template>
<template scope="{row:{createMode}}" v-else-if="column.prop==='createMode'">
{{createModeName(createMode)}}
<template v-else-if="column.prop==='createMode'">
{{createModeName(row.createMode)}}
</template>
<template scope="{row}" v-else-if="column.prop==='belongUnionName'">
<template v-else-if="column.prop==='belongUnionName'">
{{pageForm.mode == 2 && pageForm.selectStatus == 1 ? '校工会' : row.belongUnionName}}
</template>
<template scope="{row}" v-else-if="column.prop==='playTime'">
<template v-else-if="column.prop==='playTime'">
<template v-if="row.playTimes">
<!--<el-tooltip placement="top">
<div slot="content">
@@ -183,16 +184,18 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
选择并设置出行时间段
</el-button>
</template>
<template scope="{row}" v-else-if="column.prop==='createUnionName'">
<template v-else-if="column.prop==='createUnionName'">
<span v-if="!row.isSelect">
{{row.createUnionName}}
</span>
<span v-else>{{row.belongUnionName}}</span>
</template>
<template v-else>{{row[column.prop]}}</template>
</template>
</el-table-column>
<el-table-column label="操作" width="100px">
<template scope="{row}">
<template slot-scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
@@ -720,11 +723,15 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}
},
async doSelect() {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('doSelect')) return
this._therapyActions.add('doSelect')
try {
if (!this.assertCanSelectLine()) return
const valid = await this.$refs['form'].validate()
const valid = await this.$validateForm(this.$refs['form'])
if (!valid) return
const confirm = await this.$confirm('请再次确认,是否选择此线路为疗休养线路?', '提示', {
const confirm = await this.$confirmAction('请再次确认,是否选择此线路为疗休养线路?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -749,6 +756,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('doSelect')
}
},
createModeName(val) {
const d = this.createModeList.find(v => v.value === val)
@@ -759,9 +771,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return d ? d.label : null
},
async deSelect({applyCount, id: lineId, usUnionId: unionId}) {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('deSelect')) return
this._therapyActions.add('deSelect')
try {
if (!this.assertCanSelectLine()) return
const msg = applyCount > 0 ? '已经有教工选择本线路,请确认是否取消选择本线路,一旦取消将清空报名人员!!!' : '您确定要取消吗?'
const confirm = await this.$confirm(msg, '提示', {
const confirm = await this.$confirmAction(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -775,6 +791,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} else {
this.notifyWarning(resp.msg)
}
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('deSelect')
}
},
async getTravelAgencyOptions() {
const {data} = await $.get(loc() + '/getTravelAgencyOptions', {year: this.pageForm.year})
@@ -857,7 +878,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.travelAgencyList = resp.data
},
async doEditOpen(row) {
console.log(row)
try {
const resp = await $.get(loc() + '/doEditOpen', {id: row.usId})
if (resp.code === 0) {
this.$message.success(resp.msg)
@@ -865,6 +886,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$message.warning(resp.msg)
}
this.pageData()
} catch (error) {
this.$actionError(error)
this.pageData()
}
}
},
async created() {
@@ -60,7 +60,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="col-title">
旅行社平均分
<el-rate style="float: right"
value="5"
:value="5"
disabled
show-text
:texts="aaa"
@@ -79,7 +79,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="col-title">
线路平均分
<el-rate style="float: right"
value="5"
:value="5"
disabled
show-text
:texts="aaa"
@@ -125,7 +125,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
async getLineRating() {
let data = []
const refs = await $.post(loc() + "/getLineRating", {year: this.year})
refs.data.forEach(v => {
if (refs.code !== 0) { this.notifyWarning(refs.msg); return }
(refs.data || []).forEach(v => {
data.push({lineName: v.lineName, avg: v.avg})
})
if (chart.lineRating) {
@@ -154,7 +155,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
async getTravelAgencyRating() {
let data = []
const refs = await $.post(loc() + "/getTravelAgencyRating", {year: this.year})
refs.data.forEach(v => {
if (refs.code !== 0) { this.notifyWarning(refs.msg); return }
(refs.data || []).forEach(v => {
data.push({travelAgencyName: v.travelAgencyName, avg: v.avg})
})
if (chart.travelAgencyRating) {
@@ -183,7 +185,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
async getLineBar() {
let data = []
const refs = await $.post(loc() + "/getLineBar", {regionalNature: this.regionalNature, year: this.year})
refs.data.forEach(v => {
if (refs.code !== 0) { this.notifyWarning(refs.msg); return }
(refs.data || []).forEach(v => {
data.push({lineName: v.lineName, lineNum: (v.enrollNum + v.companionNum)})
})
if (chart.lineBar) {
@@ -212,7 +215,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
async getSnSwNum() {
const {data} = await $.post(loc() + "/getSnSwNum", {year: this.year})
this.snNum = data.snNum
this.swNum = data.snNum
this.swNum = data.swNum
}
},
@@ -228,4 +231,4 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<!--#
}
#-->
#-->
@@ -200,14 +200,14 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column type="selection" reserve-selection width="55px"></el-table-column>
<el-table-column align="center" header-align="center" type="index" label="序号"
width="80px" key="#index" fixed="left">
<template scope="scope">
<template slot-scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}} </span>
</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
v-for="column in tableColumns" :key="column.prop"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
@@ -215,21 +215,22 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
:fixed="column.fixed"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop=='lineName'">
<template slot-scope="{row}" v-if="column.prop=='lineName'">
<el-link type="primary" @click="openLine(row)">{{row.lineName}}
</el-link>
</template>
<template scope="{row}" v-if="column.prop=='signUpMode'">
<template slot-scope="{row}" v-else-if="column.prop=='signUpMode'">
<span>{{row.signUpMode == '1' ? '校工会组织' : '分工会组织'}}</span>
</template>
<template scope="{row}" v-else-if="column.prop=='groupCount'">
<template slot-scope="{row}" v-else-if="column.prop=='groupCount'">
<el-link type="primary" @click="openUserData(row)">
{{Number(row.lineNum || 0) + Number(row.adultFamilyNum || 0)}}
</el-link>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
<el-table-column label="操作" width="380px" fixed="right">
<template scope="{row}">
<template slot-scope="{row}">
<template>
<el-button @click="openUserData(row)" size="mini" type="primary">
查看人员
@@ -271,7 +272,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
filterable="true"
placeholder="所属工会" style="width: 100%;"
v-model="userPageForm.unionId">
<el-option :label="item.unionname" :value="item.id" v-for="item in unions"></el-option>
<el-option :label="item.unionname" :value="item.id" v-for="(item, therapyIndex) in unions" :key="item.id || item.code || therapyIndex"></el-option>
</el-select>
</div>
</div>
@@ -282,7 +283,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-select clearable="true" filterable="true" placeholder="所属单位"
style="width: 100%;"
v-model="userPageForm.unitId">
<el-option :label="item.name" :value="item.id" v-for="item in units"></el-option>
<el-option :label="item.name" :value="item.id" v-for="(item, therapyIndex) in units" :key="item.id || item.code || therapyIndex"></el-option>
</el-select>
</div>
</div>
@@ -298,13 +299,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column
align="center"
header-align="center"
v-for="column in userDataTableColumns"
v-for="(column, therapyIndex) in userDataTableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
>
<template scope="{row}" v-if="column.prop=='isFamily'">
:key="column.id || column.code || therapyIndex">
<template slot-scope="{row}" v-if="column.prop=='isFamily'">
<el-link v-if="!row.familyNumber" type="primary">
{{row.isFamily?'携带':'未携带'}}({{row.isFamily}})
</el-link>
@@ -312,6 +313,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
{{row.familyNumber?'携带':'未携带'}}({{row.familyNumber}})
</el-link>
</template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template>
</el-table-column>
</el-table>
<el-row class="el-pagination-container" style="margin-bottom: 0px">
@@ -599,7 +601,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
regionalNature,
travelAgencyId,
} = this.pageForm
window.open("/platform/inclusiveTherapyV3/user/query/doExport?" +
this.$downloadFile("/platform/inclusiveTherapyV3/user/query/doExport?" +
"startYear=" + startYear +
"&endYear=" + endYear +
"&unionId=" + unionId +
@@ -632,7 +634,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.doSearch()
},
async sendSuccess(row) {
this.$confirm("确定发送<span style='color: red'>成团通知</span>吗?", '提示', {
if (!this._therapyActions) this._therapyActions = new Set()
if (this._therapyActions.has('sendSuccess')) return
this._therapyActions.add('sendSuccess')
try {
await this.$confirm("确定发送<span style='color: red'>成团通知</span>吗?", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
@@ -645,9 +651,15 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$message.warning(resp.msg)
}
})
} catch (error) {
this.$actionError(error)
} finally {
this._therapyActions.delete('sendSuccess')
}
},
sendFail(row) {
this.$confirm("确定发送<span style='color: red'>未成团通知</span>并<span style='color: red'>保留报名记录</span>吗?", '提示', {
async sendFail(row) {
try {
await this.$confirm("确定发送<span style='color: red'>未成团通知</span>并<span style='color: red'>保留报名记录</span>吗?", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
@@ -660,6 +672,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$message.warning(resp.msg)
}
})
} catch (error) {
this.$actionError(error)
}
},
sendGroupMail() {
if (!this.multipleSelection || this.multipleSelection.length === 0) {
@@ -699,14 +714,15 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}).catch(() => {
})
},
resendFailNotice() {
this.$confirm("确定补发<span style='color: red'>2026年已删除报名记录的未成团通知</span>吗?", '提示', {
async resendFailNotice() {
try {
await this.$confirm("确定补发<span style='color: red'>2026年已删除报名记录的未成团通知</span>吗?", '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
$.post('/platform/inclusiveTherapyV3/statistics/resendFailNotice')
return $.post('/platform/inclusiveTherapyV3/statistics/resendFailNotice')
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
@@ -717,6 +733,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
.always(() => {
})
})
} catch (error) {
this.$actionError(error)
}
},
openLine(row) {
this.$refs.guava.public()
@@ -262,10 +262,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
})
},
doExportExcel() {
window.open(loc() + '/doExportExcel?year=' + encodeURIComponent(this.pageForm.year || ''))
this.$downloadFile(loc() + '/doExportExcel?year=' + encodeURIComponent(this.pageForm.year || ''))
},
doExportUnionExcel() {
window.open(loc() + '/doExportUnionExcel?year=' + encodeURIComponent(this.pageForm.year || ''))
this.$downloadFile(loc() + '/doExportUnionExcel?year=' + encodeURIComponent(this.pageForm.year || ''))
}
},
created() {
@@ -27,7 +27,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
ref="table"
v-loading="tableLoading">
<el-table-column align="center" header-align="center" type="index" label="序号" width="80px">
<template scope="scope">
<template slot-scope="scope">
<span>{{scope.$index + 1}}</span>
</template>
</el-table-column>
@@ -42,7 +42,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column align="center" header-align="center" prop="selectedProvinceInNumber"
label="已选择省内数量"></el-table-column>
<el-table-column align="center" header-align="center" prop="finished" label="是否完成">
<template scope="{row}">
<template slot-scope="{row}">
<el-tag v-if="row.finished" type="success">已完成</el-tag>
<el-tag v-else type="danger">未完成</el-tag>
</template>

Some files were not shown because too many files have changed in this diff Show More