Compare commits

13 Commits
73 changed files with 2554 additions and 919 deletions
@@ -1,34 +1,29 @@
package com.budwk.app.sys.controller; package com.budwk.app.sys.controller;
import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.budwk.app.base.constant.RoleConstant; import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.result.Result; 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_home_template;
import com.budwk.app.sys.models.Sys_menu; 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.SysHomeNewsService;
import com.budwk.app.sys.services.SysMenuService; import com.budwk.app.sys.services.SysMenuService;
import com.budwk.app.sys.services.SysUserService; import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.web.commons.auth.utils.AuthUtil; import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.nutz.dao.Cnd; import org.nutz.dao.Cnd;
import org.nutz.dao.Dao; import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter; import org.nutz.dao.FieldFilter;
import org.nutz.dao.Sqls; import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos; import org.nutz.dao.util.Daos;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings; import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log; import org.nutz.log.Log;
import org.nutz.log.Logs; import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
@@ -52,7 +47,7 @@ public class SysHomeController {
@Inject @Inject
private SysUserService sysUserService; private SysUserService sysUserService;
@Inject @Inject
private ActivityBasicScopeService activityBasicScopeService; private SysHomeActivityService sysHomeActivityService;
@Inject @Inject
private SysHomeNewsService sysHomeNewsService; private SysHomeNewsService sysHomeNewsService;
@@ -201,71 +196,16 @@ public class SysHomeController {
} }
/**
* includeEnded可选:true供PC首页展示已结束活动,缺省false保持既有调用行为。
* 返回Result,data为当前登录用户可见的活动实体列表,含名称、封面、链接及起止时间,不含内部SQL和类路径。
*/
@At @At
@SaCheckLogin @SaCheckLogin
@ApiOperation("首页推送活动") @ApiOperation("首页推送活动")
@Ok("json") @Ok("json")
public Result listHomeActivity() { public Result listHomeActivity(@Param(value = "includeEnded", df = "false") boolean includeEnded) {
FieldFilter fieldFilter = FieldFilter.locked(Sys_home_activity.class, "classPath"); return Result.success(sysHomeActivityService.listHomeActivity(SecurityUtil.getUserId(), includeEnded));
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);
} }
@At @At
@@ -8,7 +8,10 @@ import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.CommonDownloadUtil; import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.sys.models.*; import com.budwk.app.sys.models.*;
import com.budwk.app.sys.services.SysDictService; import com.budwk.app.sys.services.SysDictService;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.sys.views.View_user; import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@@ -17,6 +20,9 @@ import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap; import org.nutz.lang.util.NutMap;
import org.nutz.lang.random.R;
import org.nutz.trans.Atom;
import org.nutz.trans.Trans;
import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.AdaptBy;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Ok;
@@ -26,9 +32,15 @@ import org.nutz.mvc.upload.UploadAdaptor;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.InputStream; import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Slf4j @Slf4j
@@ -45,6 +57,10 @@ public class SysUnionCadreImportController {
private SysDictService sysDictService; private SysDictService sysDictService;
@Inject @Inject
private SysUnionController sysUnionController; private SysUnionController sysUnionController;
@Inject
private SysRoleService sysRoleService;
@Inject
private SysUserService sysUserService;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private List<NutMap> roleOptions() { private List<NutMap> roleOptions() {
@@ -72,7 +88,7 @@ public class SysUnionCadreImportController {
append(notes, "届次编码(选填)", "可留空;填写时使用届次对照表中的编码,与单个添加一致。"); append(notes, "届次编码(选填)", "可留空;填写时使用届次对照表中的编码,与单个添加一致。");
append(notes, "所属单位编码(书记必填)", "仅二级党委书记填写,多个单位用英文逗号分隔,必须为当前分工会的二级单位;其他角色留空。"); append(notes, "所属单位编码(书记必填)", "仅二级党委书记填写,多个单位用英文逗号分隔,必须为当前分工会的二级单位;其他角色留空。");
append(notes, "重复记录", "普通干部按人员和角色跳过;二级党委书记按人员、角色和工会跳过。禁用的已有关系也跳过,不覆盖。"); append(notes, "重复记录", "普通干部按人员和角色跳过;二级党委书记按人员、角色和工会跳过。禁用的已有关系也跳过,不覆盖。");
append(notes, "保存方式", "系统管理员直接授权,写入干部及角色记录并清理权限缓存,不发起审批。逐行保存,失败行不影响其他行。"); append(notes, "保存方式", "系统管理员直接授权,批量校验并保存干部及角色记录,统一清理权限缓存,不发起审批。校验失败行不写入;保存异常时拆分定位失败行,其他有效行继续导入。");
append(notes, "已有干部记录", "已有在任或待审核干部记录但未分配角色时跳过,避免重复创建或绕过已有审批。"); append(notes, "已有干部记录", "已有在任或待审核干部记录但未分配角色时跳过,避免重复创建或绕过已有审批。");
Sheet unions = createSheet(workbook, "工会对照", "工会编码", "工会名称"); Sheet unions = createSheet(workbook, "工会对照", "工会编码", "工会名称");
List<Sys_union> unionList = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode")); List<Sys_union> unionList = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode"));
@@ -145,101 +161,271 @@ public class SysUnionCadreImportController {
if (rows.isEmpty()) { if (rows.isEmpty()) {
return Result.error("文件中没有需要导入的数据"); return Result.error("文件中没有需要导入的数据");
} }
List<String> roleCodes = roleOptions().stream().map(item -> item.getString("code")).toList(); Set<String> roleCodes = sysDictService.getSubListByCode("BRANCH_UNION_ROLES").stream()
List<String> terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream() .map(Sys_dict::getCode).collect(Collectors.toSet());
.map(Sys_dict::getCode).toList(); roleCodes.add(RoleConstant.UNIT_PARTY_SECRETARY.name());
int success = 0; Set<String> terms = sysDictService.getSubListByCode("TEACHER_CONGRESS_J").stream()
int skipped = 0; .map(Sys_dict::getCode).collect(Collectors.toSet());
List<String> unionCodes = values(rows, "unionCode");
List<String> loginnames = values(rows, "loginname");
List<String> inputRoleCodes = values(rows, "roleCode");
List<String> unitCodes = rows.stream().flatMap(row -> splitUnitCodes(row.getString("unitCodes")).stream())
.distinct().toList();
// 各类基础数据及已有关系按表一次查询,逐行校验时不再访问数据库。
Map<String, List<Sys_union>> unions = group(unionCodes.isEmpty() ? List.of()
: dao.query(Sys_union.class, Cnd.where("unionCode", "in", unionCodes)), Sys_union::getUnionCode);
Map<String, List<View_user>> users = group(loginnames.isEmpty() ? List.of()
: dao.query(View_user.class, Cnd.where("loginname", "in", loginnames)), View_user::getLoginname);
Map<String, List<Sys_role>> roles = group(inputRoleCodes.isEmpty() ? List.of()
: dao.query(Sys_role.class, Cnd.where("code", "in", inputRoleCodes)), Sys_role::getCode);
Map<String, List<Sys_unit>> units = group(unitCodes.isEmpty() ? List.of()
: dao.query(Sys_unit.class, Cnd.where("unitcode", "in", unitCodes)), Sys_unit::getUnitcode);
List<String> userIds = users.values().stream().flatMap(List::stream).map(View_user::getId).distinct().toList();
List<String> roleIds = roles.values().stream().flatMap(List::stream).map(Sys_role::getId).distinct().toList();
Set<List<String>> existingRoles = new HashSet<>();
if (!userIds.isEmpty() && !roleIds.isEmpty()) {
for (Sys_user_role relation : dao.query(Sys_user_role.class,
Cnd.where("userId", "in", userIds).and("roleId", "in", roleIds))) {
existingRoles.add(roleKey(relation.getUserId(), relation.getRoleId(), relation.getUnionId(),
roles.getOrDefault(RoleConstant.UNIT_PARTY_SECRETARY.name(), List.of()).stream()
.anyMatch(role -> role.getId().equals(relation.getRoleId()))));
}
}
Set<List<String>> existingCadres = new HashSet<>();
if (!userIds.isEmpty() && !inputRoleCodes.isEmpty() && !unionCodes.isEmpty()) {
List<String> unionIds = unions.values().stream().flatMap(List::stream).map(Sys_union::getId).distinct().toList();
if (!unionIds.isEmpty()) {
for (Sys_union_cadre cadre : dao.query(Sys_union_cadre.class, Cnd.where("userId", "in", userIds)
.and("roleCode", "in", inputRoleCodes).and("unionId", "in", unionIds).and("isServing", "=", true))) {
existingCadres.add(Arrays.asList(cadre.getUserId(), cadre.getRoleCode(), cadre.getUnionId()));
}
}
}
List<ImportEntry> entries = new ArrayList<>();
Map<List<String>, Integer> fileRoles = new java.util.HashMap<>();
String operator = SecurityUtil.getUserId();
for (NutMap row : rows) { for (NutMap row : rows) {
try { ImportEntry entry = prepareRow(row, roleCodes, terms, unions, users, roles, units,
importRow(row, roleCodes, terms); existingRoles, existingCadres, fileRoles, operator);
} catch (Exception e) { if (entry != null) {
log.error("导入分工会干部失败,行号:{}", row.getInt("rowNumber"), e); entries.add(entry);
outcome(row, "失败", "保存失败,请检查该行数据或联系管理员");
}
if ("成功".equals(row.getString("status"))) {
success++;
} else if ("跳过".equals(row.getString("status"))) {
skipped++;
} }
} }
saveBatch(entries);
int success = (int) rows.stream().filter(row -> "成功".equals(row.getString("status"))).count();
int skipped = (int) rows.stream().filter(row -> "跳过".equals(row.getString("status"))).count();
if (success > 0) {
sysRoleService.clearCache();
sysUserService.clearCache();
}
return Result.success(NutMap.NEW().addv("success", success).addv("skipped", skipped) return Result.success(NutMap.NEW().addv("success", success).addv("skipped", skipped)
.addv("failed", rows.size() - success - skipped).addv("rows", rows)); .addv("failed", rows.size() - success - skipped).addv("rows", rows));
} }
private void importRow(NutMap row, List<String> roleCodes, List<String> terms) { private List<String> values(List<NutMap> rows, String field) {
return rows.stream().map(row -> row.getString(field)).filter(StrUtil::isNotBlank).distinct().toList();
}
private List<String> splitUnitCodes(String codes) {
return Arrays.stream(codes.split("[,,]")).map(String::trim).filter(StrUtil::isNotBlank).distinct().toList();
}
private <T> Map<String, List<T>> group(List<T> items, Function<T, String> key) {
return items.stream().collect(Collectors.groupingBy(key));
}
private List<String> roleKey(String userId, String roleId, String unionId, boolean secretary) {
return Arrays.asList(userId, roleId, secretary ? unionId : "");
}
private <T> T unique(Map<String, List<T>> records, String code, String label, List<String> errors) {
if (StrUtil.isBlank(code)) {
errors.add(label + "不能为空");
return null;
}
List<T> matches = records.getOrDefault(code, List.of());
if (matches.isEmpty()) {
errors.add(label + "【" + code + "】不存在");
return null;
}
if (matches.size() > 1) {
errors.add(label + "【" + code + "】匹配到" + matches.size() + "条记录,需先处理系统中的重复编码");
return null;
}
return matches.get(0);
}
private ImportEntry prepareRow(NutMap row, Set<String> roleCodes, Set<String> terms,
Map<String, List<Sys_union>> unions, Map<String, List<View_user>> users,
Map<String, List<Sys_role>> roles, Map<String, List<Sys_unit>> units,
Set<List<String>> existingRoles, Set<List<String>> existingCadres,
Map<List<String>, Integer> fileRoles, String operator) {
String unionCode = row.getString("unionCode"); String unionCode = row.getString("unionCode");
String loginname = row.getString("loginname"); String loginname = row.getString("loginname");
String roleCode = row.getString("roleCode"); String roleCode = row.getString("roleCode");
String j = row.getString("j"); String j = row.getString("j");
if (StrUtil.isBlank(unionCode) || StrUtil.isBlank(loginname) || StrUtil.isBlank(roleCode)) { List<String> errors = new ArrayList<>();
outcome(row, "失败", "工会编码、工号、角色编码不能为空"); Sys_union union = unique(unions, unionCode, "工会编码", errors);
return; View_user user = unique(users, loginname, "工号", errors);
Sys_role role = unique(roles, roleCode, "角色编码", errors);
if (StrUtil.isNotBlank(roleCode) && !roleCodes.contains(roleCode)) {
errors.add("角色编码【" + roleCode + "】不在允许导入的分工会干部角色范围内,请参照角色对照表");
} }
List<Sys_union> unions = dao.query(Sys_union.class, Cnd.where("unionCode", "=", unionCode)); if (!errors.isEmpty()) {
List<View_user> users = dao.query(View_user.class, Cnd.where("loginname", "=", loginname)); outcome(row, "失败", String.join(";", errors));
List<Sys_role> roles = dao.query(Sys_role.class, Cnd.where("code", "=", roleCode)); return null;
if (unions.size() != 1 || users.size() != 1 || roles.size() != 1 || !roleCodes.contains(roleCode)) {
outcome(row, "失败", "工会、工号或分工会角色编码不存在或不唯一,请按模板对照表填写");
return;
} }
Sys_union union = unions.get(0);
View_user user = users.get(0);
Sys_role role = roles.get(0);
boolean secretary = RoleConstant.UNIT_PARTY_SECRETARY.name().equals(roleCode); boolean secretary = RoleConstant.UNIT_PARTY_SECRETARY.name().equals(roleCode);
Cnd existing = Cnd.where("userId", "=", user.getId()).and("roleId", "=", role.getId()); List<String> key = roleKey(user.getId(), role.getId(), union.getId(), secretary);
if (secretary) { if (existingRoles.contains(key)) {
existing.and("unionId", "=", union.getId()); outcome(row, "跳过", "工号【" + loginname + "】已分配角色【" + roleCode + "】"
} + (secretary ? "(工会编码【" + unionCode + "】)" : "") + ",保留原有记录(含禁用关系)");
if (dao.count(Sys_user_role.class, existing) > 0) { return null;
outcome(row, "跳过", "已分配该角色,保留原有记录(含禁用关系)");
return;
} }
if (!union.getId().equals(user.getUnionId())) { if (!union.getId().equals(user.getUnionId())) {
outcome(row, "失败", "所选人员不属于该分工会"); errors.add("工号【" + loginname + "】所属工会为【" + StrUtil.blankToDefault(user.getUnionName(), "未分配工会")
return; + "】,与填写的工会【" + union.getName() + "(" + unionCode + ")】不一致");
} }
if (StrUtil.isNotBlank(j) && !terms.contains(j)) { if (StrUtil.isNotBlank(j) && !terms.contains(j)) {
outcome(row, "失败", "届次编码不存在,请参照届次对照表或留空"); errors.add("届次编码【" + j + "】不存在,请参照届次对照表或留空");
return;
} }
if (dao.count(Sys_union_cadre.class, Cnd.where("userId", "=", user.getId()) if (existingCadres.contains(Arrays.asList(user.getId(), roleCode, union.getId()))) {
.and("roleCode", "=", roleCode).and("unionId", "=", union.getId()).and("isServing", "=", true)) > 0) { outcome(row, "跳过", "工号【" + loginname + "】在工会【" + unionCode + "】已有角色【" + roleCode
outcome(row, "跳过", "已有在任或待审核干部记录,请通过原记录处理"); + "】的在任或待审核干部记录,请通过原记录处理");
return; return null;
} }
List<String> unitIds = new ArrayList<>(); List<String> unitIds = new ArrayList<>();
String unitCodes = row.getString("unitCodes"); String unitCodes = row.getString("unitCodes");
if (secretary) { if (secretary) {
List<String> codes = Arrays.stream(unitCodes.split("[,,]")) List<String> codes = splitUnitCodes(unitCodes);
.map(String::trim).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
if (codes.isEmpty()) { if (codes.isEmpty()) {
outcome(row, "失败", "二级党委书记必须填写所属单位编码"); errors.add("角色【二级党委书记】必须填写所属单位编码,请参照所属单位对照表");
return;
} }
for (String code : codes) { for (String code : codes) {
List<Sys_unit> units = dao.query(Sys_unit.class, Cnd.where("unitcode", "=", code) List<Sys_unit> matches = units.getOrDefault(code, List.of());
.and("unionId", "=", union.getId()).and("unitLevel", "=", 2)); List<Sys_unit> valid = matches.stream().filter(unit -> union.getId().equals(unit.getUnionId())
if (units.size() != 1) { && Integer.valueOf(2).equals(unit.getUnitLevel())).toList();
outcome(row, "失败", "所属单位编码不存在、不唯一或不是该分工会的二级单位:" + code); if (matches.isEmpty()) {
return; errors.add("所属单位编码【" + code + "】不存在");
} else if (valid.isEmpty()) {
boolean inUnion = matches.stream().anyMatch(unit -> union.getId().equals(unit.getUnionId()));
errors.add(inUnion ? "所属单位编码【" + code + "】属于工会【" + unionCode + "】,但单位级别不是二级"
: "所属单位编码【" + code + "】不属于填写的工会【" + union.getName() + "(" + unionCode + ")】");
} else if (valid.size() > 1) {
errors.add("所属单位编码【" + code + "】在工会【" + unionCode + "】下匹配到" + valid.size() + "个二级单位,编码不唯一");
} else {
unitIds.add(valid.get(0).getId());
} }
unitIds.add(units.get(0).getId());
} }
} else if (StrUtil.isNotBlank(unitCodes)) { } else if (StrUtil.isNotBlank(unitCodes)) {
outcome(row, "失败", "普通干部角色的所属单位编码应留空"); errors.add("角色【" + roleCode + "】不是二级党委书记,所属单位编码【" + unitCodes + "】应留空");
}
if (!errors.isEmpty()) {
outcome(row, "失败", String.join(";", errors));
return null;
}
Integer previousRow = fileRoles.putIfAbsent(key, row.getInt("rowNumber"));
if (previousRow != null) {
outcome(row, "跳过", "与本文件第" + previousRow + "行的人员角色授权重复");
return null;
}
Sys_union_cadre cadre = new Sys_union_cadre();
cadre.setId(R.UU32());
cadre.setUserId(user.getId());
cadre.setUnionId(union.getId());
cadre.setMobile(user.getMobile());
cadre.setUnionName(user.getUnionName());
cadre.setLoginName(user.getLoginname());
cadre.setUserName(user.getUsername());
cadre.setRoleCode(roleCode);
cadre.setJ(j);
cadre.setApplyDate(new Date());
cadre.setIsServing(true);
cadre.setIsJoin(true);
// fastInsert不执行实体插入拦截器,显式补齐主键及审计字段。
cadre.setCreatedBy(operator);
cadre.setUpdatedBy(operator);
cadre.setCreatedAt(System.currentTimeMillis());
cadre.setUpdatedAt(cadre.getCreatedAt());
cadre.setDelFlag(false);
List<Sys_user_role> relations = new ArrayList<>();
for (String unitId : secretary ? unitIds : java.util.Collections.singletonList((String) null)) {
Sys_user_role relation = new Sys_user_role();
relation.setUserId(user.getId());
relation.setRoleId(role.getId());
relation.setUnionId(union.getId());
relation.setUnitId(unitId);
relations.add(relation);
}
return new ImportEntry(row, cadre, relations);
}
private void saveBatch(List<ImportEntry> entries) {
if (entries.isEmpty()) {
return; return;
} }
// 经由注入的原控制器代理调用,保留单行事务、直接授权及缓存清理逻辑。 try {
Result result = secretary // 两张表各批量写入一次,同一事务保证干部记录和角色授权同时生效。
? sysUnionController.insertBranchUnionPartySecretaryRole(user.getId(), union.getId(), unitIds.toArray(new String[0]), j) Trans.exec((Atom) () -> {
: sysUnionController.insertBranchUnionUserRole(user.getId(), roleCode, union.getId(), j); dao.fastInsert(entries.stream().map(entry -> entry.cadre).toList());
if (result.isSuccess()) { dao.fastInsert(entries.stream().flatMap(entry -> entry.relations.stream()).toList());
outcome(row, "成功", "添加成功"); });
} else if ("请勿重复添加".equals(result.getMsg()) || "该人员已设置二级党委书记,请先删除后再重新设置".equals(result.getMsg())) { entries.forEach(entry -> outcome(entry.row, "成功", "添加成功"));
outcome(row, "跳过", result.getMsg()); } catch (Exception e) {
} else { if (entries.size() > 1) {
outcome(row, "失败", result.getMsg()); // 仅保存异常时拆分批次定位坏行,正常导入不产生逐行写入。
int middle = entries.size() / 2;
saveBatch(entries.subList(0, middle));
saveBatch(entries.subList(middle, entries.size()));
} else {
NutMap row = entries.get(0).row;
log.error("导入分工会干部保存失败,行号:{},工号:{},角色编码:{}",
row.getInt("rowNumber"), row.getString("loginname"), row.getString("roleCode"), e);
outcome(row, "失败", saveFailure(e));
}
}
}
private String saveFailure(Exception error) {
for (Throwable cause = error; cause != null; cause = cause.getCause()) {
if (cause instanceof SQLException) {
SQLException sql = (SQLException) cause;
String state = sql.getSQLState();
if ("23505".equals(state) || sql.getErrorCode() == 1062) {
return "保存时发生唯一键冲突,可能已有相同干部或角色授权记录;本行已回滚";
}
if ("22001".equals(state) || sql.getErrorCode() == 1406) {
return "干部信息字段超出数据库长度限制,请检查工号、姓名、手机号、工会名称及届次长度;本行已回滚";
}
if ("23502".equals(state) || sql.getErrorCode() == 1048 || sql.getErrorCode() == 1364) {
return "干部记录或角色授权缺少数据库要求的必填值,请检查该人员的基础信息及干部表必填字段;本行已回滚";
}
if ("23503".equals(state) || sql.getErrorCode() == 1452) {
return "人员、工会、角色或所属单位的关联记录已不存在,请核对对应系统数据;本行已回滚";
}
if (state != null && state.startsWith("23")) {
return "干部记录或角色授权违反数据库必填、关联或唯一性约束,请核对人员、工会和角色数据;本行已回滚";
}
if (state != null && state.startsWith("08")) {
return "保存干部及角色授权时数据库连接异常,本行未完成导入,可稍后重新导入";
}
if (state != null && state.startsWith("40")) {
return "保存干部及角色授权时发生事务冲突,本行已回滚,可重新导入";
}
}
}
return "干部记录或角色授权写入异常,本行未完成导入;请管理员按Excel行号、工号及角色编码查看导入日志";
}
private static class ImportEntry {
private final NutMap row;
private final Sys_union_cadre cadre;
private final List<Sys_user_role> relations;
private ImportEntry(NutMap row, Sys_union_cadre cadre, List<Sys_user_role> relations) {
this.row = row;
this.cadre = cadre;
this.relations = relations;
} }
} }
@@ -22,7 +22,6 @@ import com.budwk.app.sys.services.SysDictService;
import com.budwk.app.sys.services.SysRoleService; import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.sys.services.SysUnitService; import com.budwk.app.sys.services.SysUnitService;
import com.budwk.app.sys.services.SysUserService; 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.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil; import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil; 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())) { if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) { if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId()); cnd.and("parentId", "=", "").or("parentId", "is", null);
} else { } else {
cnd.and("parentId", "=", pid).and("id", "<>", pid); cnd.and("parentId", "=", pid);
} }
cnd.asc("location").asc("path"); cnd.asc("location").asc("path");
list = sysUnitService.query(cnd); list = sysUnitService.query(cnd);
@@ -228,9 +227,9 @@ public class SysUnitController {
} else { } else {
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) { if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId()); cnd.and("parentId", "=", "").or("parentId", "is", null);
} else { } else {
cnd.and("parentId", "=", pid).and("id", "<>", pid); cnd.and("parentId", "=", pid);
} }
cnd.asc("location").asc("path"); cnd.asc("location").asc("path");
list = sysUnitService.query(cnd); list = sysUnitService.query(cnd);
@@ -259,9 +258,9 @@ public class SysUnitController {
if (StpUtil.hasRole("SYSADMIN")) { if (StpUtil.hasRole("SYSADMIN")) {
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) { if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId()); cnd.and("parentId", "=", "").or("parentId", "is", null);
} else { } else {
cnd.and("parentId", "=", pid).and("id", "<>", pid); cnd.and("parentId", "=", pid);
} }
cnd.asc("location").asc("path"); cnd.asc("location").asc("path");
list = sysUnitService.query(cnd); list = sysUnitService.query(cnd);
@@ -272,9 +271,9 @@ public class SysUnitController {
} else { } else {
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
if (Strings.isBlank(pid)) { if (Strings.isBlank(pid)) {
cnd.and("id", "=", DataCenterUtil.findRootUnit(sysUnitService.query(Cnd.NEW())).getId()); cnd.and("parentId", "=", "").or("parentId", "is", null);
} else { } else {
cnd.and("parentId", "=", pid).and("id", "<>", pid); cnd.and("parentId", "=", pid);
} }
cnd.asc("location").asc("path"); cnd.asc("location").asc("path");
list = sysUnitService.query(cnd); 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") @At("/tree")
@Ok("json") @Ok("json")
@SaCheckLogin @SaCheckLogin
public Object tree(@Param("pid") String pid, HttpServletRequest req) { public Object tree(@Param("pid") String pid, HttpServletRequest req) {
try { try {
String rootId = StrUtil.blankToDefault(pid, "0");
String virtualRootId = "root"; String virtualRootId = "root";
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
cnd.asc("unitcode"); cnd.asc("unitcode");
List<Sys_unit> list = sysUnitService.query(cnd); List<Sys_unit> list = sysUnitService.query(cnd);
String rootId = StrUtil.isBlank(pid) ? DataCenterUtil.findRootUnit(list).getId() : pid;
List<TreeNode<String>> nodeList = CollUtil.newArrayList(); List<TreeNode<String>> nodeList = CollUtil.newArrayList();
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
Sys_unit unit = list.get(i); Sys_unit unit = list.get(i);
/* /*
* 动态查询根挂到虚拟根下,兼容根节点父级为空或指向自身的数据。 * 单位根节点存在 id 与 parentId 都为 0 的自引用数据。
* 构建树时把当前查询根挂到虚拟根下,避免“中国地质大学”和 parentId=0 的学院被构造成同级。
*/ */
String parentId = rootId.equals(unit.getId()) ? virtualRootId : unit.getParentId(); String parentId = rootId.equals(unit.getId()) ? virtualRootId : unit.getParentId();
nodeList.add(new TreeNode<>(unit.getId(), parentId, unit.getName(), i) nodeList.add(new TreeNode<>(unit.getId(), parentId, unit.getName(), i)
.setExtra( .setExtra(
Map.of( Map.of(
// 历史手工新建单位可能未设置类型,展示时按其他类处理,避免空值使整棵树加载失败。
"unitTypeCode", unit.getUnitTypeCode() == null ? 0 : unit.getUnitTypeCode() "unitTypeCode", unit.getUnitTypeCode() == null ? 0 : unit.getUnitTypeCode()
) )
)); ));
@@ -324,23 +333,37 @@ public class SysUnitController {
List<Tree<String>> treeList = TreeUtil.build(nodeList, virtualRootId); List<Tree<String>> treeList = TreeUtil.build(nodeList, virtualRootId);
return Result.success(treeList); return Result.success(treeList);
} catch (Exception e) { } catch (Exception e) {
log.error("加载单位树失败", e);
return Result.error(); 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 @At
@Ok("json") @Ok("json")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("sys.manager.unit.add") @SaCheckPermission("sys.manager.unit.add")
@SLog(tag = "新建单位", msg = "单位名称:${args[0].name}") @SLog(tag = "新建单位", msg = "单位名称:${args[0].name}")
public Object addDo(@Param("..") Sys_unit unit, @Param("parentId") String parentId, HttpServletRequest req) { public Object addDo(@Param("..") Sys_unit unit, @Param("parentId") String parentId, HttpServletRequest req) {
try { try {
if ("root".equals(parentId)) { if (Strings.isBlank(unit.getName()) || Strings.isBlank(unit.getUnitcode()) || Strings.isBlank(parentId) || "root".equals(parentId)) {
parentId = ""; return Result.error("单位名称、单位编码和上级单位不能为空");
} }
unit.setCreatedBy(SecurityUtil.getUserId()); unit.setCreatedBy(SecurityUtil.getUserId());
sysUnitService.save(unit, parentId); sysUnitService.save(unit, parentId);
return Result.success(); return Result.success();
} catch (BaseException e) {
return Result.error(e.getMessage());
} catch (Exception e) { } catch (Exception e) {
log.error("新建单位失败", e);
return Result.error(); return Result.error();
} }
} }
@@ -3,5 +3,17 @@ package com.budwk.app.sys.services;
import com.budwk.app.base.service.BaseService; import com.budwk.app.base.service.BaseService;
import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.sys.models.Sys_home_activity;
import java.util.List;
public interface SysHomeActivityService extends BaseService<Sys_home_activity> { public interface SysHomeActivityService extends BaseService<Sys_home_activity> {
/**
* 获取指定用户有权查看的已启用首页活动。
*
* @param userId 当前登录用户ID,用于人员分组及自定义SQL的可见范围校验
* @param includeEnded true包含已结束活动并按状态、置顶和开始时间排序;false保持原有过滤和排序
* @return 活动实体列表,包含id、name、cover、url、h5Url、startDate、endDate等展示字段,
* 不返回classPath和allowUserSql内部配置
*/
List<Sys_home_activity> listHomeActivity(String userId, boolean includeEnded);
} }
@@ -1,15 +1,87 @@
package com.budwk.app.sys.services.impl; package com.budwk.app.sys.services.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.sys.models.Sys_home_activity;
import com.budwk.app.sys.services.SysHomeActivityService; import com.budwk.app.sys.services.SysHomeActivityService;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao; import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
@IocBean(args = {"refer:dao"}) @IocBean(args = {"refer:dao"})
public class SysHomeActivityServiceImpl extends BaseServiceImpl<Sys_home_activity> implements SysHomeActivityService { public class SysHomeActivityServiceImpl extends BaseServiceImpl<Sys_home_activity> implements SysHomeActivityService {
@Inject
private ActivityBasicScopeService activityBasicScopeService;
public SysHomeActivityServiceImpl(Dao dao) { public SysHomeActivityServiceImpl(Dao dao) {
super(dao); super(dao);
} }
/**
* 沿用首页原有的启用及人员可见范围校验,仅在调用方明确要求时展示已结束活动。
* 参数和返回结构见服务接口;查询过程不更新活动配置。
*/
@Override
public List<Sys_home_activity> listHomeActivity(String userId, boolean includeEnded) {
FieldFilter fieldFilter = FieldFilter.locked(Sys_home_activity.class, "classPath");
List<Sys_home_activity> list = Daos.ext(dao(), fieldFilter).query(Sys_home_activity.class,
Cnd.where("enable", "=", 1).desc("top"));
List<Sys_home_activity> allowActivityList = new ArrayList<>();
// 同一次请求使用同一个时间点,保证过滤与排序对活动是否结束的判断一致。
Date today = DateUtil.date();
for (Sys_home_activity activity : list) {
// 未传includeEnded的既有调用继续过滤已结束活动,保留原来的日期比较口径。
if (!includeEnded && DateUtil.compare(today, activity.getEndDate()) > 0) {
continue;
}
Integer allowUserGroupId = activity.getAllowUserGroupId();
String allowUserSql = activity.getAllowUserSql();
// 自定义SQL仅用于服务端判断可见范围,禁止随活动列表返回前端。
activity.setAllowUserSql(null);
if (allowUserGroupId == null && StrUtil.isBlank(allowUserSql)) {
allowActivityList.add(activity);
continue;
}
if (allowUserGroupId != null) {
if (activityBasicScopeService.isUserInGroup(allowUserGroupId, userId)) {
allowActivityList.add(activity);
continue;
}
}
if (StrUtil.isNotBlank(allowUserSql)) {
Sql sql = Sqls.create(allowUserSql).setParam("userId", userId);
sql.setCallback(Sqls.callback.map());
dao().execute(sql);
NutMap nutMap = (NutMap) sql.getResult();
if (Lang.isNotEmpty(nutMap) && StrUtil.isNotBlank(nutMap.getString("userId"))) {
allowActivityList.add(activity);
}
}
}
if (includeEnded) {
// 未结束活动整体在前,已结束置顶活动也不能越组;组内置顶优先,再按开始时间倒序,空开始时间排后。
allowActivityList.sort(Comparator
.comparing((Sys_home_activity activity) -> DateUtil.compare(today, activity.getEndDate()) > 0)
.thenComparing(activity -> Boolean.TRUE.equals(activity.getTop()), Comparator.reverseOrder())
.thenComparing(Sys_home_activity::getStartDate, Comparator.nullsLast(Comparator.reverseOrder())));
}
return allowActivityList;
}
} }
@@ -54,9 +54,8 @@ public class ActivityBasicSettingsController {
if (parentId != null) { if (parentId != null) {
parentId.setChild(child(parentId.getId())); parentId.setChild(child(parentId.getId()));
list.add(parentId); list.add(parentId);
return Result.success().addData(list);
} }
return Result.success(); return Result.success(list);
} }
private List<ActivityBasicSettings> child(String parentId) { private List<ActivityBasicSettings> child(String parentId) {
@@ -73,6 +72,9 @@ public class ActivityBasicSettingsController {
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
if (StrUtil.isBlank(parentId)) { if (StrUtil.isBlank(parentId)) {
ActivityBasicSettings rootSetting = dao.fetch(ActivityBasicSettings.class, Cnd.where("parentId", "=", 0)); ActivityBasicSettings rootSetting = dao.fetch(ActivityBasicSettings.class, Cnd.where("parentId", "=", 0));
if (rootSetting == null) {
return Result.success(new Pagination<ActivityBasicSettings>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, new ArrayList<ActivityBasicSettings>()));
}
cnd.and("parentId", "=", rootSetting.getId()); cnd.and("parentId", "=", rootSetting.getId());
} else { } else {
cnd.and("parentId", "=", parentId); cnd.and("parentId", "=", parentId);
@@ -116,7 +118,13 @@ public class ActivityBasicSettingsController {
@At @At
public Result getActivityTwoLevelType(String code) { public Result getActivityTwoLevelType(String code) {
if (StrUtil.isBlank(code)) {
return Result.success(new ArrayList<ActivityBasicSettings>());
}
ActivityBasicSettings fetch = dao.fetch(ActivityBasicSettings.class, Cnd.where("code", "=", code)); ActivityBasicSettings fetch = dao.fetch(ActivityBasicSettings.class, Cnd.where("code", "=", code));
if (fetch == null) {
return Result.success(new ArrayList<ActivityBasicSettings>());
}
List<ActivityBasicSettings> query = dao.query(ActivityBasicSettings.class, Cnd.where("parentId", "=", fetch.getId()).asc("code")); List<ActivityBasicSettings> query = dao.query(ActivityBasicSettings.class, Cnd.where("parentId", "=", fetch.getId()).asc("code"));
return Result.success(query); return Result.success(query);
} }
@@ -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); fillCourseResponsibles(courseList);
courseList.forEach(c -> { courseList.forEach(c -> {
dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime"));
if (c.getCourseTimeList() == null) {
c.setCourseTimeList(new ArrayList<>());
}
if (StrUtil.isNotBlank(c.getCourseType())) { if (StrUtil.isNotBlank(c.getCourseType())) {
dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime"));
int courseCount = statisticsService.queryCourseCount(c.getId(), c.getCourseType()); int courseCount = statisticsService.queryCourseCount(c.getId(), c.getCourseType());
c.setHasRegisterNum(courseCount); c.setHasRegisterNum(courseCount);
int courseWaitCount = statisticsService.queryCourseWaitCount(c.getId(), c.getCourseType()); int courseWaitCount = statisticsService.queryCourseWaitCount(c.getId(), c.getCourseType());
@@ -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.mobile,
u.unitname as unitName, u.unitname as unitName,
u.userState, 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 FROM
club_user c club_user c
LEFT JOIN `vw_user` u ON u.id = c.userId LEFT JOIN `vw_user` u ON u.id = c.userId
@@ -98,14 +98,14 @@ public class TherapyRecuperationModule {
Sys_config setting = new Sys_config(); Sys_config setting = new Sys_config();
setting.setConfigKey("staffTherapyRecuperationVersion"); setting.setConfigKey("staffTherapyRecuperationVersion");
setting.setConfigValue("zjnu"); setting.setConfigValue("zjnu");
setting.setNote("普惠疗休养V3独立子模块报名规则版本"); setting.setNote("普惠疗休养独立子模块报名规则版本");
dao.insert(setting); dao.insert(setting);
} }
private void seedConfig() { private void seedConfig() {
if (dao.count(TheRapyRecuperationConfig.class) != 0) return; if (dao.count(TheRapyRecuperationConfig.class) != 0) return;
TheRapyRecuperationConfig config = new TheRapyRecuperationConfig(); TheRapyRecuperationConfig config = new TheRapyRecuperationConfig();
config.setConfigName("普惠疗休养V3配置"); config.setConfigName("普惠疗休养配置");
config.setIsSnLine(false); config.setIsSnLine(false);
config.setIsSwLine(false); config.setIsSwLine(false);
config.setTravelAudit(false); config.setTravelAudit(false);
@@ -128,10 +128,10 @@ public class TherapyRecuperationModule {
module.setFaIcon("fa fa-heart"); module.setFaIcon("fa fa-heart");
dao.insert(module); 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)); List<Sys_role> roles = dao.query(Sys_role.class, Cnd.where("disabled", "=", false));
for (String[] screen : SCREENS) { 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"); "inclusiveTherapyV3." + screen[3], "pc");
int position = MENU_SCREENS.indexOf(screen[0]); int position = MENU_SCREENS.indexOf(screen[0]);
dao.update(Sys_menu.class, Chain.make("showit", position >= 0) dao.update(Sys_menu.class, Chain.make("showit", position >= 0)
@@ -147,7 +147,7 @@ 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())); 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")); Sys_module h5Module = dao.fetch(Sys_module.class, Cnd.where("name", "=", module.getName()).and("platform", "=", "h5"));
if (h5Module == null) { if (h5Module == null) {
@@ -158,7 +158,7 @@ public class TherapyRecuperationModule {
h5Module.setFaIcon("fa fa-heart"); h5Module.setFaIcon("fa fa-heart");
dao.insert(h5Module); 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) { for (Sys_role role : roles) {
if (List.of("public", "PUBLIC", "MEMBER", "sysadmin", "superadmin", "SYSADMIN").contains(role.getCode())) { if (List.of("public", "PUBLIC", "MEMBER", "sysadmin", "superadmin", "SYSADMIN").contains(role.getCode())) {
grant(role.getId(), root.getId()); grant(role.getId(), root.getId());
@@ -5,18 +5,16 @@ import cn.dev33.satoken.stp.StpUtil;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.TherapyRecuperationModule; import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.TherapyRecuperationModule;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.*; import org.nutz.mvc.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList; import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@IocBean @IocBean
@At("/platform/inclusiveTherapyV3") @At("/platform/inclusiveTherapyV3")
public class TherapyWorkspaceController { public class TherapyWorkspaceController {
@At("") @At("")
@SaCheckLogin @SaCheckLogin
@Ok("beetl:/platform/zhgh/staffbenefit/therapyRecuperation/index.html") @Ok("void")
public void index(String screen, HttpServletRequest request) { public void index(String screen, HttpServletResponse response) throws IOException {
if (screen == null) { if (screen == null) {
for (String key : TherapyRecuperationModule.MENU_SCREENS) { for (String key : TherapyRecuperationModule.MENU_SCREENS) {
for (String[] candidate : TherapyRecuperationModule.SCREENS) { for (String[] candidate : TherapyRecuperationModule.SCREENS) {
@@ -39,25 +37,8 @@ public class TherapyWorkspaceController {
break; break;
} }
} }
if (!found) throw new IllegalArgumentException("未知的普惠疗休养V3页面"); if (!found) throw new IllegalArgumentException("未知的普惠疗休养页面");
} }
List<String[]> tabs = new ArrayList<>(); response.sendRedirect(url);
String[][] groups = {{"overview", "cluster", "adjustment"},
{"branchQuery", "branchAudit", "travelAudit"}, {"userQuery", "schoolAudit", "import"}};
for (String[] group : groups) {
if (Arrays.asList(group).contains(screen)) {
for (String key : group) {
for (String[] candidate : TherapyRecuperationModule.SCREENS) {
if (candidate[0].equals(key) && StpUtil.hasPermission("inclusiveTherapyV3." + candidate[3])) {
tabs.add(candidate);
}
}
}
break;
}
}
request.setAttribute("therapyTabs", tabs);
request.setAttribute("therapyShowTabs", tabs.size() > 1);
request.setAttribute("therapyPageUrl", url);
} }
} }
@@ -96,12 +96,12 @@ public class TheRapyRecuperationLineController {
/** /**
* 新线路导入模板中“联系方式”列下标,设置为文本格式避免手机号被Excel转成科学计数法。 * 新线路导入模板中“联系方式”列下标,设置为文本格式避免手机号被Excel转成科学计数法。
*/ */
private static final int LINE_IMPORT_CONTACT_PHONE_COLUMN_INDEX = 10; private static final int LINE_IMPORT_CONTACT_PHONE_COLUMN_INDEX = 12;
/** /**
* 新线路导入模板中“移动端缩略图”列下标,用于定位Excel内嵌图片。 * 新线路导入模板中“移动端缩略图”列下标,用于定位Excel内嵌图片。
*/ */
private static final int LINE_IMPORT_THUMBNAIL_COLUMN_INDEX = 13; private static final int LINE_IMPORT_THUMBNAIL_COLUMN_INDEX = 15;
@Inject @Inject
private TheRapyRecuperationLineService lineService; private TheRapyRecuperationLineService lineService;
@@ -458,7 +458,7 @@ public class TheRapyRecuperationLineController {
List<String> excelLots = lots.stream().map(v -> v.getLotName() + "_" + v.getId()).collect(Collectors.toList()); List<String> excelLots = lots.stream().map(v -> v.getLotName() + "_" + v.getId()).collect(Collectors.toList());
List<Field> needAddReplaceFields = Arrays.stream(TheRapyLineImportExcelMode.class.getDeclaredFields()) 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()); .collect(Collectors.toList());
for (Field field : needAddReplaceFields) { for (Field field : needAddReplaceFields) {
Excel excelAnnotation = field.getAnnotation(Excel.class); Excel excelAnnotation = field.getAnnotation(Excel.class);
@@ -476,7 +476,7 @@ public class TheRapyRecuperationLineController {
e.put("replace", buildRegionalNatureExcelOptions()); e.put("replace", buildRegionalNatureExcelOptions());
} else if (field.getName().equals("signUpMode")) { } else if (field.getName().equals("signUpMode")) {
e.put("replace", buildSignUpModeExcelOptions()); 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[]{"是_是", "否_否"}); e.put("replace", new String[]{"是_是", "否_否"});
} }
} }
@@ -24,6 +24,9 @@ public class TheRapyLineImportExcelMode {
@Excel(name = "线路类型") @Excel(name = "线路类型")
private String regionalNature; private String regionalNature;
@Excel(name = "旅行社名称")
private String travelAgencyName;
@Excel(name = "交通工具") @Excel(name = "交通工具")
private String trafficTools; private String trafficTools;
@@ -33,6 +36,9 @@ public class TheRapyLineImportExcelMode {
@Excel(name = "预计费用(元/人次)") @Excel(name = "预计费用(元/人次)")
private String estimatedCost; private String estimatedCost;
@Excel(name = "家属报名")
private String familySignUp;
@Excel(name = "组织形式") @Excel(name = "组织形式")
private String signUpMode; private String signUpMode;
@@ -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.TheRapyRecuperationLine;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.model.TheRapyRecuperationLineUnionSelect; 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.TheRapyRecuperationLot;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.model.TheRapyRecuperationTravelAgency;
import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.service.TheRapyRecuperationLineService; import com.budwk.app.zhgh.staffbenefit.therapyRecuperation.service.TheRapyRecuperationLineService;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.RenderingHints; import java.awt.RenderingHints;
@@ -229,6 +230,8 @@ public class TheRapyRecuperationLineServiceImpl extends TherapyServiceImpl<TheRa
&& StrUtil.isBlank(mode.getLineContactPhone()) && StrUtil.isBlank(mode.getLineContactPhone())
&& StrUtil.isBlank(mode.getContent()) && StrUtil.isBlank(mode.getContent())
&& StrUtil.isBlank(mode.getIsEnabled()) && StrUtil.isBlank(mode.getIsEnabled())
&& StrUtil.isBlank(mode.getTravelAgencyName())
&& StrUtil.isBlank(mode.getFamilySignUp())
&& StrUtil.isBlank(mode.getFiles())); && StrUtil.isBlank(mode.getFiles()));
} }
@@ -239,6 +242,12 @@ public class TheRapyRecuperationLineServiceImpl extends TherapyServiceImpl<TheRa
* @param rowNumber Excel行号 * @param rowNumber Excel行号
*/ */
private void validImportRequired(TheRapyLineImportExcelMode mode, int rowNumber) { 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) { if (mode.getYear() == null) {
throw new IllegalArgumentException("第" + rowNumber + "行年度不能为空"); throw new IllegalArgumentException("第" + rowNumber + "行年度不能为空");
} }
@@ -268,7 +277,17 @@ public class TheRapyRecuperationLineServiceImpl extends TherapyServiceImpl<TheRa
* @return 线路实体 * @return 线路实体
*/ */
private TheRapyRecuperationLine buildLineByImportMode(TheRapyLineImportExcelMode mode, TheRapyLineImportImageMode imageMode, int rowNumber) { 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(); TheRapyRecuperationLine line = new TheRapyRecuperationLine();
line.setTravelAgencyId(agencies.get(0).getId());
line.setIsFamilySignUp("是".equals(StrUtil.trim(mode.getFamilySignUp())));
line.setYear(mode.getYear()); line.setYear(mode.getYear());
line.setSerialNumber(mode.getSerialNumber()); line.setSerialNumber(mode.getSerialNumber());
line.setLineName(mode.getLineName()); line.setLineName(mode.getLineName());
@@ -71,7 +71,7 @@ public class TheRapyRecuperationLineUnionSelectServiceImpl extends TherapyServic
us.playEndTime, us.playEndTime,
us.changeEndTime, us.changeEndTime,
us.isOpen, us.isOpen,
us.signUpMode, IFNULL(us.signUpMode, line.signUpMode) AS signUpMode,
line.createMode, line.createMode,
gh.unionname AS createUnionName, gh.unionname AS createUnionName,
u.username AS createUserName, u.username AS createUserName,
@@ -13,6 +13,15 @@ import java.util.Collection;
@IocBean @IocBean
public class TherapyContext { 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() { public static String getUserId() {
return SecurityUtil.getUserId(); return SecurityUtil.getUserId();
} }
@@ -29,7 +29,7 @@ public class TherapyEmail {
String user = setting("user"); String user = setting("user");
String password = setting("password"); String password = setting("password");
if (host == null || from == null || user == null || password == null) { if (host == null || from == null || user == null || password == null) {
throw new IllegalStateException("普惠疗休养V3邮件发送配置不完整"); throw new IllegalStateException("普惠疗休养邮件发送配置不完整");
} }
String portSetting = setting("port"); String portSetting = setting("port");
int port = portSetting == null ? 465 : Integer.parseInt(portSetting); int port = portSetting == null ? 465 : Integer.parseInt(portSetting);
+1
View File
@@ -13,6 +13,7 @@
port: 6379 port: 6379
database: 4 database: 4
mode: normal mode: normal
password: dd3s@Redis#2026
jdbc: 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 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 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');
@@ -155,7 +155,7 @@ def main():
output = args.output.resolve() output = args.output.resolve()
if output.exists(): if output.exists():
raise ValueError("导出文件已存在,不覆盖:" + str(output)) raise ValueError("导出文件已存在,不覆盖:" + str(output))
log("开始导出普惠疗休养V3;源数据库:" + args.database) log("开始导出普惠疗休养;源数据库:" + args.database)
log("[1/4] 连接数据库并检查源表结构") log("[1/4] 连接数据库并检查源表结构")
client = MySQL(args) client = MySQL(args)
tables = {suffix: "the_rapy_recuperation_" + suffix for suffix in SUFFIXES} tables = {suffix: "the_rapy_recuperation_" + suffix for suffix in SUFFIXES}
@@ -145,7 +145,7 @@ class IdentityMap:
def default_config(row): def default_config(row):
permitted = {"id": None, "configName": {"智慧工会疗休养配置", "普惠疗休养V3配置"}, permitted = {"id": None, "configName": {"智慧工会疗休养配置", "普惠疗休养配置"},
"isSnLine": {"0"}, "isSwLine": {"0"}, "travelAudit": {"0"}, "bedInfo": {"1"}, "isSnLine": {"0"}, "isSwLine": {"0"}, "travelAudit": {"0"}, "bedInfo": {"1"},
"familyInfo": {"1"}, "outsideQuotaProportion": {"0", "0.00", "0.0"}, "familyInfo": {"1"}, "outsideQuotaProportion": {"0", "0.00", "0.0"},
"unionLineNumberConfigs": {"[]"}, "lots": {"[]"}} "unionLineNumberConfigs": {"[]"}, "lots": {"[]"}}
@@ -271,7 +271,7 @@ def main():
parser.add_argument("--minio-region", default=os.environ.get("MINIO_REGION", "us-east-1")) parser.add_argument("--minio-region", default=os.environ.get("MINIO_REGION", "us-east-1"))
parser.add_argument("--mapping", type=Path) parser.add_argument("--mapping", type=Path)
args = parser.parse_args() args = parser.parse_args()
log("开始导入普惠疗休养V3;目标数据库:" + args.database) log("开始导入普惠疗休养;目标数据库:" + args.database)
log("[1/5] 读取导出包并校验数据:" + str(args.input)) log("[1/5] 读取导出包并校验数据:" + str(args.input))
overrides = json.loads(args.mapping.read_text(encoding="utf-8-sig")) if args.mapping else {} overrides = json.loads(args.mapping.read_text(encoding="utf-8-sig")) if args.mapping else {}
uploaded_location = None uploaded_location = None
@@ -415,7 +415,7 @@ def main():
for row in source: for row in source:
user = get(row, "userId") user = get(row, "userId")
prepared["activity_user_scope"].append({ 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 "", "userId": identities["user"].resolve(user, "user") if user else "",
"groupType": "1", "groupSql": None, "groupType": "1", "groupSql": None,
"creator": identities["user"].resolve(get(row, "creator"), "user", required=False), "delFlag": "0"}) "creator": identities["user"].resolve(get(row, "creator"), "user", required=False), "delFlag": "0"})
@@ -478,7 +478,7 @@ def main():
",".join(literal(value) for value in row.values()) + ");") ",".join(literal(value) for value in row.values()) + ");")
sql.append("UPDATE sys_config SET configValue=" + literal(version) + " WHERE configKey='staffTherapyRecuperationVersion';") sql.append("UPDATE sys_config SET configValue=" + literal(version) + " WHERE configKey='staffTherapyRecuperationVersion';")
sql.append("INSERT INTO sys_config(configKey,configValue,note,delFlag) SELECT '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');") "(SELECT 1 FROM sys_config WHERE configKey='staffTherapyRecuperationVersion');")
sql.append("COMMIT;") sql.append("COMMIT;")
log("[5/5] 开始数据库事务,写入 %s 条记录;数据量较大时请等待事务提交" % log("[5/5] 开始数据库事务,写入 %s 条记录;数据量较大时请等待事务提交" %
@@ -492,7 +492,7 @@ def main():
print("已上传附件保留在 MinIO 前缀:" + uploaded_location, file=sys.stderr) print("已上传附件保留在 MinIO 前缀:" + uploaded_location, file=sys.stderr)
raise raise
log("数据库事务提交成功") log("数据库事务提交成功")
log("导入完成:普惠疗休养V3,表前缀 " + PREFIX) log("导入完成:普惠疗休养,表前缀 " + PREFIX)
log("业务记录:%s;审核记录:%s;附件:%s" % log("业务记录:%s;审核记录:%s;附件:%s" %
(sum(len(records[name]) for name in SUFFIXES), len(records["_audit"]), len(file_info))) (sum(len(records[name]) for name in SUFFIXES), len(records["_audit"]), len(file_info)))
if uploaded_location: if uploaded_location:
@@ -1,4 +1,4 @@
-- 仅清理普惠疗休养V3菜单及角色菜单关联,保留职工权益模块和业务数据。 -- 仅清理普惠疗休养菜单及角色菜单关联,保留职工权益模块和业务数据。
START TRANSACTION; START TRANSACTION;
DELETE rm FROM sys_role_menu rm DELETE rm FROM sys_role_menu rm
@@ -1,98 +1,98 @@
-- 普惠疗休养V3:父菜单及12个子菜单,归属已有的职工权益模块。 -- 普惠疗休养:PC父菜单及12个子菜单、移动端入口,归属职工权益模块。
-- 角色菜单关系暂时只授予本项目超级管理员角色 SYSADMIN。 -- 角色菜单关系暂时只授予本项目超级管理员角色 SYSADMIN。
SET NAMES utf8mb4; SET NAMES utf8mb4;
START TRANSACTION; START TRANSACTION;
-- 普惠疗休养V3 -- 普惠疗休养
INSERT INTO sys_menu (id, parentId, path, name, type, href, target, icon, showit, disabled, permission, location, hasChildren, platform, moduleId, createdBy, createdAt, updatedBy, updatedAt, delFlag) 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 '7ea90000000000000000000000000000', '',
(SELECT LPAD(COALESCE(MAX(CAST(path AS UNSIGNED)),0)+1,4,'0') FROM sys_menu WHERE CHAR_LENGTH(path)=4), (SELECT LPAD(COALESCE(MAX(CAST(path AS UNSIGNED)),0)+1,4,'0') FROM sys_menu WHERE CHAR_LENGTH(path)=4),
'普惠疗休养V3', 'menu', '/platform/inclusiveTherapyV3', '_self', 'fa fa-heart', 1, 0, '普惠疗休养', 'menu', '/platform/inclusiveTherapyV3', '_self', 'fa fa-heart', 1, 0,
'inclusiveTherapyV3', 50, 1, 'pc', id, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 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; 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) 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'), SELECT '7ea90000000000000000000000000001', id, CONCAT(path, '0001'),
'旅行社管理', 'menu', '/platform/inclusiveTherapyV3?screen=agency', '_self', 'fa fa-th-large', 1, 0, '旅行社管理', '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 'inclusiveTherapyV3.travelAgency', 1, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000002', id, CONCAT(path, '0002'),
'线路管理', 'menu', '/platform/inclusiveTherapyV3?screen=line', '_self', 'fa fa-th-large', 1, 0, '线路管理', '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 'inclusiveTherapyV3.line', 2, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000003', id, CONCAT(path, '0003'),
'分工会选择线路', 'menu', '/platform/inclusiveTherapyV3?screen=branchSelect', '_self', 'fa fa-th-large', 1, 0, '分工会选择线路', '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 'inclusiveTherapyV3.lineFghSelect', 3, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000004', id, CONCAT(path, '0004'),
'校工会选择线路', 'menu', '/platform/inclusiveTherapyV3?screen=schoolSelect', '_self', 'fa fa-th-large', 1, 0, '校工会选择线路', '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 'inclusiveTherapyV3.lineXghSelect', 4, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000005', id, CONCAT(path, '0005'),
'满意度统计', 'menu', '/platform/inclusiveTherapyV3?screen=queryStatistics', '_self', 'fa fa-th-large', 1, 0, '满意度统计', '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 'inclusiveTherapyV3.queryStatics', 5, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000006', id, CONCAT(path, '0006'),
'分工会信息查询', 'menu', '/platform/inclusiveTherapyV3?screen=branchQuery', '_self', 'fa fa-th-large', 1, 0, '分工会信息查询', '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 'inclusiveTherapyV3.TheRapyQuery', 6, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000007', id, CONCAT(path, '0007'),
'校工会信息查询', 'menu', '/platform/inclusiveTherapyV3?screen=userQuery', '_self', 'fa fa-th-large', 1, 0, '校工会信息查询', '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 'inclusiveTherapyV3.TheRapyUserQuery', 7, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000008', id, CONCAT(path, '0008'),
'线路选择查询', 'menu', '/platform/inclusiveTherapyV3?screen=overview', '_self', 'fa fa-th-large', 1, 0, '线路选择查询', 'menu', '/platform/inclusiveTherapyV3/statistics/unionLineNumberStatistics', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.lineSelectionOverview', 8, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0 'inclusiveTherapyV3.unionLineNumberStatistics', 8, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea90000000000000000000000000009', id, CONCAT(path, '0009'),
'成团结果通知', 'menu', '/platform/inclusiveTherapyV3?screen=lineStatistics', '_self', 'fa fa-th-large', 1, 0, '成团结果通知', '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 'inclusiveTherapyV3.statistics', 9, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea9000000000000000000000000000a', id, CONCAT(path, '0010'),
'基础设置', 'menu', '/platform/inclusiveTherapyV3?screen=config', '_self', 'fa fa-th-large', 1, 0, '基础设置', '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 'inclusiveTherapyV3.TheRapyConfig', 10, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea9000000000000000000000000000b', id, CONCAT(path, '0011'),
'分工会线路选择统计', 'menu', '/platform/inclusiveTherapyV3?screen=unionStatistics', '_self', 'fa fa-th-large', 1, 0, '分工会线路选择统计', 'menu', '/platform/inclusiveTherapyV3/lineSelectionOverview', '_self', 'fa fa-th-large', 1, 0,
'inclusiveTherapyV3.unionLineNumberStatistics', 11, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0 'inclusiveTherapyV3.lineSelectionOverview', 11, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; 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) 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'), SELECT '7ea9000000000000000000000000000c', id, CONCAT(path, '0012'),
'人数统计', 'menu', '/platform/inclusiveTherapyV3?screen=agencyStatistics', '_self', 'fa fa-th-large', 1, 0, '人数统计', '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 'inclusiveTherapyV3.travelAgencyMonthlyStatistics', 12, 0, 'pc', moduleId, '', UNIX_TIMESTAMP(NOW())*1000, '', UNIX_TIMESTAMP(NOW())*1000, 0
FROM sys_menu WHERE permission='inclusiveTherapyV3'; FROM sys_menu WHERE permission='inclusiveTherapyV3';
@@ -115,4 +115,41 @@ WHERE r.code='SYSADMIN' AND r.disabled=0 AND COALESCE(r.delFlag,0)=0
'inclusiveTherapyV3.unionLineNumberStatistics', 'inclusiveTherapyV3.unionLineNumberStatistics',
'inclusiveTherapyV3.travelAgencyMonthlyStatistics'); '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; COMMIT;
@@ -1,4 +1,4 @@
-- v4 职工福利 / 普惠疗休养V3独立子模块初始化脚本(MySQL 8)。 -- v4 职工福利 / 普惠疗休养独立子模块初始化脚本(MySQL 8)。
-- 在 v4 目标数据库中执行;表结构依据 therapyRecuperation 模块实体定义。 -- 在 v4 目标数据库中执行;表结构依据 therapyRecuperation 模块实体定义。
-- v3 the_rapy_recuperation_* 对应本模块 inclusive_therapy_v3_*,不覆盖 v4 其他疗休养表。 -- v3 the_rapy_recuperation_* 对应本模块 inclusive_therapy_v3_*,不覆盖 v4 其他疗休养表。
-- 仅新增表、视图和默认配置,不迁移 v3 历史业务数据。 -- 仅新增表、视图和默认配置,不迁移 v3 历史业务数据。
@@ -353,12 +353,12 @@ SELECT 2750,'审核通过','#67c23a'
WHERE NOT EXISTS (SELECT 1 FROM `inclusive_therapy_v3_audit_state` WHERE `stateId`=2750); 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`) 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'); WHERE NOT EXISTS (SELECT 1 FROM `sys_config` WHERE `configKey`='staffTherapyRecuperationVersion');
INSERT INTO `inclusive_therapy_v3_config` INSERT INTO `inclusive_therapy_v3_config`
(`id`,`configName`,`isSnLine`,`isSwLine`,`travelAudit`,`bedInfo`,`familyInfo`,`outsideQuotaProportion`,`unionLineNumberConfigs`) (`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`); WHERE NOT EXISTS (SELECT 1 FROM `inclusive_therapy_v3_config`);
COMMIT; 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
})
}
@@ -1,17 +1,6 @@
const sublime = { const sublime = {
jumpPagePjax(url) { jumpPagePjax(url) {
window.location.href = url; window.location.href = url;
},
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();
} }
}; };
@@ -89,7 +78,6 @@ Vue.directive('throttle', {
$.ajaxSetup({ $.ajaxSetup({
traditional: true, traditional: true,
error(xhr) { error(xhr) {
sublime.closeLoadingbar();
const message = xhr.responseJSON && xhr.responseJSON.msg || '请求失败,请稍后重试'; const message = xhr.responseJSON && xhr.responseJSON.msg || '请求失败,请稍后重试';
if (window.ELEMENT) ELEMENT.Message.error(message); if (window.ELEMENT) ELEMENT.Message.error(message);
else if (window.vant) vant.Toast.fail(message); else if (window.vant) vant.Toast.fail(message);
@@ -1,8 +1,8 @@
Vue.component('vi-title', { Vue.component('vi-title', {
props: ['title'], props: ['title'],
template: ` template: `
<div style="display: flex;flex-direction:row;color: #1867b0;font-weight: bolder;margin-bottom: 20px"> <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: #1867b0;border-radius: 2px"></div> <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"> <div style="margin-left: 20px;line-height: 24px;font-size: 15px;letter-spacing: 1px">
{{ title }} {{ title }}
</div> </div>
@@ -61,7 +61,7 @@
} }
.search .search-item-label { .search .search-item-label {
color: rgb(100, 100, 100); color: var(--color-text-regular);
margin-right: 10px; margin-right: 10px;
width: 80px; width: 80px;
min-width: 80px; min-width: 80px;
@@ -97,18 +97,18 @@
.table-tool-group { .table-tool-group {
margin-left: 15px; margin-left: 15px;
overflow: hidden; overflow: hidden;
border-radius: 20px; border-radius: 2px;
display: flex; display: flex;
} }
.table-tool-group .table-tool-group-item { .table-tool-group .table-tool-group-item {
width: 40px; width: 40px;
height: 40px; height: 32px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
background-color: rgba(240, 240, 240, .7); background-color: var(--background-color-base);
font-weight: bolder; font-weight: bolder;
transition: all 250ms; transition: all 250ms;
} }
@@ -119,7 +119,7 @@
.table-tool-group .table-tool-group-item:hover { .table-tool-group .table-tool-group-item:hover {
color: white; color: white;
background-color: rgb(64, 158, 255); background-color: var(--color-primary);
} }
.width-100 { .width-100 {
@@ -176,11 +176,11 @@
.w-e-toolbar { .w-e-toolbar {
background-color: white !important; background-color: white !important;
border-color: #DCDFE6 !important; border-color: var(--border-color-base) !important;
} }
.w-e-text-container { .w-e-text-container {
border-color: #DCDFE6 !important; border-color: var(--border-color-base) !important;
} }
.el-radio-group label { .el-radio-group label {
@@ -195,4 +195,4 @@
.main-navigation { .main-navigation {
border-right: 3px solid rgb(240, 240, 240); border-right: 3px solid rgb(240, 240, 240);
} }
@@ -16,15 +16,16 @@
} }
.el-pagination { .el-pagination {
height: 50px; min-height: 32px;
overflow: hidden; flex-wrap: wrap;
row-gap: 8px;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.el-pagination button, .el-pagination span:not([class*=suffix]) { .el-pagination button, .el-pagination span:not([class*=suffix]) {
line-height: 50px; line-height: 28px;
height: 50px; height: 28px;
} }
a .collapsed { a .collapsed {
@@ -128,7 +129,7 @@ a .expanded {
.el-upload__tip { .el-upload__tip {
margin-top: 0px; margin-top: 0px;
color: #c33714; color: var(--color-danger);
} }
.el-dialog { .el-dialog {
@@ -137,16 +138,12 @@ a .expanded {
.el-table__empty-block { .el-table__empty-block {
width: 100% !important; width: 100% !important;
min-height: 300px; min-height: 120px;
background: url("/none.png") no-repeat center center;
background-size: 360px 260px;
} }
.el-table__empty-text { .el-table__empty-text {
display: block; display: block;
position: absolute; position: static;
bottom: 80px; line-height: 24px;
height: 40px;
line-height: 40px;
/*display: none !important;*/ /*display: none !important;*/
} }
@@ -93,10 +93,8 @@ const initTableMixins = {
}, },
pageData(url) { pageData(url) {
const address = url ? url : loc() + "/pageData" const address = url ? url : loc() + "/pageData"
sublime.showLoadingbar();
this.tableLoading = true this.tableLoading = true
$.post(address, this.pageForm, (data) => { $.post(address, this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code == 0) { if (data.code == 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -105,7 +103,6 @@ const initTableMixins = {
this.$message.error(data.msg); this.$message.error(data.msg);
} }
}, "json").always(() => { }, "json").always(() => {
sublime.closeLoadingbar();
this.tableLoading = false; this.tableLoading = false;
}); });
}, },
@@ -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" <el-table-column label="总分" prop="totalScore" header-align="center"
align="center" show-overflow-tooltip></el-table-column> 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> width="80px"></el-table-column>
</el-table> </el-table>
@@ -47,7 +47,21 @@ module.exports = {
this.tableData = [] this.tableData = []
const {data} = await this.$axios.post(loc() + "/isScoreTopEight", this.Form) const {data} = await this.$axios.post(loc() + "/isScoreTopEight", this.Form)
const table = data.score.sort(this.compare("totalScore")) 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) { } catch (e) {
this.$message.error(e.msg) this.$message.error(e.msg)
} finally { } finally {
@@ -384,7 +384,7 @@ layout("/layouts/v4/baseLayout.html"){
return search(menus, []); return search(menus, []);
} }
const result = findMenuPath(this.menus, targetHref) const result = findMenuPath(this.menus, this.getMenuOwnerFullPath()) || findMenuPath(this.menus, targetHref)
if(result){ if(result){
this.activeMenuIndex = result[result.length-1]['id'] this.activeMenuIndex = result[result.length-1]['id']
this.openedMenus = result.map(v=>v.id) this.openedMenus = result.map(v=>v.id)
@@ -399,6 +399,10 @@ layout("/layouts/v4/baseLayout.html"){
// 默认选中 // 默认选中
getMenuOwnerPath() { getMenuOwnerPath() {
const pathname = window.location.pathname 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配置菜单。 // API配置表单不是独立菜单,直接刷新表单地址时仍归属API配置菜单。
if (pathname === "/platform/personGovernance/apiConfig/form") { if (pathname === "/platform/personGovernance/apiConfig/form") {
return "/platform/personGovernance/apiConfig" return "/platform/personGovernance/apiConfig"
@@ -283,6 +283,11 @@
})() })()
function pjaxReplace(url, data = null) { function pjaxReplace(url, data = null) {
// 普惠疗休养移动端使用独立布局,没有公共 PJAX 容器,需整页跳转以保留应用中心样式。
if (url && url.indexOf("/platform/inclusiveTherapyV3/mobile/") === 0) {
window.location.href = url
return
}
showH5PageSkeleton(url) showH5PageSkeleton(url)
// 疗休养报名页面使用独立 H5 布局,其中包含图片懒加载等专用初始化逻辑。 // 疗休养报名页面使用独立 H5 布局,其中包含图片懒加载等专用初始化逻辑。
// 禁止通过公共 PJAX 只替换页面片段,否则专用布局脚本不会执行,首次进入会出现图片懒加载指令未注册。 // 禁止通过公共 PJAX 只替换页面片段,否则专用布局脚本不会执行,首次进入会出现图片懒加载指令未注册。
@@ -15,7 +15,7 @@ const act = {
<el-image :src="activity.cover" fit="cover" :alt="activity.name"> <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> <div slot="error" class="portal-cover-empty"><i class="fa fa-picture-o" aria-hidden="true"></i><span>暂无图片</span></div>
</el-image> </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)}} {{getStatusText(activity)}}
</span> </span>
</div> </div>
@@ -76,9 +76,9 @@ const act = {
if (!this.swiper) return if (!this.swiper) return
this.swiper.isEnd ? this.swiper.slideTo(0) : this.swiper.slideNext() this.swiper.isEnd ? this.swiper.slideTo(0) : this.swiper.slideNext()
}, },
/*查询活动*/ // PC首页包含已结束活动;接口data为按未结束在前、已结束在后排列的活动实体数组。
listAct() { listAct() {
this.$axios.post("/platform/home/listHomeActivity").then((res) => { this.$axios.post("/platform/home/listHomeActivity", {includeEnded: true}).then((res) => {
if (res.code === 0) { if (res.code === 0) {
// for (let i = 0; i < 10; i++) { // for (let i = 0; i < 10; i++) {
// this.actList = this.actList.concat(res.data) // this.actList = this.actList.concat(res.data)
@@ -149,7 +149,7 @@ const act = {
// 活动状态 // 活动状态
getStatusText(item) { getStatusText(item) {
if (this.$moment().unix() > this.$moment(item.endDate).unix()) { if (this.$moment().unix() > this.$moment(item.endDate).unix()) {
return "已结束" return "报名已结束"
} else if (this.$moment().unix() < this.$moment(item.startDate).unix()) { } else if (this.$moment().unix() < this.$moment(item.startDate).unix()) {
return "未开始" return "未开始"
} else { } else {
@@ -40,7 +40,7 @@ const branchUnionGroupManage = {
</el-card> </el-card>
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogFormVisible" width="600px" <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 ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="小组编码" prop="code"> <el-form-item label="小组编码" prop="code">
<el-input v-model="formData.code" placeholder="小组编码" maxlength="10" <el-input v-model="formData.code" placeholder="小组编码" maxlength="10"
@@ -103,6 +103,7 @@ const branchUnionGroupManage = {
unitIds: [{ required: true, message: "请选择组成单位", trigger: "change" }], unitIds: [{ required: true, message: "请选择组成单位", trigger: "change" }],
}, },
userOptions: [], userOptions: [],
userOptionsRequestId: 0,
units: [], units: [],
} }
}, },
@@ -173,13 +174,21 @@ const branchUnionGroupManage = {
}) })
}, },
clearUserOptions() {
this.userOptions = []
// 关闭后使未完成的搜索失效,防止旧结果回填到下一次打开的弹窗。
this.userOptionsRequestId++
},
getUserOptions(keyword, userIds = null) { getUserOptions(keyword, userIds = null) {
if (!this.dialogFormVisible && !userIds) return
const requestId = ++this.userOptionsRequestId
$.get("/platform/sys/unionGroup/listUser", { $.get("/platform/sys/unionGroup/listUser", {
keyword, keyword,
unionId: this.union_id, unionId: this.union_id,
userIds: JSON.stringify(userIds) userIds: JSON.stringify(userIds)
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0 && this.dialogFormVisible && requestId === this.userOptionsRequestId) {
this.userOptions = res.data 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-if="cadreImportLoading">正在导入,请稍候…</div>
<div class="el-upload__text" v-else>将文件拖到此处,或<em>点击选择文件</em></div> <div class="el-upload__text" v-else>将文件拖到此处,或<em>点击选择文件</em></div>
</el-upload> </el-upload>
<div class="union-cadre-import-note">选择文件后点击“开始导入”。逐行保存,一行失败不影响其他行。</div> <div class="union-cadre-import-note">选择文件后点击“开始导入”。批量校验并保存,失败行显示具体原因,其他有效行继续导入。</div>
</section> </section>
</div> </div>
<section v-if="cadreImportResult" class="union-cadre-import-results"> <section v-if="cadreImportResult" class="union-cadre-import-results">
@@ -77,6 +77,7 @@ layout("/layouts/platform.html"){
<el-input placeholder="输入关键字进行查找" v-model="filterText" clearable></el-input> <el-input placeholder="输入关键字进行查找" v-model="filterText" clearable></el-input>
<div style="max-height: calc(100vh - 200px); overflow-y: auto"> <div style="max-height: calc(100vh - 200px); overflow-y: auto">
<el-tree <el-tree
v-loading="treeLoading"
:data="treeData" :data="treeData"
ref="treeRef" ref="treeRef"
:expand-on-click-node="false" :expand-on-click-node="false"
@@ -151,13 +152,14 @@ layout("/layouts/platform.html"){
<!--#include("unitLeader.js"){}#--> <!--#include("unitLeader.js"){}#-->
new Vue({ new Vue({
el: "#app", el: "#app",
data: function () { data() {
return { return {
unitTabActive: "threeUnitManage", unitTabActive: "threeUnitManage",
filterText: null, filterText: null,
currentTreeNode: null, currentTreeNode: null,
currentTreeData: null, currentTreeData: null,
defaultExpandedKeys: [], defaultExpandedKeys: [],
treeLoading: false,
treeData: [] treeData: []
} }
}, },
@@ -173,26 +175,45 @@ layout("/layouts/platform.html"){
}, },
methods: { methods: {
getTreeData() { getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => { this.$set(this, "treeLoading", true)
this.treeData = res.data // tree 返回单位树数组;失败时保留现有内容,成功后按 ID 恢复当前单位。
if (this.treeData) { return this.$axios.post(loc() + "/tree").then((res) => {
this.currentTreeData = this.treeData[0] if (res.code !== 0 || !Array.isArray(res.data)) return
this.defaultExpandedKeys = this.treeData.length > 0 ? [this.treeData[0].id] : [] 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) { treeNodeClick(data, node) {
this.currentTreeData = data this.$set(this, "currentTreeData", data)
this.currentTreeNode = node this.$set(this, "currentTreeNode", node)
this.$nextTick(()=>{ // 单位列表由 currentData 监听刷新,部门类另外更新人员和干部页签。
if (data.unitTypeCode==1) { this.$nextTick(() => {
this.$refs.bmlRef.pageData() if (data.unitTypeCode == 1) {
this.$refs.userRef.pageData() this.$refs.userRef.pageData()
this.$refs.leaderRef.pageData() this.$refs.leaderRef.pageData()
} else { }
this.$refs.bzlRef.pageData() })
}
})
}, },
filterNode(value, data, node) { filterNode(value, data, node) {
if (!value) return true if (!value) return true
@@ -11,7 +11,7 @@ const UNIT_MANAGE_TEMPLATE = {
<table-tool label="单位列表"> <table-tool label="单位列表">
<el-button @click="openAdd" type="primary" size="small">新建单位</el-button> <el-button @click="openAdd" type="primary" size="small">新建单位</el-button>
</table-tool> </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"> <el-table-column label="序号" type="index" width="60">
<template v-slot="scope">{{scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</template> <template v-slot="scope">{{scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</template>
</el-table-column> </el-table-column>
@@ -75,8 +75,8 @@ const UNIT_MANAGE_TEMPLATE = {
<!-- </el-form-item>--> <!-- </el-form-item>-->
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button> <el-button :disabled="formLoading" @click="closeDialog">取 消</el-button>
<el-button type="primary" @click="doHandle">确 定</el-button> <el-button type="primary" :loading="formLoading" @click="doHandle">确 定</el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
@@ -110,6 +110,8 @@ const UNIT_MANAGE_TEMPLATE = {
audit: false audit: false
}, },
tableData: [], tableData: [],
tableLoading: false,
formLoading: false,
dialogVisible: false, dialogVisible: false,
formData: {}, formData: {},
formRules: { formRules: {
@@ -128,96 +130,130 @@ const UNIT_MANAGE_TEMPLATE = {
} }
}, },
computed: {}, computed: {},
watch: {
// 首次进入、切换节点以及刷新树后,均按最新上级单位从第一页重新查询。
currentData: {
immediate: true,
handler() {
this.doSearch()
}
}
},
methods: { methods: {
doSearch() { doSearch() {
this.pageForm.pageNumber = 1 this.$set(this.pageForm, "pageNumber", 1)
this.pageData() return this.pageData()
}, },
openAdd() { openAdd() {
this.dialogVisible = true // 上级关系取当前单位 ID,与用户是否点击过树节点无关;手工新增默认其他类。
this.formData = {} //打开新增窗口,表单先清空 this.$set(this, "formData", {
this.parentUnit = [] parentId: this.currentData.id,
this.options = [] 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() { 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: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
type: "warning" type: "warning"
}).then(() => { }).then(() => {
const self = this return this.$axios.post("/platform/sys/unit/delete/" + id).then((resp) => {
const url = this.formData.id ? "/platform/sys/unit/editDo" : "/platform/sys/unit/addDo" if (resp.code === 0) {
this.$refs["form"].validate(async function (valid) { this.$message.success(resp.msg)
if (valid) { this.$emit("refresh", null)
if (self.currentNode) { } else {
self.formData.parentId = self.currentData.id this.$message.warning(resp.msg)
}
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)
}
} }
}) })
}) })
}, },
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) { pageNumberChange(val) {
this.pageForm.pageNumber = val this.$set(this.pageForm, "pageNumber", val)
this.pageData() this.pageData()
}, },
pageSizeChange(val) { pageSizeChange(val) {
this.pageForm.pageSize = val this.$set(this.pageForm, "pageSize", val)
this.pageData() this.pageData()
}, },
pageData() { pageData() {
this.pageForm.unitId = this.currentData.id if (!this.currentData || !this.currentData.id) return
// this.pageForm.unitLevel = this.unitLevel // unitId 限定当前上级,返回 data.list 为下设单位,data.totalCount 为分页总数。
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => { 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) { if (res.code === 0) {
this.tableData = res.data.list this.$set(this, "tableData", res.data.list)
this.pageForm.totalCount = res.data.totalCount this.$set(this.pageForm, "totalCount", res.data.totalCount)
} }
}).finally(() => {
this.$set(this, "tableLoading", false)
}) })
} }
}, },
async created() { created() {
this.pageData() const unionId = this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN') ? null : this.store.state.user.union.id
this.$businessTool.listUnion(unionId).then((unions) => {
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')) { this.$set(this, "unions", unions)
this.unions = await this.$businessTool.listUnion() })
} else {
this.unions = await this.$businessTool.listUnion(this.store.state.user.union.id)
}
} }
} }
@@ -119,7 +119,7 @@ layout("/layouts/platform.html"){
currentTreeNode: null, currentTreeNode: null,
currentTreeData: null, currentTreeData: null,
checkData: {}, checkData: { id: "0", name: "无(新建根节点)" },
tableData: [], tableData: [],
basicTypeDialog: false, basicTypeDialog: false,
@@ -146,10 +146,8 @@ layout("/layouts/platform.html"){
getTreeData() { getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => { this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data this.treeData = res.data || []
if (this.treeData) { this.checkData = this.treeData.length ? this.treeData[0] : { id: "0", name: "无(新建根节点)" }
this.checkData = this.treeData[0]
}
}) })
}, },
@@ -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"> <el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<table-tool> <table-tool>
<el-button @click="openAdd" icon="ti-plus" type="primary" style="margin-left: auto" size="small">新建临时分工会</el-button> <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> </table-tool>
<el-table :data="tableData" border size="small" height="calc(100vh - 375px)"> <el-table :data="tableData" border size="small" height="calc(100vh - 375px)">
<el-table-column label="序号" type="index" :index="indexMethod" width="100px"></el-table-column> <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], mixins: [initTableMixins],
data() { data() {
return { return {
pageDataUrl: "/platform/activity/basic/union/pageData",
dialogFormVisible: false, dialogFormVisible: false,
dialogGlyFormVisible: false, dialogGlyFormVisible: false,
formData: {}, formData: {},
@@ -88,10 +90,25 @@ const ACTIVITY_BASIC_BRANCH_UNION_MANAGE = {
} }
}, },
methods: { methods: {
pageData() { // 同步新增工会和已有工会名称;复用表格查询及父页面刷新事件,保留现有查询和分页逻辑。
this.$axios.post("/platform/activity/basic/union/pageData", this.pageForm).then((res) => { updateUnions() {
this.tableData = res.data.list if (this.formLoading) {
this.pageForm.totalCount = res.data.totalCount 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() { openAdd() {
@@ -9,10 +9,10 @@ layout("/layouts/platform.html"){
<div style="max-height: calc(100vh - 160px); overflow-y: auto"> <div style="max-height: calc(100vh - 160px); overflow-y: auto">
<el-tree <el-tree
:data="treeData" :data="treeData"
:default-expanded-keys="['1']" :default-expanded-keys="pageForm.parentId ? [pageForm.parentId] : []"
:expand-on-click-node="false" :expand-on-click-node="false"
:props="{ :props="{
children: 'child', children: 'children',
label: 'name' label: 'name'
}" }"
@node-click="treeNodeClick" @node-click="treeNodeClick"
@@ -52,6 +52,7 @@ layout("/layouts/platform.html"){
</div> </div>
<div class="search-item"> <div class="search-item">
<el-button @click="doSearch" icon="el-icon-search" type="primary">搜索</el-button> <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>
</div> </div>
</el-card> </el-card>
@@ -104,6 +105,36 @@ layout("/layouts/platform.html"){
}, },
components: {}, components: {},
methods: { 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) { async doDelete(id) {
const confirm = await this.$confirm("确定要删除该单位吗?", "提示", { const confirm = await this.$confirm("确定要删除该单位吗?", "提示", {
confirmButtonText: "确定", confirmButtonText: "确定",
@@ -122,24 +153,42 @@ layout("/layouts/platform.html"){
} }
}, },
treeNodeClick(data, node) { treeNodeClick(data, node) {
this.currentTreeData = data this.$set(this, "currentTreeData", data)
this.currentTreeNode = node this.$set(this, "currentTreeNode", node)
this.pageForm.parentId = data.id this.$set(this.pageForm, "parentId", data.id)
this.doSearch() this.doSearch()
}, },
getTreeData() { getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => { return this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data if (res.code !== 0) {
if (this.treeData) { this.notifyWarning(res.msg)
this.currentTreeData = this.treeData[0] 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() {} openUnit() {}
}, },
created() { created() {
this.pageData() this.getTreeData().then((loaded) => {
this.getTreeData() if (loaded) {
this.doSearch()
}
}).catch(() => {
this.notifyError("加载单位失败,请稍后重试")
})
} }
}) })
</script> </script>
@@ -370,12 +370,14 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
</el-form-item> </el-form-item>
</el-col> </el-col>
<!--
<el-col :span="24"> <el-col :span="24">
<el-form-item label="报名表单" prop="formConfig" <el-form-item label="报名表单" prop="formConfig"
v-if="formData.isEnrollSystem&&formData.signUpMethod===1"> v-if="formData.isEnrollSystem&&formData.signUpMethod===1">
<custom-form-field v-model="formData.formConfig"></custom-form-field> <custom-form-field v-model="formData.formConfig"></custom-form-field>
</el-form-item> </el-form-item>
</el-col> </el-col>
-->
<el-col :span="24" v-if="formData.signUpMethod!=null&&formData.isEnrollSystem"> <el-col :span="24" v-if="formData.signUpMethod!=null&&formData.isEnrollSystem">
<el-form-item label="封面图" prop="cover"> <el-form-item label="封面图" prop="cover">
@@ -592,6 +594,7 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
name: [{required: true, message: "必填", trigger: ["blur", "change"]}], name: [{required: true, message: "必填", trigger: ["blur", "change"]}],
type: [{required: true, message: "必填", trigger: ["blur", "change"]}], type: [{required: true, message: "必填", trigger: ["blur", "change"]}],
projectTypeCode: [{required: true, message: "必填", trigger: ["blur", "change"]}], projectTypeCode: [{required: true, message: "必填", trigger: ["blur", "change"]}],
mobile: this.activity_type === 40001 ? [{pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号码", trigger: ["blur", "change"]}] : [],
address: [{required: true, message: "必填", trigger: ["blur", "change"]}], address: [{required: true, message: "必填", trigger: ["blur", "change"]}],
plannedDate: [{required: true, message: "必填", trigger: ["blur", "change"]}], plannedDate: [{required: true, message: "必填", trigger: ["blur", "change"]}],
time: [{required: true, message: "必填", trigger: ["blur", "change"]}], time: [{required: true, message: "必填", trigger: ["blur", "change"]}],
@@ -725,7 +728,15 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
return true return true
}, },
// 保存 // 保存
onSave() { async onSave() {
if (this.activity_type === 40001) {
const mobileValid = await new Promise(resolve => {
this.$refs["addForm"].validateField("mobile", error => resolve(!error))
})
if (!mobileValid) {
return
}
}
if (!this.formData.projectTypeCode) { if (!this.formData.projectTypeCode) {
this.$message.error("请选择活动项目类型") this.$message.error("请选择活动项目类型")
return return
@@ -6,18 +6,19 @@ layout("/layouts/platform.html"){
<template> <template>
<el-card shadow="never"> <el-card shadow="never">
<search @search="doSearch" :is-search-button="false"> <search @search="refreshPrizes" :is-search-button="false">
<search-item label="年度"> <search-item label="年度">
<el-date-picker <el-date-picker
:clearable="false" :clearable="false"
:disabled="tableLoading"
@change="getActivitys" @change="getActivitys"
placeholder="选择年" placeholder="选择年"
style="width: 100%" type="year" style="width: 100%" type="year"
v-model="pageForm.year" value-format="yyyy"> v-model="pageForm.year" value-format="yyyy">
</el-date-picker> </el-date-picker>
</search-item> </search-item>
<search-item label="活动名称" v-if="!pageForm.status"> <search-item label="活动名称" v-if="pageForm.status!=='1'">
<el-select :clearable="false" @change="actChange(pageForm.activityId)" <el-select :clearable="false" :disabled="tableLoading" @change="actChange(pageForm.activityId)"
filterable filterable
placeholder="请选择活动名称" placeholder="请选择活动名称"
style="width: 100%" v-model="pageForm.activityId"> style="width: 100%" v-model="pageForm.activityId">
@@ -30,7 +31,7 @@ layout("/layouts/platform.html"){
</el-select> </el-select>
</search-item> </search-item>
<search-item label="工会名称" v-if="!pageForm.status"> <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 filterable
placeholder="请选择工会" placeholder="请选择工会"
style="width: 100%" v-model="pageForm.unionId"> style="width: 100%" v-model="pageForm.unionId">
@@ -43,9 +44,9 @@ layout("/layouts/platform.html"){
</el-select> </el-select>
</search-item> </search-item>
<search-item label="性别" v-if="pageForm.status==='1'||!pageForm.status"> <search-item label="性别" v-if="pageForm.status==='1'||!pageForm.status">
<el-select filterable <el-select filterable :disabled="tableLoading"
placeholder="请选择性别" 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-option label="女" value="女"></el-option> <el-option label="女" value="女"></el-option>
</el-select> </el-select>
@@ -56,7 +57,7 @@ layout("/layouts/platform.html"){
<el-card class="mt10" shadow="never"> <el-card class="mt10" shadow="never">
<table-tool <table-tool
:label="pageForm.status==='2'?('浙江师范大学'+pageForm.year+'年教职工运动会获奖个数汇总表'):'奖品名单'"> :label="pageForm.status==='2'?('中国地质大学(武汉)'+pageForm.year+'年教职工运动会获奖个数汇总表'):'奖品名单'">
<el-tag <el-tag
:effect="pageForm.status===item.code?'dark':'plain'" :effect="pageForm.status===item.code?'dark':'plain'"
:key="item.code" :key="item.code"
@@ -66,17 +67,32 @@ layout("/layouts/platform.html"){
v-for="item in statusOptions"> v-for="item in statusOptions">
{{ item.name }} {{ item.name }}
</el-tag> </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> </table-tool>
<div id=print> <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"> <table class="table table-bordered" v-if="isSummary==1" v-loading="tableLoading">
<tr> <tr>
<td class="text-center" colspan="11"> <td class="text-center" colspan="11">
<span v-if="activityList.find(v=>v.id === pageForm.activityId)"> <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}})获奖名单 ({{unionName}})获奖名单
</span> </span>
</td> </td>
@@ -97,10 +113,10 @@ layout("/layouts/platform.html"){
<td>{{k}}</td> <td>{{k}}</td>
<td v-for="i in 8"> <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"> <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> </span>
</td> </td>
<td></td> <td>{{ prizeSourceText(o) }}</td>
</tr> </tr>
<tr v-for="(o,k,index) in tableDataUnionPrize['男子项目']"> <tr v-for="(o,k,index) in tableDataUnionPrize['男子项目']">
<td :rowspan="Object.keys(tableDataUnionPrize['男子项目']).length" <td :rowspan="Object.keys(tableDataUnionPrize['男子项目']).length"
@@ -111,7 +127,7 @@ layout("/layouts/platform.html"){
<td v-for="i in 8"> <td v-for="i in 8">
{{o.filter(f=>f.ranking==i).map(g=>g.username).join('、')}} {{o.filter(f=>f.ranking==i).map(g=>g.username).join('、')}}
</td> </td>
<td></td> <td>{{ prizeSourceText(o) }}</td>
</tr> </tr>
<tr v-for="(o,k,index) in tableDataUnionPrize['女子项目']"> <tr v-for="(o,k,index) in tableDataUnionPrize['女子项目']">
<td :rowspan="Object.keys(tableDataUnionPrize['女子项目']).length" dd <td :rowspan="Object.keys(tableDataUnionPrize['女子项目']).length" dd
@@ -122,7 +138,13 @@ layout("/layouts/platform.html"){
<td v-for="i in 8"> <td v-for="i in 8">
{{o.filter(f=>f.ranking==i).map(g=>g.username).join('、')}} {{o.filter(f=>f.ranking==i).map(g=>g.username).join('、')}}
</td> </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>
<tr> <tr>
<td>合计</td> <td>合计</td>
@@ -283,200 +305,161 @@ layout("/layouts/platform.html"){
], ],
tableDataUnionPrize: {}, tableDataUnionPrize: {},
lastSum: {}, lastSum: {},
tableDataPrize: [], tableDataPrize: {},
confirmedTotal: 0,
pendingResults: [],
queryFailed: false,
statusOptions: [{code: "1", name: "分组汇总年度前八"}, {code: "2", name: "奖品个数年度汇总表"}] statusOptions: [{code: "1", name: "分组汇总年度前八"}, {code: "2", name: "奖品个数年度汇总表"}]
} }
}, },
components: {}, components: {},
methods: { methods: {
async statusType(state) { statusType(state) {
this.tableLoading = true if (this.tableLoading) return
if (state === "1") { const next = this.pageForm.status === state ? null : state
const data = await this.summaryYearPrizes() if (next === '1' && !this.pageForm.sex) {
if (!data) { this.$message.warning('请选择性别')
this.tableLoading = false return
return
}
} else if (state === "2") {
this.pageForm.sex = null
await this.summary()
} }
this.$set(this.pageForm, 'status', next)
if (this.pageForm.status === state) { this.$set(this, 'isSummary', next === '1' ? 3 : (next === '2' ? 2 : 1))
this.pageForm.status = null return this.refreshPrizes()
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
}, },
getSummaryByYear(o, i, type) { // 三种展示分别刷新,沿用mixins的分页能力,不另写公共表格分页方法。
if (type === "集体项目") { refreshPrizes() {
const datas = o.filter(o => o.ranking === i).map(o => o.unionname) if (this.isSummary === 3) return this.summaryYearPrizes()
if (datas) { if (this.isSummary === 2) return this.summary()
return datas.join(",") return this.getPrizes()
} else {
return ""
}
} else {
//甲组里面有可能有团体项目,所以说如果这个没有username就代表是团体
return o.filter(f => f.ranking === i).map(g => g.username ? g.username : g.unionname).join('、')
}
}, },
async summaryYearPrizes() { sexChange() {
try { if (this.isSummary === 3) return this.summaryYearPrizes()
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
}
}, },
getTableTdContent(d, i) { getSummaryByYear(rows, ranking, type) {
return d.filter(v => { return rows.filter(item => item.ranking === ranking).map(item => type === '集体项目' ? item.unionname : (item.username || item.unionname)).join('、')
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()
}, },
prizeSourceText(rows) {
async summary() { return [...new Set(rows.map(item => item.participantUnionName).filter(Boolean))].join('、')
try { },
if (this.activityList.length === 0) { resultsInputUrl(item) {
return return '/platform/activity/results/input?activityId=' + encodeURIComponent(item.activityId)
} + '&eventId=' + encodeURIComponent(item.eventId) + '&year=' + encodeURIComponent(this.pageForm.year)
if (!this.pageForm.activityId) { },
this.pageForm.activityId = this.activityList[0].id acceptPrizeStatistics(data) {
} this.$set(this, 'confirmedTotal', Number(data.confirmedTotal) || 0)
this.$set(this.pageForm, "unionId", null) this.$set(this, 'pendingResults', data.pendingResults || [])
this.isSummary = 2 },
this.tableData = [] clearPrizeStatistics() {
this.$set(this, 'confirmedTotal', 0)
const {data} = await this.$axios.post(loc() + "/summary", this.pageForm) this.$set(this, 'pendingResults', [])
this.$set(this, "tableData", data.score) this.$set(this, 'lastSum', {})
this.unionName = "汇总" this.$set(this, 'tableDataUnionPrize', {})
} catch (e) { this.$set(this, 'tableData', [])
this.$message.error(e.msg) },
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() { print() {
let subOutputRankPrint = document.getElementById('print'); if (this.tableLoading || this.queryFailed) return
let newContent = subOutputRankPrint.innerHTML; let newContent = document.getElementById('print').innerHTML
let oldContent = document.body.innerHTML; let oldContent = document.body.innerHTML
document.body.innerHTML = newContent; document.body.innerHTML = newContent
window.print(); window.print()
window.location.reload(); window.location.reload()
document.body.innerHTML = oldContent; document.body.innerHTML = oldContent
return false; return false
}, },
actChange(activityId) { actChange(activityId) {
this.tableColumns = [] this.$set(this.pageForm, 'activityId', activityId)
this.tableData = [] return this.refreshPrizes()
this.pageForm.activityId = ""
const activityData = this.activityList.find(v => v.id == activityId)
this.pageForm.activityId = activityData.id
this.getPrizes()
}, },
unionChange(unionId) { unionChange(unionId) {
this.tableColumns = [] this.$set(this.pageForm, 'unionId', unionId)
this.tableData = [] const union = this.unionList.find(item => item.id === unionId)
this.pageForm.unionId = "" this.$set(this, 'unionName', union ? union.name : '')
this.isSummary = 1 return this.getPrizes()
const unionData = this.unionList.find(v => v.id == unionId)
this.pageForm.unionId = unionData.id
this.unionName = unionData.name
this.getPrizes()
}, },
async getActivitys() { getActivitys() {
this.tableData = [] this.clearPrizeStatistics()
const {data} = await this.$axios.post("/platform/activity/score/statistics/getActivitys", {year: this.pageForm.year}) this.$set(this, 'tableDataPrize', {})
this.pageForm.activityId = "" this.$set(this, 'tableLoading', true)
this.activityList = data this.$set(this, 'queryFailed', false)
if (data && data.length > 0) { return this.$axios.post('/platform/activity/score/statistics/getActivitys', {year: this.pageForm.year}).then((resp) => {
this.pageForm.activityId = data[0].id if (resp.code !== 0) throw new Error(resp.msg || '活动查询失败')
} const activities = resp.data || []
await this.getPrizes() this.$set(this, 'activityList', activities)
if (!activities.some(item => item.id === this.pageForm.activityId)) {
}, this.$set(this.pageForm, 'activityId', activities.length ? activities[0].id : '')
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
} }
return this.refreshPrizes()
lastSum[9] = Object.values(lastSum).reduce((a, b) => a + b) }).catch((error) => {
this.lastSum = lastSum this.$set(this, 'queryFailed', true)
} catch (e) { this.$message.error(error.message || error.msg || '活动查询失败')
this.$message.error(e.msg) }).finally(() => {
} finally { this.$set(this, 'tableLoading', false)
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() { created() {
await this.getActivitys() this.$set(this, 'tableLoading', true)
this.unionList = await this.$businessTool.listUnion() this.$businessTool.listUnion().then((unions) => {
if (this.unionList.length > 0) { this.$set(this, 'unionList', unions || [])
this.pageForm.unionId = this.unionList[0].id this.$set(this.pageForm, 'unionId', unions.length ? unions[0].id : '')
this.unionName = this.unionList[0].unionname this.$set(this, 'unionName', unions.length ? unions[0].name : '')
} return this.getActivitys()
await this.getPrizes() }).catch((error) => {
this.$set(this, 'queryFailed', true)
this.$message.error(error.message || error.msg || '工会查询失败')
}).finally(() => {
this.$set(this, 'tableLoading', false)
})
} }
}) })
</script> </script>
File diff suppressed because it is too large Load Diff
@@ -73,7 +73,8 @@ layout("/layouts/platform.html"){
</el-select> </el-select>
</search-item> </search-item>
<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> </el-button>
</search-item> </search-item>
</search> </search>
@@ -301,10 +302,18 @@ layout("/layouts/platform.html"){
}, },
doExcelCj() { doExcelCj() {
const {activityId, unionname} = this.pageForm const {activityId, unionname} = this.pageForm
// 年度统计视图下 activityId 已被清空,此处导出会查不到数据
if (!activityId) {
this.$message.warning("当前为年度统计视图,无法导出单个活动的成绩明细,请先选择「运动会成绩统计」中的任一维度")
return
}
let unionId = '' let unionId = ''
if (unionname) { if (unionname) {
const unionlist = clone(this.unionList) 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}) this.$downLoad(loc() + "/doExcelCj", {activityId: activityId, unionId: unionId})
@@ -585,11 +585,13 @@ const basicForm = {
return return
} }
const courseValid = this.formData.courseList.some((v, i) => { const courseValid = this.formData.courseList.some((v, i) => {
// 新活动通过多选关系设置负责人;未重新设置的旧活动仍允许保留历史联系人。 const missingFields = []
const hasResponsible = Array.isArray(v.responsibleList) if (!v.courseName) missingFields.push(this.trainType + "名称")
? v.responsibleList.length > 0 : !!v.courseInstructor if (!v.coursePeopleNumber) missingFields.push(this.trainType + "人数(不能为空或为0)")
const basicValid = v.courseName && v.coursePeopleNumber && v.courseLocation && hasResponsible && v.courseType if (!v.courseLocation) missingFields.push(this.trainType + "地点")
if (!v.courseType) missingFields.push("类型")
const timeValid = const timeValid =
Array.isArray(v.courseTimeList) &&
v.courseTimeList.length > 0 && v.courseTimeList.length > 0 &&
v.courseTimeList.every((x) => { v.courseTimeList.every((x) => {
return x.courseStartTime && x.courseEndTime && x.courseStartTime < x.courseEndTime return x.courseStartTime && x.courseEndTime && x.courseStartTime < x.courseEndTime
@@ -598,8 +600,8 @@ const basicForm = {
this.$message.warning("第" + (i + 1) + "行时间填写有误,请核查") this.$message.warning("第" + (i + 1) + "行时间填写有误,请核查")
return true return true
} }
if (!basicValid) { if (missingFields.length > 0) {
this.$message.warning("第" + (i + 1) + "行信息填写有误,请核查") this.$message.warning("第" + (i + 1) + "行请补充:" + missingFields.join("、"))
return true return true
} }
// 联系方式允许手机号或办公电话,逐人校验,不能只检查兼容展示的第一位。 // 联系方式允许手机号或办公电话,逐人校验,不能只检查兼容展示的第一位。
@@ -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"]}], paymentWay: [{required: true, message: "请选择支付方式", trigger: ["change", "blur"]}],
reimburseProject: [{required: true, message: "请选择报销项目", trigger: ["change", "blur"]}], reimburseProject: [{required: true, message: "请选择报销项目", trigger: ["change", "blur"]}],
reimburseFundSource: [{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: [{ bankUserName: [{
required: true, required: true,
whitespace: true, whitespace: true,
@@ -1890,10 +1894,14 @@ layout("/layouts/platform.html"){
this.normalizeFundBalance() this.normalizeFundBalance()
resolve(true) resolve(true)
} else { } else {
// 支付信息已移至发票信息页,支付明细校验失败时跳转到对应页签。 // 新增必填项属于基本信息;同时存在支付错误时优先展示这两个字段的校验提示。
const basicInfoInvalid = Object.keys(invalidFields || {})
.some((field) => ["paymentNotes", "clubId"].includes(field))
const paymentDetailInvalid = Object.keys(invalidFields || {}) const paymentDetailInvalid = Object.keys(invalidFields || {})
.some((field) => field.indexOf("paymentDetails.") === 0) .some((field) => field.indexOf("paymentDetails.") === 0)
if (paymentDetailInvalid) { if (basicInfoInvalid) {
this.$set(this, "activeTabName", "basic")
} else if (paymentDetailInvalid) {
this.$set(this, "activeTabName", "invoice") this.$set(this, "activeTabName", "invoice")
} }
this.$message.warning("请完善必填信息") this.$message.warning("请完善必填信息")
@@ -954,14 +954,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return data return data
}, },
pageData() { pageData() {
sublime.showLoadingbar();
this.tableLoading = true this.tableLoading = true
const pageForm = clone(this.pageForm) const pageForm = clone(this.pageForm)
pageForm.states = JSON.stringify(pageForm.states) pageForm.states = JSON.stringify(pageForm.states)
$.post(loc() + "/pageData", pageForm, (data) => { $.post(loc() + "/pageData", pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -797,14 +797,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.unionOptions = data this.unionOptions = data
}, },
pageData() { pageData() {
sublime.showLoadingbar();
this.tableLoading = true this.tableLoading = true
const pageForm = clone(this.pageForm) const pageForm = clone(this.pageForm)
pageForm.states = JSON.stringify(pageForm.states) pageForm.states = JSON.stringify(pageForm.states)
$.post(loc() + "/pageData", pageForm, (data) => { $.post(loc() + "/pageData", pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -201,8 +201,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
(pageForm.regionalNature==='省内'&&modifyConfig.isSnLine)|| (pageForm.regionalNature==='省内'&&modifyConfig.isSnLine)||
(pageForm.regionalNature==='省外'&&modifyConfig.isSwLine)"> (pageForm.regionalNature==='省外'&&modifyConfig.isSwLine)">
<el-button size="small" <el-button size="small" type="primary" plain
style="background-color: #fff;border-color: #b3d8ff;color: #1867b0;font-size: 15px"
>{{selectLine.lineName?selectLine.lineName:'全部'}}线路的人数:{{lineSignNumber}}人 >{{selectLine.lineName?selectLine.lineName:'全部'}}线路的人数:{{lineSignNumber}}人
</el-button> </el-button>
@@ -957,14 +956,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return data return data
}, },
pageData() { pageData() {
sublime.showLoadingbar();
this.tableLoading = true this.tableLoading = true
const pageForm = clone(this.pageForm) const pageForm = clone(this.pageForm)
pageForm.states = JSON.stringify(pageForm.states) pageForm.states = JSON.stringify(pageForm.states)
$.post(loc() + "/pageData", pageForm, (data) => { $.post(loc() + "/pageData", pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -243,6 +243,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-row :gutter="20">
<el-col :md="12" :sm="24" :xs="24"> <el-col :md="12" :sm="24" :xs="24">
<el-form-item label="旅行社名称" prop="travelAgencyId"> <el-form-item label="旅行社名称" prop="travelAgencyId">
<el-select clearable filterable style="width: 100%" v-model="formData.travelAgencyId"> <el-select clearable filterable style="width: 100%" v-model="formData.travelAgencyId">
@@ -272,7 +274,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-col :md="12" :sm="24" :xs="24"> <el-col :md="12" :sm="24" :xs="24">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="24">
<el-form-item label="线路类型" prop="regionalNature"> <el-form-item label="线路类型" prop="regionalNature">
<el-radio-group class="mr0-radio" size="small" v-model="formData.regionalNature"> <el-radio-group class="mr0-radio" size="small" v-model="formData.regionalNature">
<el-radio :label="item.value" <el-radio :label="item.value"
@@ -284,6 +286,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-col> </el-col>
</el-row> </el-row>
</el-col> </el-col>
</el-row>
<el-row :gutter="20">
<el-col :md="12" :sm="24" :xs="24"> <el-col :md="12" :sm="24" :xs="24">
<el-form-item label="交通工具" prop="trafficTools"> <el-form-item label="交通工具" prop="trafficTools">
<el-input clearable maxlength="50" v-model="formData.trafficTools"></el-input> <el-input clearable maxlength="50" v-model="formData.trafficTools"></el-input>
@@ -312,6 +316,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-col> </el-col>
</el-row> </el-row>
</el-col> </el-col>
</el-row>
<el-row :gutter="20">
<el-col :md="12" :sm="24" :xs="24"> <el-col :md="12" :sm="24" :xs="24">
<el-form-item label="预计费用(元/人次)" prop="estimatedCost"> <el-form-item label="预计费用(元/人次)" prop="estimatedCost">
<el-input clearable maxlength="50" v-model="formData.estimatedCost"></el-input> <el-input clearable maxlength="50" v-model="formData.estimatedCost"></el-input>
@@ -821,6 +827,13 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
const valid = await this.$validateForm(this.$refs['form']) const valid = await this.$validateForm(this.$refs['form'])
if (!valid) return if (!valid) return
const confirm = await this.$confirmAction('确定保存该线路吗?', '保存确认', {
confirmButtonText: '确认保存',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm !== 'confirm') return
loading = this.$loading({ loading = this.$loading({
lock: true, lock: true,
text: '提交中', text: '提交中',
@@ -829,6 +842,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
}); });
delete this.formData.travelAgency delete this.formData.travelAgency
const resp = await $.post(loc() + '/doSubmit', this.formData) const resp = await $.post(loc() + '/doSubmit', this.formData)
loading.close()
loading = null
if (resp.code === 0) { if (resp.code === 0) {
this.$message.success(resp.msg) this.$message.success(resp.msg)
await this.$confirm('需要将该线路设置为出行线路吗?', '提示', { await this.$confirm('需要将该线路设置为出行线路吗?', '提示', {
@@ -836,11 +851,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(async () => { }).then(async () => {
if ("${@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.hasRole('sysadmin')||@com.budwk.app.zhgh.staffbenefit.therapyRecuperation.support.TherapyContext.hasRole('A06')}" === 'true') { window.top.location.href = '/platform/inclusiveTherapyV3/lineXghSelect?mode=2'
sublime.jumpPagePjax('/platform/inclusiveTherapyV3/lineXghSelect?mode=2')
} else {
sublime.jumpPagePjax('/platform/inclusiveTherapyV3/lineFghSelect?mode=1')
}
}).catch(() => { }).catch(() => {
this.$refs.guava.index() this.$refs.guava.index()
this.pageData() this.pageData()
@@ -1,12 +1,5 @@
<!--# <!--#
layout("/layouts/platform.html"){ layout("/layouts/platform.html"){
#--> #-->
<!--# if(therapyShowTabs && therapyPageUrl != '/platform/inclusiveTherapyV3/line' && therapyPageUrl != '/platform/inclusiveTherapyV3/baseManagement'){ #--> <iframe src="${therapyPageUrl,escape}" title="普惠疗休养" style="width:100%;height:calc(100vh - 100px);border:0;background:#fff"></iframe>
<div style="padding:10px;background:#fff;border-bottom:1px solid #eee">
<!--# for(tab in therapyTabs){ #-->
<a class="btn btn-default" href="/platform/inclusiveTherapyV3?screen=${tab[0],escape}">${tab[1],escape}</a>
<!--# } #-->
</div>
<!--# } #-->
<iframe src="${therapyPageUrl,escape}" title="普惠疗休养V3" style="width:100%;height:calc(100vh - 100px);border:0;background:#fff"></iframe>
<!--# } #--> <!--# } #-->
@@ -1,23 +1,36 @@
<!doctype html> <!doctype html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"> <html lang="zh-CN">
<title>普惠疗休养V3</title> <head>
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script> <meta charset="UTF-8">
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script> <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.js"></script> <title>普惠疗休养</title>
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script> <script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script> <script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<script>const APP_DOMAIN = location.origin; const FILE_DOMAIN = location.origin;</script> <script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.js"></script>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vant/index.css"> <script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/theme.css"> <script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/main.css"> <script>const APP_DOMAIN = location.origin;
<script src="${base!}/assets/platform/plugins/vant/index.js"></script> const FILE_DOMAIN = location.origin;</script>
<script src="${base!}/assets/staffbenefit/therapyRecuperation/basic.js"></script> <link rel="stylesheet" href="${base!}/assets/platform/plugins/vant/index.css">
<script src="${base!}/assets/staffbenefit/therapyRecuperation/v.js"></script> <link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/theme.css">
<script src="${base!}/assets/staffbenefit/therapyRecuperation/mobileMixins.js"></script> <link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/main.css">
<script src="${base!}/assets/staffbenefit/therapyRecuperation/compat.js"></script> <link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/mobile/pages.css">
<link rel="stylesheet" href="${base!}/assets/platform/css/pdf/pdfh5.css"> <script src="${base!}/assets/platform/plugins/vant/index.js"></script>
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.js"></script> <script src="${base!}/assets/staffbenefit/therapyRecuperation/basic.js"></script>
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.worker.js"></script> <script src="${base!}/assets/staffbenefit/therapyRecuperation/v.js"></script>
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdfh5.js"></script> <script src="${base!}/assets/staffbenefit/therapyRecuperation/mobileMixins.js"></script>
<style>[v-cloak]{display:none}body{margin:0}</style> <script src="${base!}/assets/staffbenefit/therapyRecuperation/compat.js"></script>
</head><body>${layoutContent}</body></html> <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,12 +1,17 @@
<!--# 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> <!doctype html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>普惠疗休养V3</title> <title>普惠疗休养</title>
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script> <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/jquery/jquery.js"></script>
<script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.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/moment/moment.min.js"></script>
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script> <script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<script>const APP_DOMAIN = location.origin; const FILE_DOMAIN = location.origin;</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/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/font-awesome.min.css">
<link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css"> <link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css">
@@ -16,7 +21,18 @@
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/css/main.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/elmain.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/css/panel.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 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/wangEditor4/wangEditor.js"></script>
<script src="${base!}/assets/platform/plugins/sortablejs/sortable.min.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> <script src="${base!}/assets/platform/plugins/vuedraggable/vuedraggable.umd.min.js"></script>
@@ -47,5 +63,6 @@ Vue.directive('auth', {inserted(el, binding) {
if (!requested.some(role => roles.includes(role))) el.parentNode.removeChild(el); if (!requested.some(role => roles.includes(role))) el.parentNode.removeChild(el);
}}); }});
</script> </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> </head><body>${layoutContent}</body></html>
<!--# } #-->
@@ -280,7 +280,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<!-- <el-button icon="el-icon-s-promotion" @click="openImport" size="small" <!-- <el-button icon="el-icon-s-promotion" @click="openImport" size="small"
type="primary">参加人员导入 type="primary">参加人员导入
</el-button>--> </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> <template>
<el-button icon="el-icon-s-promotion" <el-button icon="el-icon-s-promotion"
@click="$downloadFile('/platform/inclusiveTherapyV3/query/exportDeclareForm')" @click="$downloadFile('/platform/inclusiveTherapyV3/query/exportDeclareForm')"
@@ -424,7 +424,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-if="pageForm.lb==='ry'"> v-if="pageForm.lb==='ry'">
<template scope="{row}"> <template scope="{row}">
<el-card shadow="never"> <el-card shadow="never">
<h4 slot="header" style="color: #1867b0"> <h4 slot="header" style="color: var(--color-primary)">
家属信息 家属信息
</h4> </h4>
<el-table :data="row.companionList"> <el-table :data="row.companionList">
@@ -528,7 +528,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="家属信息" type="expand" width="150px"> <el-table-column label="家属信息" type="expand" width="150px">
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-card shadow="never"> <el-card shadow="never">
<h4 slot="header" style="color: #1867b0"> <h4 slot="header" style="color: var(--color-primary)">
家属信息 家属信息
</h4> </h4>
<el-table :data="row.companionList"> <el-table :data="row.companionList">
@@ -752,7 +752,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
title="家属信息" title="家属信息"
:visible.sync="familyDrawer" :visible.sync="familyDrawer"
direction="rtl"> direction="rtl">
<h4 slot="header" style="color: #1867b0"> <h4 slot="header" style="color: var(--color-primary)">
家属信息 家属信息
</h4> </h4>
<el-table :data="companionList"> <el-table :data="companionList">
@@ -1450,7 +1450,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.$message.warning('请先选择需要查看的记录'); this.$message.warning('请先选择需要查看的记录');
return return
} }
sublime.showLoadingbar();
this.tableLoading = true this.tableLoading = true
const pageForm = clone(this.pageFormUser) const pageForm = clone(this.pageFormUser)
pageForm.id = this.applyUserRow.id pageForm.id = this.applyUserRow.id
@@ -1466,7 +1465,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} }
}) })
.always(() => { .always(() => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
}); });
this.$refs.guava.view() this.$refs.guava.view()
@@ -1505,7 +1503,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true this.tableLoading = true
this.tableData = [] this.tableData = []
$.post(loc() + "/getSelfUnionUser", this.pageForm, (data) => { $.post(loc() + "/getSelfUnionUser", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -1640,7 +1637,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true this.tableLoading = true
this.tableData = [] this.tableData = []
$.post(loc() + "/getLxsData", this.pageForm, (data) => { $.post(loc() + "/getLxsData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -1654,7 +1650,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true this.tableLoading = true
this.tableData = [] this.tableData = []
$.post(loc() + "/getJdData", this.pageForm, (data) => { $.post(loc() + "/getJdData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -1668,7 +1663,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true this.tableLoading = true
this.tableData = [] this.tableData = []
$.post(loc() + "/getXlData", this.pageForm, (data) => { $.post(loc() + "/getXlData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -1682,7 +1676,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
this.tableLoading = true this.tableLoading = true
this.tableData = [] this.tableData = []
$.post(loc() + "/getRyData", this.pageForm, (data) => { $.post(loc() + "/getRyData", this.pageForm, (data) => {
sublime.closeLoadingbar();
this.tableLoading = false this.tableLoading = false
if (data.code === 0) { if (data.code === 0) {
this.tableData = data.data.list; this.tableData = data.data.list;
@@ -35,7 +35,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div id="app"> <div id="app">
<el-card class="m10" shadow="never" style="height: calc(100% - 20px)"> <el-card class="m10" shadow="never" style="height: calc(100% - 20px)">
<template #header> <template #header>
<h3 style="color: #1867b0">导入参加人员</h3> <h3 style="color: var(--color-primary)">导入参加人员</h3>
</template> </template>
<el-steps :active="stepActive"> <el-steps :active="stepActive">
@@ -4,7 +4,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<style> <style>
.companion_card { .companion_card {
border: 1px #1867b0 solid; border: 1px var(--color-primary) solid;
} }
.row-expand-cover .el-table__expand-icon { .row-expand-cover .el-table__expand-icon {
@@ -189,7 +189,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<el-table-column label="序号" type="expand" width="150px"> <el-table-column label="序号" type="expand" width="150px">
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-card class="companion_card" shadow="never"> <el-card class="companion_card" shadow="never">
<h4 slot="header" style="color: #1867b0"> <h4 slot="header" style="color: var(--color-primary)">
家属信息 家属信息
</h4> </h4>
<el-table :data="row.companionList"> <el-table :data="row.companionList">
@@ -317,7 +317,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
return d ? d.label : null return d ? d.label : null
}, },
async pageData() { async pageData() {
sublime.showLoadingbar()
this.tableLoading = true this.tableLoading = true
try { try {
const resp = await $.post(loc() + '/pageData', this.pageForm) const resp = await $.post(loc() + '/pageData', this.pageForm)
@@ -330,7 +329,6 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
} catch (error) { } catch (error) {
this.$actionError(error) this.$actionError(error)
} finally { } finally {
sublime.closeLoadingbar()
this.tableLoading = false this.tableLoading = false
} }
}, },
@@ -145,16 +145,17 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-model="row.isDisabled"> v-model="row.isDisabled">
</el-switch> </el-switch>
</template>--> </template>-->
<template slot-scope="{row:{signUpMode}}" v-if="column.prop==='signUpMode'"> <template slot-scope="{row}">
{{signUpModeName(signUpMode)}} <template v-if="column.prop==='signUpMode'">
{{signUpModeName(row.signUpMode)}}
</template> </template>
<template slot-scope="{row:{createMode}}" v-else-if="column.prop==='createMode'"> <template v-else-if="column.prop==='createMode'">
{{createModeName(createMode)}} {{createModeName(row.createMode)}}
</template> </template>
<template slot-scope="{row}" v-else-if="column.prop==='belongUnionName'"> <template v-else-if="column.prop==='belongUnionName'">
{{pageForm.mode == 2 && pageForm.selectStatus == 1 ? '校工会' : row.belongUnionName}} {{pageForm.mode == 2 && pageForm.selectStatus == 1 ? '校工会' : row.belongUnionName}}
</template> </template>
<template slot-scope="{row}" v-else-if="column.prop==='playTime'"> <template v-else-if="column.prop==='playTime'">
<template v-if="row.playTimes"> <template v-if="row.playTimes">
<!--<el-tooltip placement="top"> <!--<el-tooltip placement="top">
<div slot="content"> <div slot="content">
@@ -183,13 +184,14 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
选择并设置出行时间段 选择并设置出行时间段
</el-button> </el-button>
</template> </template>
<template slot-scope="{row}" v-else-if="column.prop==='createUnionName'"> <template v-else-if="column.prop==='createUnionName'">
<span v-if="!row.isSelect"> <span v-if="!row.isSelect">
{{row.createUnionName}} {{row.createUnionName}}
</span> </span>
<span v-else>{{row.belongUnionName}}</span> <span v-else>{{row.belongUnionName}}</span>
</template> </template>
<template slot-scope="{row}" v-else>{{row[column.prop]}}</template> <template v-else>{{row[column.prop]}}</template>
</template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="100px"> <el-table-column label="操作" width="100px">
@@ -24,7 +24,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<guava> <guava>
<el-card shadow="never"> <el-card shadow="never">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<h3 style="color: rgb(24, 103, 176);font-family: Microsoft YaHei;">疗休养配置</h3> <h3 style="color: var(--color-primary);font-family: Microsoft YaHei;">疗休养配置</h3>
</div> </div>
<el-form ref="addForm" :model="formData" :rules="formRules" label-width="170px"> <el-form ref="addForm" :model="formData" :rules="formRules" label-width="170px">
@@ -340,7 +340,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
travelAudit: 0, travelAudit: 0,
lots: [], lots: [],
unionLineNumberConfigs: [], unionLineNumberConfigs: [],
configName: '普惠疗休养V3配置', configName: '普惠疗休养配置',
// 报名时间范围对应后台 signUpStartTime/signUpEndTime 两个字段。 // 报名时间范围对应后台 signUpStartTime/signUpEndTime 两个字段。
signUpStartTime: null, signUpStartTime: null,
signUpEndTime: null, signUpEndTime: null,
@@ -170,6 +170,7 @@ layout("/layouts/platform.html"){
<el-table-column align="center" header-align="center" label="更新时间" <el-table-column align="center" header-align="center" label="更新时间"
min-width="145px" prop="changeTime" min-width="145px" prop="changeTime"
show-overflow-tooltip sortable> show-overflow-tooltip sortable>
<template scope="{row}">{{row.changeTime || '--'}}</template>
</el-table-column> </el-table-column>
<el-table-column align="center" header-align="center" label="异动类型" <el-table-column align="center" header-align="center" label="异动类型"
prop="changeType" show-overflow-tooltip sortable> prop="changeType" show-overflow-tooltip sortable>
@@ -649,17 +650,16 @@ layout("/layouts/platform.html"){
} }
}, },
getChangeTypes(changeTypes){ getChangeTypes(changeTypes){
if (!changeTypes) return null if (!changeTypes) return '--'
const changeTypesList = JSON.parse(changeTypes) const changeTypesList = Array.isArray(changeTypes) ? changeTypes : JSON.parse(changeTypes)
if (changeTypesList) { if (!Array.isArray(changeTypesList) || changeTypesList.length === 0) return '--'
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null // 历史编码可能已不在当前枚举中,保留原编码,避免整张表格渲染中断。
return changeTypesList return changeTypesList
.map((v) => { .map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName const changeType = (this.changeTypeData || []).find((item) => item.code === v)
}) return changeType ? changeType.changeTypeName : (v || '未知异动类型')
.join(",") })
} .join(",")
return null
}, },
changeDateRangeChange(val) { changeDateRangeChange(val) {
if (val && val.length > 0) { if (val && val.length > 0) {
@@ -200,7 +200,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
<div id="app" v-cloak> <div id="app" v-cloak>
<van-sticky> <van-sticky>
<van-nav-bar @click-left="history.back()" fixed left-arrow placeholder title="普惠疗休养V3-酒店介绍"></van-nav-bar> <van-nav-bar @click-left="history.back()" fixed left-arrow placeholder title="普惠疗休养-酒店介绍"></van-nav-bar>
</van-sticky> </van-sticky>
<!--线路详情--> <!--线路详情-->
@@ -3,60 +3,94 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
#--> #-->
<style> <style>
.van-doc-card { .therapy-home {
margin: 10px; padding-bottom: calc(16px + env(safe-area-inset-bottom));
padding: 12px 12px 12px 12px; color: #323233;
}
.therapy-home .van-nav-bar--fixed {
left: 50%;
width: 100%;
max-width: 640px;
transform: translateX(-50%);
}
.therapy-home .van-doc-card {
margin: 12px;
padding: 16px;
background-color: #fff; background-color: #fff;
border-radius: 6px; border-radius: 12px;
box-shadow: 0 8px 12px #ebedf0; line-height: 24px;
line-height: 20px;
position: relative; position: relative;
} }
.van-grid-item__content { .therapy-home .therapy-banner {
padding: 0; display: block;
width: calc(100% - 24px);
margin: 12px;
height: clamp(140px, 42vw, 220px);
overflow: hidden;
border-radius: 12px;
} }
.choose_button .button_text { .therapy-home .van-grid-item__content {
padding: 12px 8px;
border-radius: 8px;
}
.therapy-home .van-grid-item__content:active {
background-color: #f2f7fc;
}
.therapy-home .choose_button .button_text {
font-size: 14px; font-size: 14px;
margin-top: 6px; margin-top: 10px;
font-weight: 500;
} }
.list-card { .therapy-home .notice-title {
width: auto; margin: 0 0 12px;
padding-left: 10px;
border-left: 3px solid #1867b0;
font-size: 16px;
font-weight: 600;
} }
.pre_text { .therapy-home .pre_text {
white-space: break-spaces; white-space: break-spaces;
padding-left: 7px; overflow-wrap: anywhere;
font-size: 14px;
line-height: 1.8;
overflow-x: auto;
} }
.pdfjs { .therapy-home .pre_text img,
height: 90%; .therapy-home .pre_text video {
max-width: 100% !important;
height: auto !important;
}
.therapy-home .pdf_div {
height: 70vh;
min-height: 320px;
overflow: auto;
} }
</style> </style>
<div id="app" v-cloak> <div id="app" class="therapy-home therapy-mobile" v-cloak>
<van-sticky> <van-sticky>
<van-nav-bar @click-left="history.back()" fixed left-arrow placeholder title="普惠疗休养V3"></van-nav-bar> <van-nav-bar @click-left="historyBack" fixed left-arrow placeholder title="普惠疗休养"></van-nav-bar>
</van-sticky> </van-sticky>
<!--顶部轮播图--> <!--顶部轮播图-->
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white"> <van-image class="therapy-banner" fit="cover" alt="疗休养风景" src="/assets/staffbenefit/therapyRecuperation/img/index1.jpeg"></van-image>
<van-swipe-item>
<van-image width="100%" height="180" src="/assets/staffbenefit/therapyRecuperation/img/index1.jpeg"></van-image>
</van-swipe-item>
<van-swipe-item>
<van-image height="180" src="/assets/staffbenefit/therapyRecuperation/img/index1.jpeg"></van-image>
</van-swipe-item>
</van-swipe>
<!--按钮导航--> <!--按钮导航-->
<div class="choose_button van-doc-card"> <div class="choose_button van-doc-card">
<van-grid :column-num="chooseButton.length" :border="false"> <van-grid :column-num="Math.max(chooseButton.length, 1)" :border="false">
<van-grid-item @click="toLineList(item.value)" v-for="item in chooseButton"> <van-grid-item @click="toLineList(item.value)" v-for="item in chooseButton" :key="item.value">
<van-image width="46" height="46" :src="item.imgUrl"></van-image> <van-image width="46" height="46" :src="item.imgUrl"></van-image>
<div class="button_text">{{item.label}}</div> <div class="button_text">{{item.label}}</div>
</van-grid-item> </van-grid-item>
@@ -64,8 +98,8 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
</div> </div>
<!--疗休养描述--> <!--疗休养描述-->
<div class="van-doc-card" style="margin-top: 20px; height: calc(100vh - 200px)"> <div class="van-doc-card">
<van-image width="190" height="43" src="/assets/staffbenefit/therapyRecuperation/img/title.png"></van-image> <h2 class="notice-title">疗休养须知</h2>
<div v-if="isPdf" class="pre_text" v-html="configData.notice"></div> <div v-if="isPdf" class="pre_text" v-html="configData.notice"></div>
<div v-else id="demo" class="pdf_div"></div> <div v-else id="demo" class="pdf_div"></div>
</div> </div>
@@ -84,6 +118,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
} }
}, },
methods: { methods: {
historyBack() {
window.history.back()
},
async toLineList(index) { async toLineList(index) {
/*const isExist = await getScopeUser(this.configData.activityGroupId) /*const isExist = await getScopeUser(this.configData.activityGroupId)
if (!isExist) { if (!isExist) {
@@ -222,7 +222,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
<van-sticky> <van-sticky>
<van-nav-bar @click-left="history.go(-1)" fixed left-arrow placeholder <van-nav-bar @click-left="history.go(-1)" fixed left-arrow placeholder
title="普惠疗休养V3-线路介绍"></van-nav-bar> title="普惠疗休养-线路介绍"></van-nav-bar>
</van-sticky> </van-sticky>
<template v-if="isLoad"> <template v-if="isLoad">
@@ -303,9 +303,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
</style> </style>
<div id="app" v-cloak v-if="isLoad"> <div id="app" class="therapy-mobile" v-cloak v-if="isLoad">
<van-sticky> <van-sticky>
<van-nav-bar @click-left="history.back()" fixed left-arrow placeholder title="疗休养线路"></van-nav-bar> <van-nav-bar @click-left="historyBack" fixed left-arrow placeholder title="疗休养线路"></van-nav-bar>
<!--<van-dropdown-menu> <!--<van-dropdown-menu>
@@ -631,6 +631,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
} }
}, },
methods: { methods: {
historyBack() {
window.history.back()
},
async openSignUser(row, type) { async openSignUser(row, type) {
const id = type === 'line' ? row.usId : row.id const id = type === 'line' ? row.usId : row.id
location.href = '/platform/inclusiveTherapyV3/mobile/userSignInfo?type=' + type + '&id=' + id location.href = '/platform/inclusiveTherapyV3/mobile/userSignInfo?type=' + type + '&id=' + id
@@ -179,9 +179,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
</style> </style>
<div id="app" v-cloak> <div id="app" class="therapy-mobile" v-cloak>
<van-sticky> <van-sticky>
<van-nav-bar @click-left="history.back()" fixed left-arrow placeholder <van-nav-bar @click-left="historyBack" fixed left-arrow placeholder
title="我的疗休养"></van-nav-bar> title="我的疗休养"></van-nav-bar>
</van-sticky> </van-sticky>
@@ -413,6 +413,9 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/mobile.html"){
} }
}, },
methods: { methods: {
historyBack() {
window.history.back()
},
isValidDate(value) { isValidDate(value) {
return value && moment(value).isValid() return value && moment(value).isValid()
}, },