This commit is contained in:
2026-06-12 09:28:09 +08:00
parent 67bf620d01
commit 742a0ff388
13 changed files with 591 additions and 95 deletions
@@ -119,6 +119,21 @@ public class TourBranchUserAssignmentController {
}
}
/**
* 给当前分工会已分配正式人员补选分配路线,具体快照回写、代报名和最大成团人数校验由 service 统一处理。
*/
@At
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("tour.branchUserAssignment")
@SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "选择分工会分配事项")
public Result selectMatter(String id, String matterId) {
try {
return Result.success(tourUserAssignmentService.selectCurrentBranchAssignmentMatter(id, matterId));
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 恢复当前分工会已取消退出的人员分配记录,只恢复状态,不恢复已删除台账。
*/
@@ -29,6 +29,7 @@ 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 com.budwk.app.zhgh.dayofficework.tour.service.TourUserAssignmentService;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
@@ -93,6 +94,9 @@ public class TourLedgerController {
@Inject
private TourLedgerDirectRelativeService tourLedgerDirectRelativeService;
@Inject
private TourUserAssignmentService tourUserAssignmentService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/Tour/ledger/index.html")
@SaCheckPermission("tour.ledger")
@@ -234,8 +238,11 @@ public class TourLedgerController {
if (!canAccessLedgerUnion(ledger.getUnionId())) {
return Result.error("无权删除该台账记录");
}
// 删除台账时同步清理台账明细和人员分配中的线路快照,避免人员分配列表继续显示已删除报名的路线信息。
tourLedgerFamilyService.clear(Cnd.where(TourLedgerFamily::getLedgerId, "=", id));
tourLedgerDirectRelativeService.clear(Cnd.where(TourLedgerDirectRelative::getLedgerId, "=", id));
tourLedgerService.delete(id);
tourUserAssignmentService.clearExistingAssignmentMatterAfterLedgerDelete(ledger.getMatterId(), ledger.getJobNo());
return Result.success();
}
@@ -139,11 +139,13 @@ public class TourSignupController {
@At("/h5/pageData")
@SaCheckPermission(value = {"tour.signup", "h5.tour.signup"}, mode = SaMode.OR)
public Result h5PageData(PageForm pageForm, Integer year, String lineName, String lineType, String unionId, Boolean directFamilyUnitLine) {
public Result h5PageData(PageForm pageForm, Integer year, String lineName, String lineType, String unionId,
String travelPeriod, Boolean directFamilyUnitLine) {
if (StrUtil.isBlank(pageForm.getPageOrderName())) {
pageForm.defaultSortAsc("lineName");
}
Cnd cnd = buildQueryCnd(year, lineName, lineType, unionId);
appendTravelPeriodCnd(cnd, travelPeriod);
cnd.andEX("l.directFamilyUnitLine", "=", directFamilyUnitLine);
String currentJobNo = currentJobNo();
@@ -372,6 +374,34 @@ public class TourSignupController {
return Result.success(sql.getList(NutMap.class));
}
/**
* 查询移动端选择路线页的出行时间筛选项,按 yyyyMMdd-yyyyMMdd 格式拼接事项出行起止时间并去重。
*/
@At("/h5/travelPeriodOptions")
@SaCheckPermission(value = {"tour.signup", "h5.tour.signup"}, mode = SaMode.OR)
public Result h5TravelPeriodOptions(Integer year, String lineType, Boolean directFamilyUnitLine) {
Cnd cnd = buildQueryCnd(year, null, null, null);
cnd.andEX("l.lineType", "=", lineType);
cnd.andEX("l.directFamilyUnitLine", "=", directFamilyUnitLine);
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 $travelPeriodExpr 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
ORDER BY travelPeriod ASC
""");
sql.setVar("travelPeriodExpr", travelPeriodKeyExpr());
sql.setCondition(cnd);
sql.setCallback(Sqls.callback.maps());
tourMatterService.dao().execute(sql);
return Result.success(sql.getList(NutMap.class));
}
@At
@SaCheckPermission(value = {"tour.signup", "h5.tour.signup"}, mode = SaMode.OR)
public Result lineDetail(String lineId) {
@@ -820,6 +850,18 @@ public class TourSignupController {
return cnd;
}
private void appendTravelPeriodCnd(Cnd cnd, String travelPeriod) {
if (cnd == null || StrUtil.isBlank(travelPeriod)) {
return;
}
// 移动端出行时间筛选使用 yyyyMMdd-yyyyMMdd 作为稳定值,避免前端直接依赖数据库原始时间格式。
cnd.and(travelPeriodKeyExpr(), "=", travelPeriod);
}
private String travelPeriodKeyExpr() {
return "CONCAT(REPLACE(SUBSTRING(m.travelStartTime, 1, 10), '-', ''), '-', REPLACE(SUBSTRING(m.travelEndTime, 1, 10), '-', ''))";
}
private Result checkSignup(TourLedger ledger) {
if (ledger == null) {
return Result.error("参数错误");
@@ -15,6 +15,7 @@ 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 com.budwk.app.zhgh.dayofficework.tour.service.TourUserAssignmentService;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
@@ -58,6 +59,9 @@ public class TourUnionLedgerController {
@Inject
private TourLedgerDirectRelativeService tourLedgerDirectRelativeService;
@Inject
private TourUserAssignmentService tourUserAssignmentService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/Tour/unionledger/index.html")
@SaCheckPermission("tour.unionledger")
@@ -206,8 +210,11 @@ public class TourUnionLedgerController {
if (ledger == null) {
return Result.error("台账记录不存在或无权删除");
}
// 删除分工会台账时同步清理台账明细和人员分配中的线路快照,避免人员分配列表继续显示已删除报名的路线信息。
tourLedgerFamilyService.clear(Cnd.where(TourLedgerFamily::getLedgerId, "=", ledger.getId()));
tourLedgerDirectRelativeService.clear(Cnd.where(TourLedgerDirectRelative::getLedgerId, "=", ledger.getId()));
tourLedgerService.clear(Cnd.where(TourLedger::getId, "=", ledger.getId()));
tourUserAssignmentService.clearExistingAssignmentMatterAfterLedgerDelete(ledger.getMatterId(), ledger.getJobNo());
return Result.success();
}
@@ -115,6 +115,16 @@ public interface TourUserAssignmentService extends BaseService<TourUserAssignmen
*/
NutMap selectSchoolAssignmentMatter(String id, String matterId);
/**
* 给当前分工会已分配的正式人员补选分配路线并按代报名写入疗休养台账
* 只处理当前登录人所在分工会BRANCH_UNION 来源且尚未选择路线的记录写台账前校验最多成团人数
*
* @param id 人员分配记录ID
* @param matterId 疗休养事项ID
* @return 处理结果包含台账写入数量
*/
NutMap selectCurrentBranchAssignmentMatter(String id, String matterId);
/**
* 保存分工会人员分配保存前会重新按配置可参加人员范围和当前登录人所在分工会过滤并校验正式/替补名额
* 疗休养事项为可选正式人员选择事项时视为代报名并同步写入疗休养台账替补人员不能分配事项
@@ -159,6 +169,16 @@ public interface TourUserAssignmentService extends BaseService<TourUserAssignmen
*/
int clearExistingAssignmentMatterAfterCancel(String settingId, String userId);
/**
* 台账管理删除报名台账后按原台账的事项和工号清空对应人员分配记录的事项快照
* 仅清空事项线路旅行社和乘车地点字段出行时间由事项关联展示清空事项后页面不再显示原出行时间
*
* @param matterId 台账原报名事项ID
* @param jobNo 台账原报名人工号
* @return 更新记录数
*/
int clearExistingAssignmentMatterAfterLedgerDelete(String matterId, String jobNo);
/**
* 查询当前登录人所在分工会在指定疗休养配置下的名额使用情况
*
@@ -310,20 +310,38 @@ public class TourUserAssignmentServiceImpl extends BaseServiceImpl<TourUserAssig
if (matterInfo == null) {
throw new IllegalArgumentException("分配线路不存在或未配置线路");
}
// 补选事项时同时回写人员分配表事项快照后续列表筛选无需再跨表追溯事项信息
update(Chain.make("matterId", matterInfo.getString("matterId"))
.add("matterName", matterInfo.getString("matterName"))
.add("lineId", matterInfo.getString("lineId"))
.add("lineName", matterInfo.getString("lineName"))
.add("travelAgencyId", matterInfo.getString("travelAgencyId"))
.add("travelAgencyName", matterInfo.getString("travelAgencyName"))
.add("boardingPlace", matterInfo.getString("defaultBoardingPlace")),
Cnd.where(TourUserAssignment::getId, "=", id)
.and(TourUserAssignment::getAssignSource, "=", TourUserAssignment.ASSIGN_SOURCE_SCHOOL_UNION));
updateAssignmentMatterSnapshot(id, matterInfo, TourUserAssignment.ASSIGN_SOURCE_SCHOOL_UNION);
int ledgerCount = insertProxySignupLedgers(matterInfo, Collections.singletonList(fetchAssignmentUserSnapshot(assignment)));
return NutMap.NEW().addv("ledgerCount", ledgerCount);
}
@Override
public NutMap selectCurrentBranchAssignmentMatter(String id, String matterId) {
if (StrUtil.isBlank(id) || StrUtil.isBlank(matterId)) {
throw new IllegalArgumentException("请选择人员分配记录和分配路线");
}
TourUserAssignment assignment = fetchCurrentBranchAssignment(id);
if (assignment == null) {
throw new IllegalArgumentException("人员分配记录不存在");
}
if (StrUtil.isNotBlank(assignment.getMatterId())) {
throw new IllegalArgumentException("该人员已选择分配路线");
}
String personType = normalizePersonType(assignment.getPersonType());
if (!TourUserAssignment.PERSON_TYPE_FORMAL.equals(personType)) {
throw new IllegalArgumentException("只有正式人员可以选择分配路线");
}
NutMap matterInfo = fetchMatterInfo(assignment.getSettingId(), matterId);
if (matterInfo == null) {
throw new IllegalArgumentException("分配路线不存在或未配置线路");
}
List<NutMap> users = Collections.singletonList(fetchAssignmentUserSnapshot(assignment));
checkProxySignupMaxGroupPeople(matterInfo, users);
updateAssignmentMatterSnapshot(id, matterInfo, TourUserAssignment.ASSIGN_SOURCE_BRANCH_UNION);
int ledgerCount = insertProxySignupLedgers(matterInfo, users);
return NutMap.NEW().addv("ledgerCount", ledgerCount);
}
@Override
public NutMap assignBranchUsers(String settingId, String matterId, String personType, List<String> userIds) {
String unionId = SecurityUtil.getUnionId();
@@ -358,6 +376,8 @@ public class TourUserAssignmentServiceImpl extends BaseServiceImpl<TourUserAssig
if (candidateUsers.size() > remainingQuota) {
throw new IllegalArgumentException("选择人数超过当前分工会剩余名额");
}
// 分工会代报名会占用线路成团人数人员分配和台账写入前先做后端兜底校验
checkProxySignupMaxGroupPeople(matterInfo, candidateUsers);
List<TourUserAssignment> assignments = candidateUsers.stream()
.map(user -> buildAssignment(settingId, matterInfo, normalizedPersonType, user,
TourUserAssignment.ASSIGN_SOURCE_BRANCH_UNION))
@@ -506,6 +526,29 @@ public class TourUserAssignmentServiceImpl extends BaseServiceImpl<TourUserAssig
.and(TourUserAssignment::getDelFlag, "=", false));
}
@Override
public int clearExistingAssignmentMatterAfterLedgerDelete(String matterId, String jobNo) {
if (StrUtil.isBlank(matterId) || StrUtil.isBlank(jobNo)) {
return 0;
}
TourMatter matter = dao().fetch(TourMatter.class, matterId);
Cnd cnd = Cnd.where(TourUserAssignment::getMatterId, "=", matterId)
.and(TourUserAssignment::getLoginName, "=", jobNo)
.and(TourUserAssignment::getDelFlag, "=", false);
if (matter != null && StrUtil.isNotBlank(matter.getSettingId())) {
cnd.and(TourUserAssignment::getSettingId, "=", matter.getSettingId());
}
// 台账管理按原台账删除时无法依赖当前登录人需用台账工号精准清空同事项的人员分配快照
return update(Chain.make("matterId", null)
.add("matterName", null)
.add("lineId", null)
.add("lineName", null)
.add("travelAgencyId", null)
.add("travelAgencyName", null)
.add("boardingPlace", null),
cnd);
}
@Override
public NutMap schoolDeleteInfo(String id) {
return assignmentDeleteInfo(fetchAssignmentBySource(id, TourUserAssignment.ASSIGN_SOURCE_SCHOOL_UNION));
@@ -867,6 +910,7 @@ public class TourUserAssignmentServiceImpl extends BaseServiceImpl<TourUserAssig
m.`year` AS `year`,
m.settingId,
m.defaultBoardingPlace,
m.maxGroupPeople,
m.lineId,
l.lineName,
l.lineType,
@@ -928,6 +972,19 @@ public class TourUserAssignmentServiceImpl extends BaseServiceImpl<TourUserAssig
assignment.setBoardingPlace(matterInfo.getString("defaultBoardingPlace"));
}
private void updateAssignmentMatterSnapshot(String id, NutMap matterInfo, String assignSource) {
// 补选事项时同时回写人员分配表事项快照后续列表筛选无需再跨表追溯事项信息
update(Chain.make("matterId", matterInfo.getString("matterId"))
.add("matterName", matterInfo.getString("matterName"))
.add("lineId", matterInfo.getString("lineId"))
.add("lineName", matterInfo.getString("lineName"))
.add("travelAgencyId", matterInfo.getString("travelAgencyId"))
.add("travelAgencyName", matterInfo.getString("travelAgencyName"))
.add("boardingPlace", matterInfo.getString("defaultBoardingPlace")),
Cnd.where(TourUserAssignment::getId, "=", id)
.and(TourUserAssignment::getAssignSource, "=", assignSource));
}
private NutMap prepareMatterInfoForAssignment(String settingId, String matterId, String personType) {
if (TourUserAssignment.PERSON_TYPE_BACKUP.equals(personType) && StrUtil.isNotBlank(matterId)) {
throw new IllegalArgumentException("替补人员不能分配疗休养事项");
@@ -958,6 +1015,52 @@ public class TourUserAssignmentServiceImpl extends BaseServiceImpl<TourUserAssig
return ledgers.size();
}
private void checkProxySignupMaxGroupPeople(NutMap matterInfo, List<NutMap> users) {
if (matterInfo == null || Lang.isEmpty(users)) {
return;
}
Integer maxGroupPeople = matterInfo.getInt("maxGroupPeople");
if (maxGroupPeople == null || maxGroupPeople <= 0) {
return;
}
String matterId = matterInfo.getString("matterId");
List<NutMap> newSignupUsers = users.stream()
// 已存在同事项台账的人员不会重复代报名也不再计入本次新增人数
.filter(user -> !existsMatterLedger(matterId, user.getString("loginName")))
.collect(Collectors.toList());
if (Lang.isEmpty(newSignupUsers)) {
return;
}
int signedPeople = countMatterSignupPeople(matterId);
int totalPeople = signedPeople + newSignupUsers.size();
if (totalPeople > maxGroupPeople) {
throw new IllegalArgumentException("当前报名人数 " + signedPeople + " 人,本次代报名 "
+ newSignupUsers.size() + " 人,最多成团人数 " + maxGroupPeople + " 人,报名后将超过人数上限,不能提交");
}
}
private int countMatterSignupPeople(String matterId) {
if (StrUtil.isBlank(matterId)) {
return 0;
}
Sql sql = Sqls.create("""
SELECT IFNULL(SUM(1 + IFNULL(f.familyCount, 0)), 0) AS signupPeople
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 = @matterId
""");
sql.setParam("matterId", matterId);
sql.setCallback(Sqls.callback.integer());
dao().execute(sql);
return sql.getInt();
}
private boolean existsMatterLedger(String matterId, String loginName) {
if (StrUtil.isBlank(matterId) || StrUtil.isBlank(loginName)) {
return false;
@@ -82,6 +82,7 @@ layout("/layouts/platform.html"){
<el-table-column label="分配时间" prop="assignedAt" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="320" align="center" header-align="center" fixed="right">
<template slot-scope="{row}">
<el-button v-if="!row.matterId && row.personType !== 'BACKUP'" size="mini" type="primary" @click="openSelectMatter(row)">选择路线</el-button>
<el-button size="mini" type="primary" :loading="personTypeSwitching === row.id" @click="switchPersonType(row, row.personType === 'BACKUP' ? 'FORMAL' : 'BACKUP')">{{ row.personType === 'BACKUP' ? '转为正式' : '转为替补' }}</el-button>
<el-button v-if="isCancelled(row) && $auth.hasPermission('tour.branchUserAssignment.cancelRestore')" size="mini" type="warning" @click="restoreCancel(row)">取消退出</el-button>
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
@@ -198,6 +199,28 @@ layout("/layouts/platform.html"){
<el-button type="primary" :loading="assignSubmitting" @click="doAssign">保存分配</el-button>
</span>
</el-dialog>
<el-dialog
title="选择分配路线"
:visible.sync="selectMatterDialogVisible"
:close-on-click-modal="false"
width="520px"
@closed="resetSelectMatterDialog">
<el-form :model="selectMatterForm" :rules="selectMatterRules" ref="selectMatterFormRef" label-width="110px">
<el-form-item label="分配人员">
<el-input v-model="selectMatterForm.userName" disabled></el-input>
</el-form-item>
<el-form-item label="分配路线" prop="matterId">
<el-select v-model="selectMatterForm.matterId" clearable filterable placeholder="请选择分配路线" style="width: 100%">
<el-option v-for="item in selectMatterOptions" :key="item.matterId" :label="matterOptionLabel(item)" :value="item.matterId"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="selectMatterDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="selectMatterSubmitting" @click="doSelectMatter">保存</el-button>
</span>
</el-dialog>
</div>
<style>
@@ -292,6 +315,9 @@ layout("/layouts/platform.html"){
candidateData: [],
selectedCandidates: [],
assignSubmitting: false,
selectMatterDialogVisible: false,
selectMatterSubmitting: false,
selectMatterOptions: [],
personTypeSwitching: "",
pageForm: {
pageNumber: 1,
@@ -317,10 +343,19 @@ layout("/layouts/platform.html"){
totalCount: 0,
keyword: ""
},
selectMatterForm: {
id: "",
settingId: "",
matterId: "",
userName: ""
},
assignRules: {
year: [{required: true, message: "请选择年度", trigger: ["change", "blur"]}],
settingId: [{required: true, message: "请选择疗休养配置", trigger: ["change", "blur"]}],
personType: [{required: true, message: "请选择人员类型", trigger: ["change", "blur"]}]
},
selectMatterRules: {
matterId: [{required: true, message: "请选择分配路线", trigger: ["change", "blur"]}]
}
}
},
@@ -351,6 +386,14 @@ layout("/layouts/platform.html"){
backupRemaining: 0
}
},
defaultSelectMatterForm() {
return {
id: "",
settingId: "",
matterId: "",
userName: ""
}
},
resetSearch() {
const currentYear = moment().format("YYYY")
this.pageForm.year = currentYear
@@ -583,6 +626,54 @@ layout("/layouts/platform.html"){
this.personTypeSwitching = ""
})
},
openSelectMatter(row) {
this.selectMatterForm = {
id: row.id,
settingId: row.settingId,
matterId: "",
userName: row.userName || ""
}
this.selectMatterOptions = []
this.selectMatterDialogVisible = true
this.loadSelectMatterOptions()
},
resetSelectMatterDialog() {
this.selectMatterForm = this.defaultSelectMatterForm()
this.selectMatterOptions = []
this.selectMatterSubmitting = false
},
loadSelectMatterOptions() {
if (!this.selectMatterForm.settingId) {
this.selectMatterOptions = []
return
}
this.$axios.post(loc() + "/matterOptions", {settingId: this.selectMatterForm.settingId}).then((res) => {
if (res.code === 0) {
this.selectMatterOptions = res.data || []
}
})
},
doSelectMatter() {
this.$refs.selectMatterFormRef.validate((valid) => {
if (!valid) return
this.selectMatterSubmitting = true
this.$axios.post(loc() + "/selectMatter", {
id: this.selectMatterForm.id,
matterId: this.selectMatterForm.matterId
}).then((res) => {
if (res.code === 0) {
const data = res.data || {}
this.$message.success("分配路线选择成功" + (data.ledgerCount > 0 ? ",已代报名" + data.ledgerCount + "人" : ""))
this.selectMatterDialogVisible = false
this.doSearch()
} else {
this.$message.warning(res.msg || "分配路线选择失败")
}
}).finally(() => {
this.selectMatterSubmitting = false
})
})
},
doDelete(row) {
this.$axios.post(loc() + "/deleteInfo", {id: row.id}).then((infoRes) => {
if (infoRes.code !== 0) {
@@ -633,12 +724,9 @@ layout("/layouts/platform.html"){
})
}).catch(() => {})
},
// 分配路线选项展示线路管理中的线路类型,便于同名线路按类型区分
// 分配路线选项按业务事项展示线路名称仅作为历史数据缺失事项名称时的兜底
matterOptionLabel(item) {
const lineName = item.lineName || ""
const lineType = item.lineType || ""
const label = lineName || item.matterName || ""
return label && lineType ? label + "" + lineType + "" : label
return item.matterName || item.lineName || ""
}
},
mounted() {
@@ -99,6 +99,7 @@ layout("/layouts/platform.html"){
<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="年龄">{{ staffAge(detail) }}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
</el-descriptions>
@@ -113,7 +114,6 @@ layout("/layouts/platform.html"){
<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="detailFillBedInfo" label="床型">{{ detail.bedType || '' }}</el-descriptions-item>
@@ -229,6 +229,13 @@ layout("/layouts/platform.html"){
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="年龄">
<el-input :value="staffAge(signupForm)" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<div class="tour-title tour-section">报名信息</div>
<el-row :gutter="20">
@@ -249,11 +256,6 @@ layout("/layouts/platform.html"){
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="报名酒店">
<el-input v-model="signupForm.hotelName" :disabled="isDirectFamilyLine(signupForm)" maxlength="100" placeholder="请输入报名酒店"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="乘车地点">
<el-select v-model="signupForm.boardingPlace" clearable filterable placeholder="请选择乘车地点" style="width: 100%">
@@ -826,6 +828,24 @@ layout("/layouts/platform.html"){
toBoolean(value) {
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
},
// 年龄根据报名人身份证出生日期实时计算,只做页面展示不写回后端。
staffAge(row) {
const idCard = row && row.idCard ? String(row.idCard).trim() : ""
if (!/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(idCard)) {
return ""
}
const year = Number(idCard.substring(6, 10))
const month = Number(idCard.substring(10, 12))
const day = Number(idCard.substring(12, 14))
const today = new Date()
let age = today.getFullYear() - year
const currentMonth = today.getMonth() + 1
const currentDay = today.getDate()
if (currentMonth < month || (currentMonth === month && currentDay < day)) {
age--
}
return age >= 0 ? String(age) : ""
},
isDirectFamilyRow(row) {
return this.toBoolean(row && row.directFamilyUnitLine) || !!(row && row.directRelativeId)
},
@@ -686,12 +686,9 @@ layout("/layouts/platform.html"){
})
}).catch(() => {})
},
// 分配线路选项展示线路管理中的线路类型,便于同名线路按类型区分
// 分配线路选项按业务事项展示线路名称仅作为历史数据缺失事项名称时的兜底
matterOptionLabel(item) {
const lineName = item.lineName || ""
const lineType = item.lineType || ""
const label = lineName || item.matterName || ""
return label && lineType ? label + "" + lineType + "" : label
return item.matterName || item.lineName || ""
}
},
mounted() {
@@ -128,6 +128,13 @@ layout("/layouts/platform.html"){
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="年龄">
<el-input :value="staffAge(signupForm)" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<div class="tour-signup-title tour-signup-section">报名信息</div>
<el-row :gutter="20">
@@ -148,11 +155,6 @@ layout("/layouts/platform.html"){
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="报名酒店">
<el-input v-model="signupForm.hotelName" :disabled="isDirectFamilyLine(signupForm)" maxlength="100" placeholder="请输入报名酒店"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="乘车地点">
<el-select v-model="signupForm.boardingPlace" clearable filterable placeholder="请选择乘车地点" style="width: 100%">
@@ -571,6 +573,24 @@ layout("/layouts/platform.html"){
toBoolean(value) {
return value === true || value === 1 || value === "1" || value === "true"
},
// 年龄根据报名人身份证出生日期实时计算,只做页面展示不写回后端。
staffAge(row) {
const idCard = row && row.idCard ? String(row.idCard).trim() : ""
if (!/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(idCard)) {
return ""
}
const year = Number(idCard.substring(6, 10))
const month = Number(idCard.substring(10, 12))
const day = Number(idCard.substring(12, 14))
const today = new Date()
let age = today.getFullYear() - year
const currentMonth = today.getMonth() + 1
const currentDay = today.getDate()
if (currentMonth < month || (currentMonth === month && currentDay < day)) {
age--
}
return age >= 0 ? String(age) : ""
},
tableRowClassName({ row }) {
return this.isDirectFamilyLine(row) ? "direct-family-row" : ""
},
@@ -416,6 +416,7 @@ layout("/layouts/platform_h5.html"){
<van-cell title="姓名" :value="detail.userName || ''"></van-cell>
<van-cell title="性别" :value="detail.gender || ''"></van-cell>
<van-cell title="身份证号" :value="detail.idCard || ''"></van-cell>
<van-cell title="年龄" :value="staffAge(detail)"></van-cell>
<van-cell title="所在单位" :value="detail.unitName || ''"></van-cell>
<van-cell title="所在工会" :value="detail.unionName || ''"></van-cell>
</div>
@@ -424,7 +425,6 @@ layout("/layouts/platform_h5.html"){
<van-cell title="报名线路" :value="detail.lineName || ''"></van-cell>
<van-cell title="线路类型" :value="detail.lineType || ''"></van-cell>
<van-cell title="出行时间" :value="detail.travelPeriod || ''"></van-cell>
<van-cell title="报名酒店" :value="detail.hotelName || ''"></van-cell>
<van-cell title="旅行社" :value="detail.travelAgencyName || ''"></van-cell>
<van-cell v-if="detailFillBedInfo" title="床型" :value="detail.bedType || ''"></van-cell>
<van-cell v-if="detailFillBedInfo" title="床位信息" :value="detail.bedInfo || ''"></van-cell>
@@ -470,6 +470,7 @@ layout("/layouts/platform_h5.html"){
<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="年龄" readonly :value="staffAge(signupForm)"></van-field>
<van-field label="所在工会" readonly v-model="signupForm.unionName"></van-field>
</div>
@@ -478,7 +479,6 @@ layout("/layouts/platform_h5.html"){
<van-field label="报名线路" readonly v-model="signupForm.lineName"></van-field>
<van-field label="线路类型" readonly v-model="signupForm.lineType"></van-field>
<van-field label="出行时间" readonly v-model="signupForm.travelPeriod"></van-field>
<van-field label="报名酒店" v-model="signupForm.hotelName" maxlength="100" placeholder="请输入报名酒店"></van-field>
<van-field readonly clickable is-link label="乘车地点" v-model="signupForm.boardingPlace" placeholder="请选择乘车地点" @click="openBoardingPlacePicker"></van-field>
<van-field v-if="fillBedInfo" readonly clickable is-link label="床型" v-model="signupForm.bedType" placeholder="请选择床型" @click="openBedPicker('self')"></van-field>
<van-field v-if="fillBedInfo" label="床位信息" v-model="signupForm.bedInfo" maxlength="100" placeholder="请输入床位信息"></van-field>
@@ -646,6 +646,24 @@ layout("/layouts/platform_h5.html"){
this.pageForm.lineName = ""
this.doSearch()
},
// 年龄根据报名人身份证出生日期实时计算,只做页面展示不写回后端。
staffAge(row) {
const idCard = row && row.idCard ? String(row.idCard).trim() : ""
if (!/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(idCard)) {
return ""
}
const year = Number(idCard.substring(6, 10))
const month = Number(idCard.substring(10, 12))
const day = Number(idCard.substring(12, 14))
const today = new Date()
let age = today.getFullYear() - year
const currentMonth = today.getMonth() + 1
const currentDay = today.getDate()
if (currentMonth < month || (currentMonth === month && currentDay < day)) {
age--
}
return age >= 0 ? String(age) : ""
},
doSearch() {
this.list = []
this.finished = false
@@ -52,16 +52,35 @@ layout("/layouts/platform_h5.html"){
flex-shrink: 0;
}
.tour-family-tab {
margin: 10px 12px 0;
height: 30px;
border-radius: 5px;
background: #1684d2;
color: #ffffff;
.tour-family-list {
max-height: 54vh;
overflow-y: auto;
padding: 10px 12px;
-webkit-overflow-scrolling: touch;
box-sizing: border-box;
}
.tour-family-card {
margin-bottom: 10px;
border: 1px solid #edf0f4;
border-radius: 6px;
overflow: hidden;
background: #ffffff;
}
.tour-family-card:last-child {
margin-bottom: 0;
}
.tour-family-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 10px;
background: #f8fafc;
color: #0f172a;
font-size: 14px;
font-weight: 700;
line-height: 30px;
text-align: center;
}
.tour-field-tip {
@@ -110,6 +129,7 @@ layout("/layouts/platform_h5.html"){
<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="年龄" readonly :value="staffAge(signupForm)"></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>
@@ -119,7 +139,6 @@ layout("/layouts/platform_h5.html"){
<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
label="乘车地点"
readonly
@@ -177,51 +196,55 @@ layout("/layouts/platform_h5.html"){
<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>
<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-if="familyData.length > 0" class="tour-family-list">
<div v-for="(item,index) in familyData" :key="index" class="tour-family-card">
<div class="tour-family-head">
<span>亲属{{ index + 1 }}</span>
<van-button size="mini" type="danger" plain @click="removeFamily(index)">删除</van-button>
</div>
<van-field label="姓名" v-model="item.familyName" maxlength="100" placeholder="请填写姓名"></van-field>
<van-field label="年龄" v-model.number="item.age" type="digit" placeholder="请填写年龄"></van-field>
<van-field label="性别">
<template #input>
<van-radio-group v-model="item.gender" direction="horizontal">
<van-radio name="男"></van-radio>
<van-radio name="女"></van-radio>
</van-radio-group>
</template>
</van-field>
<van-field label="身份证号码" v-model="item.idCard" maxlength="18" placeholder="请填写身份证号码" @blur="normalizeFamilyIdCard(item)"></van-field>
<van-field label="手机号" v-model="item.mobile" maxlength="30" placeholder="请填写手机号"></van-field>
<van-field
label="与本人关系"
readonly
clickable
is-link
placeholder="请选择关系"
v-model="item.relationship"
@click="openRelationshipPicker(index)">
</van-field>
<van-field
v-if="fillBedInfo"
label="床型"
readonly
clickable
is-link
placeholder="请选择房型"
v-model="item.bedType"
@click="openBedPicker('family', index)">
</van-field>
<van-field v-if="fillBedInfo" label="床位" v-model="item.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="item.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
<div v-if="fillBedInfo" class="tour-field-tip">提醒:如果跟报名人员同一房间,无须选择!</div>
</div>
</div>
<div v-else class="tour-apply-empty">暂无亲属,请按需添加</div>
</div>
</template>
@@ -261,7 +284,6 @@ layout("/layouts/platform_h5.html"){
signupForm: {},
directRelativeForm: {},
familyData: [],
familyActive: 0,
bedTypeOptions: [],
familyRelationshipOptions: [],
directRelativeOptions: [],
@@ -271,13 +293,12 @@ layout("/layouts/platform_h5.html"){
directRelativePickerVisible: false,
boardingPlacePickerVisible: false,
bedPickerTarget: "self",
bedPickerFamilyIndex: -1,
relationshipFamilyIndex: -1,
matterId: GetQueryString("matterId") || ""
}
},
computed: {
currentFamily() {
return this.familyData[this.familyActive] || {}
},
bedTypeColumns() {
return this.bedTypeOptions.map(item => item.name || item.code).filter(Boolean)
},
@@ -306,6 +327,24 @@ layout("/layouts/platform_h5.html"){
+ ":"
+ pad(date.getSeconds())
},
// 年龄根据报名人身份证出生日期实时计算,只做页面展示不写回后端。
staffAge(row) {
const idCard = row && row.idCard ? String(row.idCard).trim() : ""
if (!/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(idCard)) {
return ""
}
const year = Number(idCard.substring(6, 10))
const month = Number(idCard.substring(10, 12))
const day = Number(idCard.substring(12, 14))
const today = new Date()
let age = today.getFullYear() - year
const currentMonth = today.getMonth() + 1
const currentDay = today.getDate()
if (currentMonth < month || (currentMonth === month && currentDay < day)) {
age--
}
return age >= 0 ? String(age) : ""
},
init() {
if (!this.matterId) {
vant.Dialog.alert({ title: "提示", message: "报名事项参数缺失", confirmButtonColor: "#1867b0" })
@@ -467,40 +506,42 @@ layout("/layouts/platform_h5.html"){
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() {
removeFamily(index) {
if (this.familyData.length === 0) return
this.familyData.splice(this.familyActive, 1)
this.familyActive = Math.max(0, this.familyActive - 1)
this.familyData.splice(index, 1)
this.signupForm.hasFamily = this.familyData.length > 0
},
openBedPicker(target) {
openBedPicker(target, index) {
if (this.bedTypeColumns.length === 0) {
vant.Toast("暂无床型选项")
return
}
this.bedPickerTarget = target
this.bedPickerFamilyIndex = index === undefined ? -1 : index
this.bedPickerVisible = true
},
confirmBedType(value) {
if (this.bedPickerTarget === "family") {
this.currentFamily.bedType = value
if (this.bedPickerTarget === "family" && this.familyData[this.bedPickerFamilyIndex]) {
this.familyData[this.bedPickerFamilyIndex].bedType = value
} else {
this.signupForm.bedType = value
}
this.bedPickerVisible = false
},
openRelationshipPicker() {
openRelationshipPicker(index) {
if (this.relationshipColumns.length === 0) {
vant.Toast("暂无关系选项")
return
}
this.relationshipFamilyIndex = index
this.relationshipPickerVisible = true
},
confirmRelationship(value) {
this.currentFamily.relationship = value
if (this.familyData[this.relationshipFamilyIndex]) {
this.familyData[this.relationshipFamilyIndex].relationship = value
}
this.relationshipPickerVisible = false
},
openDirectRelativePicker() {
@@ -207,6 +207,36 @@ layout("/layouts/platform_h5.html"){
font-weight: 400;
}
.tour-line-filter-bar {
margin-top: 10px;
padding-right: 16px;
}
.tour-line-period-entry {
width: 100%;
min-height: 40px;
border: 0;
border-radius: 8px;
padding: 0 12px;
background: #ffffff;
color: #0f172a;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
line-height: 1.4;
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
box-sizing: border-box;
}
.tour-line-period-entry--active {
color: #0b75bd;
}
.tour-line-period-placeholder {
color: #64748b;
}
.tour-line-list {
padding: 0 8px;
}
@@ -434,6 +464,16 @@ layout("/layouts/platform_h5.html"){
</div>
</div>
</div>
<div class="tour-line-filter-bar">
<button
type="button"
class="tour-line-period-entry"
:class="{'tour-line-period-entry--active': !!pageForm.travelPeriod}"
@click="openTravelPeriodPopup">
<span :class="{'tour-line-period-placeholder': !pageForm.travelPeriod}">{{ selectedTravelPeriodText() }}</span>
<van-icon name="arrow-down"></van-icon>
</button>
</div>
</div>
<div class="tour-line-scroll">
@@ -515,6 +555,26 @@ layout("/layouts/platform_h5.html"){
</div>
</div>
</van-popup>
<van-popup v-model="showTravelPeriodPopup" 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 travelPeriodList"
:key="item.value || 'all'"
clickable
class="tour-line-union-popup__item"
:class="{'tour-line-union-popup__item--active': pageForm.travelPeriod === item.value}"
:title="item.name"
@click="selectTravelPeriod(item)">
<template #right-icon>
<van-icon v-if="pageForm.travelPeriod === item.value" name="success" color="#0b75bd"></van-icon>
</template>
</van-cell>
</div>
</div>
</van-popup>
</div>
<script nonce="${cspNonce!}">
@@ -528,9 +588,13 @@ layout("/layouts/platform_h5.html"){
finished: false,
lineChecking: false,
showUnionPopup: false,
showTravelPeriodPopup: false,
unionList: [
{id: "", name: "全部分工会"}
],
travelPeriodList: [
{value: "", name: "全部出行时段"}
],
pageForm: {
pageNumber: 1,
pageSize: 10,
@@ -539,6 +603,7 @@ layout("/layouts/platform_h5.html"){
lineName: "",
lineType: "",
unionId: "",
travelPeriod: "",
directFamilyUnitLine: null,
pageOrderName: "lineName",
pageOrderBy: "ascending"
@@ -558,6 +623,13 @@ layout("/layouts/platform_h5.html"){
}
return ""
},
selectedTravelPeriodText() {
if (!this.pageForm.travelPeriod) {
return "选择出行时段"
}
const selected = this.travelPeriodList.find((item) => item.value === this.pageForm.travelPeriod)
return selected && selected.name ? selected.name : this.pageForm.travelPeriod
},
isSigned(row) {
return !!(row && (row.signed === true || row.signed === 1 || row.signed === "1" || row.ledgerId))
},
@@ -679,12 +751,16 @@ layout("/layouts/platform_h5.html"){
const active = this.pageForm.lineType === lineType && this.pageForm.directFamilyUnitLine === null
this.pageForm.lineType = active ? "" : lineType
this.pageForm.directFamilyUnitLine = null
this.pageForm.travelPeriod = ""
this.loadTravelPeriodOptions()
this.doSearch()
},
toggleDirectFamilyLine() {
const active = this.pageForm.directFamilyUnitLine === true
this.pageForm.directFamilyUnitLine = active ? null : true
this.pageForm.lineType = ""
this.pageForm.travelPeriod = ""
this.loadTravelPeriodOptions()
this.doSearch()
},
openUnionPopup() {
@@ -693,6 +769,12 @@ layout("/layouts/platform_h5.html"){
this.loadUnionOptions()
}
},
openTravelPeriodPopup() {
this.showTravelPeriodPopup = true
if (this.travelPeriodList.length <= 1) {
this.loadTravelPeriodOptions()
}
},
selectUnion(item) {
const unionId = item && item.id ? item.id : ""
this.showUnionPopup = false
@@ -702,6 +784,15 @@ layout("/layouts/platform_h5.html"){
this.pageForm.unionId = unionId
this.doSearch()
},
selectTravelPeriod(item) {
const travelPeriod = item && item.value ? item.value : ""
this.showTravelPeriodPopup = false
if (this.pageForm.travelPeriod === travelPeriod) {
return
}
this.pageForm.travelPeriod = travelPeriod
this.doSearch()
},
loadUnionOptions() {
this.$axios.post("/platform/tour/signup/unionOptions").then((res) => {
if (res.code !== 0) {
@@ -716,6 +807,31 @@ layout("/layouts/platform_h5.html"){
}))
})
},
loadTravelPeriodOptions() {
this.$axios.post("/platform/tour/signup/h5/travelPeriodOptions", {
year: this.pageForm.year,
lineType: this.pageForm.lineType,
directFamilyUnitLine: this.pageForm.directFamilyUnitLine
}).then((res) => {
if (res.code !== 0) {
return
}
const rows = res.data || []
this.travelPeriodList = [{value: "", name: "全部出行时段"}].concat(rows.map((item) => {
return {
value: item.travelPeriod || "",
name: item.travelPeriod || "未设置出行时间"
}
}).filter((item) => item.value))
})
},
showSignupNotice() {
vant.Dialog.alert({
title: "温馨提示",
message: "请确认并选择对应的出行路线时间段进行报名",
confirmButtonColor: "#1867b0"
})
},
loadData() {
if (this.finished) {
this.loading = false
@@ -783,7 +899,9 @@ layout("/layouts/platform_h5.html"){
}
},
created() {
this.showSignupNotice()
this.loadUnionOptions()
this.loadTravelPeriodOptions()
this.loadData()
}
})