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
@@ -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()
}
})