疗休养1.0版本
This commit is contained in:
@@ -50,6 +50,7 @@ RoleConstant {
|
||||
BRANCH_UNION_WENTI_WY("分工会文体委员"),
|
||||
BRANCH_UNION_SHENGGHUO_WY("分工会生活委员"),
|
||||
BRANCH_UNION_TIAOJIE_WY("分工会调解委员"),
|
||||
BRANCH_UNION_WENTI_SPORTS("分工会文体福利委员"),
|
||||
|
||||
UNIT_PARTY_SECRETARY("单位党委书记"),
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.budwk.app.sys.utils.DataCenterUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
@@ -84,10 +85,15 @@ public class SysDataUnitPullServiceImpl extends BaseServiceImpl<Sys_unit> implem
|
||||
// 需要更新的单位
|
||||
List<Sys_unit> updateList = new ArrayList<>();
|
||||
|
||||
List<Sys_unit> sysUnits = dao().query(Sys_unit.class, Cnd.NEW());
|
||||
|
||||
// 拉取过来的数据,全部的单位,一万四千多条,这里只保留 “部门类”
|
||||
List<JSONObject> data = jsonBody.getJSONArray("data").stream()
|
||||
.map(o -> (JSONObject) o)
|
||||
.filter(row -> StrUtil.isNotBlank(row.getStr("bmlb")) && Objects.equals("隶属部门类", row.getStr("bmlb")))
|
||||
.filter(row ->
|
||||
sysUnits.stream().anyMatch(e -> row.getStr("zzjgdm").equals(e.getId()))
|
||||
|| (StrUtil.isNotBlank(row.getStr("bmlb")) && Objects.equals("隶属部门类", row.getStr("bmlb")))
|
||||
)
|
||||
.toList();
|
||||
|
||||
Map<String, String> api2db = Arrays.stream(Api2UnitFiledMap.values())
|
||||
|
||||
@@ -20,7 +20,8 @@ import java.io.Serializable;
|
||||
@Comment("活动人员范围设置")
|
||||
@TableIndexes({
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_GROUPID", fields = {"groupId"}, unique = false),
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_USERID", fields = {"userId"}, unique = false)
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_USERID", fields = {"userId"}, unique = false),
|
||||
@Index(name = "INDEX_ACTIVITY_USER_SCOPE_GROUPID_USERID", fields = {"groupId", "userId"}, unique = false)
|
||||
})
|
||||
public class ActivityUserScope extends BaseModel implements Serializable {
|
||||
|
||||
@@ -46,6 +47,16 @@ public class ActivityUserScope extends BaseModel implements Serializable {
|
||||
@Comment("userid")
|
||||
private String userId;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.INT, width = 2)
|
||||
@Comment("分组类型 1.结果分组 2.SQL条件分组")
|
||||
private Integer groupType;
|
||||
|
||||
@Column
|
||||
@ColDefine(customType = "longtext")
|
||||
@Comment("SQL条件分组保存的查询SQL")
|
||||
private String groupSql;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("创建人")
|
||||
|
||||
+45
@@ -21,4 +21,49 @@ public interface ActivityBasicScopeService extends BaseService<ActivityUserScope
|
||||
*/
|
||||
void largeDataInsert(List<ActivityUserScope> list) ;
|
||||
|
||||
/**
|
||||
* 查询分组基础信息。
|
||||
* SQL条件分组与结果分组都只从同一张 activity_user_scope 表读取。
|
||||
*/
|
||||
ActivityUserScope getGroupInfo(Integer groupId);
|
||||
|
||||
/**
|
||||
* 查询分组类型,未配置时默认按结果分组处理。
|
||||
*/
|
||||
Integer getGroupType(Integer groupId);
|
||||
|
||||
/**
|
||||
* 构造分组对应的人员ID子查询。
|
||||
* 结果分组直接取 activity_user_scope.userId,SQL条件分组则按保存的 groupSql 动态生成查询。
|
||||
*/
|
||||
Sql buildGroupUserIdSubSql(Integer groupId);
|
||||
|
||||
/**
|
||||
* 构造可直接拼接到业务SQL中的人员ID子查询文本。
|
||||
* 仅用于已有大量原生SQL场景,避免每个模块重复拼接 groupSql 逻辑。
|
||||
*/
|
||||
String buildGroupUserIdSubSqlText(Integer groupId);
|
||||
|
||||
/**
|
||||
* 查询分组当前命中的人员ID列表。
|
||||
*/
|
||||
List<String> listGroupUserIds(Integer groupId);
|
||||
|
||||
/**
|
||||
* 判断指定用户是否在某个分组内。
|
||||
* SQL条件分组会按保存的 groupSql 动态校验,而不是依赖落库的 userId 明细。
|
||||
*/
|
||||
boolean isUserInGroup(Integer groupId, String userId);
|
||||
|
||||
/**
|
||||
* 批量过滤出当前用户可见的分组ID。
|
||||
* 用于列表页先查活动、再按活动分组做二次权限过滤的场景。
|
||||
*/
|
||||
List<Integer> filterGroupIdsByUser(List<Integer> groupIds, String userId);
|
||||
|
||||
/**
|
||||
* SQL条件分组删除人员时,不再删除主表记录,而是把排除条件追加到已保存的 groupSql 中。
|
||||
*/
|
||||
void excludeUsersFromSqlGroup(Integer groupId, List<String> userIds);
|
||||
|
||||
}
|
||||
|
||||
+123
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.zhgh.activity.basic.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.utils.DateUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
||||
@@ -8,17 +9,20 @@ import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.impl.NutTxDao;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author zxy
|
||||
@@ -29,6 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
@Slf4j
|
||||
public class ActivityBasicScopeServiceImpl extends BaseServiceImpl<ActivityUserScope> implements ActivityBasicScopeService {
|
||||
|
||||
private static final int GROUP_TYPE_RESULT = 1;
|
||||
|
||||
public ActivityBasicScopeServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
@@ -80,4 +85,122 @@ public class ActivityBasicScopeServiceImpl extends BaseServiceImpl<ActivityUserS
|
||||
}
|
||||
log.info("结束时间" + DateUtil.getDateTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityUserScope getGroupInfo(Integer groupId) {
|
||||
if (groupId == null) {
|
||||
return null;
|
||||
}
|
||||
List<ActivityUserScope> list = dao().query(ActivityUserScope.class, Cnd.where("groupId", "=", groupId).desc("id"));
|
||||
return CollectionUtil.isEmpty(list) ? null : list.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getGroupType(Integer groupId) {
|
||||
ActivityUserScope userScope = getGroupInfo(groupId);
|
||||
if (userScope == null || userScope.getGroupType() == null) {
|
||||
return GROUP_TYPE_RESULT;
|
||||
}
|
||||
return userScope.getGroupType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sql buildGroupUserIdSubSql(Integer groupId) {
|
||||
return Sqls.create(buildGroupUserIdSubSqlText(groupId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildGroupUserIdSubSqlText(Integer groupId) {
|
||||
ActivityUserScope groupInfo = getGroupInfo(groupId);
|
||||
if (groupInfo == null) {
|
||||
return "SELECT NULL AS userId WHERE 1 = 0";
|
||||
}
|
||||
if (GROUP_TYPE_RESULT == getGroupType(groupId)) {
|
||||
return "SELECT userId FROM activity_user_scope WHERE groupId = " + groupId + " AND userId IS NOT NULL";
|
||||
}
|
||||
if (StrUtil.isBlank(groupInfo.getGroupSql())) {
|
||||
return "SELECT NULL AS userId WHERE 1 = 0";
|
||||
}
|
||||
return """
|
||||
SELECT DISTINCT
|
||||
u.id AS userId
|
||||
FROM
|
||||
`vw_user` u
|
||||
LEFT JOIN sys_user_role sur ON sur.userid = u.id
|
||||
LEFT JOIN club_user clubuser ON clubuser.userid = u.id
|
||||
WHERE
|
||||
""" + groupInfo.getGroupSql();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listGroupUserIds(Integer groupId) {
|
||||
Sql sql = Sqls.queryString(buildGroupUserIdSubSqlText(groupId));
|
||||
dao().execute(sql);
|
||||
String[] userIds = (String[]) sql.getResult();
|
||||
return userIds == null ? new ArrayList<>() : List.of(userIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInGroup(Integer groupId, String userId) {
|
||||
if (groupId == null || StrUtil.isBlank(userId)) {
|
||||
return false;
|
||||
}
|
||||
if (GROUP_TYPE_RESULT == getGroupType(groupId)) {
|
||||
return dao().count(ActivityUserScope.class, Cnd.where("groupId", "=", groupId).and("userId", "=", userId)) > 0;
|
||||
}
|
||||
ActivityUserScope groupInfo = getGroupInfo(groupId);
|
||||
if (groupInfo == null || StrUtil.isBlank(groupInfo.getGroupSql())) {
|
||||
return false;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
COUNT(1)
|
||||
FROM
|
||||
`vw_user` u
|
||||
LEFT JOIN sys_user_role sur ON sur.userid = u.id
|
||||
LEFT JOIN club_user clubuser ON clubuser.userid = u.id
|
||||
WHERE
|
||||
u.id = @userId
|
||||
AND
|
||||
""" + "(" + groupInfo.getGroupSql() + ")");
|
||||
sql.setParam("userId", userId);
|
||||
return count(sql) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> filterGroupIdsByUser(List<Integer> groupIds, String userId) {
|
||||
LinkedHashSet<Integer> result = new LinkedHashSet<>();
|
||||
if (CollectionUtil.isEmpty(groupIds) || StrUtil.isBlank(userId)) {
|
||||
return new ArrayList<>(result);
|
||||
}
|
||||
groupIds.stream()
|
||||
.filter(groupId -> groupId != null)
|
||||
.distinct()
|
||||
.forEach(groupId -> {
|
||||
if (isUserInGroup(groupId, userId)) {
|
||||
result.add(groupId);
|
||||
}
|
||||
});
|
||||
return new ArrayList<>(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void excludeUsersFromSqlGroup(Integer groupId, List<String> userIds) {
|
||||
ActivityUserScope groupInfo = getGroupInfo(groupId);
|
||||
if (groupInfo == null || getGroupType(groupId) != 2 || CollectionUtil.isEmpty(userIds) || StrUtil.isBlank(groupInfo.getGroupSql())) {
|
||||
return;
|
||||
}
|
||||
String excludeUserSql = userIds.stream()
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.map(userId -> "'" + StrUtil.replace(userId, "'", "''") + "'")
|
||||
.collect(Collectors.joining(","));
|
||||
if (StrUtil.isBlank(excludeUserSql)) {
|
||||
return;
|
||||
}
|
||||
// SQL分组只有一条主记录,删除人员时通过追加排除条件持久化删除结果。
|
||||
String groupSql = "(" + groupInfo.getGroupSql() + ") AND u.id NOT IN (" + excludeUserSql + ")";
|
||||
groupInfo.setGroupSql(groupSql);
|
||||
dao().updateIgnoreNull(groupInfo);
|
||||
}
|
||||
}
|
||||
|
||||
+625
@@ -0,0 +1,625 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.sys.models.Sys_union;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourMatterService;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/group")
|
||||
public class TourGroupController {
|
||||
|
||||
@Inject
|
||||
private TourMatterService tourMatterService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerService tourLedgerService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/group/index.html")
|
||||
@SaCheckPermission("tour.group")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.group")
|
||||
public Result pageData(PageForm pageForm, Integer year, String lineName, String lineType, String unionId) {
|
||||
if (StrUtil.isBlank(pageForm.getPageOrderName())) {
|
||||
pageForm.defaultSortAsc("lineName");
|
||||
}
|
||||
Cnd cnd = buildQueryCnd(year, lineName, lineType, unionId);
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM tour_matter m
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
LEFT JOIN sys_union u ON u.id = m.unionId
|
||||
$condition
|
||||
""");
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourMatterService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
m.id AS matterId,
|
||||
m.`year`,
|
||||
m.matterName,
|
||||
m.unionId,
|
||||
COALESCE(u.name, '校工会') AS unionName,
|
||||
m.lineId,
|
||||
l.lineName,
|
||||
l.lineType,
|
||||
l.directFamilyUnitLine,
|
||||
m.travelStartTime,
|
||||
m.travelEndTime,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE ''
|
||||
END AS travelPeriod,
|
||||
m.minGroupPeople,
|
||||
m.maxGroupPeople,
|
||||
IFNULL(sc.signupCount, 0) AS signupCount,
|
||||
CASE
|
||||
WHEN m.maxGroupPeople IS NOT NULL AND m.maxGroupPeople > 0 AND IFNULL(sc.signupCount, 0) > m.maxGroupPeople THEN 'over'
|
||||
WHEN m.minGroupPeople IS NOT NULL AND m.minGroupPeople > 0 AND IFNULL(sc.signupCount, 0) >= m.minGroupPeople THEN 'formed'
|
||||
ELSE 'unformed'
|
||||
END AS groupStatus,
|
||||
CASE
|
||||
WHEN m.maxGroupPeople IS NOT NULL AND m.maxGroupPeople > 0 AND IFNULL(sc.signupCount, 0) > m.maxGroupPeople THEN '超员'
|
||||
WHEN m.minGroupPeople IS NOT NULL AND m.minGroupPeople > 0 AND IFNULL(sc.signupCount, 0) >= m.minGroupPeople THEN '已成团'
|
||||
ELSE '未成团'
|
||||
END AS groupStatusName
|
||||
FROM tour_matter m
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
LEFT JOIN sys_union u ON u.id = m.unionId
|
||||
LEFT JOIN (
|
||||
SELECT t.matterId, SUM(1 + IFNULL(f.familyCount, 0)) AS signupCount
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN (
|
||||
SELECT ledgerId, COUNT(1) AS familyCount
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
GROUP BY ledgerId
|
||||
) f ON f.ledgerId = t.id
|
||||
WHERE t.delFlag = 0
|
||||
AND t.matterId IS NOT NULL
|
||||
AND t.matterId <> ''
|
||||
GROUP BY t.matterId
|
||||
) sc ON sc.matterId = m.id
|
||||
$condition
|
||||
ORDER BY $orderColumn $orderBy, m.`year` DESC, m.travelStartTime ASC, l.lineName ASC, m.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
|
||||
listSql.setPager(tourMatterService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourMatterService.dao().execute(listSql);
|
||||
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, listSql.getList(NutMap.class));
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.group")
|
||||
public Result unionOptions() {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.asc("unionCode");
|
||||
cnd.asc("name");
|
||||
return Result.success(tourMatterService.dao().query(Sys_union.class, cnd));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.group")
|
||||
public Result lineTypeOptions(Integer year) {
|
||||
Cnd cnd = buildQueryCnd(year, null, null, null);
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT l.lineType
|
||||
FROM tour_matter m
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
LEFT JOIN sys_union u ON u.id = m.unionId
|
||||
$condition
|
||||
ORDER BY l.lineType ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourMatterService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.group")
|
||||
public Result signupPageData(PageForm pageForm, String matterId, String keyword, String unionId) {
|
||||
if (StrUtil.isBlank(matterId)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
if (StrUtil.isBlank(pageForm.getPageOrderName())) {
|
||||
pageForm.defaultSortDesc("signupTime");
|
||||
}
|
||||
Cnd cnd = buildSignupQueryCnd(matterId, keyword, unionId);
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM tour_ledger t
|
||||
INNER JOIN tour_matter m ON m.id = t.matterId
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
$condition
|
||||
""");
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
t.id,
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
'' AS mobile,
|
||||
t.idCard,
|
||||
t.unionId,
|
||||
t.unionName,
|
||||
t.signupTime
|
||||
FROM tour_ledger t
|
||||
INNER JOIN tour_matter m ON m.id = t.matterId
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
$condition
|
||||
ORDER BY $orderColumn $orderBy, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getSignupOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "ascending".equals(pageForm.getPageOrderBy()) ? "asc" : "desc");
|
||||
listSql.setPager(tourLedgerService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
List<NutMap> list = listSql.getList(NutMap.class);
|
||||
fillSignupMobile(list);
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("tour.group")
|
||||
public void exportParticipants(String matterId, HttpServletResponse response) {
|
||||
if (StrUtil.isBlank(matterId)) {
|
||||
return;
|
||||
}
|
||||
NutMap matter = fetchExportMatter(matterId);
|
||||
if (matter == null || matter.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<NutMap> list = queryExportParticipants(matterId);
|
||||
Workbook workbook = buildParticipantsWorkbook(matter, list);
|
||||
String lineName = StrUtil.blankToDefault(matter.getString("lineName", ""), "线路");
|
||||
CommonDownloadUtil.download(lineName + "参加人员名单.xls", workbook, response);
|
||||
}
|
||||
|
||||
private Cnd buildSignupQueryCnd(String matterId, String keyword, String unionId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.and("t.matterId", "=", matterId);
|
||||
cnd.and("m.delFlag", "=", false);
|
||||
cnd.and("m.enabled", "=", true);
|
||||
cnd.and("m.lineId", "IS NOT", null);
|
||||
cnd.and("m.lineId", "<>", "");
|
||||
cnd.and("l.delFlag", "=", false);
|
||||
cnd.and("l.enabled", "=", true);
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
SqlExpressionGroup keywordGroup = new SqlExpressionGroup();
|
||||
keywordGroup.orLike("t.userName", keyword.trim());
|
||||
keywordGroup.orLike("t.jobNo", keyword.trim());
|
||||
cnd.and(keywordGroup);
|
||||
}
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
applyMatterDataScope(cnd);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private NutMap fetchExportMatter(String matterId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("m.delFlag", "=", false);
|
||||
cnd.and("m.enabled", "=", true);
|
||||
cnd.and("m.id", "=", matterId);
|
||||
cnd.and("m.lineId", "IS NOT", null);
|
||||
cnd.and("m.lineId", "<>", "");
|
||||
cnd.and("l.delFlag", "=", false);
|
||||
cnd.and("l.enabled", "=", true);
|
||||
applyMatterDataScope(cnd);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
m.id AS matterId,
|
||||
m.`year`,
|
||||
m.unionId,
|
||||
COALESCE(u.name, '校工会') AS unionName,
|
||||
l.lineName,
|
||||
l.lineType,
|
||||
m.travelStartTime,
|
||||
m.travelEndTime,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE ''
|
||||
END AS travelPeriod
|
||||
FROM tour_matter m
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
LEFT JOIN sys_union u ON u.id = m.unionId
|
||||
$condition
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
tourMatterService.dao().execute(sql);
|
||||
return sql.getObject(NutMap.class);
|
||||
}
|
||||
|
||||
private List<NutMap> queryExportParticipants(String matterId) {
|
||||
Cnd cnd = buildSignupQueryCnd(matterId, null, null);
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t.id AS ledgerId,
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
t.idCard,
|
||||
vu.mobile,
|
||||
t.unionName,
|
||||
l.lineName,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE ''
|
||||
END AS travelPeriod,
|
||||
t.signupTime
|
||||
FROM tour_ledger t
|
||||
INNER JOIN tour_matter m ON m.id = t.matterId
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
LEFT JOIN vw_user vu ON vu.loginname = t.jobNo
|
||||
$condition
|
||||
ORDER BY t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
List<NutMap> list = sql.getList(NutMap.class);
|
||||
fillExportFamilies(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private void fillExportFamilies(List<NutMap> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<String> ledgerIds = new ArrayList<>();
|
||||
for (NutMap item : list) {
|
||||
String ledgerId = item.getString("ledgerId", "");
|
||||
if (StrUtil.isNotBlank(ledgerId)) {
|
||||
ledgerIds.add(ledgerId);
|
||||
}
|
||||
}
|
||||
if (ledgerIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
ledgerId,
|
||||
familyName,
|
||||
relationship,
|
||||
idCard
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
AND ledgerId IN (@ledgerIds)
|
||||
ORDER BY createdAt ASC
|
||||
""");
|
||||
sql.setParam("ledgerIds", ledgerIds.toArray(new String[0]));
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
|
||||
Map<String, List<NutMap>> familyMap = new HashMap<>();
|
||||
for (NutMap family : sql.getList(NutMap.class)) {
|
||||
familyMap.computeIfAbsent(family.getString("ledgerId", ""), key -> new ArrayList<>()).add(family);
|
||||
}
|
||||
for (NutMap item : list) {
|
||||
item.put("families", familyMap.getOrDefault(item.getString("ledgerId", ""), List.of()));
|
||||
}
|
||||
}
|
||||
|
||||
private Workbook buildParticipantsWorkbook(NutMap matter, List<NutMap> list) {
|
||||
Workbook workbook = new HSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("参加人员名单");
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 10));
|
||||
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 10));
|
||||
|
||||
double[] widths = {6, 14, 12, 22, 16, 24, 34, 26, 12, 12, 16};
|
||||
for (int i = 0; i < widths.length; i++) {
|
||||
sheet.setColumnWidth(i, (int) (widths[i] * 256));
|
||||
}
|
||||
|
||||
CellStyle titleStyle = createStyle(workbook, "黑体", (short) 16, true, HorizontalAlignment.CENTER, false, false);
|
||||
CellStyle unionStyle = createStyle(workbook, "宋体", (short) 12, true, HorizontalAlignment.LEFT, false, false);
|
||||
CellStyle headerStyle = createStyle(workbook, "宋体", (short) 11, true, HorizontalAlignment.CENTER, true, true);
|
||||
CellStyle bodyStyle = createStyle(workbook, "宋体", (short) 11, false, HorizontalAlignment.CENTER, true, true);
|
||||
|
||||
Row titleRow = sheet.createRow(0);
|
||||
titleRow.setHeightInPoints(30);
|
||||
setCell(titleRow, 0, StrUtil.blankToDefault(matter.getString("lineName", ""), ""), titleStyle);
|
||||
fillMergedCells(titleRow, 1, 10, titleStyle);
|
||||
|
||||
Row unionRow = sheet.createRow(1);
|
||||
unionRow.setHeightInPoints(26);
|
||||
setCell(unionRow, 0, "分工会:" + StrUtil.blankToDefault(matter.getString("unionName", ""), ""), unionStyle);
|
||||
fillMergedCells(unionRow, 1, 10, unionStyle);
|
||||
|
||||
String[] headers = {"序号", "工号", "姓名", "身份证号码", "电话号码", "所属分工会", "所选线路名称", "疗休养时间", "亲属关系", "姓名", "备注"};
|
||||
Row headerRow = sheet.createRow(2);
|
||||
headerRow.setHeightInPoints(35);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
setCell(headerRow, i, headers[i], headerStyle);
|
||||
}
|
||||
|
||||
int rowIndex = 3;
|
||||
int seq = 1;
|
||||
for (NutMap item : list == null ? List.<NutMap>of() : list) {
|
||||
Row staffRow = sheet.createRow(rowIndex++);
|
||||
staffRow.setHeightInPoints(24);
|
||||
setParticipantRow(staffRow, seq++, item.getString("jobNo", ""), item.getString("userName", ""),
|
||||
item.getString("idCard", ""), item.getString("mobile", ""), item.getString("unionName", ""),
|
||||
item.getString("lineName", matter.getString("lineName", "")), item.getString("travelPeriod", matter.getString("travelPeriod", "")),
|
||||
"", item.getString("userName", ""), bodyStyle);
|
||||
|
||||
Object familiesObj = item.get("families");
|
||||
if (familiesObj instanceof List<?> families) {
|
||||
for (Object obj : families) {
|
||||
if (!(obj instanceof NutMap family)) {
|
||||
continue;
|
||||
}
|
||||
Row familyRow = sheet.createRow(rowIndex++);
|
||||
familyRow.setHeightInPoints(24);
|
||||
setParticipantRow(familyRow, seq++, "", family.getString("familyName", ""),
|
||||
family.getString("idCard", ""), "", "",
|
||||
item.getString("lineName", matter.getString("lineName", "")),
|
||||
item.getString("travelPeriod", matter.getString("travelPeriod", "")),
|
||||
family.getString("relationship", ""), item.getString("userName", ""), bodyStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int minRows = Math.max(rowIndex, 23);
|
||||
while (rowIndex < minRows) {
|
||||
Row row = sheet.createRow(rowIndex++);
|
||||
row.setHeightInPoints(24);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
setCell(row, i, "", bodyStyle);
|
||||
}
|
||||
}
|
||||
return workbook;
|
||||
}
|
||||
|
||||
private void setParticipantRow(Row row, int seq, String jobNo, String userName, String idCard, String mobile,
|
||||
String unionName, String lineName, String travelPeriod, String relationship,
|
||||
String participantName, CellStyle style) {
|
||||
setCell(row, 0, String.valueOf(seq), style);
|
||||
setCell(row, 1, jobNo, style);
|
||||
setCell(row, 2, userName, style);
|
||||
setCell(row, 3, idCard, style);
|
||||
setCell(row, 4, mobile, style);
|
||||
setCell(row, 5, unionName, style);
|
||||
setCell(row, 6, lineName, style);
|
||||
setCell(row, 7, travelPeriod, style);
|
||||
setCell(row, 8, relationship, style);
|
||||
setCell(row, 9, participantName, style);
|
||||
setCell(row, 10, "", style);
|
||||
}
|
||||
|
||||
private CellStyle createStyle(Workbook workbook, String fontName, short fontSize, boolean bold, HorizontalAlignment alignment, boolean wrap, boolean border) {
|
||||
Font font = workbook.createFont();
|
||||
font.setFontName(fontName);
|
||||
font.setFontHeightInPoints(fontSize);
|
||||
font.setBold(bold);
|
||||
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
style.setFont(font);
|
||||
style.setAlignment(alignment);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
style.setWrapText(wrap);
|
||||
if (border) {
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
private void setCell(Row row, int col, String value, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue(StrUtil.blankToDefault(value, ""));
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private void fillMergedCells(Row row, int startCol, int endCol, CellStyle style) {
|
||||
for (int i = startCol; i <= endCol; i++) {
|
||||
setCell(row, i, "", style);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillSignupMobile(List<NutMap> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<String> jobNos = new ArrayList<>();
|
||||
for (NutMap item : list) {
|
||||
String jobNo = item.getString("jobNo", "");
|
||||
if (StrUtil.isNotBlank(jobNo) && !jobNos.contains(jobNo)) {
|
||||
jobNos.add(jobNo);
|
||||
}
|
||||
}
|
||||
if (jobNos.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sql sql = Sqls.create("SELECT loginname, mobile FROM vw_user WHERE loginname IN (@jobNos)");
|
||||
sql.setParam("jobNos", jobNos.toArray(new String[0]));
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
|
||||
Map<String, String> mobileMap = new HashMap<>();
|
||||
for (NutMap user : sql.getList(NutMap.class)) {
|
||||
mobileMap.put(user.getString("loginname", ""), user.getString("mobile", ""));
|
||||
}
|
||||
for (NutMap item : list) {
|
||||
item.put("mobile", mobileMap.getOrDefault(item.getString("jobNo", ""), ""));
|
||||
}
|
||||
}
|
||||
|
||||
private Cnd buildQueryCnd(Integer year, String lineName, String lineType, String unionId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("m.delFlag", "=", false);
|
||||
cnd.and("m.enabled", "=", true);
|
||||
cnd.and("m.lineId", "IS NOT", null);
|
||||
cnd.and("m.lineId", "<>", "");
|
||||
cnd.and("l.delFlag", "=", false);
|
||||
cnd.and("l.enabled", "=", true);
|
||||
cnd.andEX("m.`year`", "=", year == null ? LocalDate.now().getYear() : year);
|
||||
cnd.and(Cnd.likeEX("l.lineName", lineName));
|
||||
cnd.andEX("l.lineType", "=", lineType);
|
||||
cnd.andEX("m.unionId", "=", unionId);
|
||||
applyMatterDataScope(cnd);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 线路成团按事项归属控制数据范围:校工会查看全部;分工会查看本工会事项;其它角色仅查看自己创建的事项。
|
||||
*/
|
||||
private void applyMatterDataScope(Cnd cnd) {
|
||||
if (hasSchoolUnionScope()) {
|
||||
return;
|
||||
}
|
||||
if (hasBranchUnionScope()) {
|
||||
cnd.and("m.unionId", "=", SecurityUtil.getUnionId());
|
||||
return;
|
||||
}
|
||||
SqlExpressionGroup creatorGroup = new SqlExpressionGroup();
|
||||
creatorGroup.or("m.creatorUserId", "=", SecurityUtil.getUserId());
|
||||
creatorGroup.or("m.createdBy", "=", SecurityUtil.getUserId());
|
||||
cnd.and(creatorGroup);
|
||||
}
|
||||
|
||||
private boolean hasSchoolUnionScope() {
|
||||
return AuthUtil.hasRole(RoleConstant.SYSADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_CHAIRMAN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_VICE_CHAIRMAN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_WELFARE_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_MEMBER_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_TC_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_WC_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_DC_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_PROPOSAL_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_CLUB_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.SCHOOL_UNION_ACTIVITY_ADMIN.name());
|
||||
}
|
||||
|
||||
private boolean hasBranchUnionScope() {
|
||||
return AuthUtil.hasRole(RoleConstant.BRANCH_UNION_ADMIN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_VICE_CHAIRMAN.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_OPERATOR.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_GROUP_LEADER.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_ARTICLE_WRITER.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_ZUZHI_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_XUANCHUAN_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_NVGONG_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_QINGNIAN_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_WENTI_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_SHENGGHUO_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_TIAOJIE_WY.name())
|
||||
|| AuthUtil.hasRole(RoleConstant.BRANCH_UNION_WENTI_SPORTS.name());
|
||||
}
|
||||
|
||||
private String getOrderColumn(String orderName) {
|
||||
if ("lineName".equals(orderName)) {
|
||||
return "l.lineName";
|
||||
}
|
||||
if ("travelPeriod".equals(orderName)) {
|
||||
return "m.travelStartTime";
|
||||
}
|
||||
if ("matterName".equals(orderName)) {
|
||||
return "m.matterName";
|
||||
}
|
||||
if ("unionName".equals(orderName)) {
|
||||
return "u.name";
|
||||
}
|
||||
if ("lineType".equals(orderName)) {
|
||||
return "l.lineType";
|
||||
}
|
||||
if ("signupCount".equals(orderName)) {
|
||||
return "signupCount";
|
||||
}
|
||||
if ("minGroupPeople".equals(orderName)) {
|
||||
return "m.minGroupPeople";
|
||||
}
|
||||
if ("maxGroupPeople".equals(orderName)) {
|
||||
return "m.maxGroupPeople";
|
||||
}
|
||||
if ("groupStatusName".equals(orderName)) {
|
||||
return "groupStatus";
|
||||
}
|
||||
return "l.lineName";
|
||||
}
|
||||
|
||||
private String getSignupOrderColumn(String orderName) {
|
||||
if ("jobNo".equals(orderName)) {
|
||||
return "t.jobNo";
|
||||
}
|
||||
if ("userName".equals(orderName)) {
|
||||
return "t.userName";
|
||||
}
|
||||
if ("idCard".equals(orderName)) {
|
||||
return "t.idCard";
|
||||
}
|
||||
if ("unionName".equals(orderName)) {
|
||||
return "t.unionName";
|
||||
}
|
||||
return "t.signupTime";
|
||||
}
|
||||
}
|
||||
+959
@@ -0,0 +1,959 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.model.ExcelImportRes;
|
||||
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.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||
import com.budwk.app.sys.models.Sys_union;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.mode.TourLedgerImportExcelMode;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLine;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourTravelAgency;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.AdaptBy;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
import org.nutz.mvc.upload.TempFile;
|
||||
import org.nutz.mvc.upload.UploadAdaptor;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/ledger")
|
||||
public class TourLedgerController {
|
||||
|
||||
@Inject
|
||||
private TourLedgerService tourLedgerService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerFamilyService tourLedgerFamilyService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerDirectRelativeService tourLedgerDirectRelativeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/ledger/index.html")
|
||||
@SaCheckPermission("tour.ledger")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.ledger")
|
||||
public Result pageData(PageForm pageForm, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType, Boolean directFamilyOnly, Boolean overCostOnly) {
|
||||
Cnd cnd = buildQueryCnd(startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType, directFamilyOnly, overCostOnly);
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(DISTINCT t.id)
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN tour_ledger_direct_relative dr ON dr.ledgerId = t.id AND dr.delFlag = 0
|
||||
$condition
|
||||
""");
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
t.*,
|
||||
ins.id AS instanceId,
|
||||
ins.state AS instanceState,
|
||||
ins.processDefineId AS instanceProcessDefineId,
|
||||
IF(IFNULL(l.directFamilyUnitLine, 0) = 1 OR dr.id IS NOT NULL, 1, 0) AS directFamilyUnitLine,
|
||||
dr.id AS directRelativeId,
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName) AS currentLineName,
|
||||
IFNULL(f.familyCount, 0) AS familyCount,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE tp.travelPeriod
|
||||
END AS travelPeriod
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN (
|
||||
SELECT ledgerId, COUNT(1) AS familyCount
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
GROUP BY ledgerId
|
||||
) f ON f.ledgerId = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN tour_ledger_direct_relative dr ON dr.ledgerId = t.id AND dr.delFlag = 0
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
lineId,
|
||||
GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND lineId IS NOT NULL
|
||||
AND lineId <> ''
|
||||
GROUP BY `year`, lineId
|
||||
) tp ON (t.matterId IS NULL OR t.matterId = '') AND tp.`year` = t.`year` AND tp.lineId = t.lineId
|
||||
$condition
|
||||
GROUP BY t.id
|
||||
ORDER BY $orderColumn $orderBy, t.`year` DESC, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
|
||||
listSql.setPager(tourLedgerService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
var list = listSql.getList(NutMap.class);
|
||||
list.forEach(item -> item.put("lineName", item.getString("currentLineName")));
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.ledger")
|
||||
public Result detail(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourLedger ledger = tourLedgerService.fetch(id);
|
||||
if (ledger == null) {
|
||||
return Result.error("台账记录不存在");
|
||||
}
|
||||
ledger.setLineName(getCurrentLineName(ledger));
|
||||
Cnd familyCnd = Cnd.NEW();
|
||||
familyCnd.and(TourLedgerFamily::getLedgerId, "=", id);
|
||||
familyCnd.and(TourLedgerFamily::getDelFlag, "=", false);
|
||||
familyCnd.asc(TourLedgerFamily::getCreatedAt);
|
||||
TourLedgerDirectRelative directRelative = tourLedgerDirectRelativeService.fetch(
|
||||
Cnd.where(TourLedgerDirectRelative::getDelFlag, "=", false)
|
||||
.and(TourLedgerDirectRelative::getLedgerId, "=", ledger.getId()));
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("ledger", ledger)
|
||||
.addv("travelPeriod", getTravelPeriod(ledger))
|
||||
.addv("families", tourLedgerFamilyService.query(familyCnd))
|
||||
.addv("directRelative", directRelative)
|
||||
.addv("fillBedInfo", isFillBedInfo(ledger))
|
||||
.addv("directFamilyUnitLine", isDirectFamilyUnitLine(ledger)));
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.ledger")
|
||||
@SLog(type = "tour", tag = "疗休养台账", msg = "删除疗休养台账")
|
||||
public Result doDelete(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourLedger ledger = tourLedgerService.fetch(id);
|
||||
if (ledger == null) {
|
||||
return Result.error("台账记录不存在");
|
||||
}
|
||||
tourLedgerFamilyService.clear(Cnd.where(TourLedgerFamily::getLedgerId, "=", id));
|
||||
tourLedgerService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.ledger")
|
||||
@SLog(type = "tour", tag = "疗休养台账", msg = "设置参加人员")
|
||||
public Result setParticipants(@Param("ids") String ids) {
|
||||
List<String> idList = StrUtil.isBlank(ids) ? Collections.emptyList() : Json.fromJsonAsList(String.class, ids);
|
||||
if (idList.isEmpty()) {
|
||||
return Result.error("请选择要设置的参加人员");
|
||||
}
|
||||
tourLedgerService.dao().update(TourLedger.class, Chain.make("joined", true), Cnd.where("id", "in", idList));
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.ledger")
|
||||
@SLog(type = "tour", tag = "疗休养台账", msg = "参加人员导入")
|
||||
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
|
||||
public Result importParticipants(@Param("file") TempFile file) {
|
||||
if (file == null) {
|
||||
return Result.error("请选择导入文件");
|
||||
}
|
||||
List<TourLedgerImportExcelMode> importRows = ExcelImportUtil.importExcel(file.getFile(), TourLedgerImportExcelMode.class, new ImportParams());
|
||||
ExcelImportRes<TourLedgerImportExcelMode> excelImportRes = new ExcelImportRes<>();
|
||||
excelImportRes.setTotalRecords(importRows.size());
|
||||
|
||||
for (int i = 0; i < importRows.size(); i++) {
|
||||
TourLedgerImportExcelMode row = importRows.get(i);
|
||||
if (!validateImportRow(row, i)) {
|
||||
continue;
|
||||
}
|
||||
Boolean joined = parseJoined(row.getJoined());
|
||||
if (joined == null) {
|
||||
row.setErrInfo("是否参加只能填写1、0、是、否、true、false、已参加、未参加", i);
|
||||
continue;
|
||||
}
|
||||
TourLine line = fetchImportLine(row);
|
||||
if (line == null) {
|
||||
row.setErrInfo("未找到唯一匹配的线路", i);
|
||||
continue;
|
||||
}
|
||||
List<TourLedger> ledgers = queryImportLedgerCandidates(row);
|
||||
if (ledgers.isEmpty()) {
|
||||
Result createResult = insertImportLedger(row, line, joined);
|
||||
if (createResult.isSuccess()) {
|
||||
continue;
|
||||
}
|
||||
row.setErrInfo(createResult.getMsg(), i);
|
||||
continue;
|
||||
}
|
||||
TourLedger ledger = resolveImportLedger(row, ledgers, line);
|
||||
if (ledger == null) {
|
||||
row.setErrInfo("匹配到多条台账记录,报名时间或线路未能唯一匹配,请核对年度、工号、报名时间、线路名称", i);
|
||||
continue;
|
||||
}
|
||||
Chain chain = Chain.make("joined", joined)
|
||||
.add("lineId", line.getId())
|
||||
.add("lineName", line.getLineName())
|
||||
.add("lineType", line.getLineType());
|
||||
String signupTime = normalizeSignupTime(row.getSignupTime());
|
||||
if (StrUtil.isNotBlank(signupTime)) {
|
||||
chain.add("signupTime", signupTime);
|
||||
}
|
||||
tourLedgerService.dao().update(TourLedger.class, chain, Cnd.where("id", "=", ledger.getId()));
|
||||
}
|
||||
|
||||
excelImportRes.setErrorDetails(importRows.stream().filter(s -> StrUtil.isNotBlank(s.getErrMsg())).collect(Collectors.toList()));
|
||||
excelImportRes.setFailedCount(excelImportRes.getErrorDetails().size());
|
||||
excelImportRes.setSuccessCount(Math.max(importRows.size() - excelImportRes.getFailedCount(), 0));
|
||||
return Result.success(excelImportRes);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.ledger")
|
||||
@Ok("void")
|
||||
public void downloadTemplate(HttpServletResponse response) {
|
||||
List<ExcelExportEntity> entities = new ArrayList<>();
|
||||
entities.add(new ExcelExportEntity("年度", "year", 12));
|
||||
entities.add(new ExcelExportEntity("工号", "jobNo", 18));
|
||||
entities.add(new ExcelExportEntity("姓名", "userName", 18));
|
||||
entities.add(new ExcelExportEntity("报名时间", "signupTime", 24));
|
||||
entities.add(new ExcelExportEntity("线路名称", "lineName", 30));
|
||||
entities.add(new ExcelExportEntity("线路类型", "lineType", 18));
|
||||
entities.add(new ExcelExportEntity("是否参加", "joined", 14));
|
||||
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setSheetName("tour_ledger");
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, Collections.emptyList());
|
||||
CommonDownloadUtil.download("参加人员导入模板.xlsx", workbook, response);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.ledger")
|
||||
@Ok("void")
|
||||
public void exportUnionSignupZip(Integer startYear, Integer endYear, String keyword, String unionId, String lineId,
|
||||
String travelPeriod, String lineType, Boolean directFamilyOnly, Boolean overCostOnly,
|
||||
HttpServletResponse response) throws Exception {
|
||||
List<NutMap> rows = queryUnionSignupRows(startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType,
|
||||
directFamilyOnly, overCostOnly);
|
||||
Map<String, List<NutMap>> unionRows = groupRowsByUnion(rows);
|
||||
|
||||
String zipName = URLEncoder.encode("疗休养分工会报名汇总表.zip", StandardCharsets.UTF_8.toString());
|
||||
response.setContentType("application/zip");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + zipName + ";filename*=UTF-8''" + zipName);
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))) {
|
||||
if (unionRows.isEmpty()) {
|
||||
zipOutputStream.putNextEntry(new ZipEntry("无数据报名汇总表.xls"));
|
||||
try (Workbook workbook = buildUnionSignupWorkbook("无数据", Collections.emptyList())) {
|
||||
workbook.write(zipOutputStream);
|
||||
}
|
||||
zipOutputStream.closeEntry();
|
||||
} else {
|
||||
for (Map.Entry<String, List<NutMap>> entry : unionRows.entrySet()) {
|
||||
String unionName = entry.getValue().isEmpty() ? entry.getKey() : entry.getValue().get(0).getString("unionName", entry.getKey());
|
||||
String fileName = safeFileName(unionName + "报名汇总表.xls");
|
||||
zipOutputStream.putNextEntry(new ZipEntry(fileName));
|
||||
try (Workbook workbook = buildUnionSignupWorkbook(unionName, entry.getValue())) {
|
||||
workbook.write(zipOutputStream);
|
||||
}
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
}
|
||||
zipOutputStream.flush();
|
||||
}
|
||||
}
|
||||
|
||||
private List<NutMap> queryUnionSignupRows(Integer startYear, Integer endYear, String keyword, String unionId, String lineId,
|
||||
String travelPeriod, String lineType, Boolean directFamilyOnly, Boolean overCostOnly) {
|
||||
Cnd cnd = buildQueryCnd(startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType, directFamilyOnly, overCostOnly);
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t.id,
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
t.idCard,
|
||||
t.unionId,
|
||||
COALESCE(NULLIF(t.unionName, ''), su.name, vu.unionName, '') AS unionName,
|
||||
COALESCE(NULLIF(su.unionCode, ''), vu.unionCode, '') AS unionCode,
|
||||
COALESCE(NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName, '') AS lineName,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE tp.travelPeriod
|
||||
END AS travelPeriod
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN tour_ledger_direct_relative dr ON dr.ledgerId = t.id AND dr.delFlag = 0
|
||||
LEFT JOIN vw_user vu ON vu.loginname = t.jobNo
|
||||
LEFT JOIN sys_union su ON su.id = t.unionId
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
lineId,
|
||||
GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND lineId IS NOT NULL
|
||||
AND lineId <> ''
|
||||
GROUP BY `year`, lineId
|
||||
) tp ON (t.matterId IS NULL OR t.matterId = '') AND tp.`year` = t.`year` AND tp.lineId = t.lineId
|
||||
$condition
|
||||
GROUP BY t.id
|
||||
ORDER BY unionCode ASC, unionName ASC, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getList(NutMap.class);
|
||||
}
|
||||
|
||||
private Map<String, List<NutMap>> groupRowsByUnion(List<NutMap> rows) {
|
||||
Map<String, List<NutMap>> unionRows = new LinkedHashMap<>();
|
||||
for (NutMap row : rows) {
|
||||
String unionName = StrUtil.blankToDefault(row.getString("unionName"), "未分工会");
|
||||
String unionCode = StrUtil.blankToDefault(row.getString("unionCode"), "");
|
||||
String key = StrUtil.isBlank(unionCode) ? unionName : unionCode + "_" + unionName;
|
||||
unionRows.computeIfAbsent(key, item -> new ArrayList<>()).add(row);
|
||||
}
|
||||
return unionRows;
|
||||
}
|
||||
|
||||
private Workbook buildUnionSignupWorkbook(String unionName, List<NutMap> rows) {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("报名汇总表");
|
||||
sheet.setColumnWidth(0, 8 * 256);
|
||||
sheet.setColumnWidth(1, 14 * 256);
|
||||
sheet.setColumnWidth(2, 14 * 256);
|
||||
sheet.setColumnWidth(3, 24 * 256);
|
||||
sheet.setColumnWidth(4, 16 * 256);
|
||||
sheet.setColumnWidth(5, 24 * 256);
|
||||
sheet.setColumnWidth(6, 36 * 256);
|
||||
sheet.setColumnWidth(7, 26 * 256);
|
||||
sheet.setColumnWidth(8, 18 * 256);
|
||||
|
||||
CellStyle titleStyle = createUnionSignupTitleStyle(workbook);
|
||||
CellStyle headerStyle = createUnionSignupHeaderStyle(workbook);
|
||||
CellStyle bodyStyle = createUnionSignupBodyStyle(workbook);
|
||||
|
||||
Row titleRow = sheet.createRow(0);
|
||||
titleRow.setHeightInPoints(28);
|
||||
Cell titleCell = titleRow.createCell(0);
|
||||
titleCell.setCellValue(StrUtil.blankToDefault(unionName, "未分工会") + "报名汇总表");
|
||||
titleCell.setCellStyle(titleStyle);
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 8));
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
titleRow.createCell(i).setCellStyle(titleStyle);
|
||||
}
|
||||
|
||||
Row headerRow = sheet.createRow(1);
|
||||
headerRow.setHeightInPoints(24);
|
||||
String[] headers = {"序号", "工号", "姓名", "身份证号码", "电话号码", "所属分工会", "所选线路名称", "疗休养时间", "备注"};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
setCell(headerRow, i, headers[i], headerStyle);
|
||||
}
|
||||
|
||||
int rowIndex = 2;
|
||||
int seq = 1;
|
||||
for (NutMap row : rows) {
|
||||
Row dataRow = sheet.createRow(rowIndex++);
|
||||
dataRow.setHeightInPoints(22);
|
||||
setCell(dataRow, 0, String.valueOf(seq++), bodyStyle);
|
||||
setCell(dataRow, 1, row.getString("jobNo", ""), bodyStyle);
|
||||
setCell(dataRow, 2, row.getString("userName", ""), bodyStyle);
|
||||
setCell(dataRow, 3, row.getString("idCard", ""), bodyStyle);
|
||||
setCell(dataRow, 4, row.getString("mobile", ""), bodyStyle);
|
||||
setCell(dataRow, 5, row.getString("unionName", ""), bodyStyle);
|
||||
setCell(dataRow, 6, row.getString("lineName", ""), bodyStyle);
|
||||
setCell(dataRow, 7, row.getString("travelPeriod", ""), bodyStyle);
|
||||
setCell(dataRow, 8, "", bodyStyle);
|
||||
}
|
||||
return workbook;
|
||||
}
|
||||
|
||||
private CellStyle createUnionSignupTitleStyle(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(true);
|
||||
font.setFontHeightInPoints((short) 16);
|
||||
style.setFont(font);
|
||||
return style;
|
||||
}
|
||||
|
||||
private CellStyle createUnionSignupHeaderStyle(Workbook workbook) {
|
||||
CellStyle style = createUnionSignupBodyStyle(workbook);
|
||||
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
||||
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(true);
|
||||
style.setFont(font);
|
||||
return style;
|
||||
}
|
||||
|
||||
private CellStyle createUnionSignupBodyStyle(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
style.setWrapText(true);
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
return style;
|
||||
}
|
||||
|
||||
private void setCell(Row row, int index, String value, CellStyle style) {
|
||||
Cell cell = row.createCell(index);
|
||||
cell.setCellValue(StrUtil.blankToDefault(value, ""));
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private String safeFileName(String fileName) {
|
||||
String safeName = StrUtil.blankToDefault(fileName, "报名汇总表.xls")
|
||||
.replaceAll("[\\\\/:*?\"<>|]", "、");
|
||||
return safeName.length() > 120 ? safeName.substring(0, 120) : safeName;
|
||||
}
|
||||
|
||||
private boolean validateImportRow(TourLedgerImportExcelMode row, int index) {
|
||||
if (row.getYear() == null) {
|
||||
row.setErrInfo("年度为空", index);
|
||||
return false;
|
||||
}
|
||||
if (StrUtil.isBlank(row.getJobNo())) {
|
||||
row.setErrInfo("工号为空", index);
|
||||
return false;
|
||||
}
|
||||
if (StrUtil.isBlank(row.getLineName())) {
|
||||
row.setErrInfo("线路名称为空", index);
|
||||
return false;
|
||||
}
|
||||
if (StrUtil.isBlank(row.getLineType())) {
|
||||
row.setErrInfo("线路类型为空", index);
|
||||
return false;
|
||||
}
|
||||
if (StrUtil.isBlank(row.getJoined())) {
|
||||
row.setErrInfo("是否参加为空", index);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private TourLine fetchImportLine(TourLedgerImportExcelMode row) {
|
||||
Cnd cnd = Cnd.where(TourLine::getDelFlag, "=", false)
|
||||
.and(TourLine::getYear, "=", row.getYear())
|
||||
.and(TourLine::getLineName, "=", row.getLineName().trim())
|
||||
.and(TourLine::getLineType, "=", row.getLineType().trim());
|
||||
List<TourLine> lines = tourLedgerService.dao().query(TourLine.class, cnd);
|
||||
return lines.size() == 1 ? lines.get(0) : null;
|
||||
}
|
||||
|
||||
private List<TourLedger> queryImportLedgerCandidates(TourLedgerImportExcelMode row) {
|
||||
Cnd cnd = Cnd.where(TourLedger::getDelFlag, "=", false)
|
||||
.and(TourLedger::getYear, "=", row.getYear())
|
||||
.and(TourLedger::getJobNo, "=", row.getJobNo().trim());
|
||||
return tourLedgerService.query(cnd);
|
||||
}
|
||||
|
||||
private TourLedger resolveImportLedger(TourLedgerImportExcelMode row, List<TourLedger> ledgers, TourLine line) {
|
||||
if (ledgers.size() == 1) {
|
||||
return ledgers.get(0);
|
||||
}
|
||||
List<TourLedger> matched = ledgers;
|
||||
if (row.getSignupTime() != null) {
|
||||
String importSignupTime = normalizeSignupTime(row.getSignupTime());
|
||||
matched = matched.stream()
|
||||
.filter(item -> signupTimeEquals(importSignupTime, item.getSignupTime()))
|
||||
.collect(Collectors.toList());
|
||||
if (matched.size() == 1) {
|
||||
return matched.get(0);
|
||||
}
|
||||
}
|
||||
matched = ledgers.stream()
|
||||
.filter(item -> ledgerLineEquals(item, line))
|
||||
.collect(Collectors.toList());
|
||||
return matched.size() == 1 ? matched.get(0) : null;
|
||||
}
|
||||
|
||||
private boolean ledgerLineEquals(TourLedger ledger, TourLine line) {
|
||||
if (ledger == null || line == null) {
|
||||
return false;
|
||||
}
|
||||
if (StrUtil.isNotBlank(ledger.getLineId()) && ledger.getLineId().equals(line.getId())) {
|
||||
return true;
|
||||
}
|
||||
return StrUtil.equals(ledger.getLineName(), line.getLineName())
|
||||
&& StrUtil.equals(ledger.getLineType(), line.getLineType());
|
||||
}
|
||||
|
||||
private Result insertImportLedger(TourLedgerImportExcelMode row, TourLine line, Boolean joined) {
|
||||
View_user user = fetchImportUser(row.getJobNo());
|
||||
if (user == null) {
|
||||
return Result.error("系统用户中未找到该工号");
|
||||
}
|
||||
TourLedger ledger = new TourLedger();
|
||||
ledger.setYear(row.getYear());
|
||||
ledger.setJobNo(StrUtil.blankToDefault(user.getLoginname(), row.getJobNo().trim()));
|
||||
ledger.setUserName(StrUtil.blankToDefault(user.getUsername(), row.getUserName()));
|
||||
ledger.setGender(user.getSex());
|
||||
ledger.setIdCard(user.getIdCard());
|
||||
ledger.setUnitId(user.getUnitId());
|
||||
ledger.setUnitName(user.getUnitName());
|
||||
ledger.setUnionId(user.getUnionId());
|
||||
ledger.setUnionName(user.getUnionName());
|
||||
ledger.setSignupTime(normalizeSignupTime(row.getSignupTime()));
|
||||
ledger.setLineId(line.getId());
|
||||
ledger.setLineName(line.getLineName());
|
||||
ledger.setLineType(line.getLineType());
|
||||
ledger.setTravelAgencyId(line.getTravelAgencyId());
|
||||
ledger.setTravelAgencyName(getTravelAgencyName(line.getTravelAgencyId()));
|
||||
ledger.setHasFamily(false);
|
||||
ledger.setJoined(joined);
|
||||
ledger.setReimbursed(false);
|
||||
ledger.setOverCostReimbursed(false);
|
||||
tourLedgerService.insert(ledger);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private View_user fetchImportUser(String jobNo) {
|
||||
if (StrUtil.isBlank(jobNo)) {
|
||||
return null;
|
||||
}
|
||||
return tourLedgerService.dao().fetch(View_user.class, Cnd.where(View_user::getLoginname, "=", jobNo.trim()));
|
||||
}
|
||||
|
||||
private String getTravelAgencyName(String travelAgencyId) {
|
||||
if (StrUtil.isBlank(travelAgencyId)) {
|
||||
return "";
|
||||
}
|
||||
TourTravelAgency agency = tourLedgerService.dao().fetch(TourTravelAgency.class, travelAgencyId);
|
||||
return agency == null ? "" : StrUtil.blankToDefault(agency.getAgencyName(), "");
|
||||
}
|
||||
|
||||
private boolean signupTimeEquals(String importSignupTime, String ledgerSignupTime) {
|
||||
if (StrUtil.isBlank(importSignupTime) || StrUtil.isBlank(ledgerSignupTime)) {
|
||||
return false;
|
||||
}
|
||||
String ledgerTime = normalizeSignupTime(ledgerSignupTime);
|
||||
if (importSignupTime.equals(ledgerTime)) {
|
||||
return true;
|
||||
}
|
||||
return importSignupTime.length() == 16 && ledgerTime.startsWith(importSignupTime)
|
||||
|| ledgerTime.length() == 16 && importSignupTime.startsWith(ledgerTime);
|
||||
}
|
||||
|
||||
private String normalizeSignupTime(Object value) {
|
||||
if (value instanceof Date date) {
|
||||
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
|
||||
}
|
||||
String text = StrUtil.trimToEmpty(value == null ? "" : String.valueOf(value)).replace('T', ' ');
|
||||
if (StrUtil.isBlank(text)) {
|
||||
return "";
|
||||
}
|
||||
text = text.replaceAll("\\.0$", "");
|
||||
String[] dateTimePatterns = {
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
"yyyy-MM-dd HH:mm",
|
||||
"yyyy/M/d H:mm:ss",
|
||||
"yyyy/M/d H:mm",
|
||||
"M/d/yy H:mm:ss",
|
||||
"M/d/yy H:mm",
|
||||
"M/d/yyyy H:mm:ss",
|
||||
"M/d/yyyy H:mm"
|
||||
};
|
||||
for (String pattern : dateTimePatterns) {
|
||||
try {
|
||||
LocalDateTime dateTime = LocalDateTime.parse(text, DateTimeFormatter.ofPattern(pattern));
|
||||
return dateTime.format(DateTimeFormatter.ofPattern(pattern.contains(":ss") ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd HH:mm"));
|
||||
} catch (DateTimeParseException ignored) {
|
||||
}
|
||||
}
|
||||
String[] datePatterns = {"yyyy-MM-dd", "yyyy/M/d", "M/d/yy", "M/d/yyyy"};
|
||||
for (String pattern : datePatterns) {
|
||||
try {
|
||||
LocalDate date = LocalDate.parse(text, DateTimeFormatter.ofPattern(pattern));
|
||||
return date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
} catch (DateTimeParseException ignored) {
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private Boolean parseJoined(String value) {
|
||||
String joined = StrUtil.trimToEmpty(value).toLowerCase();
|
||||
if ("1".equals(joined) || "1.0".equals(joined) || "是".equals(joined) || "true".equals(joined) || "已参加".equals(joined)) {
|
||||
return true;
|
||||
}
|
||||
if ("0".equals(joined) || "0.0".equals(joined) || "否".equals(joined) || "false".equals(joined) || "未参加".equals(joined)) {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.ledger")
|
||||
public Result unionOptions() {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.asc("unionCode");
|
||||
cnd.asc("name");
|
||||
return Result.success(tourLedgerService.dao().query(Sys_union.class, cnd));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.ledger")
|
||||
public Result lineOptions(Integer startYear, Integer endYear, String travelPeriod, String lineType, String unionId, String keyword, Boolean directFamilyOnly, Boolean overCostOnly) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.and("t.lineName", "IS NOT", null);
|
||||
cnd.and("t.lineName", "<>", "");
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
appendScopeFilter(cnd, directFamilyOnly, overCostOnly);
|
||||
appendApprovedWorkflowFilter(cnd);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN IFNULL(t.lineId, '') <> '' THEN t.lineId
|
||||
ELSE CONCAT('legacy:', t.lineName)
|
||||
END AS lineId,
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName) AS lineName
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN tour_ledger_direct_relative dr ON dr.ledgerId = t.id AND dr.delFlag = 0
|
||||
$condition
|
||||
ORDER BY lineName ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.ledger")
|
||||
public Result travelPeriodOptions(Integer startYear, Integer endYear, String lineId, String lineType, String unionId, String keyword, Boolean directFamilyOnly, Boolean overCostOnly) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.and("m.travelStartTime", "IS NOT", null);
|
||||
cnd.and("m.travelStartTime", "<>", "");
|
||||
cnd.and("m.travelEndTime", "IS NOT", null);
|
||||
cnd.and("m.travelEndTime", "<>", "");
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
appendScopeFilter(cnd, directFamilyOnly, overCostOnly);
|
||||
appendApprovedWorkflowFilter(cnd);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime) AS travelPeriod
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN tour_ledger_direct_relative dr ON dr.ledgerId = t.id AND dr.delFlag = 0
|
||||
$condition
|
||||
ORDER BY travelPeriod ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
private Cnd buildQueryCnd(Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType, Boolean directFamilyOnly, Boolean overCostOnly) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
appendScopeFilter(cnd, directFamilyOnly, overCostOnly);
|
||||
appendApprovedWorkflowFilter(cnd);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private void appendApprovedWorkflowFilter(Cnd cnd) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.or("ins.id", "IS", null);
|
||||
group.or("ins.state", "=", ProcessInstanceStateEnum.FINISHED.getCode());
|
||||
cnd.and(group);
|
||||
}
|
||||
|
||||
private void appendScopeFilter(Cnd cnd, Boolean directFamilyOnly, Boolean overCostOnly) {
|
||||
if (Boolean.TRUE.equals(directFamilyOnly)) {
|
||||
cnd.and("IF(IFNULL(l.directFamilyUnitLine, 0) = 1 OR dr.id IS NOT NULL, 1, 0)", "=", 1);
|
||||
}
|
||||
if (Boolean.TRUE.equals(overCostOnly)) {
|
||||
cnd.and("t.overCostReimbursed", "=", true);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendKeywordFilter(Cnd cnd, String keyword) {
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.orLike("t.userName", keyword.trim());
|
||||
group.orLike("t.jobNo", keyword.trim());
|
||||
cnd.and(group);
|
||||
}
|
||||
}
|
||||
|
||||
private String getOrderColumn(String orderName) {
|
||||
if ("year".equals(orderName)) {
|
||||
return "t.`year`";
|
||||
}
|
||||
if ("jobNo".equals(orderName)) {
|
||||
return "t.jobNo";
|
||||
}
|
||||
if ("userName".equals(orderName)) {
|
||||
return "t.userName";
|
||||
}
|
||||
if ("lineName".equals(orderName)) {
|
||||
return "COALESCE(NULLIF(l.lineName, ''), t.lineName)";
|
||||
}
|
||||
if ("travelPeriod".equals(orderName)) {
|
||||
return "COALESCE(m.travelStartTime, tp.travelPeriod)";
|
||||
}
|
||||
if ("lineType".equals(orderName)) {
|
||||
return "t.lineType";
|
||||
}
|
||||
if ("signupTime".equals(orderName)) {
|
||||
return "t.signupTime";
|
||||
}
|
||||
if ("familyCount".equals(orderName)) {
|
||||
return "familyCount";
|
||||
}
|
||||
if ("joined".equals(orderName)) {
|
||||
return "t.joined";
|
||||
}
|
||||
return "t.`year`";
|
||||
}
|
||||
|
||||
private String getTravelPeriod(TourLedger ledger) {
|
||||
if (ledger == null || ledger.getYear() == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return "";
|
||||
}
|
||||
if (StrUtil.isNotBlank(ledger.getMatterId())) {
|
||||
Sql exactSql = Sqls.create("""
|
||||
SELECT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE ''
|
||||
END AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND id = @matterId
|
||||
""");
|
||||
exactSql.setParam("matterId", ledger.getMatterId());
|
||||
exactSql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(exactSql);
|
||||
return exactSql.getString();
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND `year` = @year
|
||||
AND lineId = @lineId
|
||||
""");
|
||||
sql.setParam("year", ledger.getYear());
|
||||
sql.setParam("lineId", ledger.getLineId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getString();
|
||||
}
|
||||
|
||||
private boolean isDirectFamilyUnitLine(TourLedger ledger) {
|
||||
if (ledger == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return false;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT IFNULL(directFamilyUnitLine, 0)
|
||||
FROM tour_line
|
||||
WHERE delFlag = 0
|
||||
AND id = @lineId
|
||||
""");
|
||||
sql.setParam("lineId", ledger.getLineId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0;
|
||||
}
|
||||
|
||||
private boolean isFillBedInfo(TourLedger ledger) {
|
||||
if (ledger == null || StrUtil.isBlank(ledger.getMatterId())) {
|
||||
return true;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT IFNULL(MAX(s.fillBedInfo), 1)
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_setting s ON s.id = m.settingId AND s.delFlag = 0
|
||||
WHERE t.id = @ledgerId
|
||||
""");
|
||||
sql.setParam("ledgerId", ledger.getId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0;
|
||||
}
|
||||
|
||||
private void appendTravelPeriodFilter(Cnd cnd, String travelPeriod) {
|
||||
if (StrUtil.isBlank(travelPeriod)) {
|
||||
return;
|
||||
}
|
||||
cnd.and("CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)", "=", travelPeriod);
|
||||
}
|
||||
|
||||
private void appendLineFilter(Cnd cnd, String lineId) {
|
||||
if (StrUtil.isBlank(lineId)) {
|
||||
return;
|
||||
}
|
||||
if (lineId.startsWith("legacy:")) {
|
||||
SqlExpressionGroup legacyGroup = new SqlExpressionGroup();
|
||||
legacyGroup.or("t.lineId", "IS", null);
|
||||
legacyGroup.or("t.lineId", "=", "");
|
||||
cnd.and(legacyGroup);
|
||||
cnd.and("t.lineName", "=", lineId.substring("legacy:".length()));
|
||||
return;
|
||||
}
|
||||
cnd.and("t.lineId", "=", lineId);
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
if (ledger == null) {
|
||||
return "";
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getLineId())) {
|
||||
return ledger.getLineName();
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT lineName
|
||||
FROM tour_line
|
||||
WHERE delFlag = 0
|
||||
AND id = @lineId
|
||||
""");
|
||||
sql.setParam("lineId", ledger.getLineId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return StrUtil.blankToDefault(sql.getString(), ledger.getLineName());
|
||||
}
|
||||
}
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.sys.models.Sys_dict;
|
||||
import com.budwk.app.sys.services.SysDictService;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLine;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourTravelAgency;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLineService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/route")
|
||||
public class TourLineController {
|
||||
|
||||
@Inject
|
||||
private TourLineService tourLineService;
|
||||
|
||||
@Inject
|
||||
private SysDictService sysDictService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/route/index.html")
|
||||
@SaCheckPermission("tour.route")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.route")
|
||||
public Result pageData(PageForm pageForm, Integer year, String lineName, String lotId) {
|
||||
if (StrUtil.isBlank(pageForm.getPageOrderName())) {
|
||||
pageForm.defaultSortDesc("enabled");
|
||||
}
|
||||
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("l.delFlag", "=", false);
|
||||
cnd.andEX("l.`year`", "=", year);
|
||||
cnd.and(Cnd.likeEX("l.lineName", lineName));
|
||||
cnd.andEX("l.lotId", "=", lotId);
|
||||
boolean sysAdmin = AuthUtil.hasRole(RoleConstant.SYSADMIN.name());
|
||||
boolean branchUnionScope = !sysAdmin && AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name());
|
||||
applyDataScope(cnd, sysAdmin, branchUnionScope);
|
||||
String creatorJoin = branchUnionScope ? """
|
||||
LEFT JOIN sys_unit lineUnit ON lineUnit.id = l.unitId
|
||||
LEFT JOIN sys_user creatorUser ON creatorUser.id = COALESCE(NULLIF(l.creatorUserId, ''), l.createdBy)
|
||||
LEFT JOIN sys_unit creatorUnit ON creatorUnit.id = creatorUser.unitId
|
||||
""" : "";
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM tour_line l
|
||||
$creatorJoin
|
||||
$condition
|
||||
""");
|
||||
countSql.setVar("creatorJoin", creatorJoin);
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourLineService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
l.*,
|
||||
a.agencyName AS travelAgencyName,
|
||||
lot.lotName AS lotName
|
||||
FROM tour_line l
|
||||
LEFT JOIN tour_travel_agency a ON a.id = l.travelAgencyId
|
||||
LEFT JOIN tour_setting_lot lot ON lot.id = l.lotId
|
||||
$creatorJoin
|
||||
$condition
|
||||
ORDER BY $orderColumn $orderBy, l.`year` DESC, l.lineCode ASC, l.createdAt DESC
|
||||
""");
|
||||
listSql.setVar("creatorJoin", creatorJoin);
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
|
||||
listSql.setPager(tourLineService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourLineService.dao().execute(listSql);
|
||||
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, listSql.getList(NutMap.class));
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.route")
|
||||
public Result detail(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourLine line = tourLineService.fetch(id);
|
||||
return line == null ? Result.error("线路不存在") : Result.success(line);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.route")
|
||||
public Result travelAgencyOptions(Integer year) {
|
||||
Cnd cnd = Cnd.where(TourTravelAgency::getEnabled, "=", true);
|
||||
cnd.andEX(TourTravelAgency::getYear, "=", year);
|
||||
cnd.asc(TourTravelAgency::getAgencyCode).asc(TourTravelAgency::getAgencyName);
|
||||
return Result.success(tourLineService.dao().query(TourTravelAgency.class, cnd));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.route")
|
||||
public Result lotOptions(Integer year) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("s.`year`", "=", year);
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT lot.id, lot.lotName, lot.lotValue, lot.activityCost
|
||||
FROM tour_setting_lot lot
|
||||
INNER JOIN tour_setting s ON s.id = lot.settingId
|
||||
$condition
|
||||
ORDER BY lot.lotValue DESC, lot.lotName ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLineService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.route")
|
||||
public Result lineTypeOptions() {
|
||||
List<Sys_dict> list = sysDictService.getSubListByCode("lineType");
|
||||
if (list == null) {
|
||||
return Result.success(Collections.emptyList());
|
||||
}
|
||||
return Result.success(list.stream().filter(item -> !item.isDisabled()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.route")
|
||||
@SLog(type = "tour", tag = "线路管理", msg = "保存线路信息")
|
||||
public Result doSubmit(TourLine line) {
|
||||
Result checkResult = check(line);
|
||||
if (checkResult != null) {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
Cnd sameCodeCnd = Cnd.where(TourLine::getYear, "=", line.getYear())
|
||||
.and(TourLine::getLineCode, "=", line.getLineCode());
|
||||
if (StrUtil.isNotBlank(line.getId())) {
|
||||
sameCodeCnd.and(TourLine::getId, "<>", line.getId());
|
||||
}
|
||||
if (tourLineService.count(sameCodeCnd) > 0) {
|
||||
return Result.error("同年度下线路编号已存在");
|
||||
}
|
||||
if (line.getEnabled() == null) {
|
||||
line.setEnabled(true);
|
||||
}
|
||||
if (line.getOpenFlag() == null) {
|
||||
line.setOpenFlag(true);
|
||||
}
|
||||
if (line.getDirectFamilyUnitLine() == null) {
|
||||
line.setDirectFamilyUnitLine(false);
|
||||
}
|
||||
if (StrUtil.isBlank(line.getId())) {
|
||||
fillCreatorInfo(line, null);
|
||||
tourLineService.insert(line);
|
||||
} else {
|
||||
fillCreatorInfo(line, tourLineService.fetch(line.getId()));
|
||||
tourLineService.updateIgnoreNull(line);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.route")
|
||||
@SLog(type = "tour", tag = "线路管理", msg = "删除线路信息")
|
||||
public Result doDelete(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
tourLineService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private Result check(TourLine line) {
|
||||
if (line == null) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
if (line.getYear() == null) {
|
||||
return Result.error("创建年度不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(line.getTravelAgencyId())) {
|
||||
return Result.error("旅行社名称不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(line.getLineName())) {
|
||||
return Result.error("线路名称不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(line.getLineCode())) {
|
||||
return Result.error("线路编号不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(line.getLineType())) {
|
||||
return Result.error("线路类型不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(line.getLotId())) {
|
||||
return Result.error("时间标段不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(line.getMobileThumb())) {
|
||||
return Result.error("移动端缩略图不能为空");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建人和所在单位由当前登录人生成,编辑时保留原创建信息。
|
||||
*/
|
||||
private void fillCreatorInfo(TourLine line, TourLine oldLine) {
|
||||
if (oldLine != null) {
|
||||
line.setCreatorUserId(defaultIfBlank(oldLine.getCreatorUserId(), SecurityUtil.getUserId()));
|
||||
line.setCreatorName(defaultIfBlank(oldLine.getCreatorName(), SecurityUtil.getUserUsername()));
|
||||
line.setUnitId(defaultIfBlank(oldLine.getUnitId(), SecurityUtil.getUnitId()));
|
||||
line.setUnitName(defaultIfBlank(oldLine.getUnitName(), getCurrentUnitName()));
|
||||
return;
|
||||
}
|
||||
line.setCreatorUserId(SecurityUtil.getUserId());
|
||||
line.setCreatorName(SecurityUtil.getUserUsername());
|
||||
line.setUnitId(SecurityUtil.getUnitId());
|
||||
line.setUnitName(getCurrentUnitName());
|
||||
}
|
||||
|
||||
private String getCurrentUnitName() {
|
||||
View_user user = tourLineService.dao().fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId()));
|
||||
return user == null ? "" : defaultIfBlank(user.getUnitName(), "");
|
||||
}
|
||||
|
||||
private String defaultIfBlank(String value, String defaultValue) {
|
||||
return StrUtil.isBlank(value) ? defaultValue : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 线路数据范围:
|
||||
* SYSADMIN 可查看全部;分工会主席查看本工会创建的线路;其它角色保持原逻辑,仅查看自己创建的线路。
|
||||
*/
|
||||
private void applyDataScope(Cnd cnd, boolean sysAdmin, boolean branchUnionScope) {
|
||||
if (sysAdmin) {
|
||||
return;
|
||||
}
|
||||
if (branchUnionScope) {
|
||||
SqlExpressionGroup unionGroup = new SqlExpressionGroup();
|
||||
unionGroup.or("lineUnit.unionId", "=", SecurityUtil.getUnionId());
|
||||
unionGroup.or("creatorUnit.unionId", "=", SecurityUtil.getUnionId());
|
||||
cnd.and(unionGroup);
|
||||
return;
|
||||
}
|
||||
SqlExpressionGroup creatorGroup = new SqlExpressionGroup();
|
||||
creatorGroup.or("l.creatorUserId", "=", SecurityUtil.getUserId());
|
||||
creatorGroup.or("l.createdBy", "=", SecurityUtil.getUserId());
|
||||
cnd.and(creatorGroup);
|
||||
}
|
||||
|
||||
private String getOrderColumn(String orderName) {
|
||||
if ("year".equals(orderName)) {
|
||||
return "l.`year`";
|
||||
}
|
||||
if ("lineCode".equals(orderName)) {
|
||||
return "l.lineCode";
|
||||
}
|
||||
if ("lotName".equals(orderName)) {
|
||||
return "lot.lotName";
|
||||
}
|
||||
if ("lineType".equals(orderName)) {
|
||||
return "l.lineType";
|
||||
}
|
||||
if ("enabled".equals(orderName)) {
|
||||
return "l.enabled";
|
||||
}
|
||||
return "l.`year`";
|
||||
}
|
||||
}
|
||||
+441
@@ -0,0 +1,441 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.sys.models.Sys_dict;
|
||||
import com.budwk.app.sys.models.Sys_union;
|
||||
import com.budwk.app.sys.services.SysDictService;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourMatter;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourSetting;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourMatterService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/matter")
|
||||
public class TourMatterController {
|
||||
|
||||
private static final String MOBILE_PATTERN = "^1[3-9]\\d{9}$";
|
||||
|
||||
@Inject
|
||||
private TourMatterService tourMatterService;
|
||||
|
||||
@Inject
|
||||
private SysDictService sysDictService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/matter/index.html")
|
||||
@SaCheckPermission("tour.matter")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result pageData(PageForm pageForm, Integer year, String matterName, String unionId, String organizationType) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("m.delFlag", "=", false);
|
||||
cnd.andEX("m.`year`", "=", year);
|
||||
cnd.and(Cnd.likeEX("m.matterName", matterName));
|
||||
cnd.andEX("m.unionId", "=", unionId);
|
||||
cnd.andEX("m.organizationType", "=", organizationType);
|
||||
applyMatterDataScope(cnd);
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM tour_matter m
|
||||
$condition
|
||||
""");
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourMatterService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
m.*,
|
||||
s.configName AS settingName,
|
||||
u.name AS unionName,
|
||||
d.name AS organizationTypeName,
|
||||
l.lineName AS lineName,
|
||||
l.lineType AS lineType,
|
||||
l.directFamilyUnitLine AS directFamilyUnitLine
|
||||
FROM tour_matter m
|
||||
LEFT JOIN tour_setting s ON s.id = m.settingId
|
||||
LEFT JOIN sys_union u ON u.id = m.unionId
|
||||
LEFT JOIN tour_line l ON l.id = m.lineId
|
||||
LEFT JOIN sys_dict d ON d.`code` = m.organizationType
|
||||
AND d.parentId = (SELECT id FROM sys_dict WHERE `code` = 'organizationType' LIMIT 1)
|
||||
$condition
|
||||
ORDER BY $orderColumn $orderBy, m.`year` DESC, m.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
|
||||
listSql.setPager(tourMatterService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourMatterService.dao().execute(listSql);
|
||||
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, listSql.getList(NutMap.class));
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result detail(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourMatter matter = tourMatterService.fetch(id);
|
||||
return matter == null ? Result.error("事项不存在") : Result.success(matter);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result settingOptions(Integer year) {
|
||||
Cnd cnd = Cnd.where(TourSetting::getEnabled, "=", true);
|
||||
cnd.andEX(TourSetting::getYear, "=", year);
|
||||
cnd.desc(TourSetting::getCreatedAt);
|
||||
cnd.desc(TourSetting::getUpdatedAt);
|
||||
cnd.asc(TourSetting::getConfigName);
|
||||
return Result.success(tourMatterService.dao().query(TourSetting.class, cnd));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result unionOptions() {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.asc("unionCode");
|
||||
cnd.asc("name");
|
||||
return Result.success(tourMatterService.dao().query(Sys_union.class, cnd));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result lineOptions(Integer year) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("l.delFlag", "=", false);
|
||||
cnd.and("l.enabled", "=", true);
|
||||
cnd.and("l.openFlag", "=", true);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
l.*,
|
||||
lot.lotName AS lotName,
|
||||
lot.lotValue AS lotValue,
|
||||
lot.lotValue AS lotDays,
|
||||
lot.activityCost AS activityCost
|
||||
FROM tour_line l
|
||||
LEFT JOIN tour_setting_lot lot ON lot.id = l.lotId
|
||||
$condition
|
||||
ORDER BY l.lineCode ASC, l.lineName ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourMatterService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result organizationTypeOptions() {
|
||||
List<Sys_dict> list = sysDictService.getSubListByCode("organizationType");
|
||||
if (list == null) {
|
||||
return Result.success(Collections.emptyList());
|
||||
}
|
||||
return Result.success(list.stream().filter(item -> !item.isDisabled()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.matter")
|
||||
@SLog(type = "tour", tag = "疗休养事项", msg = "保存疗休养事项")
|
||||
public Result doSubmit(TourMatter matter) {
|
||||
Result checkResult = check(matter);
|
||||
if (checkResult != null) {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
Cnd sameNameCnd = Cnd.where(TourMatter::getYear, "=", matter.getYear())
|
||||
.and(TourMatter::getMatterName, "=", matter.getMatterName());
|
||||
if (StrUtil.isNotBlank(matter.getId())) {
|
||||
sameNameCnd.and(TourMatter::getId, "<>", matter.getId());
|
||||
}
|
||||
if (tourMatterService.count(sameNameCnd) > 0) {
|
||||
return Result.error("同年度下事项名称已存在");
|
||||
}
|
||||
if (matter.getEnabled() == null) {
|
||||
matter.setEnabled(true);
|
||||
}
|
||||
fillCreatorAndUnion(matter);
|
||||
if (StrUtil.isBlank(matter.getId())) {
|
||||
tourMatterService.insert(matter);
|
||||
} else {
|
||||
tourMatterService.updateIgnoreNull(matter);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.matter")
|
||||
@SLog(type = "tour", tag = "疗休养事项", msg = "删除疗休养事项")
|
||||
public Result doDelete(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourMatter matter = tourMatterService.fetch(id);
|
||||
if (matter == null) {
|
||||
return Result.error("事项不存在");
|
||||
}
|
||||
long signupCount = countSignup(id);
|
||||
if (signupCount > 0) {
|
||||
return Result.error("当前事项对应线路已有人员报名,不能删除");
|
||||
}
|
||||
tourMatterService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result deleteInfo(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourMatter matter = tourMatterService.fetch(id);
|
||||
if (matter == null) {
|
||||
return Result.error("事项不存在");
|
||||
}
|
||||
long signupCount = countSignup(id);
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("signupCount", signupCount)
|
||||
.addv("canDelete", signupCount <= 0)
|
||||
.addv("message", signupCount > 0 ? "当前事项已有人员报名,不能删除" : "当前事项暂无人员报名,可删除"));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result lineConfig(String matterId) {
|
||||
if (StrUtil.isBlank(matterId)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourMatter matter = tourMatterService.fetch(matterId);
|
||||
return matter == null ? Result.error("事项不存在") : Result.success(matter);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.matter")
|
||||
public Result settingPeople(String matterId) {
|
||||
if (StrUtil.isBlank(matterId)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourMatter matter = tourMatterService.fetch(matterId);
|
||||
if (matter == null || StrUtil.isBlank(matter.getSettingId())) {
|
||||
return Result.success(NutMap.NEW());
|
||||
}
|
||||
TourSetting setting = tourMatterService.dao().fetch(TourSetting.class, matter.getSettingId());
|
||||
if (setting == null) {
|
||||
return Result.success(NutMap.NEW());
|
||||
}
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("minGroupPeople", setting.getMinGroupPeople())
|
||||
.addv("maxGroupPeople", setting.getMaxGroupPeople()));
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.matter")
|
||||
@SLog(type = "tour", tag = "疗休养事项", msg = "保存事项线路配置")
|
||||
public Result lineConfigDoSubmit(TourMatter matter) {
|
||||
Result checkResult = checkLineConfig(matter);
|
||||
if (checkResult != null) {
|
||||
return checkResult;
|
||||
}
|
||||
TourMatter oldMatter = tourMatterService.fetch(matter.getId());
|
||||
if (oldMatter == null) {
|
||||
return Result.error("事项不存在");
|
||||
}
|
||||
oldMatter.setLineId(matter.getLineId());
|
||||
oldMatter.setSignupStartTime(matter.getSignupStartTime());
|
||||
oldMatter.setSignupEndTime(matter.getSignupEndTime());
|
||||
oldMatter.setTravelStartTime(matter.getTravelStartTime());
|
||||
oldMatter.setTravelEndTime(matter.getTravelEndTime());
|
||||
oldMatter.setContactName(matter.getContactName());
|
||||
oldMatter.setContactPhone(matter.getContactPhone());
|
||||
oldMatter.setMinGroupPeople(matter.getMinGroupPeople());
|
||||
oldMatter.setMaxGroupPeople(matter.getMaxGroupPeople());
|
||||
oldMatter.setEstimatedCost(matter.getEstimatedCost());
|
||||
tourMatterService.update(oldMatter);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private Result check(TourMatter matter) {
|
||||
if (matter == null) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
if (matter.getYear() == null) {
|
||||
return Result.error("年度不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getMatterName())) {
|
||||
return Result.error("事项名称不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getSettingId())) {
|
||||
return Result.error("疗休养配置不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getOrganizationType())) {
|
||||
return Result.error("组织形式不能为空");
|
||||
}
|
||||
if (!"schoolUnion".equals(matter.getOrganizationType()) && StrUtil.isBlank(matter.getUnionId())) {
|
||||
return Result.error("所属工会不能为空");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Result checkLineConfig(TourMatter matter) {
|
||||
if (matter == null) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getId())) {
|
||||
return Result.error("事项不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getLineId())) {
|
||||
return Result.error("线路不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getSignupStartTime()) || StrUtil.isBlank(matter.getSignupEndTime())
|
||||
|| StrUtil.isBlank(matter.getTravelStartTime()) || StrUtil.isBlank(matter.getTravelEndTime())) {
|
||||
return Result.error("时间不能为空");
|
||||
}
|
||||
if (matter.getSignupStartTime().compareTo(matter.getSignupEndTime()) >= 0) {
|
||||
return Result.error("报名开始时间必须小于报名结束时间");
|
||||
}
|
||||
if (matter.getTravelStartTime().compareTo(matter.getTravelEndTime()) > 0) {
|
||||
return Result.error("出行开始时间不能晚于出行结束时间");
|
||||
}
|
||||
if (matter.getSignupEndTime().compareTo(matter.getTravelStartTime()) >= 0) {
|
||||
return Result.error("报名结束时间必须小于出行开始时间");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getContactName())) {
|
||||
return Result.error("联系人不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(matter.getContactPhone()) || !matter.getContactPhone().matches(MOBILE_PATTERN)) {
|
||||
return Result.error("联系方式格式不正确");
|
||||
}
|
||||
if (matter.getMinGroupPeople() == null || matter.getMinGroupPeople() <= 0) {
|
||||
return Result.error("最少成团人数必须大于0");
|
||||
}
|
||||
if (matter.getMaxGroupPeople() == null || matter.getMaxGroupPeople() <= 0) {
|
||||
return Result.error("最多成团人数必须大于0");
|
||||
}
|
||||
if (matter.getMinGroupPeople() > matter.getMaxGroupPeople()) {
|
||||
return Result.error("最少成团人数不能大于最多成团人数");
|
||||
}
|
||||
if (matter.getEstimatedCost() == null || matter.getEstimatedCost().signum() < 0) {
|
||||
return Result.error("预计费用不能小于0");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void fillCreatorAndUnion(TourMatter matter) {
|
||||
if (StrUtil.isBlank(matter.getId())) {
|
||||
matter.setCreatorUserId(SecurityUtil.getUserId());
|
||||
matter.setCreatorName(SecurityUtil.getUserUsername());
|
||||
} else {
|
||||
TourMatter oldMatter = tourMatterService.fetch(matter.getId());
|
||||
if (oldMatter != null) {
|
||||
matter.setCreatorUserId(oldMatter.getCreatorUserId());
|
||||
matter.setCreatorName(oldMatter.getCreatorName());
|
||||
}
|
||||
}
|
||||
if ("schoolUnion".equals(matter.getOrganizationType())) {
|
||||
matter.setUnionId("");
|
||||
}
|
||||
}
|
||||
|
||||
private long countSignup(String matterId) {
|
||||
return tourMatterService.dao().count(TourLedger.class, Cnd.where(TourLedger::getDelFlag, "=", false)
|
||||
.and(TourLedger::getMatterId, "=", matterId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 事项数据范围:SYSADMIN 查看全部;分工会主席查看本工会事项;其它角色仅查看自己创建的事项。
|
||||
*/
|
||||
private void applyMatterDataScope(Cnd cnd) {
|
||||
if (AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
||||
return;
|
||||
}
|
||||
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
|
||||
cnd.and("m.unionId", "=", SecurityUtil.getUnionId());
|
||||
return;
|
||||
}
|
||||
SqlExpressionGroup creatorGroup = new SqlExpressionGroup();
|
||||
creatorGroup.or("m.creatorUserId", "=", SecurityUtil.getUserId());
|
||||
creatorGroup.or("m.createdBy", "=", SecurityUtil.getUserId());
|
||||
cnd.and(creatorGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* 事项批次选择线路时沿用线路管理的数据范围,避免在事项页面选到权限外线路。
|
||||
*/
|
||||
private void applyLineDataScope(Cnd cnd, boolean sysAdmin, boolean branchUnionScope) {
|
||||
if (sysAdmin) {
|
||||
return;
|
||||
}
|
||||
if (branchUnionScope) {
|
||||
SqlExpressionGroup unionGroup = new SqlExpressionGroup();
|
||||
unionGroup.or("lineUnit.unionId", "=", SecurityUtil.getUnionId());
|
||||
unionGroup.or("creatorUnit.unionId", "=", SecurityUtil.getUnionId());
|
||||
cnd.and(unionGroup);
|
||||
return;
|
||||
}
|
||||
SqlExpressionGroup creatorGroup = new SqlExpressionGroup();
|
||||
creatorGroup.or("l.creatorUserId", "=", SecurityUtil.getUserId());
|
||||
creatorGroup.or("l.createdBy", "=", SecurityUtil.getUserId());
|
||||
cnd.and(creatorGroup);
|
||||
}
|
||||
|
||||
private String getOrderColumn(String orderName) {
|
||||
if ("year".equals(orderName)) {
|
||||
return "m.`year`";
|
||||
}
|
||||
if ("matterName".equals(orderName)) {
|
||||
return "m.matterName";
|
||||
}
|
||||
if ("unionName".equals(orderName)) {
|
||||
return "u.name";
|
||||
}
|
||||
if ("lineName".equals(orderName)) {
|
||||
return "l.lineName";
|
||||
}
|
||||
if ("settingName".equals(orderName)) {
|
||||
return "s.configName";
|
||||
}
|
||||
if ("organizationTypeName".equals(orderName)) {
|
||||
return "d.location";
|
||||
}
|
||||
if ("enabled".equals(orderName)) {
|
||||
return "m.enabled";
|
||||
}
|
||||
return "m.`year`";
|
||||
}
|
||||
}
|
||||
+1846
File diff suppressed because it is too large
Load Diff
+13
@@ -0,0 +1,13 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
|
||||
/**
|
||||
* 分阶段建设的菜单占位入口。
|
||||
*/
|
||||
@IocBean
|
||||
@At("/platform/tour")
|
||||
public class TourPlaceholderController {
|
||||
|
||||
}
|
||||
+581
@@ -0,0 +1,581 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
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.ProcessTaskStateEnum;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/schoolUnionApproval")
|
||||
public class TourSchoolUnionApprovalController {
|
||||
|
||||
private static final String WORKFLOW_KEY = "LXYBZXQSXL";
|
||||
private static final String TASK_DISPLAY_NAME = "校工会审核";
|
||||
|
||||
@Inject
|
||||
private TourLedgerService tourLedgerService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerFamilyService tourLedgerFamilyService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerDirectRelativeService tourLedgerDirectRelativeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/schoolUnionApproval/index.html")
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At("/h5")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/tour/schoolUnionApproval/index.html")
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public void h5() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public Result pageData(PageForm pageForm, Boolean audit, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType);
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(DISTINCT task.id)
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
$condition
|
||||
""");
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
t.*,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo,
|
||||
ins.state AS instanceState,
|
||||
ins.variable AS instanceVariable,
|
||||
ins.processDefineId AS instanceProcessDefineId,
|
||||
task.id AS taskId,
|
||||
task.taskName AS taskKey,
|
||||
task.displayName AS taskName,
|
||||
task.taskType,
|
||||
task.performType AS taskPerformType,
|
||||
task.taskState,
|
||||
task.finishTime,
|
||||
task.taskParentId,
|
||||
task.variable AS taskVariable,
|
||||
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName), '结束') AS curTaskName,
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS currentLineName,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE tp.travelPeriod
|
||||
END AS travelPeriod,
|
||||
IFNULL(f.familyCount, 0) AS familyCount
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||
LEFT JOIN (
|
||||
SELECT ledgerId, COUNT(1) AS familyCount
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
GROUP BY ledgerId
|
||||
) f ON f.ledgerId = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
lineId,
|
||||
GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND lineId IS NOT NULL
|
||||
AND lineId <> ''
|
||||
GROUP BY `year`, lineId
|
||||
) tp ON (t.matterId IS NULL OR t.matterId = '') AND tp.`year` = t.`year` AND tp.lineId = t.lineId
|
||||
$condition
|
||||
GROUP BY task.id
|
||||
ORDER BY $orderColumn $orderBy, task.createdAt DESC, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "ascending".equals(pageForm.getPageOrderBy()) ? "asc" : "desc");
|
||||
listSql.setPager(tourLedgerService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
List<NutMap> list = listSql.getList(NutMap.class);
|
||||
list.forEach(item -> item.put("lineName", item.getString("currentLineName")));
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public Result detail(String id) {
|
||||
TourLedger ledger = fetchAuditLedger(id);
|
||||
if (ledger == null) {
|
||||
return Result.error("报名记录不存在或无权查看");
|
||||
}
|
||||
ledger.setLineName(getCurrentLineName(ledger));
|
||||
Cnd familyCnd = Cnd.where(TourLedgerFamily::getLedgerId, "=", ledger.getId())
|
||||
.and(TourLedgerFamily::getDelFlag, "=", false);
|
||||
familyCnd.asc(TourLedgerFamily::getCreatedAt);
|
||||
TourLedgerDirectRelative directRelative = tourLedgerDirectRelativeService.fetch(
|
||||
Cnd.where(TourLedgerDirectRelative::getLedgerId, "=", ledger.getId())
|
||||
.and(TourLedgerDirectRelative::getDelFlag, "=", false));
|
||||
NutMap signupConfig = getSignupConfig(ledger);
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("ledger", ledger)
|
||||
.addv("travelPeriod", getTravelPeriod(ledger))
|
||||
.addv("families", tourLedgerFamilyService.query(familyCnd))
|
||||
.addv("directRelative", directRelative)
|
||||
.addv("allowFamily", signupConfig.getBoolean("allowFamily", false))
|
||||
.addv("fillBedInfo", signupConfig.getBoolean("fillBedInfo", true))
|
||||
.addv("directFamilyUnitLine", signupConfig.getBoolean("directFamilyUnitLine", false)));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public Result unionOptions(Boolean audit, Integer startYear, Integer endYear, String keyword, String lineId, String travelPeriod, String lineType) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, null, lineId, travelPeriod, lineType);
|
||||
cnd.and("t.unionId", "IS NOT", null);
|
||||
cnd.and("t.unionId", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
t.unionId AS id,
|
||||
COALESCE(NULLIF(u.name, ''), t.unionName) AS name,
|
||||
u.unionCode
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union u ON u.id = t.unionId
|
||||
$condition
|
||||
ORDER BY u.unionCode ASC, name ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public Result lineOptions(Boolean audit, Integer startYear, Integer endYear, String travelPeriod, String lineType, String unionId, String keyword) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, null, travelPeriod, lineType);
|
||||
cnd.and("t.lineName", "IS NOT", null);
|
||||
cnd.and("t.lineName", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN IFNULL(t.lineId, '') <> '' THEN CONCAT(t.lineId, '|', IFNULL(m.unionId, ''))
|
||||
ELSE CONCAT('legacy:', t.lineName, '|', IFNULL(m.unionId, ''))
|
||||
END AS lineId,
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS lineName
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
$condition
|
||||
ORDER BY lineName ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public Result travelPeriodOptions(Boolean audit, Integer startYear, Integer endYear, String lineId, String lineType, String unionId, String keyword) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, lineId, null, lineType);
|
||||
cnd.and("m.travelStartTime", "IS NOT", null);
|
||||
cnd.and("m.travelStartTime", "<>", "");
|
||||
cnd.and("m.travelEndTime", "IS NOT", null);
|
||||
cnd.and("m.travelEndTime", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime) AS travelPeriod
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
$condition
|
||||
ORDER BY travelPeriod ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.schoolUnionApproval", "h5.tour.schoolUnionApproval"}, mode = SaMode.OR)
|
||||
public Result lineTypeOptions(Boolean audit, Integer startYear, Integer endYear, String lineId, String travelPeriod, String unionId, String keyword) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, lineId, travelPeriod, null);
|
||||
cnd.and("t.lineType", "IS NOT", null);
|
||||
cnd.and("t.lineType", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT t.lineType
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
$condition
|
||||
ORDER BY t.lineType ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
private Cnd buildAuditCnd(Boolean audit, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.and("def.name", "=", WORKFLOW_KEY);
|
||||
cnd.and("task.displayName", "=", TASK_DISPLAY_NAME);
|
||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||
appendAuditStateFilter(cnd, audit);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private void appendAuditStateFilter(Cnd cnd, Boolean audit) {
|
||||
if (Boolean.TRUE.equals(audit)) {
|
||||
cnd.and("task.taskState", "in", List.of(
|
||||
ProcessTaskStateEnum.FINISHED.getCode(),
|
||||
ProcessTaskStateEnum.WITHDRAW.getCode(),
|
||||
ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
return;
|
||||
}
|
||||
cnd.and("task.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
}
|
||||
|
||||
private void appendKeywordFilter(Cnd cnd, String keyword) {
|
||||
if (StrUtil.isBlank(keyword)) {
|
||||
return;
|
||||
}
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.orLike("t.userName", keyword.trim());
|
||||
group.orLike("t.jobNo", keyword.trim());
|
||||
group.orLike("t.lineName", keyword.trim());
|
||||
group.orLike("l.lineName", keyword.trim());
|
||||
cnd.and(group);
|
||||
}
|
||||
|
||||
private void appendTravelPeriodFilter(Cnd cnd, String travelPeriod) {
|
||||
if (StrUtil.isBlank(travelPeriod)) {
|
||||
return;
|
||||
}
|
||||
cnd.and("CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)", "=", travelPeriod);
|
||||
}
|
||||
|
||||
private void appendLineFilter(Cnd cnd, String lineId) {
|
||||
if (StrUtil.isBlank(lineId)) {
|
||||
return;
|
||||
}
|
||||
LineFilter lineFilter = parseLineFilter(lineId);
|
||||
if (lineFilter.getLineId().startsWith("legacy:")) {
|
||||
SqlExpressionGroup legacyGroup = new SqlExpressionGroup();
|
||||
legacyGroup.or("t.lineId", "IS", null);
|
||||
legacyGroup.or("t.lineId", "=", "");
|
||||
cnd.and(legacyGroup);
|
||||
cnd.and("t.lineName", "=", lineFilter.getLineId().substring("legacy:".length()));
|
||||
} else {
|
||||
cnd.and("t.lineId", "=", lineFilter.getLineId());
|
||||
}
|
||||
appendMatterUnionFilter(cnd, lineFilter.getUnionId());
|
||||
}
|
||||
|
||||
private LineFilter parseLineFilter(String value) {
|
||||
int delimiterIndex = value.indexOf("|");
|
||||
if (delimiterIndex < 0) {
|
||||
return new LineFilter(value, null);
|
||||
}
|
||||
return new LineFilter(value.substring(0, delimiterIndex), value.substring(delimiterIndex + 1));
|
||||
}
|
||||
|
||||
private void appendMatterUnionFilter(Cnd cnd, String unionId) {
|
||||
if (unionId == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.or("m.unionId", "IS", null);
|
||||
group.or("m.unionId", "=", "");
|
||||
cnd.and(group);
|
||||
return;
|
||||
}
|
||||
cnd.and("m.unionId", "=", unionId);
|
||||
}
|
||||
|
||||
private String getOrderColumn(String orderName) {
|
||||
if ("jobNo".equals(orderName)) {
|
||||
return "t.jobNo";
|
||||
}
|
||||
if ("userName".equals(orderName)) {
|
||||
return "t.userName";
|
||||
}
|
||||
if ("lineName".equals(orderName)) {
|
||||
return """
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END
|
||||
""";
|
||||
}
|
||||
if ("travelPeriod".equals(orderName)) {
|
||||
return "COALESCE(m.travelStartTime, tp.travelPeriod)";
|
||||
}
|
||||
if ("lineType".equals(orderName)) {
|
||||
return "t.lineType";
|
||||
}
|
||||
if ("signupTime".equals(orderName)) {
|
||||
return "t.signupTime";
|
||||
}
|
||||
if ("familyCount".equals(orderName)) {
|
||||
return "familyCount";
|
||||
}
|
||||
if ("instanceState".equals(orderName)) {
|
||||
return "ins.state";
|
||||
}
|
||||
return "task.createdAt";
|
||||
}
|
||||
|
||||
private TourLedger fetchAuditLedger(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return null;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
WHERE t.delFlag = 0
|
||||
AND t.id = @id
|
||||
AND def.name = @workflowKey
|
||||
AND task.displayName = @taskDisplayName
|
||||
AND ta.actorId = @actorId
|
||||
""");
|
||||
sql.setParam("id", id);
|
||||
sql.setParam("workflowKey", WORKFLOW_KEY);
|
||||
sql.setParam("taskDisplayName", TASK_DISPLAY_NAME);
|
||||
sql.setParam("actorId", SecurityUtil.getUserId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
if (ledger == null) {
|
||||
return "";
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS lineName
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
WHERE t.id = @ledgerId
|
||||
""");
|
||||
sql.setParam("ledgerId", ledger.getId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return StrUtil.blankToDefault(sql.getString(), ledger.getLineName());
|
||||
}
|
||||
|
||||
private String getTravelPeriod(TourLedger ledger) {
|
||||
if (ledger == null || ledger.getYear() == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return "";
|
||||
}
|
||||
if (StrUtil.isNotBlank(ledger.getMatterId())) {
|
||||
Sql exactSql = Sqls.create("""
|
||||
SELECT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE ''
|
||||
END AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND id = @matterId
|
||||
""");
|
||||
exactSql.setParam("matterId", ledger.getMatterId());
|
||||
exactSql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(exactSql);
|
||||
return exactSql.getString();
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND `year` = @year
|
||||
AND lineId = @lineId
|
||||
""");
|
||||
sql.setParam("year", ledger.getYear());
|
||||
sql.setParam("lineId", ledger.getLineId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getString();
|
||||
}
|
||||
|
||||
private NutMap getSignupConfig(TourLedger ledger) {
|
||||
if (ledger == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return NutMap.NEW().addv("allowFamily", false).addv("fillBedInfo", true).addv("directFamilyUnitLine", false);
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
IFNULL(s.allowFamily, 0) AS allowFamily,
|
||||
IFNULL(s.fillBedInfo, 1) AS fillBedInfo,
|
||||
IFNULL(l.directFamilyUnitLine, 0) AS directFamilyUnitLine
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_setting s ON s.id = m.settingId AND s.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
WHERE t.id = @ledgerId
|
||||
""");
|
||||
sql.setParam("ledgerId", ledger.getId());
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
NutMap map = sql.getObject(NutMap.class);
|
||||
if (map == null || map.isEmpty()) {
|
||||
return NutMap.NEW().addv("allowFamily", false).addv("fillBedInfo", true).addv("directFamilyUnitLine", false);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static class LineFilter {
|
||||
private final String lineId;
|
||||
private final String unionId;
|
||||
|
||||
private LineFilter(String lineId, String unionId) {
|
||||
this.lineId = lineId;
|
||||
this.unionId = unionId;
|
||||
}
|
||||
|
||||
private String getLineId() {
|
||||
return lineId;
|
||||
}
|
||||
|
||||
private String getUnionId() {
|
||||
return unionId;
|
||||
}
|
||||
}
|
||||
}
|
||||
+246
@@ -0,0 +1,246 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
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.zhgh.dayofficework.tour.models.TourSetting;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourSettingLot;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourSettingService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/setting")
|
||||
public class TourSettingController {
|
||||
|
||||
@Inject
|
||||
private TourSettingService tourSettingService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/setting/index.html")
|
||||
@SaCheckPermission("tour.setting")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.setting")
|
||||
public Result pageData(PageForm pageForm, Integer year, String configName) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX(TourSetting::getYear, "=", year);
|
||||
cnd.and(Cnd.likeEX(TourSetting::getConfigName, configName));
|
||||
|
||||
cnd.desc(TourSetting::getYear).asc(TourSetting::getSortNo).desc(TourSetting::getCreatedAt);
|
||||
Pagination<TourSetting> pagination = tourSettingService.listPage(
|
||||
pageForm.getPageNumber(),
|
||||
pageForm.getPageSize(),
|
||||
TourSetting.class,
|
||||
cnd
|
||||
);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.setting")
|
||||
public Result detail(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourSetting tourSetting = tourSettingService.fetch(id);
|
||||
if (tourSetting == null) {
|
||||
return Result.error("配置不存在");
|
||||
}
|
||||
// 编辑页面需要一起带出标段,按标段值倒序保持与老疗休养配置一致。
|
||||
Cnd lotCnd = Cnd.NEW();
|
||||
lotCnd.desc(TourSettingLot::getLotValue);
|
||||
tourSettingService.dao().fetchLinks(tourSetting, "lots", lotCnd);
|
||||
return Result.success(tourSetting);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.setting")
|
||||
public Result previousYearInfo(Integer year) {
|
||||
if (year == null) {
|
||||
return Result.error("请先选择年度");
|
||||
}
|
||||
List<TourSetting> settings = tourSettingService.query(Cnd.where(TourSetting::getYear, "=", year - 1)
|
||||
.and(TourSetting::getDelFlag, "=", false)
|
||||
.desc(TourSetting::getUpdatedAt)
|
||||
.desc(TourSetting::getCreatedAt));
|
||||
if (Lang.isEmpty(settings)) {
|
||||
return Result.error("未找到上一年度配置");
|
||||
}
|
||||
TourSetting tourSetting = settings.get(0);
|
||||
Cnd lotCnd = Cnd.NEW();
|
||||
lotCnd.desc(TourSettingLot::getLotValue);
|
||||
tourSettingService.dao().fetchLinks(tourSetting, "lots", lotCnd);
|
||||
return Result.success(tourSetting);
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.setting")
|
||||
@SLog(type = "tour", tag = "疗休养设置", msg = "保存疗休养配置")
|
||||
public Result doSubmit(TourSetting tourSetting,
|
||||
@Param(value = "lots") String lots,
|
||||
@Param(value = "lotDeleteList") String[] lotDeleteList) {
|
||||
Result checkResult = check(tourSetting);
|
||||
if (checkResult != null) {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
Cnd sameNameCnd = Cnd.where(TourSetting::getYear, "=", tourSetting.getYear())
|
||||
.and(TourSetting::getConfigName, "=", tourSetting.getConfigName());
|
||||
if (StrUtil.isNotBlank(tourSetting.getId())) {
|
||||
sameNameCnd.and(TourSetting::getId, "<>", tourSetting.getId());
|
||||
}
|
||||
if (tourSettingService.count(sameNameCnd) > 0) {
|
||||
return Result.error("同年度下配置名称已存在");
|
||||
}
|
||||
|
||||
// 布尔值给默认值,避免前端未传时出现空状态。
|
||||
if (tourSetting.getEnabled() == null) {
|
||||
tourSetting.setEnabled(true);
|
||||
}
|
||||
if (tourSetting.getAllowFamily() == null) {
|
||||
tourSetting.setAllowFamily(false);
|
||||
}
|
||||
if (tourSetting.getFillBedInfo() == null) {
|
||||
tourSetting.setFillBedInfo(true);
|
||||
}
|
||||
if (StrUtil.isBlank(tourSetting.getOutProvinceRatioType())) {
|
||||
tourSetting.setOutProvinceRatioType("当年报名人数");
|
||||
}
|
||||
if (!"固定人数".equals(tourSetting.getOutProvinceRatioType())) {
|
||||
tourSetting.setOutProvinceFixedPeople(0);
|
||||
}
|
||||
// 前端按项目既有约定把子表数组序列化提交,这里显式解析,避免自动绑定漏掉标段。
|
||||
if (StrUtil.isNotBlank(lots)) {
|
||||
try {
|
||||
tourSetting.setLots(Json.fromJsonAsList(TourSettingLot.class, lots));
|
||||
} catch (Exception e) {
|
||||
return Result.error("标段值和标段费用必须为整数");
|
||||
}
|
||||
}
|
||||
tourSetting.setLots(normalizeLots(tourSetting));
|
||||
Result lotCheckResult = checkLots(tourSetting.getLots());
|
||||
if (lotCheckResult != null) {
|
||||
return lotCheckResult;
|
||||
}
|
||||
if (StrUtil.isBlank(tourSetting.getId())) {
|
||||
if (Lang.isEmpty(tourSetting.getLots())) {
|
||||
tourSettingService.insert(tourSetting);
|
||||
} else {
|
||||
tourSettingService.insertWith(tourSetting, "lots");
|
||||
}
|
||||
} else {
|
||||
// 编辑时先处理页面删除的标段,再保存配置和当前标段行。
|
||||
if (Lang.isNotEmpty(lotDeleteList)) {
|
||||
tourSettingService.dao().clear(TourSettingLot.class, Cnd.where(TourSettingLot::getId, "in", lotDeleteList));
|
||||
}
|
||||
tourSettingService.updateIgnoreNull(tourSetting);
|
||||
saveLots(tourSetting);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.setting")
|
||||
@SLog(type = "tour", tag = "疗休养设置", msg = "删除疗休养配置")
|
||||
public Result doDelete(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
tourSettingService.dao().clear(TourSettingLot.class, Cnd.where(TourSettingLot::getSettingId, "=", id));
|
||||
tourSettingService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private List<TourSettingLot> normalizeLots(TourSetting tourSetting) {
|
||||
if (tourSetting == null || Lang.isEmpty(tourSetting.getLots())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 过滤前端空行,避免误写入只有ID或空字段的标段记录。
|
||||
return tourSetting.getLots().stream()
|
||||
.filter(item -> item != null
|
||||
&& (StrUtil.isNotBlank(item.getLotName())
|
||||
|| StrUtil.isNotBlank(item.getLotValue())
|
||||
|| item.getActivityCost() != null))
|
||||
.peek(item -> item.setSettingId(tourSetting.getId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void saveLots(TourSetting tourSetting) {
|
||||
List<TourSettingLot> lots = tourSetting.getLots();
|
||||
if (Lang.isEmpty(lots)) {
|
||||
return;
|
||||
}
|
||||
lots.forEach(item -> item.setSettingId(tourSetting.getId()));
|
||||
tourSettingService.dao().insertOrUpdate(lots);
|
||||
}
|
||||
|
||||
private Result check(TourSetting tourSetting) {
|
||||
if (tourSetting == null) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
if (tourSetting.getYear() == null) {
|
||||
return Result.error("年度不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(tourSetting.getConfigName())) {
|
||||
return Result.error("配置名称不能为空");
|
||||
}
|
||||
if (tourSetting.getMinGroupPeople() != null && tourSetting.getMaxGroupPeople() != null
|
||||
&& tourSetting.getMinGroupPeople() > tourSetting.getMaxGroupPeople()) {
|
||||
return Result.error("最少成团人数不能大于最多成团人数");
|
||||
}
|
||||
if (tourSetting.getCycleStartYear() != null && tourSetting.getCycleEndYear() != null
|
||||
&& tourSetting.getCycleStartYear() > tourSetting.getCycleEndYear()) {
|
||||
return Result.error("周期开始年度不能大于周期结束年度");
|
||||
}
|
||||
if (StrUtil.isNotBlank(tourSetting.getOutProvinceRatioType())
|
||||
&& !"当年参加人数".equals(tourSetting.getOutProvinceRatioType())
|
||||
&& !"当年报名人数".equals(tourSetting.getOutProvinceRatioType())
|
||||
&& !"可参加教职工人数".equals(tourSetting.getOutProvinceRatioType())
|
||||
&& !"固定人数".equals(tourSetting.getOutProvinceRatioType())) {
|
||||
return Result.error("省外人数占比类型不正确");
|
||||
}
|
||||
if ("固定人数".equals(tourSetting.getOutProvinceRatioType())
|
||||
&& (tourSetting.getOutProvinceFixedPeople() == null || tourSetting.getOutProvinceFixedPeople() < 0)) {
|
||||
return Result.error("固定人数必须大于等于0");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Result checkLots(List<TourSettingLot> lots) {
|
||||
if (Lang.isEmpty(lots)) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < lots.size(); i++) {
|
||||
TourSettingLot lot = lots.get(i);
|
||||
String rowNo = "第" + (i + 1) + "行";
|
||||
if (StrUtil.isBlank(lot.getLotValue()) || !lot.getLotValue().matches("^\\d+$")) {
|
||||
return Result.error(rowNo + "标段值必须为整数");
|
||||
}
|
||||
if (lot.getActivityCost() == null || lot.getActivityCost() < 0) {
|
||||
return Result.error(rowNo + "标段费用必须为整数");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+1487
File diff suppressed because it is too large
Load Diff
+160
@@ -0,0 +1,160 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
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.zhgh.dayofficework.tour.models.TourTravelAgency;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourTravelAgencyService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/travelAgency")
|
||||
public class TourTravelAgencyController {
|
||||
|
||||
private static final String MOBILE_PATTERN = "^1[3-9]\\d{9}$";
|
||||
private static final String EMAIL_PATTERN = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
|
||||
|
||||
@Inject
|
||||
private TourTravelAgencyService travelAgencyService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/travelAgency/index.html")
|
||||
@SaCheckPermission("tour.travelAgency")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.travelAgency")
|
||||
public Result pageData(PageForm pageForm, Integer year, String agencyName, String contactName, String contactPhone) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX(TourTravelAgency::getYear, "=", year);
|
||||
cnd.and(Cnd.likeEX(TourTravelAgency::getAgencyName, agencyName));
|
||||
cnd.and(Cnd.likeEX(TourTravelAgency::getContactName, contactName));
|
||||
cnd.and(Cnd.likeEX(TourTravelAgency::getContactPhone, contactPhone));
|
||||
applyOrder(cnd, pageForm);
|
||||
Pagination<TourTravelAgency> pagination = travelAgencyService.listPage(
|
||||
pageForm.getPageNumber(),
|
||||
pageForm.getPageSize(),
|
||||
TourTravelAgency.class,
|
||||
cnd
|
||||
);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.travelAgency")
|
||||
public Result detail(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourTravelAgency agency = travelAgencyService.fetch(id);
|
||||
return agency == null ? Result.error("旅行社不存在") : Result.success(agency);
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.travelAgency")
|
||||
@SLog(type = "tour", tag = "旅行社管理", msg = "保存旅行社信息")
|
||||
public Result doSubmit(TourTravelAgency agency) {
|
||||
Result checkResult = check(agency);
|
||||
if (checkResult != null) {
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
Cnd sameCodeCnd = Cnd.where(TourTravelAgency::getYear, "=", agency.getYear())
|
||||
.and(TourTravelAgency::getAgencyCode, "=", agency.getAgencyCode());
|
||||
if (StrUtil.isNotBlank(agency.getId())) {
|
||||
sameCodeCnd.and(TourTravelAgency::getId, "<>", agency.getId());
|
||||
}
|
||||
if (travelAgencyService.count(sameCodeCnd) > 0) {
|
||||
return Result.error("同年度下旅行社编号已存在");
|
||||
}
|
||||
if (agency.getEnabled() == null) {
|
||||
agency.setEnabled(true);
|
||||
}
|
||||
if (StrUtil.isBlank(agency.getId())) {
|
||||
travelAgencyService.insert(agency);
|
||||
} else {
|
||||
travelAgencyService.updateIgnoreNull(agency);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.travelAgency")
|
||||
@SLog(type = "tour", tag = "旅行社管理", msg = "删除旅行社信息")
|
||||
public Result doDelete(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
travelAgencyService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private Result check(TourTravelAgency agency) {
|
||||
if (agency == null) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
if (agency.getYear() == null) {
|
||||
return Result.error("年度不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(agency.getAgencyName())) {
|
||||
return Result.error("旅行社名称不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(agency.getAgencyCode())) {
|
||||
return Result.error("旅行社编号不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(agency.getContactName())) {
|
||||
return Result.error("联系人不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(agency.getContactPhone())) {
|
||||
return Result.error("联系人手机不能为空");
|
||||
}
|
||||
if (!agency.getContactPhone().matches(MOBILE_PATTERN)) {
|
||||
return Result.error("联系人手机格式不正确");
|
||||
}
|
||||
if (StrUtil.isBlank(agency.getEmail())) {
|
||||
return Result.error("邮箱不能为空");
|
||||
}
|
||||
if (!agency.getEmail().matches(EMAIL_PATTERN)) {
|
||||
return Result.error("邮箱格式不正确");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void applyOrder(Cnd cnd, PageForm pageForm) {
|
||||
String orderName = pageForm.getPageOrderName();
|
||||
String orderBy = pageForm.getPageOrderBy();
|
||||
if (StrUtil.isBlank(orderName)) {
|
||||
cnd.asc(TourTravelAgency::getYear).asc(TourTravelAgency::getAgencyCode).desc(TourTravelAgency::getCreatedAt);
|
||||
return;
|
||||
}
|
||||
boolean descending = "descending".equals(orderBy);
|
||||
if ("year".equals(orderName)) {
|
||||
if (descending) {
|
||||
cnd.desc(TourTravelAgency::getYear);
|
||||
} else {
|
||||
cnd.asc(TourTravelAgency::getYear);
|
||||
}
|
||||
} else if ("agencyCode".equals(orderName)) {
|
||||
if (descending) {
|
||||
cnd.desc(TourTravelAgency::getAgencyCode);
|
||||
} else {
|
||||
cnd.asc(TourTravelAgency::getAgencyCode);
|
||||
}
|
||||
} else {
|
||||
cnd.asc(TourTravelAgency::getYear).asc(TourTravelAgency::getAgencyCode).desc(TourTravelAgency::getCreatedAt);
|
||||
}
|
||||
}
|
||||
}
|
||||
+581
@@ -0,0 +1,581 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
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.ProcessTaskStateEnum;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/unionApproval")
|
||||
public class TourUnionApprovalController {
|
||||
|
||||
private static final String WORKFLOW_KEY = "LXYBZXQSXL";
|
||||
private static final String TASK_DISPLAY_NAME = "分工会审核";
|
||||
|
||||
@Inject
|
||||
private TourLedgerService tourLedgerService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerFamilyService tourLedgerFamilyService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerDirectRelativeService tourLedgerDirectRelativeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/unionApproval/index.html")
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At("/h5")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/tour/unionApproval/index.html")
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public void h5() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public Result pageData(PageForm pageForm, Boolean audit, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType);
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(DISTINCT task.id)
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
$condition
|
||||
""");
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
t.*,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo,
|
||||
ins.state AS instanceState,
|
||||
ins.variable AS instanceVariable,
|
||||
ins.processDefineId AS instanceProcessDefineId,
|
||||
task.id AS taskId,
|
||||
task.taskName AS taskKey,
|
||||
task.displayName AS taskName,
|
||||
task.taskType,
|
||||
task.performType AS taskPerformType,
|
||||
task.taskState,
|
||||
task.finishTime,
|
||||
task.taskParentId,
|
||||
task.variable AS taskVariable,
|
||||
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName), '结束') AS curTaskName,
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS currentLineName,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE tp.travelPeriod
|
||||
END AS travelPeriod,
|
||||
IFNULL(f.familyCount, 0) AS familyCount
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||
LEFT JOIN (
|
||||
SELECT ledgerId, COUNT(1) AS familyCount
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
GROUP BY ledgerId
|
||||
) f ON f.ledgerId = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
lineId,
|
||||
GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND lineId IS NOT NULL
|
||||
AND lineId <> ''
|
||||
GROUP BY `year`, lineId
|
||||
) tp ON (t.matterId IS NULL OR t.matterId = '') AND tp.`year` = t.`year` AND tp.lineId = t.lineId
|
||||
$condition
|
||||
GROUP BY task.id
|
||||
ORDER BY $orderColumn $orderBy, task.createdAt DESC, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "ascending".equals(pageForm.getPageOrderBy()) ? "asc" : "desc");
|
||||
listSql.setPager(tourLedgerService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
List<NutMap> list = listSql.getList(NutMap.class);
|
||||
list.forEach(item -> item.put("lineName", item.getString("currentLineName")));
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public Result detail(String id) {
|
||||
TourLedger ledger = fetchAuditLedger(id);
|
||||
if (ledger == null) {
|
||||
return Result.error("报名记录不存在或无权查看");
|
||||
}
|
||||
ledger.setLineName(getCurrentLineName(ledger));
|
||||
Cnd familyCnd = Cnd.where(TourLedgerFamily::getLedgerId, "=", ledger.getId())
|
||||
.and(TourLedgerFamily::getDelFlag, "=", false);
|
||||
familyCnd.asc(TourLedgerFamily::getCreatedAt);
|
||||
TourLedgerDirectRelative directRelative = tourLedgerDirectRelativeService.fetch(
|
||||
Cnd.where(TourLedgerDirectRelative::getLedgerId, "=", ledger.getId())
|
||||
.and(TourLedgerDirectRelative::getDelFlag, "=", false));
|
||||
NutMap signupConfig = getSignupConfig(ledger);
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("ledger", ledger)
|
||||
.addv("travelPeriod", getTravelPeriod(ledger))
|
||||
.addv("families", tourLedgerFamilyService.query(familyCnd))
|
||||
.addv("directRelative", directRelative)
|
||||
.addv("allowFamily", signupConfig.getBoolean("allowFamily", false))
|
||||
.addv("fillBedInfo", signupConfig.getBoolean("fillBedInfo", true))
|
||||
.addv("directFamilyUnitLine", signupConfig.getBoolean("directFamilyUnitLine", false)));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public Result unionOptions(Boolean audit, Integer startYear, Integer endYear, String keyword, String lineId, String travelPeriod, String lineType) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, null, lineId, travelPeriod, lineType);
|
||||
cnd.and("t.unionId", "IS NOT", null);
|
||||
cnd.and("t.unionId", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
t.unionId AS id,
|
||||
COALESCE(NULLIF(u.name, ''), t.unionName) AS name,
|
||||
u.unionCode
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union u ON u.id = t.unionId
|
||||
$condition
|
||||
ORDER BY u.unionCode ASC, name ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public Result lineOptions(Boolean audit, Integer startYear, Integer endYear, String travelPeriod, String lineType, String unionId, String keyword) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, null, travelPeriod, lineType);
|
||||
cnd.and("t.lineName", "IS NOT", null);
|
||||
cnd.and("t.lineName", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN IFNULL(t.lineId, '') <> '' THEN CONCAT(t.lineId, '|', IFNULL(m.unionId, ''))
|
||||
ELSE CONCAT('legacy:', t.lineName, '|', IFNULL(m.unionId, ''))
|
||||
END AS lineId,
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS lineName
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
$condition
|
||||
ORDER BY lineName ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public Result travelPeriodOptions(Boolean audit, Integer startYear, Integer endYear, String lineId, String lineType, String unionId, String keyword) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, lineId, null, lineType);
|
||||
cnd.and("m.travelStartTime", "IS NOT", null);
|
||||
cnd.and("m.travelStartTime", "<>", "");
|
||||
cnd.and("m.travelEndTime", "IS NOT", null);
|
||||
cnd.and("m.travelEndTime", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime) AS travelPeriod
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
$condition
|
||||
ORDER BY travelPeriod ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.unionApproval", "h5.tour.unionApproval"}, mode = SaMode.OR)
|
||||
public Result lineTypeOptions(Boolean audit, Integer startYear, Integer endYear, String lineId, String travelPeriod, String unionId, String keyword) {
|
||||
Cnd cnd = buildAuditCnd(audit, startYear, endYear, keyword, unionId, lineId, travelPeriod, null);
|
||||
cnd.and("t.lineType", "IS NOT", null);
|
||||
cnd.and("t.lineType", "<>", "");
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT t.lineType
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
$condition
|
||||
ORDER BY t.lineType ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
private Cnd buildAuditCnd(Boolean audit, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.and("def.name", "=", WORKFLOW_KEY);
|
||||
cnd.and("task.displayName", "=", TASK_DISPLAY_NAME);
|
||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||
appendAuditStateFilter(cnd, audit);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private void appendAuditStateFilter(Cnd cnd, Boolean audit) {
|
||||
if (Boolean.TRUE.equals(audit)) {
|
||||
cnd.and("task.taskState", "in", List.of(
|
||||
ProcessTaskStateEnum.FINISHED.getCode(),
|
||||
ProcessTaskStateEnum.WITHDRAW.getCode(),
|
||||
ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
return;
|
||||
}
|
||||
cnd.and("task.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
}
|
||||
|
||||
private void appendKeywordFilter(Cnd cnd, String keyword) {
|
||||
if (StrUtil.isBlank(keyword)) {
|
||||
return;
|
||||
}
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.orLike("t.userName", keyword.trim());
|
||||
group.orLike("t.jobNo", keyword.trim());
|
||||
group.orLike("t.lineName", keyword.trim());
|
||||
group.orLike("l.lineName", keyword.trim());
|
||||
cnd.and(group);
|
||||
}
|
||||
|
||||
private void appendTravelPeriodFilter(Cnd cnd, String travelPeriod) {
|
||||
if (StrUtil.isBlank(travelPeriod)) {
|
||||
return;
|
||||
}
|
||||
cnd.and("CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)", "=", travelPeriod);
|
||||
}
|
||||
|
||||
private void appendLineFilter(Cnd cnd, String lineId) {
|
||||
if (StrUtil.isBlank(lineId)) {
|
||||
return;
|
||||
}
|
||||
LineFilter lineFilter = parseLineFilter(lineId);
|
||||
if (lineFilter.getLineId().startsWith("legacy:")) {
|
||||
SqlExpressionGroup legacyGroup = new SqlExpressionGroup();
|
||||
legacyGroup.or("t.lineId", "IS", null);
|
||||
legacyGroup.or("t.lineId", "=", "");
|
||||
cnd.and(legacyGroup);
|
||||
cnd.and("t.lineName", "=", lineFilter.getLineId().substring("legacy:".length()));
|
||||
} else {
|
||||
cnd.and("t.lineId", "=", lineFilter.getLineId());
|
||||
}
|
||||
appendMatterUnionFilter(cnd, lineFilter.getUnionId());
|
||||
}
|
||||
|
||||
private LineFilter parseLineFilter(String value) {
|
||||
int delimiterIndex = value.indexOf("|");
|
||||
if (delimiterIndex < 0) {
|
||||
return new LineFilter(value, null);
|
||||
}
|
||||
return new LineFilter(value.substring(0, delimiterIndex), value.substring(delimiterIndex + 1));
|
||||
}
|
||||
|
||||
private void appendMatterUnionFilter(Cnd cnd, String unionId) {
|
||||
if (unionId == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.or("m.unionId", "IS", null);
|
||||
group.or("m.unionId", "=", "");
|
||||
cnd.and(group);
|
||||
return;
|
||||
}
|
||||
cnd.and("m.unionId", "=", unionId);
|
||||
}
|
||||
|
||||
private String getOrderColumn(String orderName) {
|
||||
if ("jobNo".equals(orderName)) {
|
||||
return "t.jobNo";
|
||||
}
|
||||
if ("userName".equals(orderName)) {
|
||||
return "t.userName";
|
||||
}
|
||||
if ("lineName".equals(orderName)) {
|
||||
return """
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END
|
||||
""";
|
||||
}
|
||||
if ("travelPeriod".equals(orderName)) {
|
||||
return "COALESCE(m.travelStartTime, tp.travelPeriod)";
|
||||
}
|
||||
if ("lineType".equals(orderName)) {
|
||||
return "t.lineType";
|
||||
}
|
||||
if ("signupTime".equals(orderName)) {
|
||||
return "t.signupTime";
|
||||
}
|
||||
if ("familyCount".equals(orderName)) {
|
||||
return "familyCount";
|
||||
}
|
||||
if ("instanceState".equals(orderName)) {
|
||||
return "ins.state";
|
||||
}
|
||||
return "task.createdAt";
|
||||
}
|
||||
|
||||
private TourLedger fetchAuditLedger(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return null;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM wf_process_task task
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = task.processInstanceId
|
||||
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = task.id
|
||||
INNER JOIN tour_ledger t ON t.id = ins.businessNo
|
||||
WHERE t.delFlag = 0
|
||||
AND t.id = @id
|
||||
AND def.name = @workflowKey
|
||||
AND task.displayName = @taskDisplayName
|
||||
AND ta.actorId = @actorId
|
||||
""");
|
||||
sql.setParam("id", id);
|
||||
sql.setParam("workflowKey", WORKFLOW_KEY);
|
||||
sql.setParam("taskDisplayName", TASK_DISPLAY_NAME);
|
||||
sql.setParam("actorId", SecurityUtil.getUserId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
if (ledger == null) {
|
||||
return "";
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS lineName
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
WHERE t.id = @ledgerId
|
||||
""");
|
||||
sql.setParam("ledgerId", ledger.getId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return StrUtil.blankToDefault(sql.getString(), ledger.getLineName());
|
||||
}
|
||||
|
||||
private String getTravelPeriod(TourLedger ledger) {
|
||||
if (ledger == null || ledger.getYear() == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return "";
|
||||
}
|
||||
if (StrUtil.isNotBlank(ledger.getMatterId())) {
|
||||
Sql exactSql = Sqls.create("""
|
||||
SELECT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE ''
|
||||
END AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND id = @matterId
|
||||
""");
|
||||
exactSql.setParam("matterId", ledger.getMatterId());
|
||||
exactSql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(exactSql);
|
||||
return exactSql.getString();
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND `year` = @year
|
||||
AND lineId = @lineId
|
||||
""");
|
||||
sql.setParam("year", ledger.getYear());
|
||||
sql.setParam("lineId", ledger.getLineId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getString();
|
||||
}
|
||||
|
||||
private NutMap getSignupConfig(TourLedger ledger) {
|
||||
if (ledger == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return NutMap.NEW().addv("allowFamily", false).addv("fillBedInfo", true).addv("directFamilyUnitLine", false);
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
IFNULL(s.allowFamily, 0) AS allowFamily,
|
||||
IFNULL(s.fillBedInfo, 1) AS fillBedInfo,
|
||||
IFNULL(l.directFamilyUnitLine, 0) AS directFamilyUnitLine
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_setting s ON s.id = m.settingId AND s.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
WHERE t.id = @ledgerId
|
||||
""");
|
||||
sql.setParam("ledgerId", ledger.getId());
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
NutMap map = sql.getObject(NutMap.class);
|
||||
if (map == null || map.isEmpty()) {
|
||||
return NutMap.NEW().addv("allowFamily", false).addv("fillBedInfo", true).addv("directFamilyUnitLine", false);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static class LineFilter {
|
||||
private final String lineId;
|
||||
private final String unionId;
|
||||
|
||||
private LineFilter(String lineId, String unionId) {
|
||||
this.lineId = lineId;
|
||||
this.unionId = unionId;
|
||||
}
|
||||
|
||||
private String getLineId() {
|
||||
return lineId;
|
||||
}
|
||||
|
||||
private String getUnionId() {
|
||||
return unionId;
|
||||
}
|
||||
}
|
||||
}
|
||||
+905
@@ -0,0 +1,905 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
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.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.sys.models.Sys_union;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/tour/unionledger")
|
||||
public class TourUnionLedgerController {
|
||||
|
||||
@Inject
|
||||
private TourLedgerService tourLedgerService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerFamilyService tourLedgerFamilyService;
|
||||
|
||||
@Inject
|
||||
private TourLedgerDirectRelativeService tourLedgerDirectRelativeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/Tour/unionledger/index.html")
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public Result pageData(PageForm pageForm, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType, String scopeType, Boolean overCostOnly) {
|
||||
String currentUnionId = currentUnionId();
|
||||
if (StrUtil.isBlank(currentUnionId)) {
|
||||
return Result.error("当前登录人所属工会不能为空");
|
||||
}
|
||||
Cnd cnd = buildQueryCnd(currentUnionId, startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType, scopeType, overCostOnly);
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
SELECT COUNT(DISTINCT t.id)
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN wf_process_task task ON task.processInstanceId = ins.id AND task.taskState = 10
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
$condition
|
||||
""");
|
||||
countSql.setCondition(cnd);
|
||||
countSql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(countSql);
|
||||
int count = countSql.getInt();
|
||||
|
||||
Sql listSql = Sqls.create("""
|
||||
SELECT
|
||||
t.*,
|
||||
ins.id AS instanceId,
|
||||
ins.state AS instanceState,
|
||||
ins.processDefineId AS instanceProcessDefineId,
|
||||
IFNULL(l.directFamilyUnitLine, 0) AS directFamilyUnitLine,
|
||||
IFNULL(GROUP_CONCAT(DISTINCT task.displayName), IF(ins.id IS NULL, '', '结束')) AS curTaskName,
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS currentLineName,
|
||||
IFNULL(f.familyCount, 0) AS familyCount,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE tp.travelPeriod
|
||||
END AS travelPeriod
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN wf_process_task task ON task.processInstanceId = ins.id AND task.taskState = 10
|
||||
LEFT JOIN (
|
||||
SELECT ledgerId, COUNT(1) AS familyCount
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
GROUP BY ledgerId
|
||||
) f ON f.ledgerId = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
lineId,
|
||||
GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND lineId IS NOT NULL
|
||||
AND lineId <> ''
|
||||
GROUP BY `year`, lineId
|
||||
) tp ON (t.matterId IS NULL OR t.matterId = '') AND tp.`year` = t.`year` AND tp.lineId = t.lineId
|
||||
$condition
|
||||
GROUP BY t.id
|
||||
ORDER BY $orderColumn $orderBy, t.`year` DESC, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
|
||||
listSql.setPager(tourLedgerService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
var list = listSql.getList(NutMap.class);
|
||||
list.forEach(item -> item.put("lineName", item.getString("currentLineName")));
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public void exportOverCostSummary(PageForm pageForm, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType, String scopeType, HttpServletResponse response) {
|
||||
String currentUnionId = currentUnionId();
|
||||
if (StrUtil.isBlank(currentUnionId)) {
|
||||
return;
|
||||
}
|
||||
Cnd cnd = buildQueryCnd(currentUnionId, startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType, scopeType, true);
|
||||
List<NutMap> list = queryOverCostSummaryList(cnd, pageForm);
|
||||
Workbook workbook = buildOverCostSummaryWorkbook(currentUnionName(), list);
|
||||
CommonDownloadUtil.download("5天外超出部分疗休养费用由单位承担申请人员汇总表.xls", workbook, response);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public Result detail(String id) {
|
||||
TourLedger ledger = fetchScopedLedger(id);
|
||||
if (ledger == null) {
|
||||
return Result.error("台账记录不存在或无权查看");
|
||||
}
|
||||
ledger.setLineName(getCurrentLineName(ledger));
|
||||
Cnd familyCnd = Cnd.where(TourLedgerFamily::getLedgerId, "=", id)
|
||||
.and(TourLedgerFamily::getDelFlag, "=", false);
|
||||
familyCnd.asc(TourLedgerFamily::getCreatedAt);
|
||||
TourLedgerDirectRelative directRelative = tourLedgerDirectRelativeService.fetch(
|
||||
Cnd.where(TourLedgerDirectRelative::getDelFlag, "=", false)
|
||||
.and(TourLedgerDirectRelative::getLedgerId, "=", ledger.getId()));
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("ledger", ledger)
|
||||
.addv("travelPeriod", getTravelPeriod(ledger))
|
||||
.addv("families", tourLedgerFamilyService.query(familyCnd))
|
||||
.addv("directRelative", directRelative)
|
||||
.addv("fillBedInfo", isFillBedInfo(ledger))
|
||||
.addv("directFamilyUnitLine", isDirectFamilyUnitLine(ledger)));
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
@SLog(type = "tour", tag = "分工会疗休养台账", msg = "删除分工会疗休养台账")
|
||||
public Result doDelete(String id) {
|
||||
TourLedger ledger = fetchScopedLedger(id);
|
||||
if (ledger == null) {
|
||||
return Result.error("台账记录不存在或无权删除");
|
||||
}
|
||||
tourLedgerFamilyService.clear(Cnd.where(TourLedgerFamily::getLedgerId, "=", ledger.getId()));
|
||||
tourLedgerService.clear(Cnd.where(TourLedger::getId, "=", ledger.getId()));
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public Result unionOptions(Integer startYear, Integer endYear) {
|
||||
String currentUnionId = currentUnionId();
|
||||
if (StrUtil.isBlank(currentUnionId)) {
|
||||
return Result.error("当前登录人所属工会不能为空");
|
||||
}
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.and("t.unionId", "IS NOT", null);
|
||||
cnd.and("t.unionId", "<>", "");
|
||||
applyUnionLedgerScope(cnd, currentUnionId);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
t.unionId AS id,
|
||||
COALESCE(NULLIF(u.name, ''), t.unionName) AS name,
|
||||
u.unionCode
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN sys_union u ON u.id = t.unionId
|
||||
$condition
|
||||
ORDER BY
|
||||
CASE WHEN t.unionId = @currentUnionId THEN 0 ELSE 1 END,
|
||||
u.unionCode ASC,
|
||||
name ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setParam("currentUnionId", currentUnionId);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public Result lineOptions(Integer startYear, Integer endYear, String travelPeriod, String lineType, String unionId, String keyword, String scopeType) {
|
||||
String currentUnionId = currentUnionId();
|
||||
if (StrUtil.isBlank(currentUnionId)) {
|
||||
return Result.error("当前登录人所属工会不能为空");
|
||||
}
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.and("t.lineName", "IS NOT", null);
|
||||
cnd.and("t.lineName", "<>", "");
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendScopeFilter(cnd, currentUnionId, scopeType);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN IFNULL(t.lineId, '') <> '' THEN CONCAT(t.lineId, '|', IFNULL(m.unionId, ''))
|
||||
ELSE CONCAT('legacy:', t.lineName, '|', IFNULL(m.unionId, ''))
|
||||
END AS lineId,
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS lineName
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
$condition
|
||||
ORDER BY lineName ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public Result travelPeriodOptions(Integer startYear, Integer endYear, String lineId, String lineType, String unionId, String keyword, String scopeType) {
|
||||
String currentUnionId = currentUnionId();
|
||||
if (StrUtil.isBlank(currentUnionId)) {
|
||||
return Result.error("当前登录人所属工会不能为空");
|
||||
}
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.and("m.travelStartTime", "IS NOT", null);
|
||||
cnd.and("m.travelStartTime", "<>", "");
|
||||
cnd.and("m.travelEndTime", "IS NOT", null);
|
||||
cnd.and("m.travelEndTime", "<>", "");
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendScopeFilter(cnd, currentUnionId, scopeType);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime) AS travelPeriod
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
$condition
|
||||
ORDER BY travelPeriod ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public Result lineTypeOptions(Integer startYear, Integer endYear, String lineId, String travelPeriod, String unionId, String keyword, String scopeType) {
|
||||
String currentUnionId = currentUnionId();
|
||||
if (StrUtil.isBlank(currentUnionId)) {
|
||||
return Result.error("当前登录人所属工会不能为空");
|
||||
}
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.and("t.lineType", "IS NOT", null);
|
||||
cnd.and("t.lineType", "<>", "");
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendScopeFilter(cnd, currentUnionId, scopeType);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT t.lineType
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
$condition
|
||||
ORDER BY t.lineType ASC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return Result.success(sql.getList(NutMap.class));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("tour.unionledger")
|
||||
public Result summaryStats(Integer startYear, Integer endYear, String unionId, String lineId, String travelPeriod, String lineType) {
|
||||
String currentUnionId = currentUnionId();
|
||||
if (StrUtil.isBlank(currentUnionId)) {
|
||||
return Result.error("当前登录人所属工会不能为空");
|
||||
}
|
||||
Cnd ownCnd = buildSummaryCnd(currentUnionId, startYear, endYear, unionId, lineId, travelPeriod, lineType, "ownUnionJoined");
|
||||
Cnd organizedCnd = buildSummaryCnd(currentUnionId, startYear, endYear, unionId, lineId, travelPeriod, lineType, "organizedLineJoined");
|
||||
|
||||
Sql ownSql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
$condition
|
||||
""");
|
||||
ownSql.setCondition(ownCnd);
|
||||
ownSql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(ownSql);
|
||||
|
||||
Sql organizedSql = Sqls.create("""
|
||||
SELECT CAST(IFNULL(SUM(1 + IFNULL(f.familyCount, 0)), 0) AS SIGNED)
|
||||
FROM tour_ledger t
|
||||
INNER JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN (
|
||||
SELECT ledgerId, COUNT(1) AS familyCount
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
GROUP BY ledgerId
|
||||
) f ON f.ledgerId = t.id
|
||||
$condition
|
||||
""");
|
||||
organizedSql.setCondition(organizedCnd);
|
||||
organizedSql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(organizedSql);
|
||||
|
||||
return Result.success(NutMap.NEW()
|
||||
.addv("ownUnionJoinedStaffCount", ownSql.getInt())
|
||||
.addv("organizedLineJoinedTotalCount", organizedSql.getInt()));
|
||||
}
|
||||
|
||||
private List<NutMap> queryOverCostSummaryList(Cnd cnd, PageForm pageForm) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t.id,
|
||||
t.userName,
|
||||
t.idCard,
|
||||
t.unionName,
|
||||
vu.mobile,
|
||||
m.travelStartTime,
|
||||
m.travelEndTime,
|
||||
m.estimatedCost,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
THEN CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)
|
||||
ELSE tp.travelPeriod
|
||||
END AS travelPeriod,
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS currentLineName
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
LEFT JOIN vw_user vu ON vu.loginname = t.jobNo
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
lineId,
|
||||
GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND lineId IS NOT NULL
|
||||
AND lineId <> ''
|
||||
GROUP BY `year`, lineId
|
||||
) tp ON (t.matterId IS NULL OR t.matterId = '') AND tp.`year` = t.`year` AND tp.lineId = t.lineId
|
||||
$condition
|
||||
ORDER BY $orderColumn $orderBy, t.`year` DESC, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setVar("orderColumn", getOrderColumn(pageForm == null ? null : pageForm.getPageOrderName()));
|
||||
sql.setVar("orderBy", pageForm != null && "ascending".equals(pageForm.getPageOrderBy()) ? "asc" : "desc");
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
List<NutMap> list = sql.getList(NutMap.class);
|
||||
for (NutMap item : list) {
|
||||
item.put("lineName", item.getString("currentLineName"));
|
||||
item.put("totalDays", calcDays(item.getString("travelStartTime", ""), item.getString("travelEndTime", "")));
|
||||
item.put("estimatedCostText", formatAmount(item.get("estimatedCost")));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Workbook buildOverCostSummaryWorkbook(String unionName, List<NutMap> list) {
|
||||
Workbook workbook = new HSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("汇总表");
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 9));
|
||||
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 9));
|
||||
sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 9));
|
||||
|
||||
double[] widths = {5.14, 14.14, 21.29, 15.71, 27, 40, 50.43, 13.71, 22.57, 15.43};
|
||||
for (int i = 0; i < widths.length; i++) {
|
||||
sheet.setColumnWidth(i, (int) (widths[i] * 256));
|
||||
}
|
||||
|
||||
CellStyle attachStyle = createStyle(workbook, "宋体", (short) 12, false, HorizontalAlignment.LEFT, false, false);
|
||||
CellStyle titleStyle = createStyle(workbook, "黑体", (short) 18, true, HorizontalAlignment.CENTER, false, false);
|
||||
CellStyle unionStyle = createStyle(workbook, "仿宋_GB2312", (short) 14, true, HorizontalAlignment.LEFT, false, false);
|
||||
unionStyle.setBorderBottom(BorderStyle.THIN);
|
||||
CellStyle headerStyle = createStyle(workbook, "宋体", (short) 12, true, HorizontalAlignment.CENTER, true, true);
|
||||
CellStyle bodyStyle = createStyle(workbook, "宋体", (short) 12, false, HorizontalAlignment.CENTER, false, true);
|
||||
|
||||
Row row1 = sheet.createRow(0);
|
||||
row1.setHeightInPoints(32);
|
||||
setCell(row1, 0, "附件12", attachStyle);
|
||||
fillMergedCells(row1, 1, 9, attachStyle);
|
||||
|
||||
Row row2 = sheet.createRow(1);
|
||||
row2.setHeightInPoints(32);
|
||||
setCell(row2, 0, "5天外超出部分疗休养费用由单位承担申请人员汇总表", titleStyle);
|
||||
fillMergedCells(row2, 1, 9, titleStyle);
|
||||
|
||||
Row row3 = sheet.createRow(2);
|
||||
row3.setHeightInPoints(32);
|
||||
setCell(row3, 0, "分工会:" + StrUtil.blankToDefault(unionName, ""), unionStyle);
|
||||
fillMergedCells(row3, 1, 9, unionStyle);
|
||||
|
||||
String[] headers = {"序号", "姓名", "身份证号码", "电话号码", "所属分工会", "所选线路名称", "疗休养时间", "疗休养时长", "疗休养费用总额(元)", "备注"};
|
||||
Row header = sheet.createRow(3);
|
||||
header.setHeightInPoints(43);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
setCell(header, i, headers[i], headerStyle);
|
||||
}
|
||||
|
||||
int rowCount = Math.max(list == null ? 0 : list.size(), 20);
|
||||
for (int i = 0; i < rowCount; i++) {
|
||||
Row row = sheet.createRow(i + 4);
|
||||
row.setHeightInPoints(25);
|
||||
NutMap item = list != null && i < list.size() ? list.get(i) : null;
|
||||
setCell(row, 0, String.valueOf(i + 1), bodyStyle);
|
||||
setCell(row, 1, item == null ? "" : item.getString("userName", ""), bodyStyle);
|
||||
setCell(row, 2, item == null ? "" : item.getString("idCard", ""), bodyStyle);
|
||||
setCell(row, 3, item == null ? "" : item.getString("mobile", ""), bodyStyle);
|
||||
setCell(row, 4, item == null ? "" : item.getString("unionName", ""), bodyStyle);
|
||||
setCell(row, 5, item == null ? "" : item.getString("lineName", ""), bodyStyle);
|
||||
setCell(row, 6, item == null ? "" : item.getString("travelPeriod", ""), bodyStyle);
|
||||
setCell(row, 7, item == null ? "" : item.getString("totalDays", ""), bodyStyle);
|
||||
setCell(row, 8, item == null ? "" : item.getString("estimatedCostText", ""), bodyStyle);
|
||||
setCell(row, 9, "", bodyStyle);
|
||||
}
|
||||
return workbook;
|
||||
}
|
||||
|
||||
private CellStyle createStyle(Workbook workbook, String fontName, short fontSize, boolean bold, HorizontalAlignment alignment, boolean wrap, boolean border) {
|
||||
Font font = workbook.createFont();
|
||||
font.setFontName(fontName);
|
||||
font.setFontHeightInPoints(fontSize);
|
||||
font.setBold(bold);
|
||||
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
style.setFont(font);
|
||||
style.setAlignment(alignment);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
style.setWrapText(wrap);
|
||||
if (border) {
|
||||
style.setBorderLeft(BorderStyle.THIN);
|
||||
style.setBorderTop(BorderStyle.THIN);
|
||||
style.setBorderRight(BorderStyle.THIN);
|
||||
style.setBorderBottom(BorderStyle.THIN);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
private void setCell(Row row, int col, String value, CellStyle style) {
|
||||
Cell cell = row.createCell(col);
|
||||
cell.setCellValue(StrUtil.blankToDefault(value, ""));
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
private void fillMergedCells(Row row, int startCol, int endCol, CellStyle style) {
|
||||
for (int i = startCol; i <= endCol; i++) {
|
||||
setCell(row, i, "", style);
|
||||
}
|
||||
}
|
||||
|
||||
private Integer calcDays(String start, String end) {
|
||||
if (StrUtil.isBlank(start) || StrUtil.isBlank(end)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
LocalDate startDate = LocalDate.parse(start.substring(0, 10));
|
||||
LocalDate endDate = LocalDate.parse(end.substring(0, 10));
|
||||
return Math.toIntExact(ChronoUnit.DAYS.between(startDate, endDate) + 1);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatAmount(Object value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
BigDecimal amount = new BigDecimal(String.valueOf(value));
|
||||
return amount.stripTrailingZeros().toPlainString();
|
||||
} catch (Exception e) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
}
|
||||
|
||||
private Cnd buildQueryCnd(String currentUnionId, Integer startYear, Integer endYear, String keyword, String unionId, String lineId, String travelPeriod, String lineType, String scopeType, Boolean overCostOnly) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
if (Boolean.TRUE.equals(overCostOnly)) {
|
||||
cnd.and("t.overCostReimbursed", "=", true);
|
||||
}
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendScopeFilter(cnd, currentUnionId, scopeType);
|
||||
appendKeywordFilter(cnd, keyword);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private Cnd buildSummaryCnd(String currentUnionId, Integer startYear, Integer endYear, String unionId, String lineId, String travelPeriod, String lineType, String scopeType) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.andEX("t.`year`", ">=", startYear);
|
||||
cnd.andEX("t.`year`", "<=", endYear == null ? LocalDate.now().getYear() : endYear);
|
||||
cnd.andEX("t.unionId", "=", unionId);
|
||||
cnd.andEX("t.lineType", "=", lineType);
|
||||
appendLineFilter(cnd, lineId);
|
||||
appendTravelPeriodFilter(cnd, travelPeriod);
|
||||
appendScopeFilter(cnd, currentUnionId, scopeType);
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private void appendKeywordFilter(Cnd cnd, String keyword) {
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.orLike("t.userName", keyword.trim());
|
||||
group.orLike("t.jobNo", keyword.trim());
|
||||
cnd.and(group);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyUnionLedgerScope(Cnd cnd, String currentUnionId) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.or("t.unionId", "=", currentUnionId);
|
||||
group.or("m.unionId", "=", currentUnionId);
|
||||
cnd.and(group);
|
||||
}
|
||||
|
||||
private void appendScopeFilter(Cnd cnd, String currentUnionId, String scopeType) {
|
||||
if ("ownUnionJoined".equals(scopeType)) {
|
||||
cnd.and("t.unionId", "=", currentUnionId);
|
||||
return;
|
||||
}
|
||||
if ("organizedLineJoined".equals(scopeType)) {
|
||||
cnd.and("m.unionId", "=", currentUnionId);
|
||||
return;
|
||||
}
|
||||
applyUnionLedgerScope(cnd, currentUnionId);
|
||||
}
|
||||
|
||||
private String buildYearCondition(Integer startYear, Integer endYear) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (startYear != null) {
|
||||
builder.append(" AND t.`year` >= ").append(startYear);
|
||||
}
|
||||
if (endYear != null) {
|
||||
builder.append(" AND t.`year` <= ").append(endYear);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private TourLedger fetchScopedLedger(String id) {
|
||||
if (StrUtil.isBlank(id) || StrUtil.isBlank(currentUnionId())) {
|
||||
return null;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT COUNT(1)
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
WHERE t.delFlag = 0
|
||||
AND t.id = @id
|
||||
AND (t.unionId = @unionId OR m.unionId = @unionId)
|
||||
""");
|
||||
sql.setParam("id", id);
|
||||
sql.setParam("unionId", currentUnionId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
}
|
||||
|
||||
private String getTravelPeriod(TourLedger ledger) {
|
||||
if (ledger == null || ledger.getYear() == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return "";
|
||||
}
|
||||
if (StrUtil.isNotBlank(ledger.getMatterId())) {
|
||||
Sql exactSql = Sqls.create("""
|
||||
SELECT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE ''
|
||||
END AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND id = @matterId
|
||||
""");
|
||||
exactSql.setParam("matterId", ledger.getMatterId());
|
||||
exactSql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(exactSql);
|
||||
return exactSql.getString();
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND `year` = @year
|
||||
AND lineId = @lineId
|
||||
""");
|
||||
sql.setParam("year", ledger.getYear());
|
||||
sql.setParam("lineId", ledger.getLineId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getString();
|
||||
}
|
||||
|
||||
private boolean isDirectFamilyUnitLine(TourLedger ledger) {
|
||||
if (ledger == null || StrUtil.isBlank(ledger.getLineId())) {
|
||||
return false;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT IFNULL(directFamilyUnitLine, 0)
|
||||
FROM tour_line
|
||||
WHERE delFlag = 0
|
||||
AND id = @lineId
|
||||
""");
|
||||
sql.setParam("lineId", ledger.getLineId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0;
|
||||
}
|
||||
|
||||
private boolean isFillBedInfo(TourLedger ledger) {
|
||||
if (ledger == null || StrUtil.isBlank(ledger.getMatterId())) {
|
||||
return true;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT IFNULL(MAX(s.fillBedInfo), 1)
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_setting s ON s.id = m.settingId AND s.delFlag = 0
|
||||
WHERE t.id = @ledgerId
|
||||
""");
|
||||
sql.setParam("ledgerId", ledger.getId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0;
|
||||
}
|
||||
|
||||
private void appendTravelPeriodFilter(Cnd cnd, String travelPeriod) {
|
||||
if (StrUtil.isBlank(travelPeriod)) {
|
||||
return;
|
||||
}
|
||||
cnd.and("CONCAT(m.travelStartTime, ' 至 ', m.travelEndTime)", "=", travelPeriod);
|
||||
}
|
||||
|
||||
private void appendLineFilter(Cnd cnd, String lineId) {
|
||||
if (StrUtil.isBlank(lineId)) {
|
||||
return;
|
||||
}
|
||||
LineFilter lineFilter = parseLineFilter(lineId);
|
||||
if (lineFilter.getLineId().startsWith("legacy:")) {
|
||||
SqlExpressionGroup legacyGroup = new SqlExpressionGroup();
|
||||
legacyGroup.or("t.lineId", "IS", null);
|
||||
legacyGroup.or("t.lineId", "=", "");
|
||||
cnd.and(legacyGroup);
|
||||
cnd.and("t.lineName", "=", lineFilter.getLineId().substring("legacy:".length()));
|
||||
} else {
|
||||
cnd.and("t.lineId", "=", lineFilter.getLineId());
|
||||
}
|
||||
appendMatterUnionFilter(cnd, lineFilter.getUnionId());
|
||||
}
|
||||
|
||||
private LineFilter parseLineFilter(String value) {
|
||||
int delimiterIndex = value.indexOf("|");
|
||||
if (delimiterIndex < 0) {
|
||||
return new LineFilter(value, null);
|
||||
}
|
||||
return new LineFilter(value.substring(0, delimiterIndex), value.substring(delimiterIndex + 1));
|
||||
}
|
||||
|
||||
private void appendMatterUnionFilter(Cnd cnd, String unionId) {
|
||||
if (unionId == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.or("m.unionId", "IS", null);
|
||||
group.or("m.unionId", "=", "");
|
||||
cnd.and(group);
|
||||
return;
|
||||
}
|
||||
cnd.and("m.unionId", "=", unionId);
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
if (ledger == null) {
|
||||
return "";
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END AS lineName
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN sys_union mu ON mu.id = m.unionId
|
||||
WHERE t.id = @ledgerId
|
||||
""");
|
||||
sql.setParam("ledgerId", ledger.getId());
|
||||
sql.setCallback(Sqls.callback.str());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return StrUtil.blankToDefault(sql.getString(), ledger.getLineName());
|
||||
}
|
||||
|
||||
private static class LineFilter {
|
||||
private final String lineId;
|
||||
private final String unionId;
|
||||
|
||||
private LineFilter(String lineId, String unionId) {
|
||||
this.lineId = lineId;
|
||||
this.unionId = unionId;
|
||||
}
|
||||
|
||||
private String getLineId() {
|
||||
return lineId;
|
||||
}
|
||||
|
||||
private String getUnionId() {
|
||||
return unionId;
|
||||
}
|
||||
}
|
||||
|
||||
private String currentUnionId() {
|
||||
return SecurityUtil.getUnionId();
|
||||
}
|
||||
|
||||
private String currentUnionName() {
|
||||
String unionId = currentUnionId();
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
return "";
|
||||
}
|
||||
Sys_union union = tourLedgerService.dao().fetch(Sys_union.class, unionId);
|
||||
return union == null ? "" : StrUtil.blankToDefault(union.getName(), "");
|
||||
}
|
||||
|
||||
private String getOrderColumn(String orderName) {
|
||||
if ("year".equals(orderName)) {
|
||||
return "t.`year`";
|
||||
}
|
||||
if ("jobNo".equals(orderName)) {
|
||||
return "t.jobNo";
|
||||
}
|
||||
if ("userName".equals(orderName)) {
|
||||
return "t.userName";
|
||||
}
|
||||
if ("lineName".equals(orderName)) {
|
||||
return """
|
||||
CASE
|
||||
WHEN m.id IS NULL THEN COALESCE(NULLIF(l.lineName, ''), t.lineName)
|
||||
ELSE CONCAT(
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName),
|
||||
'(',
|
||||
CASE
|
||||
WHEN IFNULL(m.unionId, '') = '' THEN '校工会'
|
||||
ELSE IFNULL(mu.name, '')
|
||||
END,
|
||||
')'
|
||||
)
|
||||
END
|
||||
""";
|
||||
}
|
||||
if ("travelPeriod".equals(orderName)) {
|
||||
return "COALESCE(m.travelStartTime, tp.travelPeriod)";
|
||||
}
|
||||
if ("lineType".equals(orderName)) {
|
||||
return "t.lineType";
|
||||
}
|
||||
if ("signupTime".equals(orderName)) {
|
||||
return "t.signupTime";
|
||||
}
|
||||
if ("familyCount".equals(orderName)) {
|
||||
return "familyCount";
|
||||
}
|
||||
if ("joined".equals(orderName)) {
|
||||
return "t.joined";
|
||||
}
|
||||
return "t.`year`";
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.mode;
|
||||
|
||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import com.budwk.app.base.model.ExcelImportError;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class TourLedgerImportExcelMode extends ExcelImportError {
|
||||
|
||||
@Excel(name = "年度")
|
||||
private Integer year;
|
||||
|
||||
@Excel(name = "工号")
|
||||
private String jobNo;
|
||||
|
||||
@Excel(name = "姓名")
|
||||
private String userName;
|
||||
|
||||
@Excel(name = "报名时间", format = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date signupTime;
|
||||
|
||||
@Excel(name = "线路名称")
|
||||
private String lineName;
|
||||
|
||||
@Excel(name = "线路类型")
|
||||
private String lineType;
|
||||
|
||||
@Excel(name = "是否参加")
|
||||
private String joined;
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 疗休养教职工报名台账。
|
||||
* 后续报名模块完成后,将已报名或已参加的教职工写入本表,台账页负责跨年度查询和详情查看。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_ledger")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养台账")
|
||||
public class TourLedger extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("年度")
|
||||
@ColDefine(type = ColType.INT, width = 4)
|
||||
private Integer year;
|
||||
|
||||
@Column
|
||||
@Comment("工号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String jobNo;
|
||||
|
||||
@Column
|
||||
@Comment("姓名")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String userName;
|
||||
|
||||
@Column
|
||||
@Comment("性别")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String gender;
|
||||
|
||||
@Column
|
||||
@Comment("身份证号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String idCard;
|
||||
|
||||
@Column
|
||||
@Comment("所在单位ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unitId;
|
||||
|
||||
@Column
|
||||
@Comment("所在单位")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String unitName;
|
||||
|
||||
@Column
|
||||
@Comment("所在工会ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unionId;
|
||||
|
||||
@Column
|
||||
@Comment("所在工会")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String unionName;
|
||||
|
||||
@Column
|
||||
@Comment("报名时间")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String signupTime;
|
||||
|
||||
@Column
|
||||
@Comment("报名事项ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String matterId;
|
||||
|
||||
@Column
|
||||
@Comment("报名线路ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String lineId;
|
||||
|
||||
@Column
|
||||
@Comment("报名线路")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String lineName;
|
||||
|
||||
@Column
|
||||
@Comment("线路类型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String lineType;
|
||||
|
||||
@Column
|
||||
@Comment("报名酒店")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String hotelName;
|
||||
|
||||
@Column
|
||||
@Comment("旅行社ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String travelAgencyId;
|
||||
|
||||
@Column
|
||||
@Comment("旅行社")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String travelAgencyName;
|
||||
|
||||
@Column
|
||||
@Comment("是否携带家属")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean hasFamily;
|
||||
|
||||
@Column
|
||||
@Comment("意向拼床人")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String intendedRoommate;
|
||||
|
||||
@Column
|
||||
@Comment("床型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String bedType;
|
||||
|
||||
@Column
|
||||
@Comment("床位信息")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String bedInfo;
|
||||
|
||||
@Column
|
||||
@Comment("是否参加")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean joined;
|
||||
|
||||
@Column
|
||||
@Comment("是否报销")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean reimbursed;
|
||||
|
||||
@Column
|
||||
@Comment("报销超出费用")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean overCostReimbursed;
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 直系亲属线路报名信息。
|
||||
* 与普通携带亲属信息分表存放,用于直系亲属线路的专属申请信息。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_ledger_direct_relative")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养直系亲属线路报名信息")
|
||||
public class TourLedgerDirectRelative extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("台账ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String ledgerId;
|
||||
|
||||
@Column
|
||||
@Comment("亲属姓名")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String relativeName;
|
||||
|
||||
@Column
|
||||
@Comment("所在单位")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String unitName;
|
||||
|
||||
@Column
|
||||
@Comment("亲属关系编码")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String relationshipCode;
|
||||
|
||||
@Column
|
||||
@Comment("亲属关系")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String relationshipName;
|
||||
|
||||
@Column
|
||||
@Comment("线路ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String lineId;
|
||||
|
||||
@Column
|
||||
@Comment("线路名称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String lineName;
|
||||
|
||||
@Column
|
||||
@Comment("出行开始日期")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String travelStartTime;
|
||||
|
||||
@Column
|
||||
@Comment("出行结束日期")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String travelEndTime;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 疗休养台账家属信息。
|
||||
* 与教职工台账通过 ledgerId 关联,用于查看教职工携带家属的历史记录。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_ledger_family")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养台账家属信息")
|
||||
public class TourLedgerFamily extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("台账ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String ledgerId;
|
||||
|
||||
@Column
|
||||
@Comment("教职工工号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String staffJobNo;
|
||||
|
||||
@Column
|
||||
@Comment("教职工姓名")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String staffName;
|
||||
|
||||
@Column
|
||||
@Comment("家属姓名")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String familyName;
|
||||
|
||||
@Column
|
||||
@Comment("性别")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String gender;
|
||||
|
||||
@Column
|
||||
@Comment("身份证号码")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String idCard;
|
||||
|
||||
@Column
|
||||
@Comment("年龄")
|
||||
@ColDefine(type = ColType.INT, width = 3)
|
||||
private Integer age;
|
||||
|
||||
@Column
|
||||
@Comment("床型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String bedType;
|
||||
|
||||
@Column
|
||||
@Comment("床位")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String bedInfo;
|
||||
|
||||
@Column
|
||||
@Comment("意向拼床人")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String intendedRoommate;
|
||||
|
||||
@Column
|
||||
@Comment("关系")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String relationship;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 疗休养线路管理。
|
||||
* 当前阶段先维护线路基础信息,后续报名、台账等模块可通过线路ID继续关联。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_line")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养线路")
|
||||
public class TourLine extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("创建年度")
|
||||
@ColDefine(type = ColType.INT, width = 4)
|
||||
private Integer year;
|
||||
|
||||
@Column
|
||||
@Comment("线路编号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String lineCode;
|
||||
|
||||
@Column
|
||||
@Comment("线路名称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String lineName;
|
||||
|
||||
@Column
|
||||
@Comment("旅行社ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String travelAgencyId;
|
||||
|
||||
@Column
|
||||
@Comment("创建人ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String creatorUserId;
|
||||
|
||||
@Column
|
||||
@Comment("创建人")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String creatorName;
|
||||
|
||||
@Column
|
||||
@Comment("所在单位ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unitId;
|
||||
|
||||
@Column
|
||||
@Comment("所在单位")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String unitName;
|
||||
|
||||
@Column
|
||||
@Comment("线路类型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String lineType;
|
||||
|
||||
@Column
|
||||
@Comment("时间标段ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String lotId;
|
||||
|
||||
@Column
|
||||
@Comment("线路内容")
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
private String lineContent;
|
||||
|
||||
@Column
|
||||
@Comment("移动端缩略图")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String mobileThumb;
|
||||
|
||||
@Column
|
||||
@Comment("是否对外开放")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean openFlag;
|
||||
|
||||
@Column
|
||||
@Comment("是否直系亲属线路")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean directFamilyUnitLine;
|
||||
|
||||
@Column
|
||||
@Comment("激活状态")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean enabled;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 疗休养事项。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_matter")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养事项")
|
||||
public class TourMatter extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("年度")
|
||||
@ColDefine(type = ColType.INT, width = 4)
|
||||
private Integer year;
|
||||
|
||||
@Column
|
||||
@Comment("事项名称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String matterName;
|
||||
|
||||
@Column
|
||||
@Comment("疗休养配置ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String settingId;
|
||||
|
||||
@Column
|
||||
@Comment("创建人ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String creatorUserId;
|
||||
|
||||
@Column
|
||||
@Comment("创建人")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String creatorName;
|
||||
|
||||
@Column
|
||||
@Comment("所属工会ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unionId;
|
||||
|
||||
@Column
|
||||
@Comment("组织形式")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String organizationType;
|
||||
|
||||
@Column
|
||||
@Comment("移动端缩略图")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String mobileThumb;
|
||||
|
||||
@Column
|
||||
@Comment("线路ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String lineId;
|
||||
|
||||
@Column
|
||||
@Comment("报名开始时间")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String signupStartTime;
|
||||
|
||||
@Column
|
||||
@Comment("报名结束时间")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String signupEndTime;
|
||||
|
||||
@Column
|
||||
@Comment("出行开始时间")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String travelStartTime;
|
||||
|
||||
@Column
|
||||
@Comment("出行结束时间")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String travelEndTime;
|
||||
|
||||
@Column
|
||||
@Comment("联系人")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String contactName;
|
||||
|
||||
@Column
|
||||
@Comment("联系方式")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String contactPhone;
|
||||
|
||||
@Column
|
||||
@Comment("最少成团人数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer minGroupPeople;
|
||||
|
||||
@Column
|
||||
@Comment("最多成团人数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer maxGroupPeople;
|
||||
|
||||
@Column
|
||||
@Comment("预计费用")
|
||||
@ColDefine(customType = "decimal(10,2)")
|
||||
private BigDecimal estimatedCost;
|
||||
|
||||
@Column
|
||||
@Comment("事项状态")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean enabled;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 疗休养基础配置。
|
||||
* 这里先沉淀创建事项会复用的基础字段,后续线路、报名等阶段可以继续通过配置ID关联扩展。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_setting")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养配置")
|
||||
public class TourSetting extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("年度")
|
||||
@ColDefine(type = ColType.INT, width = 4)
|
||||
private Integer year;
|
||||
|
||||
@Column
|
||||
@Comment("疗休养配置名称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String configName;
|
||||
|
||||
@Column
|
||||
@Comment("疗休养类型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String tourType;
|
||||
|
||||
@Column
|
||||
@Comment("可参加人员范围ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String activityGroupId;
|
||||
|
||||
@Column
|
||||
@Comment("排序编号")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer sortNo;
|
||||
|
||||
@Column
|
||||
@Comment("最少成团人数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer minGroupPeople;
|
||||
|
||||
@Column
|
||||
@Comment("最多成团人数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer maxGroupPeople;
|
||||
|
||||
@Column
|
||||
@Comment("省外几年去一次")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer outProvinceYears;
|
||||
|
||||
@Column
|
||||
@Comment("省外人数占比")
|
||||
@ColDefine(customType = "decimal(10,2)")
|
||||
private BigDecimal outProvinceRatio;
|
||||
|
||||
@Column
|
||||
@Comment("省外人数占比类型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String outProvinceRatioType;
|
||||
|
||||
@Column
|
||||
@Comment("省外固定人数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer outProvinceFixedPeople;
|
||||
|
||||
@Column
|
||||
@Comment("周期开始年度")
|
||||
@ColDefine(type = ColType.INT, width = 4)
|
||||
private Integer cycleStartYear;
|
||||
|
||||
@Column
|
||||
@Comment("周期结束年度")
|
||||
@ColDefine(type = ColType.INT, width = 4)
|
||||
private Integer cycleEndYear;
|
||||
|
||||
@Column
|
||||
@Comment("周期内总费用")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer cycleTotalCost;
|
||||
|
||||
@Column
|
||||
@Comment("周期允许次数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer cycleAllowedTimes;
|
||||
|
||||
@Column
|
||||
@Comment("是否允许携带家属")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean allowFamily;
|
||||
|
||||
@Column
|
||||
@Comment("是否填报床位信息")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean fillBedInfo;
|
||||
|
||||
@Column
|
||||
@Comment("是否启用")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean enabled;
|
||||
|
||||
/**
|
||||
* 标段管理沿用老疗休养配置的子表设计,后续线路、旅行社等模块可通过标段ID继续关联。
|
||||
*/
|
||||
@Many(field = "settingId")
|
||||
private List<TourSettingLot> lots;
|
||||
|
||||
@Column
|
||||
@Comment("服务须知")
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
private String serviceNotice;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 疗休养配置标段。
|
||||
* 标段从基础配置中拆成子表,便于后续线路、目的地、报名等模块复用同一标段口径。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_setting_lot")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养配置标段")
|
||||
public class TourSettingLot extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("所属配置ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String settingId;
|
||||
|
||||
@Column
|
||||
@Comment("标段名称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String lotName;
|
||||
|
||||
@Column
|
||||
@Comment("标段值")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String lotValue;
|
||||
|
||||
@Column
|
||||
@Comment("标段费用")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer activityCost;
|
||||
|
||||
@Column
|
||||
@Comment("允许超出报销")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
private Boolean allowOverReimbursement;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 旅行社管理。
|
||||
* 先维护疗休养线路创建会复用的旅行社基础信息,后续线路模块可通过旅行社ID关联。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("tour_travel_agency")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("普惠疗休养旅行社")
|
||||
public class TourTravelAgency extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("年度")
|
||||
@ColDefine(type = ColType.INT, width = 4)
|
||||
private Integer year;
|
||||
|
||||
@Column
|
||||
@Comment("旅行社编号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String agencyCode;
|
||||
|
||||
@Column
|
||||
@Comment("旅行社名称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String agencyName;
|
||||
|
||||
@Column
|
||||
@Comment("联系人")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String contactName;
|
||||
|
||||
@Column
|
||||
@Comment("联系人手机")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String contactPhone;
|
||||
|
||||
@Column
|
||||
@Comment("邮箱")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String email;
|
||||
|
||||
@Column
|
||||
@Comment("备注")
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
private String remark;
|
||||
|
||||
@Column
|
||||
@Comment("移动端缩略图")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||
private String mobileThumb;
|
||||
|
||||
@Column
|
||||
@Comment("激活状态")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("1")
|
||||
private Boolean enabled;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
|
||||
public interface TourLedgerDirectRelativeService extends BaseService<TourLedgerDirectRelative> {
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
|
||||
public interface TourLedgerFamilyService extends BaseService<TourLedgerFamily> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
|
||||
public interface TourLedgerService extends BaseService<TourLedger> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLine;
|
||||
|
||||
public interface TourLineService extends BaseService<TourLine> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourMatter;
|
||||
|
||||
public interface TourMatterService extends BaseService<TourMatter> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourSetting;
|
||||
|
||||
public interface TourSettingService extends BaseService<TourSetting> {
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourTravelAgency;
|
||||
|
||||
public interface TourTravelAgencyService extends BaseService<TourTravelAgency> {
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class TourLedgerDirectRelativeServiceImpl extends BaseServiceImpl<TourLedgerDirectRelative> implements TourLedgerDirectRelativeService {
|
||||
|
||||
public TourLedgerDirectRelativeServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class TourLedgerFamilyServiceImpl extends BaseServiceImpl<TourLedgerFamily> implements TourLedgerFamilyService {
|
||||
|
||||
public TourLedgerFamilyServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class TourLedgerServiceImpl extends BaseServiceImpl<TourLedger> implements TourLedgerService {
|
||||
|
||||
public TourLedgerServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLine;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLineService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class TourLineServiceImpl extends BaseServiceImpl<TourLine> implements TourLineService {
|
||||
|
||||
public TourLineServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourMatter;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourMatterService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class TourMatterServiceImpl extends BaseServiceImpl<TourMatter> implements TourMatterService {
|
||||
|
||||
public TourMatterServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourSetting;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourSettingService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class TourSettingServiceImpl extends BaseServiceImpl<TourSetting> implements TourSettingService {
|
||||
|
||||
public TourSettingServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourTravelAgency;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourTravelAgencyService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class TourTravelAgencyServiceImpl extends BaseServiceImpl<TourTravelAgency> implements TourTravelAgencyService {
|
||||
|
||||
public TourTravelAgencyServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -82,7 +82,9 @@ public class ProposalCommonController {
|
||||
@SaCheckLogin
|
||||
@ApiOperation("承办单位列表")
|
||||
public Result listUnderTake() {
|
||||
List<ProposalUndertake> list = dao.query(ProposalUndertake.class, Cnd.NEW());
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("enable","=", true);
|
||||
List<ProposalUndertake> list = dao.query(ProposalUndertake.class, cnd);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.zhgh.democratic.proposal.controller.config;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNode;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
@@ -20,10 +21,12 @@ import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
|
||||
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -37,6 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 提案承办单位配置
|
||||
@@ -98,6 +102,7 @@ public class ProposalConfigUnitController {
|
||||
cnd.where().orLike("u2.loginname", pageForm.getSearchKeyword());
|
||||
cnd.where().orLike("t1.name", pageForm.getSearchKeyword());
|
||||
}
|
||||
cnd.and("t1.enable","=", true);
|
||||
cnd.asc("t1.code");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
@@ -124,6 +129,20 @@ public class ProposalConfigUnitController {
|
||||
return proposalUndertake;
|
||||
}).toList();
|
||||
dao.fastInsert(proposalUndertakes);
|
||||
|
||||
dao.update(ProposalUndertake.class, Chain.make("enable",true), Cnd.where("1","=","1"));
|
||||
Cnd cnd = Cnd.NEW();
|
||||
SqlExpressionGroup group = Cnd.NEW().where();
|
||||
group.and("delFlag", "=", true);
|
||||
cnd.and(group);
|
||||
List<Sys_unit> delFlagUnit = dao.query(Sys_unit.class, cnd);
|
||||
if(CollectionUtil.isNotEmpty(delFlagUnit)){
|
||||
List<String> unitCodeList = delFlagUnit.stream().map(Sys_unit::getUnitcode).collect(Collectors.toList());
|
||||
Cnd cndUnit = Cnd.NEW();
|
||||
cndUnit.where().andInStrList("code", unitCodeList);
|
||||
dao.update(ProposalUndertake.class, Chain.make("enable",false), cndUnit);
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
ALTER TABLE activity_user_scope
|
||||
ADD COLUMN groupType INT(2) NULL COMMENT '分组类型 1.结果分组 2.SQL条件分组' AFTER userId;
|
||||
|
||||
ALTER TABLE activity_user_scope
|
||||
ADD COLUMN groupSql LONGTEXT NULL COMMENT 'SQL条件分组保存的查询SQL' AFTER groupType;
|
||||
|
||||
ALTER TABLE activity_user_scope
|
||||
ADD INDEX INDEX_ACTIVITY_USER_SCOPE_GROUPID_USERID (groupId, userId);
|
||||
@@ -0,0 +1,122 @@
|
||||
-- 普惠疗休养平台电脑端菜单。
|
||||
-- 使用 permission 做幂等判断,避免同一环境重复执行时插入重复菜单。
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bb1a10001',
|
||||
'',
|
||||
LPAD(IFNULL(MAX(CAST(path AS UNSIGNED)), 0) + 1, 4, '0'),
|
||||
'普惠疗休养',
|
||||
'Tour',
|
||||
'menu',
|
||||
'',
|
||||
'',
|
||||
'ti-map-alt',
|
||||
1,
|
||||
0,
|
||||
'tour',
|
||||
NULL,
|
||||
991,
|
||||
1,
|
||||
'',
|
||||
UNIX_TIMESTAMP(NOW()) * 1000,
|
||||
'',
|
||||
UNIX_TIMESTAMP(NOW()) * 1000,
|
||||
0,
|
||||
'PC',
|
||||
NULL,
|
||||
NULL,
|
||||
'p',
|
||||
0,
|
||||
0
|
||||
FROM sys_menu
|
||||
WHERE (parentId = '' OR parentId IS NULL)
|
||||
AND CHAR_LENGTH(path) = 4
|
||||
HAVING NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10002', p.id, CONCAT(p.path, '0001'), '疗休养设置', 'Tour Setting', 'menu', '/platform/tour/setting', 'data-pjax', '', 1, 0, 'tour.setting', NULL, 1, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.setting') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10003', p.id, CONCAT(p.path, '0002'), '旅行社管理', 'Travel Agency', 'menu', '/platform/tour/travelAgency', 'data-pjax', '', 1, 0, 'tour.travelAgency', NULL, 2, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.travelAgency') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10004', p.id, CONCAT(p.path, '0003'), '线路管理', 'Route Manage', 'menu', '/platform/tour/route', 'data-pjax', '', 1, 0, 'tour.route', NULL, 3, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'x', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.route') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10005', p.id, CONCAT(p.path, '0004'), '疗休养事项', 'Tour Matter', 'menu', '/platform/tour/matter', 'data-pjax', '', 1, 0, 'tour.matter', NULL, 4, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.matter') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10006', p.id, CONCAT(p.path, '0005'), '疗休养报名', 'Tour Signup', 'menu', '/platform/tour/signup', 'data-pjax', '', 1, 0, 'tour.signup', NULL, 5, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.signup') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10008', p.id, CONCAT(p.path, '0006'), '我的报名', 'My Signup', 'menu', '/platform/tour/mysignup', 'data-pjax', '', 1, 0, 'tour.mysignup', NULL, 6, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'w', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.mysignup') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10009', p.id, CONCAT(p.path, '0007'), '分工会查询', 'Union Ledger', 'menu', '/platform/tour/unionledger', 'data-pjax', '', 1, 0, 'tour.unionledger', NULL, 7, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'f', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.unionledger') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10011', p.id, CONCAT(p.path, '0010'), '分工会审核', 'Union Approval', 'menu', '/platform/tour/unionApproval', 'data-pjax', '', 1, 0, 'tour.unionApproval', NULL, 8, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'f', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.unionApproval') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10012', p.id, CONCAT(p.path, '0011'), '校工会审核', 'School Union Approval', 'menu', '/platform/tour/schoolUnionApproval', 'data-pjax', '', 1, 0, 'tour.schoolUnionApproval', NULL, 9, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'x', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.schoolUnionApproval') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10007', p.id, CONCAT(p.path, '0008'), '疗休养台账', 'Tour Ledger', 'menu', '/platform/tour/ledger', 'data-pjax', '', 1, 0, 'tour.ledger', NULL, 10, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.ledger') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10010', p.id, CONCAT(p.path, '0009'), '线路成团', 'Tour Group', 'menu', '/platform/tour/group', 'data-pjax', '', 1, 0, 'tour.group', NULL, 11, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'x', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.group') t);
|
||||
|
||||
-- 给系统管理员默认授权,其他角色可在角色管理中按需分配。
|
||||
INSERT INTO sys_role_menu (roleId, menuId)
|
||||
SELECT r.id, m.id
|
||||
FROM sys_role r
|
||||
JOIN sys_menu m ON m.permission IN (
|
||||
'tour',
|
||||
'tour.setting',
|
||||
'tour.travelAgency',
|
||||
'tour.route',
|
||||
'tour.matter',
|
||||
'tour.signup',
|
||||
'tour.group',
|
||||
'tour.mysignup',
|
||||
'tour.unionledger',
|
||||
'tour.unionApproval',
|
||||
'tour.schoolUnionApproval',
|
||||
'tour.ledger'
|
||||
)
|
||||
LEFT JOIN sys_role_menu rm ON rm.roleId = r.id AND rm.menuId = m.id
|
||||
WHERE r.code = 'SYSADMIN'
|
||||
AND rm.roleId IS NULL;
|
||||
@@ -0,0 +1,253 @@
|
||||
-- 普惠疗休养系统字典初始化。
|
||||
-- 执行后可在 /platform/sys/dict 页面看到:疗休养(Tour) -> 组织形式/疗休养类型/线路类型/床型。
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict001', '', '9500', '疗休养', '普惠疗休养平台字典', 'Tour', 0, 9500, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'Tour') t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict002', p.id, CONCAT(p.path, '0001'), '组织形式', '疗休养组织形式', 'organizationType', 0, 1, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'organizationType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict003', p.id, CONCAT(p.path, '0001'), '校工会组织', '疗休养组织形式', 'schoolUnion', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'organizationType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'schoolUnion' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict004', p.id, CONCAT(p.path, '0002'), '分工会组织', '疗休养组织形式', 'branchUnion', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'organizationType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'branchUnion' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict005', p.id, CONCAT(p.path, '0003'), '个人组织', '疗休养组织形式', 'personal', 0, 3, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'organizationType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'personal' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict006', p.id, CONCAT(p.path, '0002'), '疗休养类型', '疗休养类型', 'tourType', 0, 2, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'tourType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict007', p.id, CONCAT(p.path, '0001'), '普惠性疗休养', '疗休养类型', 'inclusiveTour', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'tourType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'inclusiveTour' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict008', p.id, CONCAT(p.path, '0002'), '优秀职工疗休养', '疗休养类型', 'excellentWorkerTour', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'tourType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'excellentWorkerTour' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict009', p.id, CONCAT(p.path, '0003'), '线路类型', '线路类型', 'lineType', 0, 3, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'lineType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict010', p.id, CONCAT(p.path, '0001'), '省内线路', '线路类型', 'inProvinceLine', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'lineType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'inProvinceLine' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict011', p.id, CONCAT(p.path, '0002'), '省外线路', '线路类型', 'outProvinceLine', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'lineType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'outProvinceLine' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict020', p.id, CONCAT(p.path, '0004'), '床型', '床型', 'bedType', 0, 4, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'bedType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict021', p.id, CONCAT(p.path, '0001'), '双人床', '床型', 'doubleBed', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'bedType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'doubleBed' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict022', p.id, CONCAT(p.path, '0002'), '单人床', '床型', 'singleBed', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'bedType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'singleBed' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict023', p.id, CONCAT(p.path, '0003'), '大床', '床型', 'kingBed', 0, 3, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'bedType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'kingBed' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict012', '', '9600', '亲属关系', '亲属关系', 'familyRelationship', 0, 9600, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'familyRelationship') t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict013', p.id, CONCAT(p.path, '0001'), '直系亲属', '亲属关系', 'directRelative', 0, 1, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'familyRelationship'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'directRelative' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict014', p.id, CONCAT(p.path, '0001'), '父亲', '直系亲属', 'father', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'father' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict015', p.id, CONCAT(p.path, '0002'), '母亲', '直系亲属', 'mother', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'mother' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict016', p.id, CONCAT(p.path, '0003'), '丈夫', '直系亲属', 'husband', 0, 3, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'husband' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict017', p.id, CONCAT(p.path, '0004'), '妻子', '直系亲属', 'wife', 0, 4, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'wife' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict018', p.id, CONCAT(p.path, '0005'), '儿子', '直系亲属', 'son', 0, 5, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'son' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict019', p.id, CONCAT(p.path, '0006'), '女儿', '直系亲属', 'daughter', 0, 6, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'daughter' AND `parentId` = p.id) t);
|
||||
|
||||
UPDATE `sys_dict` SET `hasChildren` = 1 WHERE `code` IN ('Tour', 'organizationType', 'tourType', 'lineType', 'bedType', 'familyRelationship', 'directRelative');
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Add matter reference so signup records are unique per travel period/matter.
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD COLUMN `matterId` varchar(32) DEFAULT NULL COMMENT '报名事项ID' AFTER `signupTime`;
|
||||
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD KEY `idx_tour_ledger_matter` (`matterId`),
|
||||
ADD KEY `idx_tour_ledger_matter_job` (`matterId`, `jobNo`);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD COLUMN `overCostReimbursed` tinyint(1) DEFAULT 0 COMMENT '报销超出费用' AFTER `reimbursed`;
|
||||
@@ -0,0 +1,9 @@
|
||||
-- 疗休养台账查询加速索引。
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD KEY `idx_tour_ledger_year_signup` (`year`, `delFlag`, `signupTime`),
|
||||
ADD KEY `idx_tour_ledger_year_line` (`year`, `lineId`, `delFlag`),
|
||||
ADD KEY `idx_tour_ledger_year_union_type` (`year`, `unionId`, `lineType`, `delFlag`),
|
||||
ADD KEY `idx_tour_ledger_year_job` (`year`, `jobNo`, `delFlag`);
|
||||
|
||||
ALTER TABLE `wf_process_instance`
|
||||
ADD KEY `idx_wf_process_instance_business_state` (`businessNo`, `state`);
|
||||
@@ -0,0 +1,21 @@
|
||||
-- 直系亲属线路报名信息表,独立于普通携带亲属信息表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_ledger_direct_relative` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`ledgerId` varchar(32) DEFAULT NULL COMMENT '台账ID',
|
||||
`relativeName` varchar(100) DEFAULT NULL COMMENT '亲属姓名',
|
||||
`unitName` varchar(100) DEFAULT NULL COMMENT '所在单位',
|
||||
`relationshipCode` varchar(50) DEFAULT NULL COMMENT '亲属关系编码',
|
||||
`relationshipName` varchar(50) DEFAULT NULL COMMENT '亲属关系',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`lineName` varchar(100) DEFAULT NULL COMMENT '线路名称',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始日期',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束日期',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_ledger_direct_relative_ledger` (`ledgerId`),
|
||||
KEY `idx_tour_ledger_direct_relative_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养直系亲属线路报名信息';
|
||||
@@ -0,0 +1,10 @@
|
||||
-- 线路管理增加创建人和所在单位业务字段。
|
||||
ALTER TABLE `tour_line`
|
||||
ADD COLUMN `creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID' AFTER `travelAgencyId`,
|
||||
ADD COLUMN `creatorName` varchar(100) DEFAULT NULL COMMENT '创建人' AFTER `creatorUserId`,
|
||||
ADD COLUMN `unitId` varchar(32) DEFAULT NULL COMMENT '所在单位ID' AFTER `creatorName`,
|
||||
ADD COLUMN `unitName` varchar(100) DEFAULT NULL COMMENT '所在单位' AFTER `unitId`;
|
||||
|
||||
ALTER TABLE `tour_line`
|
||||
ADD KEY `idx_tour_line_creator` (`creatorUserId`),
|
||||
ADD KEY `idx_tour_line_unit` (`unitId`);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 线路管理增加是否直系亲属线路字段,默认否。
|
||||
ALTER TABLE `tour_line`
|
||||
ADD COLUMN `directFamilyUnitLine` tinyint(1) DEFAULT 0 COMMENT '是否直系亲属线路' AFTER `openFlag`;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 线路管理增加是否对外开放字段,默认是。
|
||||
ALTER TABLE `tour_line`
|
||||
ADD COLUMN `openFlag` tinyint(1) DEFAULT 1 COMMENT '是否对外开放' AFTER `mobileThumb`;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- 疗休养事项增加创建人字段。
|
||||
ALTER TABLE `tour_matter`
|
||||
ADD COLUMN `creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID' AFTER `settingId`,
|
||||
ADD COLUMN `creatorName` varchar(100) DEFAULT NULL COMMENT '创建人' AFTER `creatorUserId`;
|
||||
|
||||
ALTER TABLE `tour_matter`
|
||||
ADD KEY `idx_tour_matter_creator` (`creatorUserId`);
|
||||
@@ -0,0 +1,26 @@
|
||||
-- 疗休养事项批次表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter_batch` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`matterId` varchar(32) DEFAULT NULL COMMENT '事项ID',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`batchName` varchar(100) DEFAULT NULL COMMENT '批次名称',
|
||||
`signupStartTime` varchar(20) DEFAULT NULL COMMENT '报名开始时间',
|
||||
`signupEndTime` varchar(20) DEFAULT NULL COMMENT '报名结束时间',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始时间',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束时间',
|
||||
`changeDeadline` varchar(20) DEFAULT NULL COMMENT '变更截止时间',
|
||||
`contactName` varchar(30) DEFAULT NULL COMMENT '联系人',
|
||||
`contactPhone` varchar(30) DEFAULT NULL COMMENT '联系方式',
|
||||
`minGroupPeople` int DEFAULT NULL COMMENT '最少成团人数',
|
||||
`maxGroupPeople` int DEFAULT NULL COMMENT '最多成团人数',
|
||||
`estimatedCost` decimal(10,2) DEFAULT NULL COMMENT '预计费用',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_matter_batch_matter` (`matterId`),
|
||||
KEY `idx_tour_matter_batch_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项批次';
|
||||
@@ -0,0 +1,25 @@
|
||||
-- 疗休养事项表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`matterName` varchar(100) DEFAULT NULL COMMENT '事项名称',
|
||||
`settingId` varchar(32) DEFAULT NULL COMMENT '疗休养配置ID',
|
||||
`creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID',
|
||||
`creatorName` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`unionId` varchar(32) DEFAULT NULL COMMENT '所属工会ID',
|
||||
`organizationType` varchar(100) DEFAULT NULL COMMENT '组织形式',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '事项状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_matter_year_name` (`year`, `matterName`),
|
||||
KEY `idx_tour_matter_year` (`year`),
|
||||
KEY `idx_tour_matter_creator` (`creatorUserId`),
|
||||
KEY `idx_tour_matter_setting` (`settingId`),
|
||||
KEY `idx_tour_matter_union` (`unionId`),
|
||||
KEY `idx_tour_matter_org_type` (`organizationType`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项';
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Add activity user scope reference for tour settings.
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `activityGroupId` varchar(32) DEFAULT NULL COMMENT '可参加人员范围ID' AFTER `tourType`;
|
||||
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD KEY `idx_tour_setting_activity_group` (`activityGroupId`);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 疗休养配置增加周期允许次数字段。
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `cycleAllowedTimes` int DEFAULT NULL COMMENT '周期允许次数' AFTER `cycleTotalCost`;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `cycleTotalCost` int DEFAULT NULL COMMENT '周期内总费用' AFTER `cycleEndYear`;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Add optional cycle year range for tour settings.
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `cycleStartYear` int DEFAULT NULL COMMENT '周期开始年度' AFTER `outProvinceRatio`,
|
||||
ADD COLUMN `cycleEndYear` int DEFAULT NULL COMMENT '周期结束年度' AFTER `cycleStartYear`;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 疗休养配置增加是否填报床位信息字段,默认开启以兼容历史配置。
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `fillBedInfo` tinyint(1) DEFAULT 1 COMMENT '是否填报床位信息' AFTER `allowFamily`;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `outProvinceRatioType` varchar(50) DEFAULT '当年报名人数' COMMENT '省外人数占比类型' AFTER `outProvinceRatio`,
|
||||
ADD COLUMN `outProvinceFixedPeople` int DEFAULT 0 COMMENT '省外固定人数' AFTER `outProvinceRatioType`;
|
||||
@@ -0,0 +1,183 @@
|
||||
-- 普惠疗休养基础配置表。
|
||||
-- 若生产环境未开启 Nutz 自动建表,请先执行本脚本再使用“疗休养设置”菜单。
|
||||
CREATE TABLE IF NOT EXISTS `tour_setting` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`configName` varchar(100) DEFAULT NULL COMMENT '疗休养配置名称',
|
||||
`tourType` varchar(50) DEFAULT NULL COMMENT '疗休养类型',
|
||||
`activityGroupId` varchar(32) DEFAULT NULL COMMENT '可参加人员范围ID',
|
||||
`sortNo` int DEFAULT NULL COMMENT '排序编号',
|
||||
`minGroupPeople` int DEFAULT NULL COMMENT '最少成团人数',
|
||||
`maxGroupPeople` int DEFAULT NULL COMMENT '最多成团人数',
|
||||
`outProvinceYears` int DEFAULT NULL COMMENT '省外几年去一次',
|
||||
`outProvinceRatio` decimal(10,2) DEFAULT NULL COMMENT '省外人数占比',
|
||||
`outProvinceRatioType` varchar(50) DEFAULT '当年报名人数' COMMENT '省外人数占比类型',
|
||||
`outProvinceFixedPeople` int DEFAULT 0 COMMENT '省外固定人数',
|
||||
`cycleStartYear` int DEFAULT NULL COMMENT '周期开始年度',
|
||||
`cycleEndYear` int DEFAULT NULL COMMENT '周期结束年度',
|
||||
`cycleTotalCost` int DEFAULT NULL COMMENT '周期内总费用',
|
||||
`cycleAllowedTimes` int DEFAULT NULL COMMENT '周期允许次数',
|
||||
`allowFamily` tinyint(1) DEFAULT 0 COMMENT '是否允许携带家属',
|
||||
`fillBedInfo` tinyint(1) DEFAULT 1 COMMENT '是否填报床位信息',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '是否启用',
|
||||
`serviceNotice` text COMMENT '服务须知',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_setting_year` (`year`),
|
||||
KEY `idx_tour_setting_activity_group` (`activityGroupId`),
|
||||
KEY `idx_tour_setting_sort` (`sortNo`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养配置';
|
||||
|
||||
-- 疗休养配置标段表。
|
||||
-- 标段先挂在配置上维护,后续线路、旅行社、报名等模块可继续通过 lotId 做业务关联。
|
||||
CREATE TABLE IF NOT EXISTS `tour_setting_lot` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`settingId` varchar(32) DEFAULT NULL COMMENT '所属配置ID',
|
||||
`lotName` varchar(50) DEFAULT NULL COMMENT '标段名称',
|
||||
`lotValue` varchar(50) DEFAULT NULL COMMENT '标段值',
|
||||
`activityCost` int DEFAULT NULL COMMENT '标段费用',
|
||||
`allowOverReimbursement` tinyint(1) DEFAULT 0 COMMENT '允许超出报销',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_setting_lot_setting` (`settingId`),
|
||||
KEY `idx_tour_setting_lot_value` (`lotValue`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养配置标段';
|
||||
|
||||
-- 旅行社管理表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_travel_agency` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`agencyCode` varchar(50) DEFAULT NULL COMMENT '旅行社编号',
|
||||
`agencyName` varchar(100) DEFAULT NULL COMMENT '旅行社名称',
|
||||
`contactName` varchar(30) DEFAULT NULL COMMENT '联系人',
|
||||
`contactPhone` varchar(30) DEFAULT NULL COMMENT '联系人手机',
|
||||
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
|
||||
`remark` text COMMENT '备注',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '激活状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_travel_agency_year_code` (`year`, `agencyCode`),
|
||||
KEY `idx_tour_travel_agency_name` (`agencyName`),
|
||||
KEY `idx_tour_travel_agency_contact` (`contactName`, `contactPhone`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养旅行社';
|
||||
|
||||
-- 线路管理表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_line` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '创建年度',
|
||||
`lineCode` varchar(50) DEFAULT NULL COMMENT '线路编号',
|
||||
`lineName` varchar(100) DEFAULT NULL COMMENT '线路名称',
|
||||
`travelAgencyId` varchar(32) DEFAULT NULL COMMENT '旅行社ID',
|
||||
`creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID',
|
||||
`creatorName` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`unitId` varchar(32) DEFAULT NULL COMMENT '所在单位ID',
|
||||
`unitName` varchar(100) DEFAULT NULL COMMENT '所在单位',
|
||||
`lineType` varchar(50) DEFAULT NULL COMMENT '线路类型',
|
||||
`lotId` varchar(32) DEFAULT NULL COMMENT '时间标段ID',
|
||||
`lineContent` text COMMENT '线路内容',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`openFlag` tinyint(1) DEFAULT 1 COMMENT '是否对外开放',
|
||||
`directFamilyUnitLine` tinyint(1) DEFAULT 0 COMMENT '是否直系亲属线路',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '激活状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_line_year_code` (`year`, `lineCode`),
|
||||
KEY `idx_tour_line_year` (`year`),
|
||||
KEY `idx_tour_line_name` (`lineName`),
|
||||
KEY `idx_tour_line_agency` (`travelAgencyId`),
|
||||
KEY `idx_tour_line_creator` (`creatorUserId`),
|
||||
KEY `idx_tour_line_unit` (`unitId`),
|
||||
KEY `idx_tour_line_lot` (`lotId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养线路';
|
||||
|
||||
-- 疗休养事项表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`matterName` varchar(100) DEFAULT NULL COMMENT '事项名称',
|
||||
`settingId` varchar(32) DEFAULT NULL COMMENT '疗休养配置ID',
|
||||
`creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID',
|
||||
`creatorName` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`unionId` varchar(32) DEFAULT NULL COMMENT '所属工会ID',
|
||||
`organizationType` varchar(100) DEFAULT NULL COMMENT '组织形式',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '事项状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_matter_year_name` (`year`, `matterName`),
|
||||
KEY `idx_tour_matter_year` (`year`),
|
||||
KEY `idx_tour_matter_creator` (`creatorUserId`),
|
||||
KEY `idx_tour_matter_setting` (`settingId`),
|
||||
KEY `idx_tour_matter_union` (`unionId`),
|
||||
KEY `idx_tour_matter_org_type` (`organizationType`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项';
|
||||
|
||||
-- 疗休养事项批次表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter_batch` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`matterId` varchar(32) DEFAULT NULL COMMENT '事项ID',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`batchName` varchar(100) DEFAULT NULL COMMENT '批次名称',
|
||||
`signupStartTime` varchar(20) DEFAULT NULL COMMENT '报名开始时间',
|
||||
`signupEndTime` varchar(20) DEFAULT NULL COMMENT '报名结束时间',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始时间',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束时间',
|
||||
`changeDeadline` varchar(20) DEFAULT NULL COMMENT '变更截止时间',
|
||||
`contactName` varchar(30) DEFAULT NULL COMMENT '联系人',
|
||||
`contactPhone` varchar(30) DEFAULT NULL COMMENT '联系方式',
|
||||
`minGroupPeople` int DEFAULT NULL COMMENT '最少成团人数',
|
||||
`maxGroupPeople` int DEFAULT NULL COMMENT '最多成团人数',
|
||||
`estimatedCost` decimal(10,2) DEFAULT NULL COMMENT '预计费用',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_matter_batch_matter` (`matterId`),
|
||||
KEY `idx_tour_matter_batch_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项批次';
|
||||
|
||||
-- 直系亲属线路报名信息表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_ledger_direct_relative` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`ledgerId` varchar(32) DEFAULT NULL COMMENT '台账ID',
|
||||
`relativeName` varchar(100) DEFAULT NULL COMMENT '亲属姓名',
|
||||
`unitName` varchar(100) DEFAULT NULL COMMENT '所在单位',
|
||||
`relationshipCode` varchar(50) DEFAULT NULL COMMENT '亲属关系编码',
|
||||
`relationshipName` varchar(50) DEFAULT NULL COMMENT '亲属关系',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`lineName` varchar(100) DEFAULT NULL COMMENT '线路名称',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始日期',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束日期',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_ledger_direct_relative_ledger` (`ledgerId`),
|
||||
KEY `idx_tour_ledger_direct_relative_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养直系亲属线路报名信息';
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `tour_setting_lot`
|
||||
ADD COLUMN `allowOverReimbursement` tinyint(1) DEFAULT 0 COMMENT '允许超出报销' AFTER `activityCost`;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,353 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="线路名称">
|
||||
<el-input
|
||||
v-model="pageForm.lineName"
|
||||
clearable
|
||||
placeholder="请输入线路名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="线路列表"></table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
:default-sort="{prop: 'lineName', order: 'ascending'}"
|
||||
:row-class-name="tableRowClassName"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="线路名称" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" width="260" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="事项名称" prop="matterName" min-width="200" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所属工会" prop="unionName" min-width="180" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="最少成团人数" prop="minGroupPeople" width="140" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
{{ row.minGroupPeople || 0 }}人
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最多成团人数" prop="maxGroupPeople" width="140" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
{{ row.maxGroupPeople || 0 }}人
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报名人数" prop="signupCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.signupCount || 0) > 0 ? 'success' : 'info'">{{ row.signupCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="成团状态" prop="groupStatusName" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="groupStatusType(row.groupStatus)">{{ row.groupStatusName || '未成团' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="primary" @click="exportLine(row)">导出</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<el-drawer
|
||||
:title="viewTitle"
|
||||
:visible.sync="viewVisible"
|
||||
direction="rtl"
|
||||
size="72%"
|
||||
custom-class="tour-group-view-drawer"
|
||||
:close-on-click-modal="false">
|
||||
<div class="tour-group-view">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="viewForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="viewSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="viewForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="viewSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="viewReset">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<div class="tour-group-view-title">报名人员列表</div>
|
||||
<el-table
|
||||
v-loading="viewLoading"
|
||||
:data="viewTableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="viewPageOrder">
|
||||
<el-table-column label="序号" type="index" :index="viewIndexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="手机号码" prop="mobile" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="身份证号" prop="idCard" min-width="190" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所属工会" prop="unionName" min-width="180" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
<el-row class="el-pagination-container tour-group-view-pagination">
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="viewForm.pageNumber"
|
||||
:page-size="viewForm.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="viewForm.totalCount"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="viewSizeChange"
|
||||
@current-change="viewCurrentChange">
|
||||
</el-pagination>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
unionOptions: [],
|
||||
lineTypeOptions: [],
|
||||
viewVisible: false,
|
||||
viewLoading: false,
|
||||
viewRequestSeq: 0,
|
||||
viewTitle: "",
|
||||
viewRow: {},
|
||||
viewTableData: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "lineName",
|
||||
pageOrderBy: "ascending",
|
||||
year: currentYear,
|
||||
lineName: "",
|
||||
lineType: "",
|
||||
unionId: ""
|
||||
},
|
||||
viewForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
keyword: "",
|
||||
unionId: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.lineName = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.loadLineTypeOptions()
|
||||
this.doSearch()
|
||||
},
|
||||
groupStatusType(status) {
|
||||
if (status === "formed") return "success"
|
||||
if (status === "over") return "danger"
|
||||
return "info"
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyLine(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
if (!row) return false
|
||||
return row.directFamilyUnitLine === true
|
||||
|| row.directFamilyUnitLine === 1
|
||||
|| row.directFamilyUnitLine === "1"
|
||||
},
|
||||
openView(row) {
|
||||
this.viewRow = row || {}
|
||||
this.viewTitle = this.viewRow.lineName || "报名人员"
|
||||
this.viewVisible = true
|
||||
this.viewForm.pageNumber = 1
|
||||
this.viewForm.pageSize = 10
|
||||
this.viewForm.totalCount = 0
|
||||
this.viewForm.pageOrderName = "signupTime"
|
||||
this.viewForm.pageOrderBy = "descending"
|
||||
this.viewForm.keyword = ""
|
||||
this.viewForm.unionId = ""
|
||||
this.viewTableData = []
|
||||
this.loadViewData()
|
||||
},
|
||||
viewSearch() {
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
viewReset() {
|
||||
this.viewForm.keyword = ""
|
||||
this.viewForm.unionId = ""
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
viewIndexMethod(index) {
|
||||
return (this.viewForm.pageNumber - 1) * this.viewForm.pageSize + index + 1
|
||||
},
|
||||
viewSizeChange(size) {
|
||||
this.viewForm.pageSize = size
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
viewCurrentChange(page) {
|
||||
this.viewForm.pageNumber = page
|
||||
this.loadViewData()
|
||||
},
|
||||
viewPageOrder({ prop, order }) {
|
||||
this.viewForm.pageOrderName = prop || "signupTime"
|
||||
this.viewForm.pageOrderBy = order || "descending"
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
loadViewData() {
|
||||
if (!this.viewRow || !this.viewRow.matterId) {
|
||||
this.viewTableData = []
|
||||
this.viewForm.totalCount = 0
|
||||
return
|
||||
}
|
||||
this.viewLoading = true
|
||||
const requestSeq = ++this.viewRequestSeq
|
||||
this.$axios.post(loc() + "/signupPageData", {
|
||||
matterId: this.viewRow.matterId,
|
||||
keyword: this.viewForm.keyword,
|
||||
unionId: this.viewForm.unionId,
|
||||
pageNumber: this.viewForm.pageNumber,
|
||||
pageSize: this.viewForm.pageSize,
|
||||
pageOrderName: this.viewForm.pageOrderName,
|
||||
pageOrderBy: this.viewForm.pageOrderBy
|
||||
}).then((res) => {
|
||||
if (requestSeq !== this.viewRequestSeq) return
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.viewTableData = data.list || []
|
||||
this.viewForm.totalCount = data.totalCount || 0
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
if (requestSeq === this.viewRequestSeq) {
|
||||
this.viewLoading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
exportLine(row) {
|
||||
if (!row || !row.matterId) {
|
||||
this.$message.warning("线路信息不完整")
|
||||
return
|
||||
}
|
||||
window.location.href = loc() + "/exportParticipants?matterId=" + encodeURIComponent(row.matterId)
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", {
|
||||
year: this.pageForm.year
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = (res.data || []).filter(item => item.lineType)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.pageData()
|
||||
},
|
||||
watch: {
|
||||
"pageForm.year"() {
|
||||
this.pageForm.lineType = ""
|
||||
this.loadLineTypeOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tour-group-view-drawer .el-drawer__body {
|
||||
background: #f5f7fa;
|
||||
padding: 12px;
|
||||
overflow: auto;
|
||||
}
|
||||
.tour-group-view-pagination {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
.tour-group-view-title {
|
||||
border-left: 4px solid #0079c2;
|
||||
color: #0079c2;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
margin-bottom: 12px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,653 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<dict-select
|
||||
v-model="pageForm.lineType"
|
||||
code="lineType"
|
||||
option_value="name"
|
||||
placeholder="请选择线路类型">
|
||||
</dict-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<div class="tour-ledger-toolbar">
|
||||
<div class="tour-ledger-toolbar-title">
|
||||
<table-tool :app="this" label="台账列表"></table-tool>
|
||||
</div>
|
||||
<div class="tour-ledger-actions">
|
||||
<el-button size="medium" type="primary" icon="el-icon-upload2" @click="showImportDialog = true">参加人员导入</el-button>
|
||||
<el-button size="medium" type="primary" icon="el-icon-check" @click="setParticipants">设置参加人员</el-button>
|
||||
<el-button size="medium" type="primary" icon="el-icon-download" @click="exportUnionSignupZip">导出分工会报名压缩包</el-button>
|
||||
</div>
|
||||
<div class="tour-ledger-scope">
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.directFamilyOnly}"
|
||||
@click="setDirectFamilyOnly">
|
||||
参加直系亲属单位线路人员
|
||||
</el-button>
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.overCostOnly}"
|
||||
@click="setOverCostOnly">
|
||||
申请超出费用由单位承担人员
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
row-key="id"
|
||||
:row-class-name="tableRowClassName"
|
||||
@selection-change="handleSelectionChange"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="260" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否参加" prop="joined" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.joined ? 'success' : 'info'">{{ row.joined ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
<div class="tour-ledger-tip">温馨提醒:走审核流程的报名,审核通过后才在台账中显示</div>
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<excel-import
|
||||
ref="excelImportRef"
|
||||
url="/platform/tour/ledger/importParticipants"
|
||||
template_url="/platform/tour/ledger/downloadTemplate"
|
||||
:visible.sync="showImportDialog"
|
||||
title="参加人员导入"
|
||||
width="700px"
|
||||
@import-success="afterImport"
|
||||
:extra_params="{}">
|
||||
</excel-import>
|
||||
|
||||
<el-dialog
|
||||
title="台账详情"
|
||||
:visible.sync="detailVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%">
|
||||
<div class="tour-ledger-section">
|
||||
<div class="tour-ledger-title">教职工信息</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="工号">{{ detail.jobNo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">
|
||||
报名信息
|
||||
<el-link v-if="detailHasWorkflow()" type="primary" @click="openChart">点击查看流程图</el-link>
|
||||
</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="报名时间">{{ detail.signupTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名线路">{{ detail.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路类型">{{ detail.lineType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名酒店">{{ detail.hotelName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名旅行社">{{ detail.travelAgencyName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行时间">{{ detail.travelPeriod || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床型">{{ detail.bedType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床位信息">{{ detail.bedInfo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="意向拼床人">{{ detail.intendedRoommate || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否携带家属">{{ familyText() }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否参加">{{ detail.joined ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否报销">{{ detail.reimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报销超出费用">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="isDirectFamilyLine()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">直系亲属线路</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="亲属姓名">{{ directRelative.relativeName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ directRelative.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="亲属关系">{{ directRelative.relationshipName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路名称">{{ directRelative.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行开始日期">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行结束日期">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="showFamilySection()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">家属信息</div>
|
||||
<el-table :data="familyData" border :size="tableSize" empty-text="暂无家属信息">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床位" prop="bedInfo" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="意向拼床人" prop="intendedRoommate" min-width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<template v-if="detailHasWorkflow()" v-for="task in doneTasks">
|
||||
<div class="tour-ledger-section mt10" :key="task.id">
|
||||
<div class="tour-ledger-title">{{ task.displayName }}</div>
|
||||
<el-descriptions border :column="3" v-if="task.ext && task.ext.isFirstTaskNode">
|
||||
<el-descriptions-item label="申请用户">
|
||||
{{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions border :column="3" v-else>
|
||||
<el-descriptions-item label="办理用户">
|
||||
{{ (task.taskFormData && task.taskFormData.userName) || '' }}({{ (task.taskFormData && task.taskFormData.loginName) || '' }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext && task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理意见" :span="3">
|
||||
{{ (task.taskFormData && (task.taskFormData.opinion || task.taskFormData.tf_opinion)) || '' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<snaker-chart ref="snakerChartRef"></snaker-chart>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="detailVisible = false">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.tour-ledger-section {
|
||||
padding: 0 2px;
|
||||
}
|
||||
.tour-ledger-title {
|
||||
border-left: 4px solid #0079c2;
|
||||
color: #0079c2;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
margin-bottom: 14px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.tour-ledger-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 24px;
|
||||
margin-bottom: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-toolbar-title {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.tour-ledger-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 auto;
|
||||
gap: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-actions .el-button {
|
||||
margin: 0;
|
||||
}
|
||||
.tour-ledger-scope {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 auto;
|
||||
flex-wrap: nowrap;
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-scope .el-button {
|
||||
margin: 0;
|
||||
}
|
||||
.tour-ledger-scope .el-button + .el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn {
|
||||
background: #ecf5ff;
|
||||
border-color: #b3d8ff;
|
||||
border-radius: 4px;
|
||||
color: #0079c2;
|
||||
font-weight: 600;
|
||||
height: 34px;
|
||||
line-height: 1;
|
||||
padding: 8px 18px;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn:hover,
|
||||
.tour-ledger-scope .tour-scope-btn:focus {
|
||||
background: #d9ecff;
|
||||
border-color: #66b1ff;
|
||||
color: #006bb0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active {
|
||||
background: #0079c2;
|
||||
border-color: #0079c2;
|
||||
box-shadow: 0 2px 6px rgba(0, 121, 194, 0.24);
|
||||
color: #fff;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:hover,
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:focus {
|
||||
background: #006bb0;
|
||||
border-color: #006bb0;
|
||||
color: #fff;
|
||||
}
|
||||
.tour-ledger-tip {
|
||||
color: #f56c6c;
|
||||
font-family: SimSun, "宋体", serif;
|
||||
font-size: 9pt;
|
||||
line-height: 1.6;
|
||||
margin-top: -4px;
|
||||
text-align: center;
|
||||
}
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
detailVisible: false,
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
directFamilyUnitLine: false,
|
||||
fillBedInfo: true,
|
||||
detailRow: {},
|
||||
doneTasks: [],
|
||||
showImportDialog: false,
|
||||
multipleSelection: [],
|
||||
filterOptionsTimer: null,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: "",
|
||||
directFamilyOnly: false,
|
||||
overCostOnly: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyRow(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyRow(row) {
|
||||
return this.toBoolean(row && row.directFamilyUnitLine) || !!(row && row.directRelativeId)
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.multipleSelection = val || []
|
||||
},
|
||||
clearTableSelection() {
|
||||
this.multipleSelection = []
|
||||
if (this.$refs.tableRef) {
|
||||
this.$refs.tableRef.clearSelection()
|
||||
}
|
||||
},
|
||||
setParticipants() {
|
||||
if (!this.multipleSelection.length) {
|
||||
this.$message.warning("请选择要设置的参加人员")
|
||||
return
|
||||
}
|
||||
this.$confirm("确定将选中的" + this.multipleSelection.length + "条台账设置为已参加吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/setParticipants", {
|
||||
ids: JSON.stringify(this.multipleSelection.map(item => item.id))
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("设置成功")
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "设置失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
exportUnionSignupZip() {
|
||||
const params = new URLSearchParams()
|
||||
;["startYear", "endYear", "keyword", "unionId", "lineId", "travelPeriod", "lineType"].forEach(key => {
|
||||
const value = this.pageForm[key]
|
||||
if (value !== undefined && value !== null && value !== "") {
|
||||
params.append(key, value)
|
||||
}
|
||||
})
|
||||
if (this.pageForm.directFamilyOnly) {
|
||||
params.append("directFamilyOnly", "true")
|
||||
}
|
||||
if (this.pageForm.overCostOnly) {
|
||||
params.append("overCostOnly", "true")
|
||||
}
|
||||
window.location.href = loc() + "/exportUnionSignupZip?" + params.toString()
|
||||
},
|
||||
afterImport() {
|
||||
this.showImportDialog = false
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.loadFilterOptions()
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail && this.detail.directFamilyUnitLine)
|
||||
|| !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
detailHasWorkflow() {
|
||||
return !!(this.detailRow && this.detailRow.instanceId)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail && this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.hasFamily()) {
|
||||
return "否"
|
||||
}
|
||||
const count = Number(this.familyData.length || 0)
|
||||
return count > 0 ? count + "人" : "是"
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
loadDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.detailRow.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.detailRow.instanceProcessDefineId || !this.detailRow.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.detailRow.instanceProcessDefineId, this.detailRow.instanceId)
|
||||
},
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.directFamilyOnly = false
|
||||
this.pageForm.overCostOnly = false
|
||||
this.doSearch()
|
||||
},
|
||||
openView(row) {
|
||||
this.detailRow = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.directFamilyUnitLine = false
|
||||
this.fillBedInfo = true
|
||||
this.doneTasks = []
|
||||
this.$axios.post(loc() + "/detail", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.detailVisible = true
|
||||
if (this.detailHasWorkflow()) {
|
||||
this.loadDoneTasks()
|
||||
}
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.userName + "】的报名台账吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
this.loadFilterOptions()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadFilterOptions() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
},
|
||||
scheduleFilterOptions(delay) {
|
||||
if (this.filterOptionsTimer) {
|
||||
clearTimeout(this.filterOptionsTimer)
|
||||
}
|
||||
this.filterOptionsTimer = setTimeout(() => {
|
||||
this.loadFilterOptions()
|
||||
this.filterOptionsTimer = null
|
||||
}, delay === undefined ? 80 : delay)
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
directFamilyOnly: this.pageForm.directFamilyOnly,
|
||||
overCostOnly: this.pageForm.overCostOnly
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
lineId: this.pageForm.lineId,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
directFamilyOnly: this.pageForm.directFamilyOnly,
|
||||
overCostOnly: this.pageForm.overCostOnly
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.tableKey = new Date().getTime()
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(0)
|
||||
},
|
||||
setDirectFamilyOnly() {
|
||||
this.pageForm.directFamilyOnly = !this.pageForm.directFamilyOnly
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(0)
|
||||
},
|
||||
setOverCostOnly() {
|
||||
this.pageForm.overCostOnly = !this.pageForm.overCostOnly
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(0)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadUnionOptions()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(150)
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.scheduleFilterOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,712 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="事项名称">
|
||||
<el-input
|
||||
v-model="pageForm.matterName"
|
||||
clearable
|
||||
placeholder="请输入事项名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="组织形式">
|
||||
<el-select v-model="pageForm.organizationType" clearable filterable placeholder="请选择组织形式" style="width: 100%">
|
||||
<el-option v-for="item in organizationTypeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="事项列表">
|
||||
<el-button @click="openAdd" size="medium" type="primary">
|
||||
<i class="el-icon-plus"></i>
|
||||
新增
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
:row-class-name="tableRowClassName"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="年度" prop="year" width="110" sortable="custom" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="事项名称" prop="matterName" min-width="200" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所属工会" prop="unionName" min-width="180" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路名称" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="组织形式" prop="organizationTypeName" width="150" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系人" prop="contactName" width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系方式" prop="contactPhone" width="150" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="事项状态" prop="enabled" width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.enabled"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
@change="toggleEnabled(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openBatchForm(row)">选择线路</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" :loading="row.deleteLoading" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="54%"
|
||||
@closed="destroyForm">
|
||||
<el-form :model="formData" :rules="formRules" label-width="110px" ref="form" :disabled="viewMode">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%"
|
||||
@change="yearChange">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="事项状态" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="事项名称" prop="matterName">
|
||||
<el-input v-model="formData.matterName" maxlength="30" show-word-limit placeholder="请输入事项名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建人">
|
||||
<el-input v-model="formData.creatorName" readonly placeholder="当前登录人"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="疗休养配置" prop="settingId">
|
||||
<el-select v-model="formData.settingId" clearable filterable placeholder="请选择配置" style="width: 100%">
|
||||
<el-option v-for="item in settingOptions" :key="item.id" :label="item.configName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="组织形式" prop="organizationType">
|
||||
<el-select v-model="formData.organizationType" clearable filterable placeholder="请选择组织形式" style="width: 100%" @change="organizationTypeChange">
|
||||
<el-option v-for="item in organizationTypeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属工会" prop="unionId">
|
||||
<el-select v-model="formData.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%" :disabled="isUnionDisabled()">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button v-if="!viewMode" type="primary" :loading="subDis" @click="doSubmit">保存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
:title="batchTitle"
|
||||
:visible.sync="batchFormVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="74%">
|
||||
<el-form :model="batchForm" :rules="batchRules" label-width="110px" ref="batchFormRef">
|
||||
<el-form-item label="线路" prop="lineId">
|
||||
<el-select v-model="batchForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%" @change="lineChange">
|
||||
<el-option v-for="item in lineOptions" :key="item.id" :label="lineOptionLabel(item)" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="报名开始时间" prop="signupStartTime">
|
||||
<el-date-picker v-model="batchForm.signupStartTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择时间" style="width: 100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="报名结束时间" prop="signupEndTime">
|
||||
<el-date-picker v-model="batchForm.signupEndTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择时间" style="width: 100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出行开始时间" prop="travelStartTime">
|
||||
<el-date-picker v-model="batchForm.travelStartTime" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 100%" @change="travelStartChange"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出行结束时间" prop="travelEndTime">
|
||||
<el-date-picker v-model="batchForm.travelEndTime" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 100%" @change="travelEndChange"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系人" prop="contactName">
|
||||
<el-input v-model="batchForm.contactName" maxlength="10" placeholder="请输入联系人"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系方式" prop="contactPhone">
|
||||
<el-input v-model="batchForm.contactPhone" maxlength="11" placeholder="请输入联系方式"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计费用" prop="estimatedCost">
|
||||
<el-input v-model="batchForm.estimatedCost" maxlength="10" placeholder="请输入预计费用"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最少成团人数" prop="minGroupPeople">
|
||||
<el-input-number v-model="batchForm.minGroupPeople" :min="1" :precision="0" controls-position="right" style="width: 100%" @change="peopleChange"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最多成团人数" prop="maxGroupPeople">
|
||||
<el-input-number v-model="batchForm.maxGroupPeople" :min="1" :precision="0" controls-position="right" style="width: 100%" @change="peopleChange"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="batchFormVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="batchSubDis" @click="submitBatch">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
const validateUnion = (rule, value, callback) => {
|
||||
if (this.formData.organizationType === "schoolUnion" || value) {
|
||||
callback()
|
||||
} else {
|
||||
callback(new Error("必填"))
|
||||
}
|
||||
}
|
||||
const validateMobile = (rule, value, callback) => {
|
||||
const mobileReg = /^1[3-9]\d{9}$/
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!mobileReg.test(value)) {
|
||||
callback(new Error("手机号格式不正确"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateMoney = (rule, value, callback) => {
|
||||
const moneyReg = /^(0|[1-9]\d*)(\.\d{1,2})?$/
|
||||
if (value === "" || value === null || value === undefined) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!moneyReg.test(String(value))) {
|
||||
callback(new Error("请输入非负金额,最多两位小数"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validatePeople = (rule, value, callback) => {
|
||||
if (!value || value <= 0) {
|
||||
callback(new Error("人数必须大于0"))
|
||||
} else if (this.batchForm.minGroupPeople && this.batchForm.maxGroupPeople
|
||||
&& this.batchForm.minGroupPeople > this.batchForm.maxGroupPeople) {
|
||||
callback(new Error("最少人数不能大于最多人数"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateBatchTime = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
return
|
||||
}
|
||||
const form = this.batchForm
|
||||
if (form.signupStartTime && form.signupEndTime && form.signupStartTime >= form.signupEndTime) {
|
||||
callback(new Error("报名开始时间必须小于报名结束时间"))
|
||||
return
|
||||
}
|
||||
if (form.travelStartTime && form.travelEndTime && form.travelStartTime > form.travelEndTime) {
|
||||
callback(new Error("出行开始时间不能晚于出行结束时间"))
|
||||
return
|
||||
}
|
||||
if (form.signupEndTime && form.travelStartTime && form.signupEndTime >= form.travelStartTime) {
|
||||
callback(new Error("报名结束时间必须小于出行开始时间"))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
viewMode: false,
|
||||
subDis: false,
|
||||
batchFormVisible: false,
|
||||
batchSubDis: false,
|
||||
batchTitle: "",
|
||||
currentMatter: {},
|
||||
batchForm: {},
|
||||
lineOptions: [],
|
||||
settingOptions: [],
|
||||
unionOptions: [],
|
||||
organizationTypeOptions: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: currentYear,
|
||||
matterName: "",
|
||||
unionId: "",
|
||||
organizationType: ""
|
||||
},
|
||||
formData: {},
|
||||
formRules: {
|
||||
year: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
matterName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
settingId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
unionId: [{ validator: validateUnion, trigger: ["blur", "change"] }],
|
||||
organizationType: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
|
||||
},
|
||||
batchRules: {
|
||||
lineId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
signupStartTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
signupEndTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
travelStartTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
travelEndTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
contactPhone: [{ validator: validateMobile, trigger: ["blur", "change"] }],
|
||||
minGroupPeople: [{ validator: validatePeople, trigger: ["blur", "change"] }],
|
||||
maxGroupPeople: [{ validator: validatePeople, trigger: ["blur", "change"] }],
|
||||
estimatedCost: [{ validator: validateMoney, trigger: ["blur", "change"] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"pageForm.year"(year) {
|
||||
this.loadSettings(year)
|
||||
},
|
||||
"batchForm.lineId"() {
|
||||
if (this.batchFormVisible) {
|
||||
this.applySelectedLineDefaults(true)
|
||||
}
|
||||
},
|
||||
"batchForm.travelStartTime"() {
|
||||
if (this.batchFormVisible) {
|
||||
this.fillTravelEndByLot()
|
||||
}
|
||||
},
|
||||
"batchForm.travelEndTime"() {
|
||||
if (this.batchFormVisible) {
|
||||
this.validateTravelFields()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.matterName = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.organizationType = ""
|
||||
this.loadSettings(this.pageForm.year)
|
||||
this.doSearch()
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyLine(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
if (!row) return false
|
||||
return row.directFamilyUnitLine === true
|
||||
|| row.directFamilyUnitLine === 1
|
||||
|| row.directFamilyUnitLine === "1"
|
||||
},
|
||||
emptyForm() {
|
||||
const user = this.currentUser()
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
matterName: "",
|
||||
settingId: "",
|
||||
creatorUserId: user.id || "",
|
||||
creatorName: user.username || "",
|
||||
unionId: "",
|
||||
organizationType: "",
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新增事项信息"
|
||||
this.viewMode = false
|
||||
this.formData = this.emptyForm()
|
||||
this.loadSettings(this.formData.year, true)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑事项信息"
|
||||
this.viewMode = false
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
openView(row) {
|
||||
this.title = "查看事项信息"
|
||||
this.viewMode = true
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
loadDetail(id) {
|
||||
this.$axios.post(loc() + "/detail", { id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign(this.emptyForm(), res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
this.ensureSelectedUnionOption()
|
||||
this.loadSettings(this.formData.year)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
currentUser() {
|
||||
return (this.$store && this.$store.state && this.$store.state.user) || {}
|
||||
},
|
||||
currentUnion() {
|
||||
return this.currentUser().union || {}
|
||||
},
|
||||
organizationTypeChange() {
|
||||
this.applyOrganizationTypeRule()
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.validateField("unionId"))
|
||||
},
|
||||
applyOrganizationTypeRule() {
|
||||
if (this.formData.organizationType === "schoolUnion") {
|
||||
this.formData.unionId = ""
|
||||
return
|
||||
}
|
||||
if (this.formData.organizationType === "branchUnion" || this.formData.organizationType === "personal") {
|
||||
const union = this.currentUnion()
|
||||
this.formData.unionId = union.id || ""
|
||||
this.ensureCurrentUnionOption(union)
|
||||
}
|
||||
},
|
||||
ensureCurrentUnionOption(union) {
|
||||
if (!union || !union.id) return
|
||||
const exists = this.unionOptions.some(item => item.id === union.id)
|
||||
if (!exists) {
|
||||
this.unionOptions.push({ id: union.id, name: union.name || "" })
|
||||
}
|
||||
},
|
||||
ensureSelectedUnionOption() {
|
||||
if (!this.formData.unionId) return
|
||||
const exists = this.unionOptions.some(item => item.id === this.formData.unionId)
|
||||
if (!exists) {
|
||||
this.unionOptions.push({ id: this.formData.unionId, name: this.formData.unionName || "" })
|
||||
}
|
||||
},
|
||||
isUnionDisabled() {
|
||||
return ["schoolUnion", "branchUnion", "personal"].includes(this.formData.organizationType)
|
||||
},
|
||||
yearChange(year) {
|
||||
this.formData.settingId = ""
|
||||
this.loadSettings(year, true)
|
||||
},
|
||||
loadSettings(year, autoSelectLatest) {
|
||||
this.$axios.post(loc() + "/settingOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.settingOptions = res.data || []
|
||||
if (autoSelectLatest && !this.formData.settingId && this.settingOptions.length > 0) {
|
||||
this.formData.settingId = this.settingOptions[0].id
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadUnions() {
|
||||
this.$axios.post(loc() + "/unionOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadOrganizationTypes() {
|
||||
this.$axios.post(loc() + "/organizationTypeOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.organizationTypeOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
emptyBatchForm() {
|
||||
return {
|
||||
id: this.currentMatter.id || "",
|
||||
lineId: "",
|
||||
signupStartTime: "",
|
||||
signupEndTime: "",
|
||||
travelStartTime: "",
|
||||
travelEndTime: "",
|
||||
contactName: "",
|
||||
contactPhone: "",
|
||||
minGroupPeople: null,
|
||||
maxGroupPeople: null,
|
||||
estimatedCost: ""
|
||||
}
|
||||
},
|
||||
openBatchForm(row) {
|
||||
this.currentMatter = row
|
||||
this.loadLines(row.year)
|
||||
this.batchTitle = "选择线路"
|
||||
this.batchForm = this.emptyBatchForm()
|
||||
this.$axios.post(loc() + "/lineConfig", { matterId: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.batchForm = Object.assign(this.emptyBatchForm(), res.data || {})
|
||||
this.batchForm.travelStartTime = this.dateOnly(this.batchForm.travelStartTime)
|
||||
this.batchForm.travelEndTime = this.dateOnly(this.batchForm.travelEndTime)
|
||||
this.applySelectedLineDefaults(false)
|
||||
if (!this.batchForm.minGroupPeople || !this.batchForm.maxGroupPeople) {
|
||||
this.loadSettingPeople((data) => {
|
||||
this.batchForm.minGroupPeople = data.minGroupPeople || null
|
||||
this.batchForm.maxGroupPeople = data.maxGroupPeople || null
|
||||
})
|
||||
}
|
||||
this.batchFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.applySelectedLineDefaults(true)
|
||||
this.$refs.batchFormRef && this.$refs.batchFormRef.clearValidate()
|
||||
})
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLines(year) {
|
||||
this.$axios.post(loc() + "/lineOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
this.applySelectedLineDefaults(true)
|
||||
}
|
||||
})
|
||||
},
|
||||
lineOptionLabel(item) {
|
||||
if (!item) return ""
|
||||
const lineName = this.lineField(item, "lineName") || ""
|
||||
const lineType = this.lineField(item, "lineType") || ""
|
||||
return lineType ? lineName + "(" + lineType + ")" : lineName
|
||||
},
|
||||
lineChange() {
|
||||
this.applySelectedLineDefaults(true)
|
||||
},
|
||||
travelStartChange() {
|
||||
this.fillTravelEndByLot()
|
||||
},
|
||||
travelEndChange() {
|
||||
this.validateTravelFields()
|
||||
},
|
||||
selectedLine() {
|
||||
return (this.lineOptions || []).find((item) => this.lineField(item, "id") === this.batchForm.lineId) || null
|
||||
},
|
||||
applySelectedLineDefaults(recalculateEnd) {
|
||||
const line = this.selectedLine()
|
||||
if (!line) return
|
||||
const activityCost = this.lineField(line, "activityCost")
|
||||
if (activityCost !== null && activityCost !== undefined && activityCost !== "") {
|
||||
this.batchForm.estimatedCost = activityCost
|
||||
}
|
||||
if (recalculateEnd) {
|
||||
this.fillTravelEndByLot()
|
||||
}
|
||||
},
|
||||
fillTravelEndByLot() {
|
||||
const line = this.selectedLine()
|
||||
const days = this.lineLotDays(line)
|
||||
if (!this.batchForm.travelStartTime || !days) return
|
||||
this.$set(this.batchForm, "travelEndTime", moment(this.batchForm.travelStartTime).add(days - 1, "days").format("YYYY-MM-DD"))
|
||||
this.validateTravelFields()
|
||||
},
|
||||
lineLotDays(line) {
|
||||
if (!line) return null
|
||||
const lotDays = this.lineField(line, "lotDays") || this.lineField(line, "lotValue")
|
||||
if (!/^\d+$/.test(String(lotDays || ""))) return null
|
||||
const days = parseInt(lotDays, 10)
|
||||
return days > 0 ? days : null
|
||||
},
|
||||
lineField(line, field) {
|
||||
if (!line) return null
|
||||
if (line[field] !== undefined) return line[field]
|
||||
const lowerField = field.toLowerCase()
|
||||
const matchedKey = Object.keys(line).find((key) => key.toLowerCase() === lowerField)
|
||||
return matchedKey ? line[matchedKey] : null
|
||||
},
|
||||
validateTravelFields() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.batchFormRef) {
|
||||
this.$refs.batchFormRef.validateField(["travelStartTime", "travelEndTime"])
|
||||
}
|
||||
})
|
||||
},
|
||||
dateOnly(value) {
|
||||
if (!value) return ""
|
||||
return String(value).substring(0, 10)
|
||||
},
|
||||
loadSettingPeople(callback) {
|
||||
this.$axios.post(loc() + "/settingPeople", { matterId: this.currentMatter.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
callback && callback(data)
|
||||
}
|
||||
})
|
||||
},
|
||||
peopleChange() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.batchFormRef) {
|
||||
this.$refs.batchFormRef.validateField(["minGroupPeople", "maxGroupPeople"])
|
||||
}
|
||||
})
|
||||
},
|
||||
submitBatch() {
|
||||
this.$refs.batchFormRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.batchSubDis = true
|
||||
this.$axios.post(loc() + "/lineConfigDoSubmit", this.batchForm).then((res) => {
|
||||
this.batchSubDis = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.batchFormVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.batchSubDis = false
|
||||
})
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.subDis = true
|
||||
this.$axios.post(loc() + "/doSubmit", this.formData).then((res) => {
|
||||
this.subDis = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.subDis = false
|
||||
})
|
||||
})
|
||||
},
|
||||
toggleEnabled(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("状态已更新")
|
||||
} else {
|
||||
row.enabled = !row.enabled
|
||||
this.$message.warning(res.msg || "状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.enabled = !row.enabled
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$set(row, "deleteLoading", true)
|
||||
this.$axios.post(loc() + "/deleteInfo", { id: row.id }).then((res) => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
if (res.code !== 0) {
|
||||
this.$message.warning(res.msg || "删除检查失败")
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
const signupCount = Number(data.signupCount || 0)
|
||||
const matterName = row.matterName || ""
|
||||
if (!data.canDelete) {
|
||||
this.$alert("事项【" + matterName + "】已有 " + signupCount + " 人报名,不能删除。", "删除提醒", {
|
||||
confirmButtonText: "知道了",
|
||||
type: "warning"
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$confirm("事项【" + matterName + "】暂无人员报名,确认删除吗?", "删除提醒", {
|
||||
confirmButtonText: "确认删除",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
confirmButtonClass: "el-button--danger"
|
||||
}).then(() => {
|
||||
this.$set(row, "deleteLoading", true)
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((deleteRes) => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
if (deleteRes.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(deleteRes.msg || "删除失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
})
|
||||
},
|
||||
destroyForm() {
|
||||
this.formData = {}
|
||||
this.viewMode = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadSettings(this.pageForm.year)
|
||||
this.loadUnions()
|
||||
this.loadOrganizationTypes()
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<el-empty description="${title!'功能建设中'}">
|
||||
<template slot="description">
|
||||
<span>${title!'功能建设中'}正在分阶段建设中</span>
|
||||
</template>
|
||||
</el-empty>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app"
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,432 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="创建年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择创建年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="线路名称">
|
||||
<el-input
|
||||
v-model="pageForm.lineName"
|
||||
clearable
|
||||
placeholder="请输入线路名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="时间标段">
|
||||
<el-select v-model="pageForm.lotId" clearable filterable placeholder="请选择时间标段" style="width: 100%">
|
||||
<el-option v-for="item in lotOptions" :key="item.id" :label="item.lotName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="线路列表">
|
||||
<el-button @click="openAdd" size="medium" type="primary">
|
||||
<i class="el-icon-plus"></i>
|
||||
新增
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
:default-sort="{prop: 'enabled', order: 'descending'}"
|
||||
:row-class-name="tableRowClassName"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="创建年度" prop="year" width="120" sortable="custom" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="线路编号" prop="lineCode" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路名称" prop="lineName" min-width="220" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="时间标段" prop="lotName" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="创建人" prop="creatorName" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="是否对外开放" prop="openFlag" width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.openFlag"
|
||||
active-text="是"
|
||||
inactive-text="否"
|
||||
@change="toggleOpenFlag(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="激活状态" prop="enabled" width="160" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.enabled"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
@change="toggleEnabled(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%"
|
||||
@closed="destroyEditor">
|
||||
<el-form :model="formData" :rules="formRules" label-width="110px" ref="form" :disabled="viewMode">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="创建年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择创建年度"
|
||||
style="width: 100%"
|
||||
@change="yearChange">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="旅行社名称" prop="travelAgencyId">
|
||||
<el-select v-model="formData.travelAgencyId" clearable filterable placeholder="请选择旅行社" style="width: 100%">
|
||||
<el-option v-for="item in travelAgencyOptions" :key="item.id" :label="item.agencyName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="线路名称" prop="lineName">
|
||||
<el-input v-model="formData.lineName" maxlength="30" show-word-limit placeholder="请输入线路名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="创建人">
|
||||
<el-input v-model="formData.creatorName" readonly placeholder="当前登录人"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所在单位">
|
||||
<el-input v-model="formData.unitName" readonly placeholder="当前登录人所在单位"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="线路编号" prop="lineCode">
|
||||
<el-input v-model="formData.lineCode" maxlength="50" placeholder="建议年度加序号,如202601"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="激活状态" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否对外开放" prop="openFlag">
|
||||
<el-radio-group v-model="formData.openFlag">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="直系亲属线路" prop="directFamilyUnitLine">
|
||||
<el-radio-group v-model="formData.directFamilyUnitLine">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="线路类型" prop="lineType">
|
||||
<el-select v-model="formData.lineType" clearable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.code" :label="item.name" :value="item.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="时间标段" prop="lotId">
|
||||
<el-select v-model="formData.lotId" clearable filterable placeholder="请选择时间标段" style="width: 100%">
|
||||
<el-option v-for="item in lotOptions" :key="item.id" :label="item.lotName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="线路内容" prop="lineContent">
|
||||
<text-editor v-model="formData.lineContent"></text-editor>
|
||||
</el-form-item>
|
||||
<el-form-item label="移动端缩略图" prop="mobileThumb">
|
||||
<!-- 与旅行社管理保持一致:移动端缩略图使用单图上传并保存URL。 -->
|
||||
<file-upload
|
||||
style="--upload-width: 200px;--upload-height:108px"
|
||||
:upload_number="1"
|
||||
:upload_size="20971520"
|
||||
:value.sync="formData.mobileThumb"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
complete_result
|
||||
upload_mode="image"
|
||||
upload_result_category="interval">
|
||||
</file-upload>
|
||||
<div class="el-upload__tip">支持jpg、jpeg、png格式,大小不超过20MB。</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button v-if="!viewMode" type="primary" :loading="submitLoading" @click="doSubmit">保存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
viewMode: false,
|
||||
submitLoading: false,
|
||||
travelAgencyOptions: [],
|
||||
lotOptions: [],
|
||||
lineTypeOptions: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "enabled",
|
||||
pageOrderBy: "descending",
|
||||
year: currentYear,
|
||||
lineName: "",
|
||||
lotId: ""
|
||||
},
|
||||
formData: {},
|
||||
formRules: {
|
||||
year: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
travelAgencyId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lineName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lineCode: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lineType: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lotId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
mobileThumb: [{ required: true, message: "请上传移动端缩略图", trigger: ["blur", "change"] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.lineName = ""
|
||||
this.pageForm.lotId = ""
|
||||
this.loadOptions(this.pageForm.year)
|
||||
this.doSearch()
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyLine(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
if (!row) return false
|
||||
return row.directFamilyUnitLine === true
|
||||
|| row.directFamilyUnitLine === 1
|
||||
|| row.directFamilyUnitLine === "1"
|
||||
},
|
||||
emptyForm() {
|
||||
const user = (this.$store && this.$store.state && this.$store.state.user) || {}
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
travelAgencyId: "",
|
||||
creatorUserId: user.id || "",
|
||||
creatorName: user.username || "",
|
||||
unitId: user.unit?.id || "",
|
||||
unitName: user.unit?.name || "",
|
||||
lineName: "",
|
||||
lineCode: "",
|
||||
enabled: true,
|
||||
openFlag: true,
|
||||
directFamilyUnitLine: false,
|
||||
lineType: "",
|
||||
lotId: "",
|
||||
lineContent: "",
|
||||
mobileThumb: ""
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新增线路信息"
|
||||
this.viewMode = false
|
||||
this.formData = this.emptyForm()
|
||||
this.loadOptions(this.formData.year)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑线路信息"
|
||||
this.viewMode = false
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
openView(row) {
|
||||
this.title = "查看线路信息"
|
||||
this.viewMode = true
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
loadDetail(id) {
|
||||
this.$axios.post(loc() + "/detail", { id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign(this.emptyForm(), res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
this.loadOptions(this.formData.year)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
yearChange(year) {
|
||||
this.formData.travelAgencyId = ""
|
||||
this.formData.lotId = ""
|
||||
this.loadOptions(year)
|
||||
},
|
||||
loadOptions(year) {
|
||||
this.loadTravelAgencies(year)
|
||||
this.loadLots(year)
|
||||
this.loadLineTypes()
|
||||
},
|
||||
loadTravelAgencies(year) {
|
||||
this.$axios.post(loc() + "/travelAgencyOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelAgencyOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLots(year) {
|
||||
this.$axios.post(loc() + "/lotOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lotOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypes() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.submitLoading = true
|
||||
this.$axios.post(loc() + "/doSubmit", this.formData).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
toggleEnabled(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("状态已更新")
|
||||
} else {
|
||||
row.enabled = !row.enabled
|
||||
this.$message.warning(res.msg || "状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.enabled = !row.enabled
|
||||
})
|
||||
},
|
||||
toggleOpenFlag(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("对外开放状态已更新")
|
||||
} else {
|
||||
row.openFlag = !row.openFlag
|
||||
this.$message.warning(res.msg || "对外开放状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.openFlag = !row.openFlag
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.lineName + "】吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
destroyEditor() {
|
||||
this.formData = {}
|
||||
this.viewMode = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadOptions(this.pageForm.year)
|
||||
this.pageData()
|
||||
},
|
||||
watch: {
|
||||
"pageForm.year"(year) {
|
||||
this.pageForm.lotId = ""
|
||||
this.loadOptions(year)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+549
@@ -0,0 +1,549 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="校工会审核">
|
||||
<el-radio-group class="mr5" size="small" v-model="pageForm.audit" @change="changeAudit">
|
||||
<el-radio-button :label="true">已审核</el-radio-button>
|
||||
<el-radio-button :label="false">未审核</el-radio-button>
|
||||
</el-radio-group>
|
||||
</table-tool>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前节点" prop="curTaskName" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="流程状态" prop="instanceState" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button v-if="row.taskState === 10" size="mini" type="primary" @click="openApproval(row)">审核</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<template #edit>
|
||||
<tour-approval-info ref="infoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">
|
||||
{{ formData.taskName }}
|
||||
</div>
|
||||
<el-form
|
||||
:model="formData"
|
||||
ref="formRef"
|
||||
label-width="0"
|
||||
label-suffix=":"
|
||||
class="flow-task-form">
|
||||
<el-form-item
|
||||
label="审批意见"
|
||||
prop="tf_opinion"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
|
||||
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
|
||||
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</tour-approval-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 150px) / 4);
|
||||
}
|
||||
#app .search .search-query {
|
||||
margin-left: auto;
|
||||
}
|
||||
@media screen and (max-width: 1350px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 100px) / 3);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1200px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 50px) / 2);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 992px) {
|
||||
#app .search .search-item {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.tour-approval-section {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.tour-approval-table {
|
||||
width: 100%;
|
||||
}
|
||||
.tour-approval-empty {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_APPROVAL_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <div>\n",
|
||||
" <div class=\"process-title\">\n",
|
||||
" 报名信息\n",
|
||||
" <el-link type=\"primary\" @click=\"openChart\">点击查看流程图</el-link>\n",
|
||||
" </div>\n",
|
||||
" <el-descriptions :column=\"3\" border class=\"tour-approval-section\">\n",
|
||||
" <el-descriptions-item label=\"工号\">{{ detail.jobNo || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"姓名\">{{ detail.userName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"性别\">{{ detail.gender || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"身份证号\">{{ detail.idCard || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ detail.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在工会\">{{ detail.unionName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名时间\">{{ detail.signupTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名线路\">{{ detail.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行时段\">{{ detail.travelPeriod || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路类型\">{{ detail.lineType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名酒店\">{{ detail.hotelName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"旅行社\">{{ detail.travelAgencyName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"是否携带家属\">\n",
|
||||
" {{ familyText() }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报销超出费用\">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"意向拼床人\">{{ detail.intendedRoommate || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床型\">{{ detail.bedType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床位信息\">{{ detail.bedInfo || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">直系亲属线路</div>\n",
|
||||
" <el-descriptions :column=\"3\" border>\n",
|
||||
" <el-descriptions-item label=\"亲属姓名\">{{ directRelative.relativeName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ directRelative.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"亲属关系\">{{ directRelative.relationshipName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路名称\">{{ directRelative.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行开始日期\">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行结束日期\">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">亲属信息</div>\n",
|
||||
" <el-table :data=\"familyData\" border size=\"mini\" empty-text=\"暂无亲属信息\" class=\"tour-approval-table\">\n",
|
||||
" <el-table-column label=\"序号\" type=\"index\" width=\"70\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"家属姓名\" prop=\"familyName\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"性别\" prop=\"gender\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"身份证号码\" prop=\"idCard\" min-width=\"180\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"年龄\" prop=\"age\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"关系\" prop=\"relationship\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床型\" prop=\"bedType\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床位\" prop=\"bedInfo\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"意向拼床人\" prop=\"intendedRoommate\" min-width=\"130\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" </el-table>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <div class=\"mt10\">\n",
|
||||
" <div class=\"process-title\">{{ task.displayName }}</div>\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-if=\"task.ext.isFirstTaskNode\">\n",
|
||||
" <el-descriptions-item label=\"申请用户\">\n",
|
||||
" {{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"申请时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-else>\n",
|
||||
" <el-descriptions-item label=\"办理用户\">\n",
|
||||
" {{ task.taskFormData.userName }}({{ task.taskFormData.loginName }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理意见\" :span=\"3\">\n",
|
||||
" {{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
" </template>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
"\n",
|
||||
" <snaker-chart ref=\"snakerChartRef\"></snaker-chart>\n",
|
||||
" </div>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
info() {
|
||||
this.$axios.post(loc() + "/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail.directFamilyUnitLine)
|
||||
|| (this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.row.instanceProcessDefineId || !this.row.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
lineTypeOptions: [],
|
||||
showApprovalForm: false,
|
||||
formData: {
|
||||
tf_opinion: ""
|
||||
},
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.loadOptions()
|
||||
this.doSearch()
|
||||
},
|
||||
changeAudit() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
clearCascadeFilters() {
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
},
|
||||
openView(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = false
|
||||
this.formData = {
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
openApproval(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.$confirm("您确定要提交吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
const loading = createLoading()
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.guava.index()
|
||||
this.$message.success(res.msg || "操作成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
},
|
||||
loadOptions() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
baseOptionParams() {
|
||||
return {
|
||||
audit: this.pageForm.audit,
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
keyword: this.pageForm.keyword,
|
||||
unionId: this.pageForm.unionId,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType
|
||||
}
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
if (this.pageForm.unionId && !this.unionOptions.some(item => item.id === this.pageForm.unionId)) {
|
||||
this.pageForm.unionId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.lineType === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
components: {
|
||||
"tour-approval-info": TOUR_APPROVAL_INFO
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.loadLineOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,636 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="配置名称">
|
||||
<el-input
|
||||
v-model="pageForm.configName"
|
||||
clearable
|
||||
placeholder="请输入疗休养配置名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<div class="search-query">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="疗休养配置">
|
||||
<el-button type="primary" size="medium" @click="openAdd">
|
||||
<i class="el-icon-plus"></i>
|
||||
新建
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
class="vi-table"
|
||||
ref="table"
|
||||
row-key="id"
|
||||
v-loading="tableLoading"
|
||||
@sort-change="pageOrder"
|
||||
>
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="年度" prop="year" width="100" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="疗休养配置名称" prop="configName" min-width="260" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="周期开始年度" prop="cycleStartYear" width="130" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="最少成团人数" prop="minGroupPeople" width="120" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="最多成团人数" prop="maxGroupPeople" width="120" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="是否携带家属" prop="allowFamily" width="120" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" type="success" v-if="row.allowFamily">允许</el-tag>
|
||||
<el-tag size="mini" type="info" v-else>不允许</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否启用" prop="enabled" width="100" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag size="mini" type="info" v-else>停用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="64.8%"
|
||||
@closed="destroyEditor">
|
||||
<el-form :model="formData" :rules="formRules" label-width="120px" ref="form">
|
||||
<div v-if="title === '新建疗休养配置'" class="tour-setting-inherit">
|
||||
<el-button type="primary" plain size="medium" icon="el-icon-copy-document" :loading="inheritLoading" @click="inheritPreviousYearInfo">延用上一年信息</el-button>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab" type="card">
|
||||
<el-tab-pane label="基本信息" name="basic">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="配置名称" prop="configName">
|
||||
<el-input v-model="formData.configName" maxlength="100" placeholder="请输入配置名称"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="疗休养类型" prop="tourType">
|
||||
<el-select v-model="formData.tourType" clearable allow-create filterable placeholder="请选择或输入类型" style="width: 100%">
|
||||
<el-option label="省内疗休养" value="省内疗休养"></el-option>
|
||||
<el-option label="省外疗休养" value="省外疗休养"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="可参加人员" prop="activityGroupId">
|
||||
<div class="tour-user-scope">
|
||||
<el-select
|
||||
v-model="formData.activityGroupId"
|
||||
placeholder="请选择可参加人员"
|
||||
filterable
|
||||
clearable
|
||||
style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in activityGroupList"
|
||||
:key="item.groupId"
|
||||
:label="item.groupName"
|
||||
:value="item.groupId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-button type="primary" @click="openUserScope">设置</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最少成团人数" prop="minGroupPeople">
|
||||
<el-input-number v-model="formData.minGroupPeople" :controls="false" :min="0" :precision="0" placeholder="请输入最少成团人数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最多成团人数" prop="maxGroupPeople">
|
||||
<el-input-number v-model="formData.maxGroupPeople" :controls="false" :min="0" :precision="0" placeholder="请输入最多成团人数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="tour-setting-basic-divider"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="省外几年去一次" prop="outProvinceYears">
|
||||
<el-input-number v-model="formData.outProvinceYears" :controls="false" :min="0" :precision="0" placeholder="请输入省外间隔年限" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="省外人数占比" prop="outProvinceRatio">
|
||||
<el-input-number v-model="formData.outProvinceRatio" :controls="false" :min="0" :max="100" :precision="2" placeholder="请输入省外人数占比" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="省外占比类型" prop="outProvinceRatioType">
|
||||
<el-select v-model="formData.outProvinceRatioType" placeholder="请选择省外占比类型" style="width: 100%" @change="outProvinceRatioTypeChange">
|
||||
<el-option label="当年报名人数" value="当年报名人数"></el-option>
|
||||
<el-option label="可参加教职工人数" value="可参加教职工人数"></el-option>
|
||||
<el-option label="固定人数" value="固定人数"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="formData.outProvinceRatioType === '固定人数'" :span="12">
|
||||
<el-form-item label="固定人数" prop="outProvinceFixedPeople">
|
||||
<el-input-number v-model="formData.outProvinceFixedPeople" :controls="false" :min="0" :precision="0" placeholder="请输入固定人数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="tour-setting-basic-divider"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期开始年度" prop="cycleStartYear">
|
||||
<el-date-picker
|
||||
v-model="formData.cycleStartYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
clearable
|
||||
placeholder="请选择周期开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期结束年度" prop="cycleEndYear">
|
||||
<el-date-picker
|
||||
v-model="formData.cycleEndYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
clearable
|
||||
placeholder="请选择周期结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期内总费用" prop="cycleTotalCost">
|
||||
<el-input-number v-model="formData.cycleTotalCost" :controls="false" :min="0" :precision="0" placeholder="请输入周期内总费用" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期允许次数" prop="cycleAllowedTimes">
|
||||
<el-input-number v-model="formData.cycleAllowedTimes" :controls="false" :min="0" :precision="0" placeholder="请输入周期允许次数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="tour-setting-basic-divider"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="允许携带家属" prop="allowFamily">
|
||||
<el-switch v-model="formData.allowFamily" active-text="允许" inactive-text="不允许"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="填报床位信息" prop="fillBedInfo">
|
||||
<el-switch v-model="formData.fillBedInfo" active-text="是" inactive-text="否"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否启用" prop="enabled">
|
||||
<el-switch v-model="formData.enabled" active-text="启用" inactive-text="停用"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="标段管理" name="lots">
|
||||
<div style="text-align: right; margin-bottom: 10px;">
|
||||
<el-button type="primary" size="medium" icon="el-icon-plus" @click="addLot">增加一条</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="formData.lots"
|
||||
border
|
||||
class="vi-table"
|
||||
empty-text="暂无标段"
|
||||
style="width: 100%">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="标段名称" min-width="180" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.lotName" maxlength="50" placeholder="请输入标段名称"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标段值" min-width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.lotValue" maxlength="10" placeholder="请输入整数" @input="integerInput(row, 'lotValue', $event)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标段费用" min-width="150" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.activityCost" maxlength="10" placeholder="请输入整数" @input="integerInput(row, 'activityCost', $event)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="允许超出报销" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-checkbox v-model="row.allowOverReimbursement"></el-checkbox>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center" header-align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="danger" size="mini" icon="el-icon-delete" @click="deleteLot(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="服务须知" name="notice">
|
||||
<el-form-item prop="serviceNotice" label-width="0">
|
||||
<text-editor v-model="formData.serviceNotice"></text-editor>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="doSubmit">确认</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<drawer-user-scope
|
||||
ref="drawerUserScope"
|
||||
:group_id.sync="formData.activityGroupId"
|
||||
@group_change="handleActivityGroupChange">
|
||||
</drawer-user-scope>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
// 前端先做成团人数区间校验,后端也会再兜底校验一次。
|
||||
const checkGroupPeople = (rule, value, callback) => {
|
||||
if (this.formData.minGroupPeople !== null && this.formData.maxGroupPeople !== null
|
||||
&& this.formData.minGroupPeople > this.formData.maxGroupPeople) {
|
||||
callback(new Error("最少成团人数不能大于最多成团人数"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkCycleYear = (rule, value, callback) => {
|
||||
const startYear = parseInt(this.formData.cycleStartYear, 10)
|
||||
const endYear = parseInt(this.formData.cycleEndYear, 10)
|
||||
if (!isNaN(startYear) && !isNaN(endYear) && startYear > endYear) {
|
||||
callback(new Error("周期开始年度不能大于周期结束年度"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkOutProvinceFixedPeople = (rule, value, callback) => {
|
||||
if (this.formData.outProvinceRatioType === "固定人数"
|
||||
&& (value === null || value === undefined || value === "" || value < 0)) {
|
||||
callback(new Error("固定人数必须大于等于0"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
activeTab: "basic",
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: "",
|
||||
configName: ""
|
||||
},
|
||||
activityGroupList: [],
|
||||
formData: {},
|
||||
lotDeleteList: [],
|
||||
inheritLoading: false,
|
||||
formRules: {
|
||||
year: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||
configName: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||
minGroupPeople: [{validator: checkGroupPeople, trigger: ["blur", "change"]}],
|
||||
maxGroupPeople: [{validator: checkGroupPeople, trigger: ["blur", "change"]}],
|
||||
outProvinceRatioType: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||
outProvinceFixedPeople: [{validator: checkOutProvinceFixedPeople, trigger: ["blur", "change"]}],
|
||||
cycleStartYear: [{validator: checkCycleYear, trigger: ["blur", "change"]}],
|
||||
cycleEndYear: [{validator: checkCycleYear, trigger: ["blur", "change"]}]
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue")
|
||||
},
|
||||
methods: {
|
||||
getActivityGroup() {
|
||||
return this.$axios.post("/platform/activity/basic/scope/getActivityUserScopeGroup").then((res) => {
|
||||
const data = res.data
|
||||
this.activityGroupList = (data || []).map((item) => {
|
||||
return Object.assign({}, item, {
|
||||
groupId: item.groupId === null || item.groupId === undefined ? "" : String(item.groupId)
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
openUserScope() {
|
||||
if (this.$refs.drawerUserScope) {
|
||||
this.$refs.drawerUserScope.groupId = this.formData.activityGroupId || ""
|
||||
this.$refs.drawerUserScope.userScopeDialog = true
|
||||
}
|
||||
},
|
||||
async handleActivityGroupChange() {
|
||||
if (this.formData.activityGroupId !== null && this.formData.activityGroupId !== undefined) {
|
||||
this.formData.activityGroupId = String(this.formData.activityGroupId)
|
||||
}
|
||||
await this.getActivityGroup()
|
||||
},
|
||||
resetSearch() {
|
||||
this.pageForm.year = ""
|
||||
this.pageForm.configName = ""
|
||||
this.doSearch()
|
||||
},
|
||||
defaultFormData() {
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
configName: "",
|
||||
tourType: "",
|
||||
activityGroupId: "",
|
||||
sortNo: 0,
|
||||
minGroupPeople: 0,
|
||||
maxGroupPeople: 0,
|
||||
outProvinceYears: 0,
|
||||
outProvinceRatio: 0,
|
||||
outProvinceRatioType: "当年报名人数",
|
||||
outProvinceFixedPeople: 0,
|
||||
cycleStartYear: "",
|
||||
cycleEndYear: "",
|
||||
cycleTotalCost: null,
|
||||
cycleAllowedTimes: null,
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
enabled: true,
|
||||
lots: [],
|
||||
serviceNotice: ""
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新建疗休养配置"
|
||||
this.lotDeleteList = []
|
||||
this.activeTab = "basic"
|
||||
// 新建时给出默认年度和开关值,减少校工会管理员录入成本。
|
||||
this.formData = this.defaultFormData()
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
inheritPreviousYearInfo() {
|
||||
const currentYear = parseInt(this.formData.year, 10)
|
||||
if (isNaN(currentYear)) {
|
||||
this.$message.warning("请先选择年度")
|
||||
return
|
||||
}
|
||||
this.inheritLoading = true
|
||||
this.$axios.post(loc() + "/previousYearInfo", {year: currentYear}).then((res) => {
|
||||
this.inheritLoading = false
|
||||
if (res.code !== 0) {
|
||||
this.$message.warning(res.msg || "未找到上一年度配置")
|
||||
return
|
||||
}
|
||||
const previous = res.data || {}
|
||||
const inheritedLots = (previous.lots || []).map(item => {
|
||||
return {
|
||||
lotName: item.lotName || "",
|
||||
lotValue: item.lotValue || "",
|
||||
activityCost: item.activityCost,
|
||||
allowOverReimbursement: !!item.allowOverReimbursement
|
||||
}
|
||||
})
|
||||
this.formData = Object.assign(this.defaultFormData(), previous, {
|
||||
year: String(currentYear),
|
||||
cycleStartYear: previous.cycleStartYear ? String(previous.cycleStartYear) : "",
|
||||
cycleEndYear: previous.cycleEndYear ? String(previous.cycleEndYear) : "",
|
||||
lots: inheritedLots
|
||||
})
|
||||
delete this.formData.id
|
||||
delete this.formData.createdAt
|
||||
delete this.formData.createdBy
|
||||
delete this.formData.updatedAt
|
||||
delete this.formData.updatedBy
|
||||
delete this.formData.delFlag
|
||||
if (!this.formData.outProvinceRatioType) {
|
||||
this.$set(this.formData, "outProvinceRatioType", "当年报名人数")
|
||||
}
|
||||
if (this.formData.outProvinceFixedPeople === null || this.formData.outProvinceFixedPeople === undefined) {
|
||||
this.$set(this.formData, "outProvinceFixedPeople", 0)
|
||||
}
|
||||
if (this.formData.fillBedInfo === null || this.formData.fillBedInfo === undefined) {
|
||||
this.$set(this.formData, "fillBedInfo", true)
|
||||
}
|
||||
this.lotDeleteList = []
|
||||
this.$message.success("已延用上一年配置信息")
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
}).catch(() => {
|
||||
this.inheritLoading = false
|
||||
})
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑疗休养配置"
|
||||
this.lotDeleteList = []
|
||||
this.activeTab = "basic"
|
||||
this.$axios.post(loc() + "/detail", {id: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign({
|
||||
activityGroupId: "",
|
||||
outProvinceRatioType: "当年报名人数",
|
||||
outProvinceFixedPeople: 0,
|
||||
cycleStartYear: "",
|
||||
cycleEndYear: "",
|
||||
cycleTotalCost: null,
|
||||
cycleAllowedTimes: null,
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
enabled: true,
|
||||
lots: [],
|
||||
serviceNotice: ""
|
||||
}, res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
if (!this.formData.outProvinceRatioType) {
|
||||
this.$set(this.formData, "outProvinceRatioType", "当年报名人数")
|
||||
}
|
||||
if (this.formData.outProvinceFixedPeople === null || this.formData.outProvinceFixedPeople === undefined) {
|
||||
this.$set(this.formData, "outProvinceFixedPeople", 0)
|
||||
}
|
||||
if (this.formData.fillBedInfo === null || this.formData.fillBedInfo === undefined) {
|
||||
this.$set(this.formData, "fillBedInfo", true)
|
||||
}
|
||||
this.formData.cycleStartYear = this.formData.cycleStartYear ? String(this.formData.cycleStartYear) : ""
|
||||
this.formData.cycleEndYear = this.formData.cycleEndYear ? String(this.formData.cycleEndYear) : ""
|
||||
this.formData.lots = (this.formData.lots || []).map(item => Object.assign({}, item, {
|
||||
allowOverReimbursement: !!item.allowOverReimbursement
|
||||
}))
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
if (!this.validateLots()) return
|
||||
this.submitLoading = true
|
||||
// Nutz 对子表集合按字符串化 JSON 绑定更稳定,和体检项目维护的提交方式保持一致。
|
||||
const submitData = JSON.parse(JSON.stringify(this.formData))
|
||||
if (submitData.outProvinceRatioType !== "固定人数") {
|
||||
submitData.outProvinceFixedPeople = 0
|
||||
}
|
||||
submitData.lots = JSON.stringify(this.formData.lots || [])
|
||||
submitData.lotDeleteList = JSON.stringify(this.lotDeleteList)
|
||||
this.$axios.post(loc() + "/doSubmit", submitData).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
addLot() {
|
||||
if (!this.formData.lots) {
|
||||
this.$set(this.formData, "lots", [])
|
||||
}
|
||||
this.formData.lots.push({
|
||||
lotName: "",
|
||||
lotValue: "",
|
||||
activityCost: null,
|
||||
allowOverReimbursement: false
|
||||
})
|
||||
},
|
||||
integerInput(row, field, value) {
|
||||
const nextValue = String(value || "").replace(/[^\d]/g, "")
|
||||
this.$set(row, field, nextValue)
|
||||
},
|
||||
outProvinceRatioTypeChange(value) {
|
||||
if (value !== "固定人数") {
|
||||
this.$set(this.formData, "outProvinceFixedPeople", 0)
|
||||
}
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.validateField("outProvinceFixedPeople"))
|
||||
},
|
||||
validateLots() {
|
||||
const lots = this.formData.lots || []
|
||||
for (let i = 0; i < lots.length; i++) {
|
||||
const row = lots[i]
|
||||
const hasContent = row && (row.lotName || row.lotValue || row.activityCost !== null && row.activityCost !== undefined && row.activityCost !== "")
|
||||
if (!hasContent) continue
|
||||
if (!/^\d+$/.test(String(row.lotValue || ""))) {
|
||||
this.$message.warning("第" + (i + 1) + "行标段值必须为整数")
|
||||
return false
|
||||
}
|
||||
if (!/^\d+$/.test(String(row.activityCost === null || row.activityCost === undefined ? "" : row.activityCost))) {
|
||||
this.$message.warning("第" + (i + 1) + "行标段费用必须为整数")
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
deleteLot(index, row) {
|
||||
this.$confirm("确定删除该标段吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
if (row && row.id) {
|
||||
this.lotDeleteList.push(row.id)
|
||||
}
|
||||
this.formData.lots.splice(index, 1)
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.configName + "】吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", {id: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
destroyEditor() {
|
||||
this.formData = {}
|
||||
this.lotDeleteList = []
|
||||
this.inheritLoading = false
|
||||
this.activeTab = "basic"
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getActivityGroup()
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tour-user-scope {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tour-user-scope .el-select {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-setting-inherit {
|
||||
margin-bottom: -40px;
|
||||
padding-right: 96px;
|
||||
position: relative;
|
||||
text-align: right;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tour-setting-basic-divider {
|
||||
border-top: 1px dashed #dcdfe6;
|
||||
margin: 2px 0 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,338 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="旅行社名称">
|
||||
<el-input
|
||||
v-model="pageForm.agencyName"
|
||||
clearable
|
||||
placeholder="请输入旅行社名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="联系人">
|
||||
<el-input
|
||||
v-model="pageForm.contactName"
|
||||
clearable
|
||||
placeholder="请输入联系人"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="联系电话">
|
||||
<el-input
|
||||
v-model="pageForm.contactPhone"
|
||||
clearable
|
||||
placeholder="请输入联系电话"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="旅行社列表">
|
||||
<el-button @click="openAdd" size="medium" type="primary">
|
||||
<i class="el-icon-plus"></i>
|
||||
新增
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="年度" prop="year" width="110" sortable="custom" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="旅行社编号" prop="agencyCode" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="旅行社名称" prop="agencyName" min-width="220" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系人" prop="contactName" width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系电话" prop="contactPhone" width="150" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="激活状态" prop="enabled" width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.enabled"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
@change="toggleEnabled(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%"
|
||||
@closed="destroyForm">
|
||||
<el-form :model="formData" :rules="formRules" label-width="110px" ref="form" :disabled="viewMode">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="旅行社名称" prop="agencyName">
|
||||
<el-input v-model="formData.agencyName" maxlength="30" show-word-limit placeholder="请输入旅行社名称"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="旅行社编号" prop="agencyCode">
|
||||
<el-input v-model="formData.agencyCode" maxlength="50" placeholder="请输入旅行社编号"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="激活状态" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系人" prop="contactName">
|
||||
<el-input v-model="formData.contactName" maxlength="10" show-word-limit placeholder="请输入联系人"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系人手机" prop="contactPhone">
|
||||
<el-input v-model="formData.contactPhone" maxlength="30" placeholder="请输入联系人手机"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="formData.email" maxlength="100" placeholder="请输入邮箱"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" type="textarea" maxlength="100" :rows="3" show-word-limit placeholder="请输入备注"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="移动端缩略图" prop="mobileThumb">
|
||||
<!-- 复用课程管理的封面上传逻辑:单图上传,保存URL,供移动端列表展示使用。 -->
|
||||
<file-upload
|
||||
style="--upload-width: 200px;--upload-height:108px"
|
||||
:upload_number="1"
|
||||
:upload_size="20971520"
|
||||
:value.sync="formData.mobileThumb"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
complete_result
|
||||
upload_mode="image"
|
||||
upload_result_category="interval">
|
||||
</file-upload>
|
||||
<div class="el-upload__tip">支持jpg、jpeg、png格式,大小不超过20MB。</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button v-if="!viewMode" type="primary" :loading="subDis" @click="doSubmit">保存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
const validateMobile = (rule, value, callback) => {
|
||||
const mobileReg = /^1[3-9]\d{9}$/
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!mobileReg.test(value)) {
|
||||
callback(new Error("手机号格式不正确"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateEmail = (rule, value, callback) => {
|
||||
const emailReg = /^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$/
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!emailReg.test(value)) {
|
||||
callback(new Error("邮箱格式不正确"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
viewMode: false,
|
||||
subDis: false,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: currentYear,
|
||||
agencyName: "",
|
||||
contactName: "",
|
||||
contactPhone: ""
|
||||
},
|
||||
formData: {},
|
||||
formRules: {
|
||||
year: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
agencyName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
agencyCode: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
contactPhone: [{ validator: validateMobile, trigger: ["blur", "change"] }],
|
||||
email: [{ validator: validateEmail, trigger: ["blur", "change"] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.agencyName = ""
|
||||
this.pageForm.contactName = ""
|
||||
this.pageForm.contactPhone = ""
|
||||
this.doSearch()
|
||||
},
|
||||
emptyForm() {
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
agencyName: "",
|
||||
agencyCode: "",
|
||||
contactName: "",
|
||||
contactPhone: "",
|
||||
email: "",
|
||||
remark: "",
|
||||
mobileThumb: "",
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新增旅行社信息"
|
||||
this.viewMode = false
|
||||
this.formData = this.emptyForm()
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑旅行社信息"
|
||||
this.viewMode = false
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
openView(row) {
|
||||
this.title = "查看旅行社信息"
|
||||
this.viewMode = true
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
loadDetail(id) {
|
||||
this.$axios.post(loc() + "/detail", { id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign(this.emptyForm(), res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.subDis = true
|
||||
this.$axios.post(loc() + "/doSubmit", this.formData).then((res) => {
|
||||
this.subDis = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.subDis = false
|
||||
})
|
||||
})
|
||||
},
|
||||
toggleEnabled(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("状态已更新")
|
||||
} else {
|
||||
row.enabled = !row.enabled
|
||||
this.$message.warning(res.msg || "状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.enabled = !row.enabled
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.agencyName + "】吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
destroyForm() {
|
||||
this.formData = {}
|
||||
this.viewMode = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,549 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="分工会审核">
|
||||
<el-radio-group class="mr5" size="small" v-model="pageForm.audit" @change="changeAudit">
|
||||
<el-radio-button :label="true">已审核</el-radio-button>
|
||||
<el-radio-button :label="false">未审核</el-radio-button>
|
||||
</el-radio-group>
|
||||
</table-tool>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前节点" prop="curTaskName" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="流程状态" prop="instanceState" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button v-if="row.taskState === 10" size="mini" type="primary" @click="openApproval(row)">审核</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<template #edit>
|
||||
<tour-approval-info ref="infoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">
|
||||
{{ formData.taskName }}
|
||||
</div>
|
||||
<el-form
|
||||
:model="formData"
|
||||
ref="formRef"
|
||||
label-width="0"
|
||||
label-suffix=":"
|
||||
class="flow-task-form">
|
||||
<el-form-item
|
||||
label="审批意见"
|
||||
prop="tf_opinion"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
|
||||
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
|
||||
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</tour-approval-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 150px) / 4);
|
||||
}
|
||||
#app .search .search-query {
|
||||
margin-left: auto;
|
||||
}
|
||||
@media screen and (max-width: 1350px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 100px) / 3);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1200px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 50px) / 2);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 992px) {
|
||||
#app .search .search-item {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.tour-approval-section {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.tour-approval-table {
|
||||
width: 100%;
|
||||
}
|
||||
.tour-approval-empty {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_APPROVAL_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <div>\n",
|
||||
" <div class=\"process-title\">\n",
|
||||
" 报名信息\n",
|
||||
" <el-link type=\"primary\" @click=\"openChart\">点击查看流程图</el-link>\n",
|
||||
" </div>\n",
|
||||
" <el-descriptions :column=\"3\" border class=\"tour-approval-section\">\n",
|
||||
" <el-descriptions-item label=\"工号\">{{ detail.jobNo || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"姓名\">{{ detail.userName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"性别\">{{ detail.gender || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"身份证号\">{{ detail.idCard || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ detail.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在工会\">{{ detail.unionName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名时间\">{{ detail.signupTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名线路\">{{ detail.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行时段\">{{ detail.travelPeriod || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路类型\">{{ detail.lineType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名酒店\">{{ detail.hotelName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"旅行社\">{{ detail.travelAgencyName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"是否携带家属\">\n",
|
||||
" {{ familyText() }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报销超出费用\">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"意向拼床人\">{{ detail.intendedRoommate || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床型\">{{ detail.bedType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床位信息\">{{ detail.bedInfo || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">直系亲属线路</div>\n",
|
||||
" <el-descriptions :column=\"3\" border>\n",
|
||||
" <el-descriptions-item label=\"亲属姓名\">{{ directRelative.relativeName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ directRelative.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"亲属关系\">{{ directRelative.relationshipName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路名称\">{{ directRelative.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行开始日期\">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行结束日期\">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">亲属信息</div>\n",
|
||||
" <el-table :data=\"familyData\" border size=\"mini\" empty-text=\"暂无亲属信息\" class=\"tour-approval-table\">\n",
|
||||
" <el-table-column label=\"序号\" type=\"index\" width=\"70\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"家属姓名\" prop=\"familyName\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"性别\" prop=\"gender\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"身份证号码\" prop=\"idCard\" min-width=\"180\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"年龄\" prop=\"age\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"关系\" prop=\"relationship\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床型\" prop=\"bedType\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床位\" prop=\"bedInfo\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"意向拼床人\" prop=\"intendedRoommate\" min-width=\"130\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" </el-table>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <div class=\"mt10\">\n",
|
||||
" <div class=\"process-title\">{{ task.displayName }}</div>\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-if=\"task.ext.isFirstTaskNode\">\n",
|
||||
" <el-descriptions-item label=\"申请用户\">\n",
|
||||
" {{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"申请时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-else>\n",
|
||||
" <el-descriptions-item label=\"办理用户\">\n",
|
||||
" {{ task.taskFormData.userName }}({{ task.taskFormData.loginName }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理意见\" :span=\"3\">\n",
|
||||
" {{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
" </template>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
"\n",
|
||||
" <snaker-chart ref=\"snakerChartRef\"></snaker-chart>\n",
|
||||
" </div>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
info() {
|
||||
this.$axios.post(loc() + "/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail.directFamilyUnitLine)
|
||||
|| (this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.row.instanceProcessDefineId || !this.row.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
lineTypeOptions: [],
|
||||
showApprovalForm: false,
|
||||
formData: {
|
||||
tf_opinion: ""
|
||||
},
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.loadOptions()
|
||||
this.doSearch()
|
||||
},
|
||||
changeAudit() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
clearCascadeFilters() {
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
},
|
||||
openView(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = false
|
||||
this.formData = {
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
openApproval(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.$confirm("您确定要提交吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
const loading = createLoading()
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.guava.index()
|
||||
this.$message.success(res.msg || "操作成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
},
|
||||
loadOptions() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
baseOptionParams() {
|
||||
return {
|
||||
audit: this.pageForm.audit,
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
keyword: this.pageForm.keyword,
|
||||
unionId: this.pageForm.unionId,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType
|
||||
}
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
if (this.pageForm.unionId && !this.unionOptions.some(item => item.id === this.pageForm.unionId)) {
|
||||
this.pageForm.unionId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.lineType === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
components: {
|
||||
"tour-approval-info": TOUR_APPROVAL_INFO
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.loadLineOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,609 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<div class="tour-ledger-toolbar">
|
||||
<div class="tour-ledger-toolbar-title">
|
||||
<table-tool :app="this" label="分工会台账"></table-tool>
|
||||
</div>
|
||||
<div class="tour-ledger-scope">
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.scopeType === 'ownUnionJoined'}"
|
||||
@click="setScopeType('ownUnionJoined')">
|
||||
本工会参加疗休养教职工({{ summaryStats.ownUnionJoinedStaffCount || 0 }})
|
||||
</el-button>
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.scopeType === 'organizedLineJoined'}"
|
||||
@click="setScopeType('organizedLineJoined')">
|
||||
参加本工会组织线路人员(含其他工会及家属)({{ summaryStats.organizedLineJoinedTotalCount || 0 }})
|
||||
</el-button>
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.overCostOnly}"
|
||||
@click="setOverCostOnly">
|
||||
超出费用由单位承担
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="pageForm.overCostOnly"
|
||||
type="primary"
|
||||
size="medium"
|
||||
icon="el-icon-download"
|
||||
@click="downloadOverCostSummary">
|
||||
导出
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="260" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否参加" prop="joined" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.joined ? 'success' : 'info'">{{ row.joined ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
title="台账详情"
|
||||
:visible.sync="detailVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%">
|
||||
<div class="tour-ledger-section">
|
||||
<div class="tour-ledger-title">教职工信息</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="工号">{{ detail.jobNo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">
|
||||
报名信息
|
||||
<el-link v-if="detailHasWorkflow()" type="primary" @click="openChart">点击查看流程图</el-link>
|
||||
</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="报名时间">{{ detail.signupTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名线路">{{ detail.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路类型">{{ detail.lineType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名酒店">{{ detail.hotelName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名旅行社">{{ detail.travelAgencyName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行时间">{{ detail.travelPeriod || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床型">{{ detail.bedType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床位信息">{{ detail.bedInfo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="意向拼床人">{{ detail.intendedRoommate || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否携带家属">{{ familyText() }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否参加">{{ detail.joined ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否报销">{{ detail.reimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报销超出费用">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="isDirectFamilyLine()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">直系亲属线路</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="亲属姓名">{{ directRelative.relativeName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ directRelative.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="亲属关系">{{ directRelative.relationshipName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路名称">{{ directRelative.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行开始日期">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行结束日期">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="showFamilySection()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">家属信息</div>
|
||||
<el-table :data="familyData" border :size="tableSize" empty-text="暂无家属信息">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床位" prop="bedInfo" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="意向拼床人" prop="intendedRoommate" min-width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<template v-if="detailHasWorkflow()" v-for="task in doneTasks">
|
||||
<div class="tour-ledger-section mt10" :key="task.id">
|
||||
<div class="tour-ledger-title">{{ task.displayName }}</div>
|
||||
<el-descriptions border :column="3" v-if="task.ext && task.ext.isFirstTaskNode">
|
||||
<el-descriptions-item label="申请用户">
|
||||
{{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions border :column="3" v-else>
|
||||
<el-descriptions-item label="办理用户">
|
||||
{{ (task.taskFormData && task.taskFormData.userName) || '' }}({{ (task.taskFormData && task.taskFormData.loginName) || '' }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext && task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理意见" :span="3">
|
||||
{{ (task.taskFormData && (task.taskFormData.opinion || task.taskFormData.tf_opinion)) || '' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<snaker-chart ref="snakerChartRef"></snaker-chart>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="detailVisible = false">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.tour-ledger-section {
|
||||
padding: 0 2px;
|
||||
}
|
||||
.tour-ledger-title {
|
||||
border-left: 4px solid #0079c2;
|
||||
color: #0079c2;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
margin-bottom: 14px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.tour-ledger-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 24px;
|
||||
margin-bottom: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-toolbar-title {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.tour-ledger-scope {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 auto;
|
||||
flex-wrap: nowrap;
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-scope .el-button {
|
||||
margin: 0;
|
||||
}
|
||||
.tour-ledger-scope .el-button + .el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn {
|
||||
background: #ecf5ff;
|
||||
border-color: #b3d8ff;
|
||||
border-radius: 4px;
|
||||
color: #0079c2;
|
||||
font-weight: 600;
|
||||
height: 34px;
|
||||
line-height: 1;
|
||||
padding: 8px 18px;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn:hover,
|
||||
.tour-ledger-scope .tour-scope-btn:focus {
|
||||
background: #d9ecff;
|
||||
border-color: #66b1ff;
|
||||
color: #006bb0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active {
|
||||
background: #0079c2;
|
||||
border-color: #0079c2;
|
||||
box-shadow: 0 2px 6px rgba(0, 121, 194, 0.24);
|
||||
color: #fff;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:hover,
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:focus {
|
||||
background: #006bb0;
|
||||
border-color: #006bb0;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
detailVisible: false,
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
lineTypeOptions: [],
|
||||
summaryStats: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
directFamilyUnitLine: false,
|
||||
fillBedInfo: true,
|
||||
detailRow: {},
|
||||
doneTasks: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: "",
|
||||
scopeType: "",
|
||||
overCostOnly: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail && this.detail.directFamilyUnitLine)
|
||||
|| !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
detailHasWorkflow() {
|
||||
return !!(this.detailRow && this.detailRow.instanceId)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail && this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.hasFamily()) {
|
||||
return "否"
|
||||
}
|
||||
const count = Number(this.familyData.length || 0)
|
||||
return count > 0 ? count + "人" : "是"
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
loadDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.detailRow.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.detailRow.instanceProcessDefineId || !this.detailRow.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.detailRow.instanceProcessDefineId, this.detailRow.instanceId)
|
||||
},
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.scopeType = ""
|
||||
this.pageForm.overCostOnly = false
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
this.doSearch()
|
||||
},
|
||||
openView(row) {
|
||||
this.detailRow = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.directFamilyUnitLine = false
|
||||
this.fillBedInfo = true
|
||||
this.doneTasks = []
|
||||
this.$axios.post(loc() + "/detail", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.detailVisible = true
|
||||
if (this.detailHasWorkflow()) {
|
||||
this.loadDoneTasks()
|
||||
}
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.userName + "】的报名台账吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
this.loadSummaryStats()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
scopeType: this.pageForm.scopeType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
lineId: this.pageForm.lineId,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
scopeType: this.pageForm.scopeType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
scopeType: this.pageForm.scopeType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.lineType === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadSummaryStats() {
|
||||
this.$axios.post(loc() + "/summaryStats", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
unionId: this.pageForm.unionId,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.summaryStats = res.data || {}
|
||||
}
|
||||
})
|
||||
},
|
||||
setScopeType(scopeType) {
|
||||
this.pageForm.scopeType = this.pageForm.scopeType === scopeType ? "" : scopeType
|
||||
this.pageForm.pageNumber = 1
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.pageData()
|
||||
},
|
||||
setOverCostOnly() {
|
||||
this.pageForm.overCostOnly = !this.pageForm.overCostOnly
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageData()
|
||||
},
|
||||
downloadOverCostSummary() {
|
||||
this.$downLoad(loc() + "/exportOverCostSummary", this.pageForm)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
this.pageData()
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.scopeType = ""
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.scopeType = ""
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.loadLineOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
File diff suppressed because it is too large
Load Diff
+480
@@ -0,0 +1,480 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tour-tag.gray {
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.tour-tag.warn {
|
||||
background: #fff3e5;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 0;
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px 12px 14px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-process-opinion {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<van-nav-bar title="校工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
<van-search
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="unionOptions" @change="doSearch" v-model="pageForm.unionId"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
<table-column label="线路名称">{{ row.lineName || '' }}</table-column>
|
||||
<table-column label="出行时段">{{ row.travelPeriod || '' }}</table-column>
|
||||
<table-column label="报销超出费用">{{ row.overCostReimbursed ? '是' : '否' }}</table-column>
|
||||
<table-column label="当前节点">{{ row.curTaskName || '' }}</table-column>
|
||||
<table-column label="流程状态">
|
||||
<enum-tag
|
||||
v-if="row.instanceState !== null && row.instanceState !== undefined && row.instanceState !== ''"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small">
|
||||
</enum-tag>
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
|
||||
<tour-info ref="infoRef">
|
||||
<div v-if="showApprovalForm" class="tour-section">
|
||||
<div class="tour-section-title">{{ formData.taskName || '审核' }}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
type="textarea"
|
||||
rows="3"
|
||||
maxlength="200"
|
||||
show-word-limit>
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div class="tour-approval-actions">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</tour-info>
|
||||
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <van-action-sheet v-model=\"visible\" title=\"报名详情\">\n",
|
||||
" <div class=\"tour-approval-sheet\">\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">教职工信息</div>\n",
|
||||
" <van-cell title=\"工号\" :value=\"detail.jobNo || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"姓名\" :value=\"detail.userName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"性别\" :value=\"detail.gender || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"身份证号\" :value=\"detail.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"detail.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在工会\" :value=\"detail.unionName || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">报名信息</div>\n",
|
||||
" <van-cell title=\"报名线路\" :value=\"detail.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路类型\" :value=\"detail.lineType || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行时段\" :value=\"detail.travelPeriod || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名时间\" :value=\"detail.signupTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名酒店\" :value=\"detail.hotelName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"旅行社\" :value=\"detail.travelAgencyName || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床型\" :value=\"detail.bedType || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床位信息\" :value=\"detail.bedInfo || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"意向拼床人\" :value=\"detail.intendedRoommate || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"携带家属\" :value=\"familyText()\"></van-cell>\n",
|
||||
" <van-cell title=\"报销超出费用\" :value=\"detail.overCostReimbursed ? '是' : '否'\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">直系亲属线路</div>\n",
|
||||
" <van-cell title=\"亲属姓名\" :value=\"directRelative.relativeName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"directRelative.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"亲属关系\" :value=\"directRelative.relationshipName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路名称\" :value=\"directRelative.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行开始\" :value=\"directRelative.travelStartTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行结束\" :value=\"directRelative.travelEndTime || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">家属信息</div>\n",
|
||||
" <template v-for=\"(item,index) in familyData\">\n",
|
||||
" <van-cell :key=\"'title_' + index\" :title=\"'家属' + (index + 1)\"></van-cell>\n",
|
||||
" <van-cell :key=\"'name_' + index\" title=\"姓名\" :value=\"item.familyName || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'gender_' + index\" title=\"性别\" :value=\"item.gender || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'id_' + index\" title=\"身份证号\" :value=\"item.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'rel_' + index\" title=\"关系\" :value=\"item.relationship || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" :key=\"'bed_' + index\" title=\"床型\" :value=\"item.bedType || ''\"></van-cell>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"doneTasks.length > 0\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">流程记录</div>\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <van-cell-group :key=\"task.id\" :title=\"task.displayName || task.taskName\">\n",
|
||||
" <van-cell title=\"办理时间\" :value=\"task.finishTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext && task.ext.submitType\"></dict-tag>\n",
|
||||
" </van-cell>\n",
|
||||
" <van-cell title=\"办理意见\" v-if=\"task.taskFormData\" class=\"direction-column-cell\">\n",
|
||||
" <div class=\"tour-process-opinion\">{{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}</div>\n",
|
||||
" </van-cell>\n",
|
||||
" </van-cell-group>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
" </div>\n",
|
||||
" </van-action-sheet>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/schoolUnionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
vant.Toast(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine || this.toBoolean(this.detail.directFamilyUnitLine) || !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine() || !this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"tour-info": TOUR_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineType: ""
|
||||
},
|
||||
auditOptions: [
|
||||
{ text: "未审核", value: false },
|
||||
{ text: "已审核", value: true }
|
||||
],
|
||||
unionOptions: [
|
||||
{ text: "全部工会", value: "" }
|
||||
],
|
||||
lineTypeOptions: [
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await Promise.all([this.loadUnionOptions(), this.loadLineTypeOptions()])
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
return this.$axios.post("/platform/tour/schoolUnionApproval/unionOptions", {
|
||||
audit: this.pageForm.audit,
|
||||
keyword: this.pageForm.keyword,
|
||||
lineType: this.pageForm.lineType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const options = (res.data || []).map(item => ({
|
||||
text: item.name,
|
||||
value: item.id
|
||||
})).filter(item => item.value)
|
||||
this.unionOptions = [{ text: "全部工会", value: "" }].concat(options)
|
||||
if (this.pageForm.unionId && !this.unionOptions.some(item => item.value === this.pageForm.unionId)) {
|
||||
this.pageForm.unionId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
return this.$axios.post("/platform/tour/schoolUnionApproval/lineTypeOptions", {
|
||||
audit: this.pageForm.audit,
|
||||
keyword: this.pageForm.keyword,
|
||||
unionId: this.pageForm.unionId
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const options = (res.data || []).map(item => ({
|
||||
text: item.lineType,
|
||||
value: item.lineType
|
||||
})).filter(item => item.value)
|
||||
this.lineTypeOptions = [{ text: "全部线路类型", value: "" }].concat(options)
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.value === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
overlay: true,
|
||||
duration: 0
|
||||
})
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
this.$toast.success(res.msg || "操作成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$toast(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,570 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-apply-page {
|
||||
min-height: 100vh;
|
||||
padding: 10px 14px 78px;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-apply-card {
|
||||
margin-bottom: 14px;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.tour-apply-title {
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-apply-title::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 0;
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-card-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tour-card-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tour-family-tab {
|
||||
margin: 10px 12px 0;
|
||||
height: 30px;
|
||||
border-radius: 5px;
|
||||
background: #1684d2;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-field-tip {
|
||||
padding: 0 16px 12px;
|
||||
color: #ee2f2f;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-over-cost /deep/ .van-field__label,
|
||||
.tour-over-cost /deep/ .van-field__label span,
|
||||
.tour-over-cost /deep/ .van-radio__label {
|
||||
color: #ee2f2f;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tour-submit-bar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 20;
|
||||
padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf0f4;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-apply-empty {
|
||||
padding: 24px 0;
|
||||
color: #94a3b8;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-apply-page">
|
||||
<van-loading v-if="pageLoading" size="24px" vertical>加载中...</van-loading>
|
||||
|
||||
<template v-else>
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">教职工信息</div>
|
||||
<van-field label="姓名" readonly v-model="signupForm.userName"></van-field>
|
||||
<van-field label="工号" readonly v-model="signupForm.jobNo"></van-field>
|
||||
<van-field label="身份证号码" v-model="signupForm.idCard" maxlength="30" placeholder="请填写身份证号码"></van-field>
|
||||
<van-field label="手机号" v-model="signupForm.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field label="所属工会" readonly v-model="signupForm.unionName"></van-field>
|
||||
</div>
|
||||
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">报名信息</div>
|
||||
<van-field label="报名线路" readonly v-model="signupForm.lineName"></van-field>
|
||||
<van-field label="线路类型" readonly v-model="signupForm.lineType"></van-field>
|
||||
<van-field v-if="signupForm.travelPeriod" label="出行时间" readonly v-model="signupForm.travelPeriod"></van-field>
|
||||
<van-field label="报名酒店" v-model="signupForm.hotelName" maxlength="100" placeholder="请输入报名酒店"></van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="signupForm.bedType"
|
||||
@click="openBedPicker('self')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位信息" v-model="signupForm.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="signupForm.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<van-field v-if="canApplyOverReimbursement(signupForm)" class="tour-over-cost" label="报销超出费用">
|
||||
<template #input>
|
||||
<van-radio-group v-model="signupForm.overCostReimbursed" direction="horizontal">
|
||||
<van-radio :name="true">是</van-radio>
|
||||
<van-radio :name="false">否</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<div v-if="canApplyOverReimbursement(signupForm) && signupForm.overCostReimbursed" class="tour-field-tip">
|
||||
提醒:您选择了报销超出费用,会影响到下一年度的疗休养,请认真思考。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isDirectFamilyLine(signupForm)" class="tour-apply-card">
|
||||
<div class="tour-apply-title">直系亲属线路</div>
|
||||
<van-field label="亲属姓名" v-model="directRelativeForm.relativeName" maxlength="100" placeholder="请输入亲属姓名"></van-field>
|
||||
<van-field label="所在单位" v-model="directRelativeForm.unitName" maxlength="100" placeholder="请输入所在单位"></van-field>
|
||||
<van-field
|
||||
label="亲属关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择亲属关系"
|
||||
v-model="directRelativeForm.relationshipName"
|
||||
@click="openDirectRelativePicker">
|
||||
</van-field>
|
||||
<van-field label="线路名称" v-model="directRelativeForm.lineName" maxlength="100" placeholder="请输入线路名称"></van-field>
|
||||
<van-field label="出行开始" v-model="directRelativeForm.travelStartTime" type="date" placeholder="请选择出行开始日期"></van-field>
|
||||
<van-field label="出行结束" v-model="directRelativeForm.travelEndTime" type="date" placeholder="请选择出行结束日期"></van-field>
|
||||
</div>
|
||||
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">
|
||||
<div class="tour-card-title-row">
|
||||
<span>亲属信息</span>
|
||||
<div class="tour-card-actions">
|
||||
<van-button size="small" type="default" :disabled="familyData.length === 0" @click="removeFamily">删除亲属</van-button>
|
||||
<van-button size="small" type="info" :disabled="!allowFamily || isDirectFamilyLine(signupForm)" @click="addFamily">添加亲属</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!allowFamily || isDirectFamilyLine(signupForm)" class="tour-apply-empty">
|
||||
当前线路不支持填写亲属
|
||||
</div>
|
||||
<template v-else-if="familyData.length > 0">
|
||||
<div class="tour-family-tab">亲属{{ familyActive + 1 }}</div>
|
||||
<van-field label="姓名" v-model="currentFamily.familyName" maxlength="100" placeholder="请填写姓名"></van-field>
|
||||
<van-field label="年龄" v-model.number="currentFamily.age" type="digit" placeholder="请填写年龄"></van-field>
|
||||
<van-field label="性别">
|
||||
<template #input>
|
||||
<van-radio-group v-model="currentFamily.gender" direction="horizontal">
|
||||
<van-radio name="男">男</van-radio>
|
||||
<van-radio name="女">女</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field label="身份证号码" v-model="currentFamily.idCard" maxlength="18" placeholder="请填写身份证号码" @blur="normalizeFamilyIdCard(currentFamily)"></van-field>
|
||||
<van-field label="手机号" v-model="currentFamily.mobile" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field
|
||||
label="与本人关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择关系"
|
||||
v-model="currentFamily.relationship"
|
||||
@click="openRelationshipPicker">
|
||||
</van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="currentFamily.bedType"
|
||||
@click="openBedPicker('family')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位" v-model="currentFamily.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="currentFamily.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<div v-if="fillBedInfo" class="tour-field-tip">提醒:如果跟报名人员同一房间,无须选择!</div>
|
||||
</template>
|
||||
<div v-else class="tour-apply-empty">暂无亲属,请按需添加</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="tour-submit-bar">
|
||||
<van-button type="info" block round :loading="submitLoading" @click="submitSignup">提交报名</van-button>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="bedPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="bedTypeColumns" @confirm="confirmBedType" @cancel="bedPickerVisible=false"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="relationshipPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="relationshipColumns" @confirm="confirmRelationship" @cancel="relationshipPickerVisible=false"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="directRelativePickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="directRelativeColumns" @confirm="confirmDirectRelative" @cancel="directRelativePickerVisible=false"></van-picker>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
pageLoading: true,
|
||||
submitLoading: false,
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
signupForm: {},
|
||||
directRelativeForm: {},
|
||||
familyData: [],
|
||||
familyActive: 0,
|
||||
bedTypeOptions: [],
|
||||
familyRelationshipOptions: [],
|
||||
directRelativeOptions: [],
|
||||
bedPickerVisible: false,
|
||||
relationshipPickerVisible: false,
|
||||
directRelativePickerVisible: false,
|
||||
bedPickerTarget: "self",
|
||||
matterId: GetQueryString("matterId") || ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentFamily() {
|
||||
return this.familyData[this.familyActive] || {}
|
||||
},
|
||||
bedTypeColumns() {
|
||||
return this.bedTypeOptions.map(item => item.name || item.code).filter(Boolean)
|
||||
},
|
||||
relationshipColumns() {
|
||||
return this.familyRelationshipOptions.map(item => item.name || item.code).filter(Boolean)
|
||||
},
|
||||
directRelativeColumns() {
|
||||
return this.directRelativeOptions.map(item => ({ text: item.name || item.code, item }))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatDateTime(date) {
|
||||
const pad = (value) => String(value).padStart(2, "0")
|
||||
return date.getFullYear()
|
||||
+ "-"
|
||||
+ pad(date.getMonth() + 1)
|
||||
+ "-"
|
||||
+ pad(date.getDate())
|
||||
+ " "
|
||||
+ pad(date.getHours())
|
||||
+ ":"
|
||||
+ pad(date.getMinutes())
|
||||
+ ":"
|
||||
+ pad(date.getSeconds())
|
||||
},
|
||||
init() {
|
||||
if (!this.matterId) {
|
||||
vant.Dialog.alert({ title: "提示", message: "报名事项参数缺失", confirmButtonColor: "#1867b0" })
|
||||
this.pageLoading = false
|
||||
return
|
||||
}
|
||||
Promise.all([this.loadOptions(), this.loadSignupDetail()]).finally(() => {
|
||||
this.pageLoading = false
|
||||
})
|
||||
},
|
||||
loadOptions() {
|
||||
return Promise.all([
|
||||
this.$axios.post("/platform/tour/signup/bedTypeOptions").then(res => {
|
||||
if (res.code === 0) this.bedTypeOptions = res.data || []
|
||||
}),
|
||||
this.$axios.post("/platform/tour/signup/familyRelationshipOptions").then(res => {
|
||||
if (res.code === 0) this.familyRelationshipOptions = res.data || []
|
||||
}),
|
||||
this.$axios.post("/platform/tour/signup/directRelativeOptions").then(res => {
|
||||
if (res.code === 0) this.directRelativeOptions = res.data || []
|
||||
})
|
||||
])
|
||||
},
|
||||
loadSignupDetail() {
|
||||
return this.$axios.post("/platform/tour/signup/signupDetail", { matterId: this.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名信息加载失败",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
const matter = data.matter || {}
|
||||
const staff = data.staff || {}
|
||||
const ledger = data.ledger || {}
|
||||
const directRelative = data.directRelative || {}
|
||||
this.allowFamily = matter.allowFamily === true || matter.allowFamily === 1 || matter.allowFamily === "1"
|
||||
this.fillBedInfo = matter.fillBedInfo === undefined || matter.fillBedInfo === null || matter.fillBedInfo === true || matter.fillBedInfo === 1 || matter.fillBedInfo === "1"
|
||||
this.signupForm = Object.assign({
|
||||
id: "",
|
||||
year: matter.year,
|
||||
jobNo: "",
|
||||
userName: "",
|
||||
gender: "",
|
||||
idCard: "",
|
||||
mobile: "",
|
||||
unitId: "",
|
||||
unitName: "",
|
||||
unionId: "",
|
||||
unionName: "",
|
||||
signupTime: this.formatDateTime(new Date()),
|
||||
matterId: matter.matterId || "",
|
||||
lineId: matter.lineId || "",
|
||||
lineName: matter.lineName || "",
|
||||
lineType: matter.lineType || "",
|
||||
directFamilyUnitLine: matter.directFamilyUnitLine,
|
||||
hotelName: "",
|
||||
travelAgencyId: matter.travelAgencyId || "",
|
||||
travelAgencyName: matter.travelAgencyName || "",
|
||||
travelPeriod: matter.travelPeriod || "",
|
||||
travelStartTime: matter.travelStartTime || "",
|
||||
travelEndTime: matter.travelEndTime || "",
|
||||
allowOverReimbursement: matter.allowOverReimbursement,
|
||||
overCostReimbursed: false,
|
||||
hasFamily: false,
|
||||
intendedRoommate: "",
|
||||
bedType: "",
|
||||
bedInfo: ""
|
||||
}, staff, ledger, {
|
||||
year: matter.year,
|
||||
matterId: matter.matterId || ledger.matterId || "",
|
||||
lineId: matter.lineId || ledger.lineId || "",
|
||||
lineName: matter.lineName || ledger.lineName || "",
|
||||
lineType: matter.lineType || ledger.lineType || "",
|
||||
directFamilyUnitLine: matter.directFamilyUnitLine,
|
||||
travelAgencyId: matter.travelAgencyId || ledger.travelAgencyId || "",
|
||||
travelAgencyName: matter.travelAgencyName || ledger.travelAgencyName || "",
|
||||
travelPeriod: matter.travelPeriod || "",
|
||||
travelStartTime: matter.travelStartTime || "",
|
||||
travelEndTime: matter.travelEndTime || "",
|
||||
allowOverReimbursement: matter.allowOverReimbursement,
|
||||
overCostReimbursed: ledger.overCostReimbursed === true || ledger.overCostReimbursed === 1 || ledger.overCostReimbursed === "1",
|
||||
hasFamily: ledger.hasFamily === true || ledger.hasFamily === 1 || ledger.hasFamily === "1"
|
||||
})
|
||||
this.directRelativeForm = Object.assign(this.emptyDirectRelative(), {
|
||||
lineId: matter.lineId || "",
|
||||
lineName: matter.lineName || "",
|
||||
travelStartTime: matter.travelStartTime || "",
|
||||
travelEndTime: matter.travelEndTime || ""
|
||||
}, directRelative)
|
||||
this.familyData = (data.families || []).map(item => Object.assign(this.emptyFamily(), item))
|
||||
if (this.familyData.length > 0) {
|
||||
this.signupForm.hasFamily = true
|
||||
}
|
||||
if (!this.allowFamily || this.isDirectFamilyLine(this.signupForm)) {
|
||||
this.familyData = []
|
||||
this.signupForm.hasFamily = false
|
||||
}
|
||||
})
|
||||
},
|
||||
emptyFamily() {
|
||||
return {
|
||||
familyName: "",
|
||||
gender: "",
|
||||
idCard: "",
|
||||
mobile: "",
|
||||
age: null,
|
||||
bedType: "",
|
||||
bedInfo: "",
|
||||
intendedRoommate: "",
|
||||
staffJobNo: this.signupForm.jobNo || "",
|
||||
staffName: this.signupForm.userName || "",
|
||||
relationship: ""
|
||||
}
|
||||
},
|
||||
emptyDirectRelative() {
|
||||
return {
|
||||
relativeName: "",
|
||||
unitName: "",
|
||||
relationshipCode: "",
|
||||
relationshipName: "",
|
||||
lineId: this.signupForm.lineId || "",
|
||||
lineName: this.signupForm.lineName || "",
|
||||
travelStartTime: this.signupForm.travelStartTime || "",
|
||||
travelEndTime: this.signupForm.travelEndTime || ""
|
||||
}
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
return row && (row.directFamilyUnitLine === true || row.directFamilyUnitLine === 1 || row.directFamilyUnitLine === "1")
|
||||
},
|
||||
canApplyOverReimbursement(row) {
|
||||
return row && (row.allowOverReimbursement === true || row.allowOverReimbursement === 1 || row.allowOverReimbursement === "1")
|
||||
},
|
||||
addFamily() {
|
||||
if (!this.allowFamily || this.isDirectFamilyLine(this.signupForm)) return
|
||||
this.familyData.push(this.emptyFamily())
|
||||
this.familyActive = this.familyData.length - 1
|
||||
this.signupForm.hasFamily = true
|
||||
},
|
||||
removeFamily() {
|
||||
if (this.familyData.length === 0) return
|
||||
this.familyData.splice(this.familyActive, 1)
|
||||
this.familyActive = Math.max(0, this.familyActive - 1)
|
||||
this.signupForm.hasFamily = this.familyData.length > 0
|
||||
},
|
||||
openBedPicker(target) {
|
||||
if (this.bedTypeColumns.length === 0) {
|
||||
vant.Toast("暂无床型选项")
|
||||
return
|
||||
}
|
||||
this.bedPickerTarget = target
|
||||
this.bedPickerVisible = true
|
||||
},
|
||||
confirmBedType(value) {
|
||||
if (this.bedPickerTarget === "family") {
|
||||
this.currentFamily.bedType = value
|
||||
} else {
|
||||
this.signupForm.bedType = value
|
||||
}
|
||||
this.bedPickerVisible = false
|
||||
},
|
||||
openRelationshipPicker() {
|
||||
if (this.relationshipColumns.length === 0) {
|
||||
vant.Toast("暂无关系选项")
|
||||
return
|
||||
}
|
||||
this.relationshipPickerVisible = true
|
||||
},
|
||||
confirmRelationship(value) {
|
||||
this.currentFamily.relationship = value
|
||||
this.relationshipPickerVisible = false
|
||||
},
|
||||
openDirectRelativePicker() {
|
||||
if (this.directRelativeColumns.length === 0) {
|
||||
vant.Toast("暂无亲属关系选项")
|
||||
return
|
||||
}
|
||||
this.directRelativePickerVisible = true
|
||||
},
|
||||
confirmDirectRelative(value) {
|
||||
const item = value && value.item ? value.item : {}
|
||||
this.directRelativeForm.relationshipCode = item.code || ""
|
||||
this.directRelativeForm.relationshipName = item.name || value.text || ""
|
||||
this.directRelativePickerVisible = false
|
||||
},
|
||||
normalizeFamilyIdCard(row) {
|
||||
if (!row || !row.idCard) return
|
||||
row.idCard = String(row.idCard).trim().toUpperCase()
|
||||
},
|
||||
isValidIdCard(value) {
|
||||
if (!value) return false
|
||||
const idCard = String(value).trim().toUpperCase()
|
||||
return /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/.test(idCard)
|
||||
},
|
||||
validateFamilies() {
|
||||
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
||||
if (this.familyData.length === 0) {
|
||||
vant.Toast("请添加亲属信息")
|
||||
return false
|
||||
}
|
||||
const invalid = this.familyData.some(item => !item.familyName || !item.gender || !item.idCard || !item.relationship)
|
||||
if (invalid) {
|
||||
vant.Toast("请完善亲属姓名、性别、身份证号码和关系")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isValidIdCard(item.idCard))
|
||||
if (invalidIdCard) {
|
||||
vant.Toast("请输入正确的亲属身份证号码")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
validateDirectRelative() {
|
||||
if (!this.isDirectFamilyLine(this.signupForm)) return true
|
||||
if (!this.directRelativeForm.relativeName) {
|
||||
vant.Toast("请输入亲属姓名")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.unitName) {
|
||||
vant.Toast("请输入亲属所在单位")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.relationshipCode) {
|
||||
vant.Toast("请选择亲属关系")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.lineName) {
|
||||
vant.Toast("请输入直系亲属线路名称")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.travelStartTime || !this.directRelativeForm.travelEndTime) {
|
||||
vant.Toast("请选择直系亲属出行时间")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
submitSignup() {
|
||||
if (this.pageLoading || this.submitLoading) return
|
||||
if (!this.validateFamilies()) return
|
||||
if (!this.validateDirectRelative()) return
|
||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||
const form = Object.assign({}, this.signupForm, {
|
||||
families: JSON.stringify(families),
|
||||
directRelative: this.isDirectFamilyLine(this.signupForm) ? JSON.stringify(this.directRelativeForm) : ""
|
||||
})
|
||||
this.submitLoading = true
|
||||
this.$axios.post("/platform/tour/signup/doSignup", form).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名成功",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(() => {
|
||||
window.location.replace("/platform/tour/signup/h5/signup")
|
||||
})
|
||||
} else {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名失败",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
vant.Toast("报名提交失败")
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,403 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-signup-h5 {
|
||||
min-height: 100vh;
|
||||
background: #f5f7fb;
|
||||
padding-bottom: 80px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-signup-banner {
|
||||
position: relative;
|
||||
height: 193px;
|
||||
overflow: hidden;
|
||||
background: #0f74bc;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tour-signup-swipe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tour-signup-swipe img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 193px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.tour-signup-banner::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(90deg, rgba(5, 83, 143, 0.72) 0%, rgba(5, 83, 143, 0.32) 48%, rgba(5, 83, 143, 0.08) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tour-signup-banner__text {
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
right: 16px;
|
||||
bottom: 20px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tour-signup-title {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.tour-signup-subtitle {
|
||||
margin-top: 8px;
|
||||
color: rgba(255, 255, 255, 0.86);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-signup-card {
|
||||
margin: 10px 12px 0;
|
||||
padding: 14px 14px 16px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 8px 20px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.tour-signup-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
}
|
||||
|
||||
.tour-signup-card__title {
|
||||
color: #111827;
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.tour-signup-card__year {
|
||||
flex-shrink: 0;
|
||||
color: #0f74bc;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-signup-notice {
|
||||
margin-top: 14px;
|
||||
color: #334155;
|
||||
font-size: 15px;
|
||||
line-height: 1.8;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-signup-notice /deep/ img,
|
||||
.tour-signup-notice /deep/ video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tour-pdf-preview {
|
||||
min-height: 560px;
|
||||
}
|
||||
|
||||
.tour-pdf-status {
|
||||
padding: 16px 0;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-pdf-toolbar {
|
||||
margin-bottom: 8px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-pdf-pages {
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
.tour-pdf-page {
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: #f8fafc;
|
||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.tour-pdf-page canvas {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tour-signup-empty {
|
||||
padding: 34px 0 26px;
|
||||
}
|
||||
|
||||
.tour-signup-footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: 0 -6px 18px rgba(15, 23, 42, 0.08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-signup-h5">
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-signup-banner">
|
||||
<van-swipe class="tour-signup-swipe" :autoplay="3500" indicator-color="white">
|
||||
<van-swipe-item v-for="item in bannerList" :key="item">
|
||||
<img :src="item" alt="疗休养报名">
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
<div class="tour-signup-banner__text">
|
||||
<div class="tour-signup-title">疗休养报名</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-signup-card">
|
||||
<div class="tour-signup-card__header">
|
||||
<div class="tour-signup-card__title">服务须知</div>
|
||||
<div class="tour-signup-card__year">{{ setting.year || currentYear }}年度</div>
|
||||
</div>
|
||||
|
||||
<van-skeleton title :row="8" :loading="loading">
|
||||
<div v-if="setting.serviceNotice" class="tour-signup-notice">
|
||||
<div v-if="serviceNoticePdfHref" class="tour-pdf-preview">
|
||||
<div v-if="pdfPageCount" class="tour-pdf-toolbar">
|
||||
已加载 {{ pdfRenderedPages }} / {{ pdfPageCount }} 页
|
||||
</div>
|
||||
<div ref="pdfPreviewContainer" class="tour-pdf-pages"></div>
|
||||
<div v-if="pdfLoading && pdfRenderedPages === 0" class="tour-pdf-status">
|
||||
<van-loading size="22px" vertical>正在加载第一页...</van-loading>
|
||||
</div>
|
||||
<div v-else-if="pdfLoading" class="tour-pdf-status">
|
||||
正在继续加载后续页面...
|
||||
</div>
|
||||
<div v-if="pdfError" class="tour-pdf-status">{{ pdfError }}</div>
|
||||
</div>
|
||||
<div v-else v-html="setting.serviceNotice"></div>
|
||||
</div>
|
||||
<van-empty v-else class="tour-signup-empty" description="暂无服务须知"></van-empty>
|
||||
</van-skeleton>
|
||||
</div>
|
||||
|
||||
<div class="tour-signup-footer">
|
||||
<van-button block type="info" color="#0f74bc" round @click="confirmRead">我已阅读</van-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
currentYear: new Date().getFullYear(),
|
||||
serviceNoticePdfHref: "",
|
||||
pdfDoc: null,
|
||||
pdfLoadingTask: null,
|
||||
pdfLoading: false,
|
||||
pdfError: "",
|
||||
pdfPageCount: 0,
|
||||
pdfRenderedPages: 0,
|
||||
pdfRenderToken: 0,
|
||||
bannerList: [
|
||||
"/assets/platform/images/tour/tour-h5-banner-1.jpg",
|
||||
"/assets/platform/images/tour/tour-h5-banner-2.jpg"
|
||||
],
|
||||
setting: {
|
||||
year: "",
|
||||
configName: "",
|
||||
serviceNotice: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
parseContentHref(content) {
|
||||
if (!content) {
|
||||
return ""
|
||||
}
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(content, "text/html")
|
||||
const link = doc.querySelector("a[href]")
|
||||
return link ? link.getAttribute("href") : ""
|
||||
} catch (e) {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
getPdfLib() {
|
||||
return window.pdfjsLib || window["pdfjs-dist/build/pdf"]
|
||||
},
|
||||
loadPdfLib() {
|
||||
const pdfLib = this.getPdfLib()
|
||||
if (pdfLib && pdfLib.getDocument) {
|
||||
return Promise.resolve(pdfLib)
|
||||
}
|
||||
return window.loadScriptOnce("/assets/platform/plugins/pdfJs/h5/pdf.js?v=20260524").then(() => {
|
||||
const loadedPdfLib = this.getPdfLib()
|
||||
if (!loadedPdfLib || !loadedPdfLib.getDocument) {
|
||||
throw new Error("pdf lib load failed")
|
||||
}
|
||||
return loadedPdfLib
|
||||
})
|
||||
},
|
||||
clearPdfPreview() {
|
||||
this.pdfRenderToken += 1
|
||||
this.pdfDoc = null
|
||||
this.pdfLoading = false
|
||||
this.pdfError = ""
|
||||
this.pdfPageCount = 0
|
||||
this.pdfRenderedPages = 0
|
||||
if (this.pdfLoadingTask && this.pdfLoadingTask.destroy) {
|
||||
try {
|
||||
this.pdfLoadingTask.destroy()
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
this.pdfLoadingTask = null
|
||||
if (this.$refs.pdfPreviewContainer) {
|
||||
this.$refs.pdfPreviewContainer.innerHTML = ""
|
||||
}
|
||||
},
|
||||
renderServiceNoticePdf() {
|
||||
this.clearPdfPreview()
|
||||
if (!this.serviceNoticePdfHref) {
|
||||
return
|
||||
}
|
||||
const token = this.pdfRenderToken
|
||||
this.pdfLoading = true
|
||||
this.loadPdfLib().then((pdfLib) => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return null
|
||||
}
|
||||
if (pdfLib.GlobalWorkerOptions) {
|
||||
pdfLib.GlobalWorkerOptions.workerSrc = "/assets/platform/plugins/pdfJs/h5/pdf.worker.js?v=20260524"
|
||||
}
|
||||
this.pdfLoadingTask = pdfLib.getDocument({
|
||||
url: this.serviceNoticePdfHref,
|
||||
disableAutoFetch: false,
|
||||
disableStream: false,
|
||||
disableRange: false
|
||||
})
|
||||
return this.pdfLoadingTask.promise
|
||||
}).then((pdf) => {
|
||||
if (token !== this.pdfRenderToken || !pdf) {
|
||||
return
|
||||
}
|
||||
this.pdfDoc = pdf
|
||||
this.pdfPageCount = pdf.numPages || 0
|
||||
return this.renderPdfPage(1, token)
|
||||
}).then(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.renderRestPdfPages(2, token)
|
||||
}).catch(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "PDF加载失败,请稍后重试"
|
||||
})
|
||||
},
|
||||
renderPdfPage(pageNumber, token) {
|
||||
if (!this.pdfDoc || token !== this.pdfRenderToken || pageNumber > this.pdfPageCount) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.pdfDoc.getPage(pageNumber).then((page) => {
|
||||
if (token !== this.pdfRenderToken || !this.$refs.pdfPreviewContainer) {
|
||||
return
|
||||
}
|
||||
const container = this.$refs.pdfPreviewContainer
|
||||
const baseViewport = page.getViewport({scale: 1})
|
||||
const containerWidth = Math.max(container.clientWidth || 0, window.innerWidth - 44)
|
||||
const cssScale = containerWidth / baseViewport.width
|
||||
const outputScale = Math.min(window.devicePixelRatio || 1, 2)
|
||||
const viewport = page.getViewport({scale: cssScale})
|
||||
const pageEl = document.createElement("div")
|
||||
pageEl.className = "tour-pdf-page"
|
||||
const canvas = document.createElement("canvas")
|
||||
const context = canvas.getContext("2d")
|
||||
canvas.width = Math.floor(viewport.width * outputScale)
|
||||
canvas.height = Math.floor(viewport.height * outputScale)
|
||||
canvas.style.width = Math.floor(viewport.width) + "px"
|
||||
canvas.style.height = Math.floor(viewport.height) + "px"
|
||||
pageEl.appendChild(canvas)
|
||||
container.appendChild(pageEl)
|
||||
return page.render({
|
||||
canvasContext: context,
|
||||
viewport: viewport,
|
||||
transform: outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null
|
||||
}).promise.then(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfRenderedPages = Math.max(this.pdfRenderedPages, pageNumber)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
renderRestPdfPages(pageNumber, token) {
|
||||
if (token !== this.pdfRenderToken || !this.pdfDoc || pageNumber > this.pdfPageCount) {
|
||||
this.pdfLoading = false
|
||||
return
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.renderPdfPage(pageNumber, token).then(() => {
|
||||
this.renderRestPdfPages(pageNumber + 1, token)
|
||||
}).catch(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "部分页面加载失败"
|
||||
}
|
||||
})
|
||||
}, 120)
|
||||
},
|
||||
loadServiceNotice() {
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/serviceNotice").then((res) => {
|
||||
this.loading = false
|
||||
if (res.code === 0) {
|
||||
this.setting = Object.assign({}, this.setting, res.data || {})
|
||||
this.serviceNoticePdfHref = this.parseContentHref(this.setting.serviceNotice)
|
||||
this.$nextTick(() => {
|
||||
this.renderServiceNoticePdf()
|
||||
})
|
||||
} else {
|
||||
vant.Toast(res.msg || "服务须知加载失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
confirmRead() {
|
||||
window.location.href = "/platform/tour/signup/h5/signup"
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadServiceNotice()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearPdfPreview()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,587 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
#app {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tour-detail-page {
|
||||
height: calc(100vh - 46px);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px 10px 70px;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-detail-header {
|
||||
padding: 14px 12px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.tour-detail-title {
|
||||
color: #0f172a;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-detail-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.tour-line-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 0 7px;
|
||||
border-radius: 4px;
|
||||
background: #0b75bd;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-detail-meta {
|
||||
margin-top: 10px;
|
||||
color: #334155;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-detail-meta-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tour-detail-meta-label {
|
||||
width: 72px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #64748b;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-detail-meta-value {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-detail-section {
|
||||
margin-top: 10px;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-detail-section-title {
|
||||
flex-shrink: 0;
|
||||
margin-bottom: 8px;
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid #0b75bd;
|
||||
color: #0f172a;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-detail-content /deep/ img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tour-detail-section-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.tour-pdf-preview {
|
||||
min-height: 220px;
|
||||
}
|
||||
|
||||
.tour-pdf-status {
|
||||
padding: 16px 0;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-pdf-toolbar {
|
||||
margin-bottom: 8px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-pdf-pages {
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
.tour-pdf-page {
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: #f8fafc;
|
||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.tour-pdf-page canvas {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tour-detail-empty {
|
||||
padding: 18px 0;
|
||||
color: #94a3b8;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-detail-footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
padding: 9px 12px calc(9px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf0f4;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="线路详情" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-detail-page">
|
||||
<van-loading v-if="detailLoading" size="24px" vertical>加载中...</van-loading>
|
||||
<template v-else>
|
||||
<div class="tour-detail-header">
|
||||
<div class="tour-detail-title">{{ lineDetail.lineName || signupDetail.lineName || '线路详情' }}</div>
|
||||
<div class="tour-detail-tags">
|
||||
<span v-if="lineDetail.lotName || signupDetail.lotName" class="tour-line-tag">{{ lineDetail.lotName || signupDetail.lotName }}</span>
|
||||
<span v-if="lineDetail.lineType || signupDetail.lineType" class="tour-line-tag">{{ lineDetail.lineType || signupDetail.lineType }}</span>
|
||||
<span v-if="signupDetail.unionName" class="tour-line-tag">{{ signupDetail.unionName }}</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta">
|
||||
<div v-if="travelPeriod(signupDetail)" class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>出行时间</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ travelPeriod(signupDetail) }}</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>已报人数</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ signupDetail.signupCount || 0 }}(家属{{ signupDetail.familyCount || 0 }}人)</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>联系人</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ signupDetail.contactName || '暂无' }}</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>联系方式</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ lineDetail.contactPhone || signupDetail.contactPhone || '暂无' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tour-detail-section">
|
||||
<div class="tour-detail-section-title">线路介绍</div>
|
||||
<div class="tour-detail-section-scroll">
|
||||
<div v-if="lineDetail.lineContent && lineContentHref" class="tour-pdf-preview">
|
||||
<div v-if="pdfPageCount" class="tour-pdf-toolbar">
|
||||
已加载 {{ pdfRenderedPages }} / {{ pdfPageCount }} 页
|
||||
</div>
|
||||
<div ref="pdfPreviewContainer" class="tour-pdf-pages"></div>
|
||||
<div v-if="pdfLoading && pdfRenderedPages === 0" class="tour-pdf-status">
|
||||
<van-loading size="22px" vertical>正在加载第一页...</van-loading>
|
||||
</div>
|
||||
<div v-else-if="pdfLoading" class="tour-pdf-status">
|
||||
正在继续加载后续页面...
|
||||
</div>
|
||||
<div v-if="pdfError" class="tour-pdf-status">{{ pdfError }}</div>
|
||||
</div>
|
||||
<div v-else-if="lineDetail.lineContent" class="tour-detail-content" v-html="lineDetail.lineContent">
|
||||
</div>
|
||||
<div v-else class="tour-detail-empty">暂无线路介绍</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="tour-detail-footer">
|
||||
<van-button :type="detailActionType()" block round :disabled="detailActionDisabled()" @click="handleDetailAction">
|
||||
{{ detailActionText() }}
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
detailLoading: true,
|
||||
lineDetail: {},
|
||||
signupDetail: {},
|
||||
lineContentHref: "",
|
||||
pdfDoc: null,
|
||||
pdfLoadingTask: null,
|
||||
pdfLoading: false,
|
||||
pdfError: "",
|
||||
pdfPageCount: 0,
|
||||
pdfRenderedPages: 0,
|
||||
pdfRenderToken: 0,
|
||||
matterId: GetQueryString("matterId") || "",
|
||||
lineId: GetQueryString("lineId") || ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
travelPeriod(row) {
|
||||
if (!row) {
|
||||
return ""
|
||||
}
|
||||
if (row.travelStartTime && row.travelEndTime) {
|
||||
return row.travelStartTime + " 至 " + row.travelEndTime
|
||||
}
|
||||
return row.travelPeriod || row.travelStartTime || row.travelEndTime || ""
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
isSigned() {
|
||||
return !!(this.signupDetail && this.signupDetail.signed)
|
||||
},
|
||||
isApprovalSignup() {
|
||||
return this.isSigned() && !!this.signupDetail.instanceId
|
||||
},
|
||||
canRevokeSignup() {
|
||||
return this.isApprovalSignup() && this.toBoolean(this.signupDetail.canRevoke) && !!this.signupDetail.startTaskId
|
||||
},
|
||||
isFinishedSignup() {
|
||||
return this.isApprovalSignup() && Number(this.signupDetail.instanceState) === 20
|
||||
},
|
||||
isRejectedSignup() {
|
||||
return this.isApprovalSignup() && Number(this.signupDetail.instanceState) === 45
|
||||
},
|
||||
canModifySignup() {
|
||||
if (!this.isSigned()) {
|
||||
return true
|
||||
}
|
||||
if (!this.isApprovalSignup()) {
|
||||
return true
|
||||
}
|
||||
return !this.isFinishedSignup() && !this.isRejectedSignup() && this.signupDetail.taskKey === "startTask"
|
||||
},
|
||||
detailActionText() {
|
||||
if (this.isSigned()) {
|
||||
if (this.canRevokeSignup()) {
|
||||
return "撤回"
|
||||
}
|
||||
if (this.isFinishedSignup()) {
|
||||
return "已完成"
|
||||
}
|
||||
if (this.isRejectedSignup()) {
|
||||
return "已拒绝"
|
||||
}
|
||||
return this.canModifySignup() ? "修改报名" : "审核中"
|
||||
}
|
||||
return "我要报名"
|
||||
},
|
||||
detailActionType() {
|
||||
return this.canRevokeSignup() ? "danger" : "info"
|
||||
},
|
||||
detailActionDisabled() {
|
||||
return this.isSigned() && this.isApprovalSignup() && (this.isFinishedSignup() || this.isRejectedSignup() || (!this.canRevokeSignup() && !this.canModifySignup()))
|
||||
},
|
||||
handleDetailAction() {
|
||||
if (this.detailActionDisabled()) {
|
||||
return
|
||||
}
|
||||
if (this.canRevokeSignup()) {
|
||||
this.revokeSignup()
|
||||
return
|
||||
}
|
||||
this.onApply()
|
||||
},
|
||||
parseLineContentHref(content) {
|
||||
if (!content) {
|
||||
return ""
|
||||
}
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(content, "text/html")
|
||||
const link = doc.querySelector("a[href]")
|
||||
return link ? link.getAttribute("href") : ""
|
||||
} catch (e) {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
getPdfLib() {
|
||||
return window.pdfjsLib || window["pdfjs-dist/build/pdf"]
|
||||
},
|
||||
loadPdfLib() {
|
||||
const pdfLib = this.getPdfLib()
|
||||
if (pdfLib && pdfLib.getDocument) {
|
||||
return Promise.resolve(pdfLib)
|
||||
}
|
||||
return window.loadScriptOnce("/assets/platform/plugins/pdfJs/h5/pdf.js?v=20260524").then(() => {
|
||||
const loadedPdfLib = this.getPdfLib()
|
||||
if (!loadedPdfLib || !loadedPdfLib.getDocument) {
|
||||
throw new Error("pdf lib load failed")
|
||||
}
|
||||
return loadedPdfLib
|
||||
})
|
||||
},
|
||||
clearPdfPreview() {
|
||||
this.pdfRenderToken += 1
|
||||
this.pdfDoc = null
|
||||
this.pdfLoading = false
|
||||
this.pdfError = ""
|
||||
this.pdfPageCount = 0
|
||||
this.pdfRenderedPages = 0
|
||||
if (this.pdfLoadingTask && this.pdfLoadingTask.destroy) {
|
||||
try {
|
||||
this.pdfLoadingTask.destroy()
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
this.pdfLoadingTask = null
|
||||
if (this.$refs.pdfPreviewContainer) {
|
||||
this.$refs.pdfPreviewContainer.innerHTML = ""
|
||||
}
|
||||
},
|
||||
renderLinePdf() {
|
||||
this.clearPdfPreview()
|
||||
if (!this.lineContentHref) {
|
||||
return
|
||||
}
|
||||
if (!this.getPdfLib() || !this.getPdfLib().getDocument) {
|
||||
const token = this.pdfRenderToken
|
||||
this.pdfLoading = true
|
||||
this.loadPdfLib().then(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.renderLinePdf()
|
||||
}
|
||||
}).catch(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "PDF预览组件加载失败"
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
const pdfLib = this.getPdfLib()
|
||||
if (!pdfLib || !pdfLib.getDocument) {
|
||||
this.pdfError = "PDF预览组件加载失败"
|
||||
return
|
||||
}
|
||||
if (pdfLib.GlobalWorkerOptions) {
|
||||
pdfLib.GlobalWorkerOptions.workerSrc = "/assets/platform/plugins/pdfJs/h5/pdf.worker.js?v=20260524"
|
||||
}
|
||||
const token = this.pdfRenderToken
|
||||
this.pdfLoading = true
|
||||
this.pdfLoadingTask = pdfLib.getDocument({
|
||||
url: this.lineContentHref,
|
||||
disableAutoFetch: false,
|
||||
disableStream: false,
|
||||
disableRange: false
|
||||
})
|
||||
this.pdfLoadingTask.promise.then((pdf) => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.pdfDoc = pdf
|
||||
this.pdfPageCount = pdf.numPages || 0
|
||||
return this.renderPdfPage(1, token)
|
||||
}).then(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.renderRestPdfPages(2, token)
|
||||
}).catch(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "PDF加载失败,请稍后重试"
|
||||
})
|
||||
},
|
||||
renderPdfPage(pageNumber, token) {
|
||||
if (!this.pdfDoc || token !== this.pdfRenderToken || pageNumber > this.pdfPageCount) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.pdfDoc.getPage(pageNumber).then((page) => {
|
||||
if (token !== this.pdfRenderToken || !this.$refs.pdfPreviewContainer) {
|
||||
return
|
||||
}
|
||||
const container = this.$refs.pdfPreviewContainer
|
||||
const baseViewport = page.getViewport({scale: 1})
|
||||
const containerWidth = Math.max(container.clientWidth || 0, window.innerWidth - 44)
|
||||
const cssScale = containerWidth / baseViewport.width
|
||||
const outputScale = Math.min(window.devicePixelRatio || 1, 2)
|
||||
const viewport = page.getViewport({scale: cssScale})
|
||||
const pageEl = document.createElement("div")
|
||||
pageEl.className = "tour-pdf-page"
|
||||
const canvas = document.createElement("canvas")
|
||||
const context = canvas.getContext("2d")
|
||||
canvas.width = Math.floor(viewport.width * outputScale)
|
||||
canvas.height = Math.floor(viewport.height * outputScale)
|
||||
canvas.style.width = Math.floor(viewport.width) + "px"
|
||||
canvas.style.height = Math.floor(viewport.height) + "px"
|
||||
pageEl.appendChild(canvas)
|
||||
container.appendChild(pageEl)
|
||||
const renderContext = {
|
||||
canvasContext: context,
|
||||
viewport: viewport,
|
||||
transform: outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null
|
||||
}
|
||||
return page.render(renderContext).promise.then(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfRenderedPages = Math.max(this.pdfRenderedPages, pageNumber)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
renderRestPdfPages(pageNumber, token) {
|
||||
if (token !== this.pdfRenderToken || !this.pdfDoc || pageNumber > this.pdfPageCount) {
|
||||
this.pdfLoading = false
|
||||
return
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.renderPdfPage(pageNumber, token).then(() => {
|
||||
this.renderRestPdfPages(pageNumber + 1, token)
|
||||
}).catch(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "部分页面加载失败"
|
||||
}
|
||||
})
|
||||
}, 120)
|
||||
},
|
||||
loadDetail() {
|
||||
if (!this.matterId || !this.lineId) {
|
||||
this.detailLoading = false
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: "线路参数不完整",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
Promise.all([
|
||||
this.$axios.post("/platform/tour/signup/lineDetail", { lineId: this.lineId }),
|
||||
this.$axios.post("/platform/tour/signup/signupDetail", { matterId: this.matterId })
|
||||
]).then(([lineRes, signupRes]) => {
|
||||
this.detailLoading = false
|
||||
if (lineRes.code !== 0) {
|
||||
vant.Toast(lineRes.msg || "线路详情加载失败")
|
||||
} else {
|
||||
this.lineDetail = lineRes.data || {}
|
||||
this.lineContentHref = this.parseLineContentHref(this.lineDetail.lineContent)
|
||||
this.$nextTick(() => {
|
||||
this.renderLinePdf()
|
||||
})
|
||||
}
|
||||
if (signupRes.code !== 0) {
|
||||
vant.Toast(signupRes.msg || "报名信息加载失败")
|
||||
} else {
|
||||
const data = signupRes.data || {}
|
||||
const process = data.process || {}
|
||||
this.signupDetail = Object.assign({}, data.matter || {}, {
|
||||
signed: !!(data.ledger && data.ledger.id)
|
||||
}, process)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
vant.Toast("线路详情加载失败")
|
||||
})
|
||||
},
|
||||
onApply() {
|
||||
if (!this.matterId) {
|
||||
vant.Toast("报名事项信息不完整")
|
||||
return
|
||||
}
|
||||
const goApply = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(this.matterId)
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: this.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: res.msg || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
if (!data.noticeRequired) {
|
||||
goApply()
|
||||
return
|
||||
}
|
||||
if (data.canApply) {
|
||||
vant.Dialog.confirm({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前可报名,是否继续报名?",
|
||||
confirmButtonText: "继续报名",
|
||||
cancelButtonText: "稍后报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(goApply).catch(() => {})
|
||||
} else {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
revokeSignup() {
|
||||
vant.Dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?",
|
||||
confirmButtonColor: "#ee2f2f"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", { taskId: this.signupDetail.startTaskId }).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
vant.Toast.success(resp.msg || "撤回成功")
|
||||
this.loadDetail()
|
||||
} else {
|
||||
vant.Dialog.alert({ title: "提示", message: resp.msg || "撤回失败", confirmButtonColor: "#1867b0" })
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadDetail()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearPdfPreview()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,794 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-line-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-toolbar {
|
||||
padding: 10px 0 8px 16px;
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-line-toolbar /deep/ .van-search {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-line-toolbar /deep/ .van-search__content {
|
||||
height: 38px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__content {
|
||||
height: 38px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-line-toolbar /deep/ .van-search__action {
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__action {
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.tour-line-search-button {
|
||||
width: 42px;
|
||||
height: 38px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #1e88e5;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-search-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-entry {
|
||||
width: 48px;
|
||||
min-height: 42px;
|
||||
flex-shrink: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-line-union-entry .van-icon {
|
||||
color: #64748b;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-union-entry--active,
|
||||
.tour-line-union-entry--active .van-icon {
|
||||
color: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-line-union-popup {
|
||||
max-height: 68vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__title {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
padding: 14px 16px 10px;
|
||||
background: #ffffff;
|
||||
color: #0f172a;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__list {
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item {
|
||||
min-height: 48px;
|
||||
transition: background-color 0.18s ease, color 0.18s ease;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item:hover,
|
||||
.tour-line-union-popup__item:active {
|
||||
background: rgba(30, 136, 229, 0.1);
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item:hover /deep/ .van-cell__title,
|
||||
.tour-line-union-popup__item:active /deep/ .van-cell__title {
|
||||
color: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item--active /deep/ .van-cell__title {
|
||||
color: #0b75bd;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tour-line-shortcuts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut {
|
||||
min-height: 76px;
|
||||
padding: 12px 8px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-shortcut--active {
|
||||
border-color: #0b75bd;
|
||||
background: rgba(11, 117, 189, 0.08);
|
||||
}
|
||||
|
||||
.tour-line-shortcut__icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
flex-shrink: 0;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__text {
|
||||
min-width: 0;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__hint {
|
||||
margin-top: 2px;
|
||||
color: #64748b;
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-line-list {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.tour-line-card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
min-height: 112px;
|
||||
margin: 8px 0;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-thumb {
|
||||
width: 145px;
|
||||
height: 98px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
background: #e5edf6;
|
||||
}
|
||||
|
||||
.tour-line-thumb img,
|
||||
.tour-line-thumb .van-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tour-line-thumb-empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #8a98a8;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tour-line-main {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-line-signed-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
background: #a78bfa;
|
||||
color: #ffffff;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
box-shadow: 0 2px 5px rgba(167, 139, 250, 0.32);
|
||||
}
|
||||
|
||||
.tour-line-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tour-line-title {
|
||||
min-width: 0;
|
||||
color: #0f172a;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-line-type-badge {
|
||||
height: 18px;
|
||||
flex-shrink: 0;
|
||||
padding: 0 5px;
|
||||
border: 1px solid #ffd6a8;
|
||||
border-radius: 4px;
|
||||
background: #fff3e5;
|
||||
color: #d97706;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
line-height: 17px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.tour-line-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 0 7px;
|
||||
border-radius: 4px;
|
||||
background: #39a9ed;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-line-info {
|
||||
margin-top: 5px;
|
||||
color: #111827;
|
||||
font-size: 13px;
|
||||
line-height: 1.55;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-line-info span {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.tour-line-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.tour-line-action {
|
||||
min-width: 70px;
|
||||
height: 28px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #1e88e5;
|
||||
border-radius: 14px;
|
||||
background: #1e88e5;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.tour-line-action--danger {
|
||||
border-color: #ee2f2f;
|
||||
background: #ee2f2f;
|
||||
}
|
||||
|
||||
.tour-line-action--disabled {
|
||||
border-color: #d1d5db;
|
||||
background: #e5e7eb;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.tour-line-card {
|
||||
gap: 9px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.tour-line-thumb {
|
||||
width: 126px;
|
||||
height: 92px;
|
||||
}
|
||||
|
||||
.tour-line-title {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-line-page">
|
||||
<van-nav-bar title="疗休养线路" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-line-toolbar">
|
||||
<div class="tour-line-search-row">
|
||||
<van-search
|
||||
v-model="pageForm.lineName"
|
||||
show-action
|
||||
clearable
|
||||
placeholder="请输入线路名称搜索"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<button type="button" class="tour-line-search-button" @click="doSearch">
|
||||
<van-icon name="search"></van-icon>
|
||||
</button>
|
||||
</template>
|
||||
</van-search>
|
||||
<button
|
||||
type="button"
|
||||
class="tour-line-union-entry"
|
||||
:class="{'tour-line-union-entry--active': !!pageForm.unionId}"
|
||||
@click="openUnionPopup">
|
||||
<van-icon name="friends-o"></van-icon>
|
||||
<span>分工会</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="tour-line-shortcuts">
|
||||
<div
|
||||
class="tour-line-shortcut"
|
||||
:class="{'tour-line-shortcut--active': pageForm.lineType === '省内线路' && pageForm.directFamilyUnitLine === null}"
|
||||
@click="toggleLineType('省内线路')">
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-in-province.png" alt="省内线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省内线路</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="tour-line-shortcut"
|
||||
:class="{'tour-line-shortcut--active': pageForm.lineType === '省外线路' && pageForm.directFamilyUnitLine === null}"
|
||||
@click="toggleLineType('省外线路')">
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-out-province.png" alt="省外线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省外线路</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="tour-line-shortcut"
|
||||
:class="{'tour-line-shortcut--active': pageForm.directFamilyUnitLine === true}"
|
||||
@click="toggleDirectFamilyLine">
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-direct-family-icon.png?v=20260524" alt="直系亲属">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>直系亲属</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-line-scroll">
|
||||
<van-list
|
||||
v-model="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
@load="loadData">
|
||||
<div class="tour-line-list">
|
||||
<div class="tour-line-card" v-for="row in list" :key="row.matterId" @click="onLine(row)">
|
||||
<div class="tour-line-thumb">
|
||||
<van-image v-if="thumbUrl(row)" :src="thumbUrl(row)" fit="cover" lazy-load>
|
||||
<template #loading>
|
||||
<div class="tour-line-thumb-empty">图片加载中</div>
|
||||
</template>
|
||||
<template #error>
|
||||
<div class="tour-line-thumb-empty">暂无图片</div>
|
||||
</template>
|
||||
</van-image>
|
||||
<div v-else class="tour-line-thumb-empty">暂无图片</div>
|
||||
</div>
|
||||
<div class="tour-line-main">
|
||||
<div class="tour-line-title-row">
|
||||
<div class="tour-line-title">{{ row.lineName || '未命名线路' }}</div>
|
||||
<span v-if="lineTypeBadge(row.lineType)" class="tour-line-type-badge">{{ lineTypeBadge(row.lineType) }}</span>
|
||||
<span v-if="isSigned(row)" class="tour-line-signed-icon">
|
||||
<van-icon name="good-job"></van-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tour-line-tags">
|
||||
<span v-if="row.lotName" class="tour-line-tag">{{ row.lotName }}</span>
|
||||
<span v-if="row.unionName" class="tour-line-tag">{{ row.unionName }}</span>
|
||||
</div>
|
||||
<div class="tour-line-info">
|
||||
<div><span>出行开始时间:</span>{{ row.travelStartTime || '暂无' }}</div>
|
||||
<div><span>出行结束时间:</span>{{ row.travelEndTime || '暂无' }}</div>
|
||||
<!-- 临时屏蔽旅行社信息,保留字段和接口便于后续恢复。
|
||||
<div><span>旅行社:</span>{{ row.travelAgencyName || '暂无' }}</div>
|
||||
-->
|
||||
</div>
|
||||
<div class="tour-line-actions">
|
||||
<button
|
||||
v-if="showSignupAction(row)"
|
||||
type="button"
|
||||
class="tour-line-action"
|
||||
:class="{
|
||||
'tour-line-action--danger': canRevokeSignup(row),
|
||||
'tour-line-action--disabled': signupActionDisabled(row)
|
||||
}"
|
||||
:disabled="signupActionDisabled(row)"
|
||||
@click.stop="handleSignupAction(row)">
|
||||
{{ signupActionText(row) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
|
||||
<van-empty v-if="!loading && list.length === 0" description="暂无线路"></van-empty>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="showUnionPopup" position="bottom" round>
|
||||
<div class="tour-line-union-popup">
|
||||
<div class="tour-line-union-popup__title">选择分工会</div>
|
||||
<div class="tour-line-union-popup__list">
|
||||
<van-cell
|
||||
v-for="item in unionList"
|
||||
:key="item.id || 'all'"
|
||||
clickable
|
||||
class="tour-line-union-popup__item"
|
||||
:class="{'tour-line-union-popup__item--active': pageForm.unionId === item.id}"
|
||||
:title="item.name"
|
||||
@click="selectUnion(item)">
|
||||
<template #right-icon>
|
||||
<van-icon v-if="pageForm.unionId === item.id" name="success" color="#0b75bd"></van-icon>
|
||||
</template>
|
||||
</van-cell>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
finished: false,
|
||||
lineChecking: false,
|
||||
showUnionPopup: false,
|
||||
unionList: [
|
||||
{id: "", name: "全部分工会"}
|
||||
],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: new Date().getFullYear(),
|
||||
lineName: "",
|
||||
lineType: "",
|
||||
unionId: "",
|
||||
directFamilyUnitLine: null,
|
||||
pageOrderName: "lineName",
|
||||
pageOrderBy: "ascending"
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
thumbUrl(row) {
|
||||
return row.lineMobileThumb || row.agencyMobileThumb || ""
|
||||
},
|
||||
lineTypeBadge(lineType) {
|
||||
if (lineType === "省内线路" || lineType === "省内") {
|
||||
return "省内"
|
||||
}
|
||||
if (lineType === "省外线路" || lineType === "省外") {
|
||||
return "省外"
|
||||
}
|
||||
return ""
|
||||
},
|
||||
isSigned(row) {
|
||||
return !!(row && (row.signed === true || row.signed === 1 || row.signed === "1" || row.ledgerId))
|
||||
},
|
||||
isApprovalSignup(row) {
|
||||
return !!(row && this.isSigned(row) && row.instanceId)
|
||||
},
|
||||
canRevokeSignup(row) {
|
||||
return this.isApprovalSignup(row) && this.toBoolean(row.canRevoke) && !!row.startTaskId
|
||||
},
|
||||
isFinishedSignup(row) {
|
||||
return this.isApprovalSignup(row) && Number(row.instanceState) === 20
|
||||
},
|
||||
isRejectedSignup(row) {
|
||||
return this.isApprovalSignup(row) && Number(row.instanceState) === 45
|
||||
},
|
||||
canModifySignup(row) {
|
||||
if (!row || !this.isSigned(row)) {
|
||||
return true
|
||||
}
|
||||
if (!this.isApprovalSignup(row)) {
|
||||
return true
|
||||
}
|
||||
return !this.isFinishedSignup(row) && !this.isRejectedSignup(row) && row.taskKey === "startTask"
|
||||
},
|
||||
signupActionText(row) {
|
||||
if (this.isSigned(row)) {
|
||||
if (this.canRevokeSignup(row)) {
|
||||
return "撤回"
|
||||
}
|
||||
if (this.isRejectedSignup(row)) {
|
||||
return "已拒绝"
|
||||
}
|
||||
return this.canModifySignup(row) ? "修改" : "审核中"
|
||||
}
|
||||
return "报名"
|
||||
},
|
||||
showSignupAction(row) {
|
||||
return this.isSigned(row) && this.canModifySignup(row)
|
||||
},
|
||||
signupActionDisabled(row) {
|
||||
return !!(this.isSigned(row) && this.isApprovalSignup(row) && (this.isRejectedSignup(row) || (!this.canRevokeSignup(row) && !this.canModifySignup(row))))
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
handleSignupAction(row) {
|
||||
if (this.signupActionDisabled(row)) {
|
||||
return
|
||||
}
|
||||
if (this.canRevokeSignup(row)) {
|
||||
this.revokeSignup(row)
|
||||
return
|
||||
}
|
||||
this.goApply(row)
|
||||
},
|
||||
goApply(row) {
|
||||
if (!row || !row.matterId) {
|
||||
vant.Toast("报名事项信息不完整")
|
||||
return
|
||||
}
|
||||
const go = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(row.matterId)
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: row.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: res.msg || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
if (!data.noticeRequired) {
|
||||
go()
|
||||
return
|
||||
}
|
||||
if (data.canApply) {
|
||||
vant.Dialog.confirm({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前可报名,是否继续报名?",
|
||||
confirmButtonText: "继续报名",
|
||||
cancelButtonText: "稍后报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(go).catch(() => {})
|
||||
} else {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
revokeSignup(row) {
|
||||
vant.Dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?",
|
||||
confirmButtonColor: "#ee2f2f"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", { taskId: row.startTaskId }).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
vant.Toast.success(resp.msg || "撤回成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
vant.Dialog.alert({ title: "提示", message: resp.msg || "撤回失败", confirmButtonColor: "#1867b0" })
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
doSearch() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.list = []
|
||||
this.finished = false
|
||||
this.loadData()
|
||||
},
|
||||
toggleLineType(lineType) {
|
||||
const active = this.pageForm.lineType === lineType && this.pageForm.directFamilyUnitLine === null
|
||||
this.pageForm.lineType = active ? "" : lineType
|
||||
this.pageForm.directFamilyUnitLine = null
|
||||
this.doSearch()
|
||||
},
|
||||
toggleDirectFamilyLine() {
|
||||
const active = this.pageForm.directFamilyUnitLine === true
|
||||
this.pageForm.directFamilyUnitLine = active ? null : true
|
||||
this.pageForm.lineType = ""
|
||||
this.doSearch()
|
||||
},
|
||||
openUnionPopup() {
|
||||
this.showUnionPopup = true
|
||||
if (this.unionList.length <= 1) {
|
||||
this.loadUnionOptions()
|
||||
}
|
||||
},
|
||||
selectUnion(item) {
|
||||
const unionId = item && item.id ? item.id : ""
|
||||
this.showUnionPopup = false
|
||||
if (this.pageForm.unionId === unionId) {
|
||||
return
|
||||
}
|
||||
this.pageForm.unionId = unionId
|
||||
this.doSearch()
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post("/platform/tour/signup/unionOptions").then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return
|
||||
}
|
||||
const rows = res.data || []
|
||||
this.unionList = [{id: "", name: "全部分工会"}].concat(rows.map((item) => {
|
||||
return {
|
||||
id: item.id || "",
|
||||
name: item.name || "未命名分工会"
|
||||
}
|
||||
}))
|
||||
})
|
||||
},
|
||||
loadData() {
|
||||
if (this.finished) {
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/pageData", this.pageForm).then((res) => {
|
||||
this.loading = false
|
||||
if (res.code !== 0) {
|
||||
vant.Toast(res.msg || "线路加载失败")
|
||||
this.finished = true
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
const rows = data.list || []
|
||||
this.pageForm.totalCount = data.totalCount || 0
|
||||
this.list = this.pageForm.pageNumber === 1 ? rows : this.list.concat(rows)
|
||||
if (this.list.length >= this.pageForm.totalCount || rows.length === 0) {
|
||||
this.finished = true
|
||||
} else {
|
||||
this.pageForm.pageNumber += 1
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.finished = true
|
||||
})
|
||||
},
|
||||
onLine(row) {
|
||||
if (!row || !row.lineId || !row.matterId) {
|
||||
vant.Toast("线路信息不完整")
|
||||
return
|
||||
}
|
||||
if (this.lineChecking) {
|
||||
return
|
||||
}
|
||||
this.lineChecking = true
|
||||
axios.post("/platform/tour/signup/signupDetail", $.param({ matterId: row.matterId }), {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
}
|
||||
}).then((resp) => {
|
||||
this.lineChecking = false
|
||||
const res = resp.data || {}
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: res.msg || "当前线路暂不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
window.location.href = "/platform/tour/signup/h5/lineInfo?matterId="
|
||||
+ encodeURIComponent(row.matterId)
|
||||
+ "&lineId="
|
||||
+ encodeURIComponent(row.lineId)
|
||||
}).catch((err) => {
|
||||
this.lineChecking = false
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: err && err.msg ? err.msg : "当前线路暂不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadUnionOptions()
|
||||
this.loadData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,455 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tour-tag.gray {
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.tour-tag.warn {
|
||||
background: #fff3e5;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 0;
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px 12px 14px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-process-opinion {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<van-nav-bar title="分工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
<van-search
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/unionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
<table-column label="线路名称">{{ row.lineName || '' }}</table-column>
|
||||
<table-column label="出行时段">{{ row.travelPeriod || '' }}</table-column>
|
||||
<table-column label="报销超出费用">{{ row.overCostReimbursed ? '是' : '否' }}</table-column>
|
||||
<table-column label="当前节点">{{ row.curTaskName || '' }}</table-column>
|
||||
<table-column label="流程状态">
|
||||
<enum-tag
|
||||
v-if="row.instanceState !== null && row.instanceState !== undefined && row.instanceState !== ''"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small">
|
||||
</enum-tag>
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
|
||||
<tour-info ref="infoRef">
|
||||
<div v-if="showApprovalForm" class="tour-section">
|
||||
<div class="tour-section-title">{{ formData.taskName || '审核' }}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
type="textarea"
|
||||
rows="3"
|
||||
maxlength="200"
|
||||
show-word-limit>
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div class="tour-approval-actions">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</tour-info>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <van-action-sheet v-model=\"visible\" title=\"报名详情\">\n",
|
||||
" <div class=\"tour-approval-sheet\">\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">教职工信息</div>\n",
|
||||
" <van-cell title=\"工号\" :value=\"detail.jobNo || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"姓名\" :value=\"detail.userName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"性别\" :value=\"detail.gender || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"身份证号\" :value=\"detail.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"detail.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在工会\" :value=\"detail.unionName || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">报名信息</div>\n",
|
||||
" <van-cell title=\"报名线路\" :value=\"detail.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路类型\" :value=\"detail.lineType || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行时段\" :value=\"detail.travelPeriod || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名时间\" :value=\"detail.signupTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名酒店\" :value=\"detail.hotelName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"旅行社\" :value=\"detail.travelAgencyName || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床型\" :value=\"detail.bedType || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床位信息\" :value=\"detail.bedInfo || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"意向拼床人\" :value=\"detail.intendedRoommate || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"携带家属\" :value=\"familyText()\"></van-cell>\n",
|
||||
" <van-cell title=\"报销超出费用\" :value=\"detail.overCostReimbursed ? '是' : '否'\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">直系亲属线路</div>\n",
|
||||
" <van-cell title=\"亲属姓名\" :value=\"directRelative.relativeName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"directRelative.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"亲属关系\" :value=\"directRelative.relationshipName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路名称\" :value=\"directRelative.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行开始\" :value=\"directRelative.travelStartTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行结束\" :value=\"directRelative.travelEndTime || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">家属信息</div>\n",
|
||||
" <template v-for=\"(item,index) in familyData\">\n",
|
||||
" <van-cell :key=\"'title_' + index\" :title=\"'家属' + (index + 1)\"></van-cell>\n",
|
||||
" <van-cell :key=\"'name_' + index\" title=\"姓名\" :value=\"item.familyName || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'gender_' + index\" title=\"性别\" :value=\"item.gender || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'id_' + index\" title=\"身份证号\" :value=\"item.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'rel_' + index\" title=\"关系\" :value=\"item.relationship || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" :key=\"'bed_' + index\" title=\"床型\" :value=\"item.bedType || ''\"></van-cell>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"doneTasks.length > 0\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">流程记录</div>\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <van-cell-group :key=\"task.id\" :title=\"task.displayName || task.taskName\">\n",
|
||||
" <van-cell title=\"办理时间\" :value=\"task.finishTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext && task.ext.submitType\"></dict-tag>\n",
|
||||
" </van-cell>\n",
|
||||
" <van-cell title=\"办理意见\" v-if=\"task.taskFormData\" class=\"direction-column-cell\">\n",
|
||||
" <div class=\"tour-process-opinion\">{{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}</div>\n",
|
||||
" </van-cell>\n",
|
||||
" </van-cell-group>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
" </div>\n",
|
||||
" </van-action-sheet>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/unionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
vant.Toast(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine || this.toBoolean(this.detail.directFamilyUnitLine) || !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine() || !this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"tour-info": TOUR_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
keyword: "",
|
||||
lineType: ""
|
||||
},
|
||||
auditOptions: [
|
||||
{ text: "未审核", value: false },
|
||||
{ text: "已审核", value: true }
|
||||
],
|
||||
lineTypeOptions: [
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await this.loadLineTypeOptions()
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
return this.$axios.post("/platform/tour/unionApproval/lineTypeOptions", {
|
||||
audit: this.pageForm.audit,
|
||||
keyword: this.pageForm.keyword
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const options = (res.data || []).map(item => ({
|
||||
text: item.lineType,
|
||||
value: item.lineType
|
||||
})).filter(item => item.value)
|
||||
this.lineTypeOptions = [{ text: "全部线路类型", value: "" }].concat(options)
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.value === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
overlay: true,
|
||||
duration: 0
|
||||
})
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
this.$toast.success(res.msg || "操作成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$toast(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
Reference in New Issue
Block a user