This commit is contained in:
那些花儿
2025-06-19 02:49:21 +08:00
parent ca1875a8a1
commit 64ac1a2621
2 changed files with 1143 additions and 5 deletions
@@ -2,34 +2,396 @@
layout("/layouts/platform.html"){
#-->
<style>
.therapy-page {
background: #ffffff;
}
.therapy-content {
position: relative;
padding: 10px 20px;
}
.category-nav {
background: white;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
overflow: hidden;
}
.category-nav .category-list {
display: flex;
border-bottom: 1px solid #ebeef5;
}
.category-nav .category-item {
flex: 1;
text-align: center;
padding: 20px 0;
font-size: 16px;
color: #606266;
cursor: pointer;
transition: all 0.3s;
position: relative;
}
.category-nav .category-item:hover {
color: #1890ff;
background-color: #f5f7fa;
}
.category-nav .category-item.active {
color: #1890ff;
font-weight: 600;
background-color: #ecf5ff;
}
.category-nav .category-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
background: #1890ff;
}
.route-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.route-card {
border-radius: 8px;
overflow: hidden;
transition: all 0.3s;
background: white;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
position: relative;
display: flex;
flex-direction: column;
height: 100%;
}
.route-card:hover {
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}
/* 卡片图片区域 */
.route-image {
height: 160px;
background-size: cover;
background-position: center;
position: relative;
}
.route-image::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.4) 100%);
}
.route-image-title {
position: absolute;
bottom: 15px;
left: 15px;
right: 15px;
color: white;
font-size: 18px;
font-weight: 600;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
z-index: 2;
}
.route-header {
padding: 15px 15px 10px;
border-bottom: 1px solid #f0f0f0;
}
.route-title {
font-size: 16px;
font-weight: 600;
color: #303133;
margin: 0 0 8px;
line-height: 1.4;
}
.route-date {
font-size: 13px;
color: #909399;
display: flex;
align-items: center;
}
.route-date i {
margin-right: 5px;
}
.route-body {
padding: 15px;
flex: 1;
}
.route-info-item {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
font-size: 14px;
}
.route-info-label {
color: #909399;
}
.route-info-value {
color: #606266;
font-weight: 500;
}
.route-footer {
padding: 15px;
background: #f9f9f9;
display: flex;
justify-content: space-between;
align-items: center;
}
.route-status {
font-size: 13px;
}
.route-signup-btn {
border-radius: 20px;
border: none;
color: white;
font-size: 13px;
}
.hotel-phone {
color: #1890ff;
display: flex;
align-items: center;
}
.hotel-phone i {
margin-right: 5px;
}
.badge {
display: inline-block;
padding: 3px 8px;
border-radius: 12px;
font-size: 12px;
line-height: 1;
}
.badge-primary {
background: rgba(24, 144, 255, 0.1);
color: #1890ff;
}
.empty-data {
padding: 60px 0;
text-align: center;
}
.empty-data i {
font-size: 60px;
color: #e0e0e0;
margin-bottom: 20px;
}
.empty-data p {
color: #909399;
font-size: 14px;
}
</style>
<div id="app" v-cloak>
<guava>
<div class="therapy-page">
<div class="therapy-content">
<!-- 分类导航 -->
<div class="category-nav">
<div class="category-list">
<div
v-for="item in categoryOptions"
:key="item.value"
class="category-item"
:class="{active: pageForm.theRapyRecuperationType === item.value}"
@click="switchCategory(item.value)">
<i :class="getCategoryIcon(item.value)" style="margin-right: 8px;"></i>
{{ item.label }}
</div>
</div>
</div>
<!-- 加载提示 -->
<div v-if="loading" style="text-align: center; padding: 40px 0;">
<i class="el-icon-loading" style="font-size: 30px; color: #1890ff;"></i>
<p style="margin-top: 10px; color: #909399;">正在加载数据...</p>
</div>
<!-- 无数据提示 -->
<div v-else-if="tableData.length === 0" class="empty-data">
<i class="el-icon-warning-outline"></i>
<p>暂无可报名的疗休养线路</p>
</div>
<!-- 卡片网格布局 - 省内/省外线路 -->
<div v-else-if="pageForm.theRapyRecuperationType !== '3'" class="route-cards">
<div class="route-card" v-for="(item, index) in tableData" :key="index">
<!-- 卡片图片区域 -->
<div
class="route-image"
:style="item.fileId ? 'background-image: url(/file_server/fileStreamPreview?id=' + item.fileId + ')' : ''">
<div class="route-image-title">{{ item.lineName }}</div>
</div>
<div class="route-header">
<div class="route-date">
<i class="el-icon-date"></i> {{ item.lotName }}
</div>
</div>
<div class="route-body">
<div class="route-info-item">
<span class="route-info-label">组织机构</span>
<span class="route-info-value">
<span class="badge badge-primary">
{{ item.signUpMode === 2 ? '校工会' : item.usUnionName }}
</span>
</span>
</div>
</div>
<div class="route-footer">
<el-button
type="text"
size="small"
@click="viewDetails(item)">
<i class="el-icon-view"></i> 查看详情
</el-button>
<el-button
class="route-signup-btn"
type="primary"
size="mini"
@click="handleSignUp(item)">
立即报名
</el-button>
</div>
</div>
</div>
<!-- 卡片网格布局 - 定点疗休养 -->
<div v-else class="route-cards">
<div class="route-card" v-for="(item, index) in tableData" :key="index">
<!-- 卡片图片区域 -->
<div
class="route-image"
:style="item.fileId ? 'background-image: url(/file_server/fileStreamPreview?id=' + item.fileId + ')' : ''">
<div class="route-image-title">{{ item.baseName }}</div>
</div>
<!-- <div class="route-header">-->
<!-- <div class="route-date">-->
<!-- <i class="el-icon-location"></i> {{ item.baseAddress || '暂无地址信息' }}-->
<!-- </div>-->
<!-- </div>-->
<div class="route-body">
<div class="route-info-item">
<span class="route-info-label">联系人</span>
<span class="route-info-value">{{ item.baseContactPerson }}</span>
</div>
<div class="route-info-item">
<span class="route-info-label">联系方式</span>
<span class="route-info-value hotel-phone">
<i class="el-icon-phone"></i>
{{ item.baseContactNumber }}
</span>
</div>
<div class="route-info-item">
<span class="route-info-label">已报名人数</span>
<span class="route-info-value">
<span class="badge badge-primary">{{ item.signUpUserNum }}</span>
</span>
</div>
<div class="route-info-item" v-if="item.baseRemark">
<span class="route-info-label">酒店说明</span>
<span class="route-info-value">{{ item.baseRemark }}</span>
</div>
</div>
<div class="route-footer">
<el-button
type="text"
size="small"
@click="viewDetails(item)">
<i class="el-icon-view"></i> 查看详情
</el-button>
<el-button
class="route-signup-btn"
type="primary"
size="mini"
@click="handleSignUp(item)">
立即报名
</el-button>
</div>
</div>
</div>
<!--#include("/layouts/pagination.html"){}#-->
</div>
</div>
</guava>
<line-sign-up ref="lineSignUpRef"></line-sign-up>
</div>
<script>
<!--#include('lineSignUp.js'){}#-->
new Vue({
el: '#app',
mixins: [initTableMixins],
components: {
'line-sign-up': LineSignUp
},
data() {
return {
modifyConfig: {},
config: {},
categoryOptions: [],
tableData: [],
loading: false,
pageForm: {
theRapyRecuperationType: 0,
theRapyRecuperationType: '0', // 默认使用字符串类型
lineUnionType: 3,
unionId: "${@shiro.getPrincipalProperty('union').getId()}",
year: null
pageNumber: 1,
pageSize: 20,
totalCount: 0
},
}
},
methods: {
// 获取数据
pageData() {
$.post('/platform/theRapyRecuperation/line/enroll/pageData', this.pageForm).then(res => {
this.loading = true;
const params = {...this.pageForm};
params.theRapyRecuperationType = parseInt(params.theRapyRecuperationType);
$.post('/platform/theRapyRecuperation/line/enroll/pageData', params).then(res => {
this.loading = false;
if (res.code === 0) {
this.tableData = res.data.list;
this.pageForm.totalCount = res.data.totalCount;
} else {
this.$message.error(res.msg || '获取数据失败');
}
})
},
@@ -37,14 +399,61 @@ layout("/layouts/platform.html"){
async getConfig() {
const res = await $.post('/platform/theRapyRecuperation/TheRapyConfig/findOne')
if (res.code === 0) {
this.modifyConfig = res.data
this.config = res.data
}
},
// 获取分类 (线路、旅行社)
getCategory() {
getEnumOptions('TheRapyRecuperationType').then(res => {
// 过滤并转换为字符串类型
this.categoryOptions = res.filter(item => item.value !== 2)
.map(item => ({
...item,
value: item.value.toString()
}));
console.log('分类选项:', this.categoryOptions);
})
},
// 获取分类图标
getCategoryIcon(value) {
const icons = {
'0': 'el-icon-map-location', // 省内线路
'1': 'el-icon-location-information', // 省外线路
'3': 'el-icon-house' // 定点疗休养
};
return icons[value] || 'el-icon-location-outline';
},
// 切换分类
switchCategory(value) {
this.pageForm.theRapyRecuperationType = value;
this.pageForm.pageNumber = 1;
this.pageData();
},
// 查看详情
viewDetails(item) {
},
// 处理报名
async handleSignUp(row) {
const {code,data,msg} = await $.post('/platform/theRapyRecuperation/line/enroll/validSignUpInfo',{
enroll: JSON.stringify({
isNormal: true,
takePartInLineId: row.usId,
takePartInUnionId: row.takePartInUnionId,
}),
})
if (code !== 0) {
this.$message.error(msg);
return;
}
if (["0", "1"].includes(this.pageForm.theRapyRecuperationType)) {
// 线路
this.$refs.lineSignUpRef.onOpen(row, this.pageForm, this.config);
} else if (this.pageForm.theRapyRecuperationType === 3) {
// 定点疗休养
}
}
},
created() {
@@ -0,0 +1,729 @@
const LineSignUp = {
template: /*language=HTML*/ `
<el-dialog title="报名" :visible.sync="visible" width="70%" :close-on-click-modal="false"
top="50px"
class="line-sign-up-dialog">
<div class="play-times-container">
<div v-if="playTimes.length > 0">
<div class="section-title">请选择出行时间</div>
<el-table :data="playTimes" highlight-current-row @current-change="handleCurrentChange"
class="time-table" :row-class-name="tableRowClassName">
<el-table-column
label="序号"
width="70"
align="center">
<template slot-scope="scope">
<div class="sequence-number">{{ scope.$index + 1 }}</div>
</template>
</el-table-column>
<el-table-column
label="出行时间"
prop="playStartTime"
min-width="120">
<template slot-scope="scope">
{{ moment(scope.row.playStartTime).format('YYYY-MM-DD') }}
</template>
</el-table-column>
<el-table-column
label="报名截止时间"
prop="signUpEndTime"
min-width="150">
<template slot-scope="scope">
{{ moment(scope.row.signUpEndTime).format('YYYY-MM-DD HH:mm') }}
</template>
</el-table-column>
<el-table-column
label="报名限制人数"
prop="maxApplyNum"
width="120"
align="center">
</el-table-column>
<el-table-column
label="已报人数"
min-width="150">
<template slot-scope="scope">
<template v-if="config.familyInfo == 2">
{{ (scope.row.signUpUserNum + scope.row.signUpUserFamilyNum) }}人
(家属{{ scope.row.signUpUserFamilyNum }}人)
</template>
<template v-else>
{{ (scope.row.signUpUserNum + scope.row.signUpUserFamilyNum) }}人
(家属{{ scope.row.familyNumber }}人)
</template>
</template>
</el-table-column>
<el-table-column
label="剩余名额"
width="100"
align="center">
<template slot-scope="scope">
{{ Math.max(0, scope.row.maxApplyNum - (scope.row.signUpUserNum +
scope.row.signUpUserFamilyNum)) }}人
</template>
</el-table-column>
<el-table-column
label="状态"
width="100"
align="center">
<template slot-scope="scope">
<el-tag size="small" type="danger"
v-if="(scope.row.signUpUserNum + scope.row.signUpUserFamilyNum) >= scope.row.maxApplyNum">
已满
</el-tag>
<el-tag size="small" type="warning"
v-else-if="new Date(scope.row.signUpEndTime) < new Date()">
已截止
</el-tag>
<el-tag size="small" type="success" v-else>
可报名
</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<div v-else class="no-times">
<i class="el-icon-warning-outline"></i>
<p>暂无可选出行时间</p>
</div>
</div>
<!-- 报名表单 -->
<div v-if="selectedTime" class="signup-form">
<div class="section-title">填写报名信息</div>
<el-form ref="signupFormRef" :model="signupForm" label-width="100px" :rules="rules">
<!-- 人员基础信息 -->
<div class="form-section">
<div class="sub-section-title">人员基础信息</div>
<el-form-item label="姓名" prop="mainName">
<el-input v-model="signupForm.userName" placeholder="请输入姓名" readonly></el-input>
</el-form-item>
<el-form-item label="工号" prop="loginName">
<el-input v-model="signupForm.loginName" placeholder="请输入工号" readonly></el-input>
</el-form-item>
<el-form-item label="身份证号" prop="idCard">
<el-input v-model="signupForm.idCard" placeholder="请输入身份证号"></el-input>
</el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input v-model="signupForm.mobile" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item label="所属工会" prop="unionName">
<el-input v-model="signupForm.unionName" readonly></el-input>
</el-form-item>
</div>
<!-- 随行人信息 -->
<div class="form-section">
<div class="sub-section-title">
随行人信息
<el-button type="text" size="small" @click="addAccompanyingPerson" icon="el-icon-plus"
v-if="config.familyInfo === 2">添加随行人
</el-button>
</div>
<div v-if="config.familyInfo === 2" class="accompanying-person-container">
<div v-for="(person, index) in signupForm.companionList" :key="index"
class="accompanying-person">
<div class="person-header">
<span>随行人 {{index + 1}}</span>
<el-button type="text" size="small" @click="removeAccompanyingPerson(index)"
icon="el-icon-delete" class="remove-btn">移除
</el-button>
</div>
<el-form-item :label="'姓名'" :prop="'companionList.' + index + '.userName'"
:rules="rules.userName">
<el-input v-model="person.userName" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item :label="'身份证号'" :prop="'companionList.' + index + '.idCard'"
:rules="rules.idCard">
<el-input v-model="person.idCard" placeholder="请输入身份证号"
@blur="parseIdCard(index)"></el-input>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item :label="'性别'" :prop="'companionList.' + index + '.sex'">
<el-input v-model="person.sex" placeholder="根据身份证号自动读取"
disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="'年龄'" :prop="'companionList.' + index + '.age'">
<el-input v-model.number="person.age" placeholder="根据身份证号自动读取"
disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="身高" :prop="'companionList.' + index + '.height'"
v-if="person.age && person.age <= 12">
<el-input v-model.number="person.height" placeholder="请输入身高">
<template slot="append">cm</template>
</el-input>
</el-form-item>
<el-form-item :label="'手机号'" :prop="'companionList.' + index + '.mobile'"
:rules="rules.mobile">
<el-input v-model="person.mobile" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-divider v-if="index < signupForm.companionList.length - 1"></el-divider>
</div>
<div v-if="signupForm.companionList.length === 0" class="empty-accompanying">
<p>暂无随行人信息,请点击上方"添加随行人"按钮添加</p>
<p>限填写1岁以上70岁以下随行人</p>
</div>
</div>
<template v-else>
<el-form-item label="家属人数" prop="familyNumber"
:rules="[{ required: true, message: '请输入家属人数', trigger: 'blur' }]">
<el-input v-model.number="signupForm.familyNumber"
placeholder="请输入家属人数"></el-input>
</el-form-item>
</template>
</div>
<!-- 房间信息 -->
<div class="form-section" v-if="config.bedInfo">
<div class="sub-section-title">房间信息</div>
<el-form-item label="房间数量" prop="roomCount"
:rules="[{ required: true, message: '请选择房间数量', trigger: 'change'}]">
<el-select v-model="signupForm.roomCount" placeholder="请选择房间数量">
<el-option v-for="room in roomColumns" :key="room.value" :label="room.label"
:value="room.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="用房备注" prop="roomRemark" v-if="signupForm.roomCount"
:rules="[{ required: true, message: '请选择用房备注', trigger: 'change'}]">
<el-select v-model="signupForm.roomRemark" placeholder="请选择用房备注">
<el-option v-for="room in roomRemarkColumns" :key="room.value" :label="room.label"
:value="room.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="拼房人" prop="roommate" v-if="signupForm.roomRemark === 2">
<el-input v-model="signupForm.roommate" placeholder="请输入拼房人"></el-input>
</el-form-item>
<el-form-item label="其它备注" prop="otherRemark">
<el-input type="textarea" v-model="signupForm.otherRemark"
placeholder="如有需要请填写其它备注信息"></el-input>
</el-form-item>
</div>
<!-- 其他信息 -->
<div class="form-section">
<div class="sub-section-title">其他信息</div>
<el-form-item label="第二意向线路" prop="intentionLineId"
:rules="[{ required: true, message: '请选择第二意向线路', trigger: 'change'}]">
<el-select v-model="signupForm.intentionLineId" placeholder="请选择第二意向线路">
<el-option v-for="item in intentionLineColumns" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="家属人数" prop="carryFamilyNum"
:rules="[{ required: true, message: '请选择是否携带家属', trigger: 'change' }]">
<el-select v-model="signupForm.carryFamilyNum" placeholder="请选择是否携带家属">
<el-option label="0" :value="0"></el-option>
<el-option label="1" :value="1"></el-option>
<el-option label="2" :value="2"></el-option>
<el-option label="3" :value="3"></el-option>
</el-select>
:
</el-form-item>
</div>
<!-- 安全告知书 -->
<div style="display: flex">
<el-checkbox size="medium" style="width: 70%;color: #F56C6C;white-space: nowrap"
@change="readChangeSafe" v-model="hasReadSafe">
我已查看
<span @click="openReadSafe" style="color: #0e5996; text-decoration: underline">
《安全告知书》
</span>
<el-tag @click="openReadSafe" size="mini" effect="dark">查看</el-tag>
</el-checkbox>
</div>
</el-form>
</div>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="submitSignup" :disabled="!selectedTime">确定</el-button>
</template>
<el-dialog title="安全告知书" :visible.sync="readVisibleSafe" :close-on-click-modal="false"
:close-on-press-escape="false" append-to-body>
<iframe
:src="readSafeUrl + '#toolbar=0'"
width="100%"
height="550px"
frameborder="0"
></iframe>
<el-row justify="end" type="flex" class="mt10">
<el-button @click="onReadSafe" type="primary">我已阅读确认</el-button>
</el-row>
</el-dialog>
</el-dialog>
`,
data() {
return {
visible: false,
line: {},
pageForm: {},
config: {},
playTimes: [],
selectedTime: null,
signupForm: {
userName: "${@shiro.getPrincipalProperty('username')}",
loginName: "${@shiro.getPrincipalProperty('loginname')}",
unionName: "${@shiro.getPrincipalProperty('union').getUnionname()}",
idCard: "${@shiro.getPrincipalProperty('idcard')}",
mobile: "${@shiro.getPrincipalProperty('mobile')}",
lineName: '',
takePartInLineId: '',
takePartInUnionId: '',
companionList: [],
bedInfo: {},
roomCount: null,
},
rules: {
mainName: [
{required: true, message: '请输入姓名', trigger: 'blur'},
{min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur'}
],
mainIdCard: [
{required: true, message: '请输入身份证号', trigger: 'blur'},
{
pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
message: '请输入正确的身份证号',
trigger: 'blur'
}
],
mainGender: [
{required: true, message: '请选择性别', trigger: 'change'}
],
mainPhone: [
{required: true, message: '请输入手机号', trigger: 'blur'},
{pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur'}
],
accompaningName: [
{required: true, message: '请输入姓名', trigger: 'blur'},
{min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur'}
],
accompanyingIdCard: [
{required: true, message: '请输入身份证号', trigger: 'blur'},
{
pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
message: '请输入正确的身份证号',
trigger: 'blur'
}
],
accompanyingPhone: [
{required: true, message: '请输入手机号', trigger: 'blur'},
{pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur'}
],
accompaningGender: [
{required: true, message: '请选择性别', trigger: 'change'}
]
},
basicRoomColumns: [
{label: '0.5间(一张床)', value: 0.5},
{label: '1间(两张床)', value: 1},
{label: '1.5间(三张床)', value: 1.5},
{label: '2间(四张床)', value: 2},
],
roomColumns: [],
basicRoomRemarkColumns: [
{label: '携带家属,1间房', value: 1},
{label: '已与其他老师自由组合共住1间房', value: 2},
{label: '1间房,额外支付单房差', value: 3},
{label: '正常报名', value: 4},
{label: '随机拼房', value: 5},
{label: '2间房,额外支付单房差', value: 6},
],
roomRemarkColumns: [],
// 第二意向线路
intentionLineColumns: [],
carryFamilyColumns: [0, 1, 2, 3],
// 安全告知书相关
readVisibleSafe: false,
clickReadSafe: false,
hasReadSafe: false,
readSafeUrl: '',
// 报名id
enrollId: null
}
},
watch: {
'signupForm.companionList': {
handler(newVal) {
const {companionList = []} = this.signupForm;
const companionCount = companionList.length;
const bedCount = 0.5 + (companionCount * 0.5);
const bedCountStrategies = {
0.5: () => this.basicRoomColumns.filter(o => o.value <= 1),
1: () => this.basicRoomColumns.filter(o => o.value === 1),
1.5: () => this.basicRoomColumns.filter(o => [1, 2].includes(o.value)),
2: () => this.basicRoomColumns.filter(o => o.value === 2)
};
this.roomColumns = bedCountStrategies[bedCount]?.() || [];
this.signupForm.carryFamilyNum = companionCount
},
deep: true,
immediate: true
},
'signupForm.roomCount'(oldVal, newVal) {
if (newVal && oldVal !== newVal) {
this.$set(this.signupForm, 'roomRemark', '')
}
this.updateRoomRemarkColumns()
}
},
methods: {
async onOpen(row, pageForm, config, enrollId = null) {
this.visible = true;
this.line = row;
this.pageForm = pageForm;
this.config = config;
this.selectedTime = null;
this.enrollId = enrollId;
this.loadSecondChoiceOptions();
await this.getPlayTimes()
if (this.enrollId) {
await this.getEnrollInfo()
}
},
// 获取报名信息
async getEnrollInfo() {
$.post('/platform/theRapyRecuperation/line/enroll/findSignUpInfoById', {id: this.enrollId}).then(res => {
if (res.code === 0) {
this.signupForm = res.data
} else {
this.$message.error(res.msg)
}
})
},
// 获取出行时间
async getPlayTimes() {
const {code, data, msg} = await $.post('/platform/theRapyRecuperation/line/enroll/getSelectLineById',
{
lineId: this.line.lineId,
unionId: this.pageForm.unionId,
theRapyRecuperationType: this.pageForm.theRapyRecuperationType,
lineUnionType: this.pageForm.lineUnionType,
}
)
if (code === 0) {
this.playTimes = data
}
},
// 选择出行时间
handleCurrentChange(row) {
if (!row) return;
if ((row.signUpUserNum + row.signUpUserFamilyNum) >= row.maxApplyNum) {
this.$message.warning('报名人数已满')
return
}
if (new Date(row.signUpEndTime) < new Date()) {
this.$message.warning('报名已截止')
return
}
this.selectedTime = row;
},
// 表格行样式
tableRowClassName({row, rowIndex}) {
if (this.selectedTime && row.usId === this.selectedTime.usId) {
return 'selected-row';
}
// 人数已满的行显示灰色
if ((row.signUpUserNum + row.signUpUserFamilyNum) >= row.maxApplyNum) {
return 'full-row';
}
// 已截止的行显示灰色
if (new Date(row.signUpEndTime) < new Date()) {
return 'expired-row';
}
return '';
},
// 添加随行人
addAccompanyingPerson() {
if (this.signupForm.companionList.length === 3) {
this.$message.warning('最多添加3个随行人')
return
}
this.signupForm.companionList.push({});
this.$set(this.signupForm, 'roomCount', '')
this.$set(this.signupForm, 'roomRemark', '')
},
// 移除随行人
removeAccompanyingPerson(index) {
this.signupForm.companionList.splice(index, 1);
this.$set(this.signupForm, 'roomCount', '')
this.$set(this.signupForm, 'roomRemark', '')
},
// 根据身份证解析年龄和性别
parseIdCard(index) {
let idCard = this.signupForm.companionList[index].idCard;
if (!idCard || idCard.length < 15) return;
// 解析性别 (第17位,奇数为男,偶数为女)
if (idCard.length >= 17) {
const genderBit = parseInt(idCard.substr(16, 1));
this.signupForm.companionList[index].gender = genderBit % 2 === 1 ? 1 : 2; // 1-男, 2-女
}
// 解析年龄
const birthYear = idCard.length === 18 ? idCard.substr(6, 4) : '19' + idCard.substr(6, 2);
const birthMonth = idCard.length === 18 ? idCard.substr(10, 2) : idCard.substr(8, 2);
const birthDay = idCard.length === 18 ? idCard.substr(12, 2) : idCard.substr(10, 2);
const birthDate = new Date(birthYear + '-' + birthMonth + '-' + birthDay)
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
if (today.getMonth() < birthDate.getMonth() ||
(today.getMonth() === birthDate.getMonth() && today.getDate() < birthDate.getDate())) {
age--;
}
this.signupForm.companionList[index].age = age;
},
// 根据房间数量更新用房备注
updateRoomRemarkColumns() {
const {roomCount, companionList = []} = this.signupForm;
const companionCount = companionList.length;
const roomCountStrategies = {
0.5: () => [2, 5],
1: () => {
if (companionCount === 0) return [3];
if (companionCount === 1) return [4];
return [1];
},
1.5: () => [1, 3],
2: () => companionCount < 3 ? [6] : [4]
};
const matchedValues = roomCountStrategies[roomCount]?.();
this.roomRemarkColumns = matchedValues !== undefined
? this.basicRoomRemarkColumns.filter(o => matchedValues.includes(o.value))
: [...this.basicRoomRemarkColumns]; // 默认处理:恢复基础列
// 如果最后的roomRemarkColumns的length只有1,直接默认第一个元素显示
if (this.roomRemarkColumns.length === 1) {
this.$set(this.signupForm, 'roomRemark', this.roomRemarkColumns[0].value)
}
},
// 加载第二意向线路选项
loadSecondChoiceOptions() {
$.post('/platform/mobile/theRapyRecuperation/getOpenLineList', {id: this.line?.usId}).then(res => {
if (res.code === 0) {
this.intentionLineColumns = res.data
}
})
},
// 展示安全告知书
async openReadSafe() {
let pdfStreamUrl = encodeURIComponent(CREATE_PREVIEW_URL(this.config.files[0].id)) //将路径转码
this.readSafeUrl = '/assets/platform/plugins/pdfJs/web/viewer.html?file=' + pdfStreamUrl
this.readVisibleSafe = true
},
// 确认阅读安全告知书
onReadSafe() {
this.clickReadSafe = true
this.hasReadSafe = true
this.readVisibleSafe = false
},
// 阅读安全告知书时,点击取消
readChangeSafe() {
if (this.clickReadSafe === false) {
// this.$message.error('请先阅读《安全告知书》')
this.hasReadSafe = false
} else {
this.hasReadSafe = true
}
},
// 提交报名
async submitSignup() {
this.$refs.signupFormRef.validate(valid => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {type: "warning"})
.then(() => {
$.post('/platform/theRapyRecuperation/line/enroll/doSignUpForLine', {enroll: JSON.stringify(this.signupForm)}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
})
}
})
},
},
style: /*language=CSS*/ `
.line-sign-up-dialog .el-dialog__body {
padding: 0 20px 20px 20px;
}
.play-times-container {
margin-bottom: 30px;
}
.section-title {
font-size: 18px;
font-weight: 600;
color: #303133;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #EBEEF5;
}
.sub-section-title {
font-size: 16px;
font-weight: 500;
color: #303133;
margin-bottom: 15px;
display: flex;
justify-content: space-between;
align-items: center;
}
.form-section {
margin-bottom: 30px;
padding: 20px;
background-color: #f9f9f9;
border-radius: 5px;
}
.time-table {
width: 100%;
margin-bottom: 20px;
}
.time-table .selected-row {
background-color: #ecf5ff;
}
.time-table .full-row td {
color: #909399;
background-color: #f8f8f8;
}
.time-table .expired-row td {
color: #909399;
background-color: #f8f8f8;
}
.sequence-number {
width: 24px;
height: 24px;
line-height: 24px;
border-radius: 50%;
background-color: #409EFF;
color: white;
font-weight: bold;
margin: 0 auto;
}
.full-row .sequence-number,
.expired-row .sequence-number {
background-color: #909399;
}
.no-times {
text-align: center;
color: #909399;
padding: 40px 0;
background: #f8f8f8;
border-radius: 8px;
}
.no-times i {
font-size: 40px;
margin-bottom: 15px;
color: #DCDFE6;
}
.signup-form {
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #EBEEF5;
}
.selected-time {
font-weight: 500;
color: #409EFF;
}
.accompanying-person-container {
/*display: flex;*/
/*column-gap: 20px;*/
}
.accompanying-person {
position: relative;
margin-bottom: 15px;
}
.person-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
font-weight: 500;
}
.remove-btn {
color: #F56C6C;
}
.empty-accompanying {
text-align: center;
padding: 20px;
color: #909399;
background-color: #f4f4f5;
border-radius: 4px;
}
`
};