ylj20011123 18959b7500 update
2025-11-07 18:33:55 +08:00

687 lines
17 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="registration-page">
<!-- 页面标题 -->
<div class="page-header">
<div class="header-title">活动报名</div>
<div class="header-subtitle">请填写以下信息完成报名</div>
</div>
<!-- 活动信息卡片 -->
<div class="event-info-card" v-if="eventInfo.ACTIVITY_ID">
<div class="event-cover">
<swiper>
<swiper-item v-for="(item, imgIndex) in eventInfo.ImageList" :key="imgIndex">
<image class="cover-image" :src="item.ImageUrl" mode="aspectFill" />
</swiper-item>
</swiper>
</div>
<div class="event-summary">
<div class="event-name">{{ eventInfo.ACTIVITY_NAME }}</div>
<div class="event-meta">
<div class="meta-item">
<span class="meta-icon">📅</span>
<span class="meta-text">{{ eventInfo.ACTIVITY_STARTDATE ? eventInfo.ACTIVITY_STARTDATE : ""
}}{{ eventInfo.ACTIVITY_ENDDATE ? `-` + eventInfo.ACTIVITY_ENDDATE : "" }}</span>
</div>
<div class="meta-item">
<span class="meta-icon">📍</span>
<span class="meta-text">{{ eventInfo.ACTIVITY_LOCATION }}</span>
</div>
<div class="meta-item">
<span class="meta-icon">👥</span>
<span class="meta-text">{{ eventInfo.MAXIMUM_CAPACITY }}</span>
</div>
</div>
</div>
</div>
<!-- 报名表单 -->
<div class="form-section">
<!-- 报名人姓名 -->
<div class="form-item">
<div class="item-label">
<span class="required">*</span>
报名人姓名
</div>
<input class="item-input" v-model="formData.participantName" placeholder="请输入您的真实姓名" />
</div>
<!-- 手机号码 -->
<div class="form-item">
<div class="item-label">
<span class="required">*</span>
手机号码
</div>
<input class="item-input" v-model="formData.phoneNumber" type="number" placeholder="请输入手机号码" maxlength="11" />
</div>
<!-- 备注信息 -->
<div class="form-item">
<div class="item-label">备注信息</div>
<textarea class="item-textarea" v-model="formData.remarks" placeholder="如有特殊需求请在此填写" :maxlength="500" />
</div>
<!-- 同意条款 -->
<div class="agreement-section">
<div class="agreement-item">
<div class="checkbox-wrapper" @click="toggleAgreement">
<div class="checkbox" :class="{ checked: formData.agreement }">
<div class="check-icon" v-if="formData.agreement"></div>
</div>
</div>
<span class="agreement-text">
我已阅读并同意
<text class="agreement-link" @click="showTerms">活动参与条款</text>
</span>
</div>
</div>
</div>
<!-- 提交按钮 -->
<div class="action-section">
<div class="action-btn" :class="[
mode === 'view' ? 'action-disabled' : 'primary-btn'
]" @click="handleSubmit">
<span class="btn-text">提交报名</span>
</div>
</div>
<!-- 条款弹窗 -->
<div class="terms-modal" v-if="showTermsModal" @click="hideTerms">
<div class="modal-content" @click.stop>
<div class="modal-header">
<div class="modal-title">活动参与条款</div>
<div class="close-btn" @click="hideTerms">×</div>
</div>
<div class="modal-body">
<div class="terms-content">
<div class="terms-section">
<div class="section-title">1. 报名须知</div>
<div class="section-content">
请确保填写信息真实有效<br>
每人限报名一个活动<br>
报名成功后请按时参加<br>
如需取消报名请提前24小时联系客服
</div>
</div>
<div class="terms-section">
<div class="section-title">2. 参与要求</div>
<div class="section-content">
请携带有效身份证件<br>
遵守现场秩序和工作人员指引<br>
保管好个人财物<br>
禁止携带危险物品入场
</div>
</div>
<div class="terms-section">
<div class="section-title">3. 免责声明</div>
<div class="section-content">
参与活动期间请自行注意人身安全<br>
主办方对意外伤害不承担责任<br>
如遇不可抗力因素活动可能调整或取消<br>
参与者表示同意上述条款
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="modal-btn" @click="hideTerms">我知道了</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
data() {
return {
eventId: "",
mode: "register", // register: 报名, view: 查看报名信息
eventInfo: {},
formData: {
participantName: "", // 报名人姓名
phoneNumber: "", // 手机号码
remarks: "", // 备注信息
agreement: false // 是否同意条款
},
showTermsModal: false,
defaultCover: 'https://picsum.photos/seed/event-registration/400/300.jpg'
};
},
computed: {
...mapGetters({
user: "user",
}),
},
onLoad(query) {
if (query.eventId) {
this.eventId = query.eventId;
}
if (query.mode) {
this.mode = query.mode;
}
this.loadEventInfo();
},
methods: {
// 加载活动信息
async loadEventInfo() {
const req = {
ACTIVITYId: this.eventId,
type: 'encryption'
}
uni.showLoading({
title: '加载中...',
mask: true
});
const data = await this.$api.$posMemberPost("/Member/GetACTIVITYDetail", req)
uni.hideLoading();
let detail = data.Result_Data
console.log('详情djaksjda', detail);
this.eventInfo = detail;
},
// 加载已报名信息
async loadRegistrationInfo() {
try {
// 这里调用接口获取用户的报名信息
// const res = await this.$api.getRegistrationInfo({
// eventId: this.eventId
// });
// 模拟已报名数据
this.formData = {
participantName: "张三",
phoneNumber: "13800138000",
email: "zhangsan@example.com",
idCard: "530102199001011234",
address: "云南省昆明市五华区xxx街道xxx号",
remarks: "需要特殊座位安排",
agreement: true
};
} catch (error) {
console.error('加载报名信息失败:', error);
}
},
// 切换同意条款状态
toggleAgreement() {
this.formData.agreement = !this.formData.agreement;
},
// 显示条款
showTerms() {
this.showTermsModal = true;
},
// 隐藏条款
hideTerms() {
this.showTermsModal = false;
},
// 格式化日期时间
formatDateTime(dateTime) {
if (!dateTime) return '';
try {
const date = new Date(dateTime);
const month = date.getMonth() + 1;
const day = date.getDate();
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${month}${day}${hours}:${minutes}`;
} catch (error) {
return dateTime;
}
},
// 验证表单
validateForm() {
if (!this.formData.participantName.trim()) {
uni.showToast({
title: "请输入报名人姓名",
icon: "none",
});
return false;
}
if (!this.formData.phoneNumber.trim()) {
uni.showToast({
title: "请输入手机号码",
icon: "none",
});
return false;
}
if (!/^1[3-9]\d{9}$/.test(this.formData.phoneNumber)) {
uni.showToast({
title: "请输入正确的手机号码",
icon: "none",
});
return false;
}
if (!this.formData.agreement) {
uni.showToast({
title: "请阅读并同意活动参与条款",
icon: "none",
});
return false;
}
return true;
},
// 提交报名
async handleSubmit() {
if (!this.validateForm()) {
return;
}
if (this.mode === 'view') {
uni.showToast({
title: '这是查看模式,无法修改',
icon: 'none'
});
return;
}
// 准备提交数据
const submitData = {
eventId: this.eventId,
...this.formData
};
console.log('submitData', submitData);
const req = {
ACTIVITY_ID: this.eventId,
MEMBERSHIP_ID: this.user.MEMBERSHIP_ID,
MEMBERSHIP_NAME: submitData.participantName,
MEMBERSHIP_MOBILEPHONE: submitData.phoneNumber,
ACTIVITYDETAIL_DESC: submitData.remarks,
ACTIVITYDETAIL_STATE: 1,
STAFF_ID: this.user.MEMBERSHIP_ID,
STAFF_NAME: this.user.MEMBERSHIP_NAME,
OPERATE_DATE: this.$moment.now().format("YYYY-MM-DD HH:mm:ss"),
type: 'encryption'
}
uni.showLoading({
title: "提交中...",
mask: true,
});
const data = await this.$api.$posMemberPost("/Member/SynchroACTIVITYDETAIL", req)
uni.hideLoading();
console.log('报名结果', data);
if (data.Result_Code === 100) {
uni.showModal({
title: "报名成功",
content: "您已成功报名该活动,请按时参加!",
showCancel: false,
success: (res) => {
if (res.confirm) {
uni.navigateBack();
}
},
});
} else {
uni.showToast({
title: data.Result_Desc,
icon: 'none'
})
}
}
}
};
</script>
<style scoped lang="less">
.registration-page {
width: 100vw;
min-height: 100vh;
background: #f8fafc;
overflow-y: scroll;
.page-header {
background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
padding: 60rpx 40rpx 40rpx;
text-align: center;
.header-title {
font-size: 30rpx;
font-weight: 600;
color: white;
margin-bottom: 12rpx;
}
.header-subtitle {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.9);
}
}
.event-info-card {
background: white;
margin: -20rpx 32rpx 32rpx;
border-radius: 24rpx 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
overflow: hidden;
.event-cover {
width: 100%;
height: 300rpx;
overflow: hidden;
.cover-image {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.event-summary {
padding: 32rpx;
.event-name {
font-size: 30rpx;
font-weight: 600;
color: #1f2937;
margin-bottom: 12rpx;
}
.event-meta {
.meta-item {
display: flex;
align-items: center;
margin-bottom: 12rpx;
&:last-child {
margin-bottom: 0;
}
.meta-icon {
font-size: 24rpx;
margin-right: 12rpx;
width: 32rpx;
text-align: center;
}
.meta-text {
font-size: 24rpx;
color: #6b7280;
}
}
}
}
}
.form-section {
padding: 40rpx 32rpx 24rpx;
background: white;
margin: 0 32rpx 0;
border-radius: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
margin-bottom: calc(160rpx + env(safe-area-inset-bottom));
box-sizing: border-box;
.form-item {
margin-bottom: 24rpx;
&:last-child {
margin-bottom: 0;
}
.item-label {
font-size: 24rpx;
color: #374151;
font-weight: 500;
margin-bottom: 16rpx;
display: flex;
align-items: center;
.required {
color: #ef4444;
margin-right: 4rpx;
}
}
.item-input {
width: 100%;
height: 66rpx;
padding: 0 24rpx;
border: 2rpx solid #e5e7eb;
border-radius: 16rpx;
font-size: 24rpx;
color: #374151;
background: #f9fafb;
box-sizing: border-box;
&:focus {
border-color: #22c55e;
background: white;
}
&::placeholder {
color: #9ca3af;
}
}
.item-textarea {
width: 100%;
min-height: 160rpx;
padding: 20rpx 24rpx;
border: 2rpx solid #e5e7eb;
border-radius: 16rpx;
font-size: 24rpx;
color: #374151;
background: #f9fafb;
box-sizing: border-box;
resize: none;
&:focus {
border-color: #22c55e;
background: white;
}
&::placeholder {
color: #9ca3af;
}
}
}
.agreement-section {
.agreement-item {
display: flex;
align-items: flex-start;
padding: 20rpx;
.checkbox-wrapper {
margin-right: 16rpx;
padding: 4rpx;
.checkbox {
width: 24rpx;
height: 24rpx;
border: 2rpx solid #d1d5db;
border-radius: 6rpx;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.checked {
background: #22c55e;
border-color: #22c55e;
.check-icon {
color: white;
font-size: 24rpx;
font-weight: bold;
}
}
}
}
.agreement-text {
font-size: 24rpx;
color: #374151;
line-height: 1.5;
.agreement-link {
color: #22c55e;
text-decoration: underline;
}
}
}
}
}
.action-section {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
border-top: 1rpx solid #f0f0f0;
padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
z-index: 100;
.action-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 24rpx;
border-radius: 40rpx;
font-size: 28rpx;
font-weight: 600;
transition: all 0.3s ease;
border: 2rpx solid #e5e7eb;
height: 40rpx;
&.primary-btn {
background: linear-gradient(135deg, #22c55e, #16a34a);
color: white;
border-color: #22c55e;
&:active {
opacity: 0.9;
}
.btn-text {
margin-right: 12rpx;
}
.btn-icon {
font-size: 28rpx;
}
}
}
}
.terms-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
.modal-content {
background: white;
border-radius: 24rpx;
margin: 40rpx;
width: calc(100% - 80rpx);
max-height: 80vh;
overflow: hidden;
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
border-bottom: 1rpx solid #f0f0f0;
.modal-title {
font-size: 32rpx;
font-weight: 600;
color: #1f2937;
}
.close-btn {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: #f3f4f6;
font-size: 32rpx;
color: #6b7280;
}
}
.modal-body {
padding: 32rpx;
max-height: 60vh;
overflow-y: auto;
.terms-content {
.terms-section {
margin-bottom: 32rpx;
&:last-child {
margin-bottom: 0;
}
.section-title {
font-size: 28rpx;
font-weight: 600;
color: #1f2937;
margin-bottom: 16rpx;
}
.section-content {
font-size: 26rpx;
color: #6b7280;
line-height: 1.6;
}
}
}
}
.modal-footer {
padding: 32rpx;
border-top: 1rpx solid #f0f0f0;
.modal-btn {
width: 100%;
padding: 24rpx;
background: linear-gradient(135deg, #22c55e, #16a34a);
color: white;
border-radius: 16rpx;
font-size: 28rpx;
font-weight: 500;
text-align: center;
box-sizing: border-box;
}
}
}
}
}
.registration-page::-webkit-scrollbar {
display: none;
}
</style>