1
This commit is contained in:
+15
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复当前分工会已取消退出的人员分配记录,只恢复状态,不恢复已删除台账。
|
||||
*/
|
||||
|
||||
+7
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+43
-1
@@ -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("参数错误");
|
||||
|
||||
+7
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+20
@@ -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);
|
||||
|
||||
/**
|
||||
* 查询当前登录人所在分工会在指定疗休养配置下的名额使用情况。
|
||||
*
|
||||
|
||||
+113
-10
@@ -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;
|
||||
|
||||
+93
-5
@@ -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)
|
||||
},
|
||||
|
||||
+2
-5
@@ -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()
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user