..
This commit is contained in:
@@ -2,36 +2,26 @@
|
||||
import {ref, onMounted, reactive} from 'vue';
|
||||
import {onLoad} from '@dcloudio/uni-app';
|
||||
import {Toast} from 'tdesign-mobile-vue';
|
||||
import {useRequest} from "@/utils/request";
|
||||
|
||||
const request = useRequest()
|
||||
|
||||
// 项目ID
|
||||
const itemId = ref(null);
|
||||
const actId = ref(null);
|
||||
// 详情数据
|
||||
const detailData = ref(null);
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
// 当前活动选项卡
|
||||
const activeTab = ref('detail');
|
||||
// 是否显示PDF预览
|
||||
const showPdfPreview = ref(false);
|
||||
// 当前预览的文件
|
||||
const currentFile = ref({});
|
||||
// 是否显示报名表单
|
||||
const showRegistrationForm = ref(false);
|
||||
// 相关推荐列表
|
||||
const relatedList = ref([]);
|
||||
// 相关推荐是否加载中
|
||||
const relatedLoading = ref(null);
|
||||
// 是否有更多相关推荐
|
||||
const hasMoreRelated = ref(true);
|
||||
// 相关推荐页码
|
||||
const relatedPage = ref(1);
|
||||
|
||||
// 获取路由参数
|
||||
onLoad((option) => {
|
||||
if (option.id) {
|
||||
itemId.value = option.id;
|
||||
actId.value = option.id;
|
||||
getDetailData(option.id);
|
||||
getRelatedList();
|
||||
} else {
|
||||
Toast({message: 'ID不存在', theme: 'error'});
|
||||
}
|
||||
@@ -41,96 +31,104 @@ onLoad((option) => {
|
||||
const getDetailData = async (id) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 模拟网络请求延迟
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 随机生成地点
|
||||
const locations = [
|
||||
'南京奥体中心',
|
||||
'苏州国际博览中心',
|
||||
'无锡太湖国际博览中心',
|
||||
'常州体育中心',
|
||||
'镇江国际会展中心'
|
||||
];
|
||||
const {code, data} = await request.get('/client/activity/get/' + id)
|
||||
if (code === 0) {
|
||||
detailData.value = data
|
||||
} else {
|
||||
Toast({message: '获取详情失败', theme: 'error'});
|
||||
}
|
||||
|
||||
// 模拟详情数据
|
||||
detailData.value = {
|
||||
id,
|
||||
title: '奋进新征程 运动促健康 2024晴江第六届"牧城之夜"荧光跑',
|
||||
status: 1, // 1-报名中 2-已结束 3-即将开始
|
||||
banner: 'https://img0.baidu.com/it/u=1693652779,2163403752&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=800',
|
||||
price: 200,
|
||||
participants: 500,
|
||||
maxParticipants: 800,
|
||||
registrationPeriod: '2025.04.03 00:00:00\n2025.04.08 20:00:00',
|
||||
date: '2024.04.19 09:00:00\n2024.04.19 19:00:00',
|
||||
location: '武汉市江夏区梁子湖龙湾半岛景区',
|
||||
organizer: '靖江市文化广电和旅游局,靖江市体育总会',
|
||||
coorganizer: '靖江市疾病预防控制中心',
|
||||
desc: '本次活动是为了推动全民健身,促进城市体育文化建设的重要赛事。活动全程约5公里,沿途设有多个补给站和打卡点,参与者完成全程将获得完赛奖牌和证书。\n\n参赛者需提前30分钟到达集合地点,并携带有效身份证件。组委会将提供统一的参赛装备,包括荧光手环、荧光贴纸等。\n\n活动期间,参与者需遵守赛事规则,服从工作人员指挥,确保安全有序参与。',
|
||||
competitions: [
|
||||
{
|
||||
name: '同心接力 聚力前行——飓风跑',
|
||||
format: '6名参赛选手,横队站于起跑线后,双手握住长杆,共同向前跑,赛程为25米绕桩跑',
|
||||
rules: '以各小组完成赛程所用时间作为评分依据,用时越短,得分越高'
|
||||
},
|
||||
{
|
||||
name: '鼓韵凝心 协作共赢——击鼓颠球',
|
||||
format: '10名参赛选手,共同牵拉一面四周绑有若干绳索的圆形鼓。通过协作牵拉绳索,让鼓面有节奏地上下颠动,使排球在鼓面上持续跳动。',
|
||||
rules: '以3分钟内各小组有效击球次数作为评分依据,击球次数越多,得分越高'
|
||||
},
|
||||
{
|
||||
name: '慧眼寻同 携手并进——连连看',
|
||||
format: '一次派2位选手进入挑战区域,每位选手各自掀开一顶斗笠,核实斗笠内物品是否一致,一致可将物品带回,斗笠掀开;如物品不同则原位盖好',
|
||||
rules: '结合参赛小组的物品获得数量进行纵向排名'
|
||||
},
|
||||
{
|
||||
name: '方块解码 共绘家韵——智俄罗斯方块',
|
||||
format: '一次派2位选手携带一块拼图进场,进场途中跟守关裁判猜拳"输"返回起点线重新进入,"赢"携带道具进场拼图',
|
||||
rules: '结合参赛小组的用时长短进行纵向排名'
|
||||
},
|
||||
{
|
||||
name: '极速接力 暖心传递——小轮车',
|
||||
format: '6位参赛选手折返接力,直至6位选手互换场地',
|
||||
rules: '结合参赛小组的用时长短进行纵向排名'
|
||||
},
|
||||
{
|
||||
name: '众志筑塔 逐梦远航——通天塔',
|
||||
format: '小组成员团队合作将8块立方体进行纵向叠高垒起,全部拼装完成后5秒倒计时,读秒结束高塔不倒即为完成',
|
||||
rules: '结合参赛小组的用时长短进行纵向排名'
|
||||
}
|
||||
],
|
||||
files: [
|
||||
{
|
||||
id: 1,
|
||||
name: '活动规则及参赛须知.pdf',
|
||||
url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
size: '1.2MB',
|
||||
date: '2024-03-15'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '参赛安全责任书.pdf',
|
||||
url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
size: '580KB',
|
||||
date: '2024-03-15'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '活动流程安排.pdf',
|
||||
url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
size: '1.5MB',
|
||||
date: '2024-03-16'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '比赛评分标准.pdf',
|
||||
url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
size: '890KB',
|
||||
date: '2024-03-16'
|
||||
}
|
||||
]
|
||||
};
|
||||
// // 模拟网络请求延迟
|
||||
// await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
//
|
||||
// // 随机生成地点
|
||||
// const locations = [
|
||||
// '南京奥体中心',
|
||||
// '苏州国际博览中心',
|
||||
// '无锡太湖国际博览中心',
|
||||
// '常州体育中心',
|
||||
// '镇江国际会展中心'
|
||||
// ];
|
||||
//
|
||||
// // 模拟详情数据
|
||||
// detailData.value = {
|
||||
// id,
|
||||
// title: '奋进新征程 运动促健康 2024晴江第六届"牧城之夜"荧光跑',
|
||||
// status: 1, // 1-报名中 2-已结束 3-即将开始
|
||||
// banner: 'https://img0.baidu.com/it/u=1693652779,2163403752&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=800',
|
||||
// price: 200,
|
||||
// participants: 500,
|
||||
// maxParticipants: 800,
|
||||
// registrationPeriod: '2025.04.03 00:00:00\n2025.04.08 20:00:00',
|
||||
// date: '2024.04.19 09:00:00\n2024.04.19 19:00:00',
|
||||
// location: '武汉市江夏区梁子湖龙湾半岛景区',
|
||||
// organizer: '靖江市文化广电和旅游局,靖江市体育总会',
|
||||
// coorganizer: '靖江市疾病预防控制中心',
|
||||
// desc: '本次活动是为了推动全民健身,促进城市体育文化建设的重要赛事。活动全程约5公里,沿途设有多个补给站和打卡点,参与者完成全程将获得完赛奖牌和证书。\n\n参赛者需提前30分钟到达集合地点,并携带有效身份证件。组委会将提供统一的参赛装备,包括荧光手环、荧光贴纸等。\n\n活动期间,参与者需遵守赛事规则,服从工作人员指挥,确保安全有序参与。',
|
||||
// competitions: [
|
||||
// {
|
||||
// name: '同心接力 聚力前行——飓风跑',
|
||||
// format: '6名参赛选手,横队站于起跑线后,双手握住长杆,共同向前跑,赛程为25米绕桩跑',
|
||||
// rules: '以各小组完成赛程所用时间作为评分依据,用时越短,得分越高'
|
||||
// },
|
||||
// {
|
||||
// name: '鼓韵凝心 协作共赢——击鼓颠球',
|
||||
// format: '10名参赛选手,共同牵拉一面四周绑有若干绳索的圆形鼓。通过协作牵拉绳索,让鼓面有节奏地上下颠动,使排球在鼓面上持续跳动。',
|
||||
// rules: '以3分钟内各小组有效击球次数作为评分依据,击球次数越多,得分越高'
|
||||
// },
|
||||
// {
|
||||
// name: '慧眼寻同 携手并进——连连看',
|
||||
// format: '一次派2位选手进入挑战区域,每位选手各自掀开一顶斗笠,核实斗笠内物品是否一致,一致可将物品带回,斗笠掀开;如物品不同则原位盖好',
|
||||
// rules: '结合参赛小组的物品获得数量进行纵向排名'
|
||||
// },
|
||||
// {
|
||||
// name: '方块解码 共绘家韵——智俄罗斯方块',
|
||||
// format: '一次派2位选手携带一块拼图进场,进场途中跟守关裁判猜拳"输"返回起点线重新进入,"赢"携带道具进场拼图',
|
||||
// rules: '结合参赛小组的用时长短进行纵向排名'
|
||||
// },
|
||||
// {
|
||||
// name: '极速接力 暖心传递——小轮车',
|
||||
// format: '6位参赛选手折返接力,直至6位选手互换场地',
|
||||
// rules: '结合参赛小组的用时长短进行纵向排名'
|
||||
// },
|
||||
// {
|
||||
// name: '众志筑塔 逐梦远航——通天塔',
|
||||
// format: '小组成员团队合作将8块立方体进行纵向叠高垒起,全部拼装完成后5秒倒计时,读秒结束高塔不倒即为完成',
|
||||
// rules: '结合参赛小组的用时长短进行纵向排名'
|
||||
// }
|
||||
// ],
|
||||
// files: [
|
||||
// {
|
||||
// id: 1,
|
||||
// name: '活动规则及参赛须知.pdf',
|
||||
// url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
// size: '1.2MB',
|
||||
// date: '2024-03-15'
|
||||
// },
|
||||
// {
|
||||
// id: 2,
|
||||
// name: '参赛安全责任书.pdf',
|
||||
// url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
// size: '580KB',
|
||||
// date: '2024-03-15'
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// name: '活动流程安排.pdf',
|
||||
// url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
// size: '1.5MB',
|
||||
// date: '2024-03-16'
|
||||
// },
|
||||
// {
|
||||
// id: 4,
|
||||
// name: '比赛评分标准.pdf',
|
||||
// url: 'https://www.africau.edu/images/default/sample.pdf',
|
||||
// size: '890KB',
|
||||
// date: '2024-03-16'
|
||||
// }
|
||||
// ]
|
||||
// };
|
||||
} catch (error) {
|
||||
console.error('获取详情失败', error);
|
||||
Toast({message: '获取详情失败', theme: 'error'});
|
||||
@@ -139,85 +137,6 @@ const getDetailData = async (id) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 报名表单数据
|
||||
const registration = reactive({
|
||||
organization: '',
|
||||
contactName: '',
|
||||
contactPhone: '',
|
||||
agreementChecked: false,
|
||||
participants: [
|
||||
{
|
||||
name: '',
|
||||
gender: '男',
|
||||
position: '',
|
||||
idNumber: '',
|
||||
phone: '',
|
||||
accommodation: false
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// 获取相关推荐列表
|
||||
const getRelatedList = async () => {
|
||||
relatedLoading.value = 'loading';
|
||||
try {
|
||||
// 模拟网络请求延迟
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 随机生成地点
|
||||
const locations = [
|
||||
'南京奥体中心',
|
||||
'苏州国际博览中心',
|
||||
'无锡太湖国际博览中心',
|
||||
'常州体育中心',
|
||||
'镇江国际会展中心'
|
||||
];
|
||||
|
||||
// 模拟数据
|
||||
const mockData = Array.from({length: 5}, (_, index) => {
|
||||
const id = relatedPage.value * 5 + index;
|
||||
const randomPrice = Math.floor(Math.random() * 150) + 30;
|
||||
const randomParticipants = Math.floor(Math.random() * 500) + 50;
|
||||
|
||||
return {
|
||||
id,
|
||||
title: index % 2 === 0 ? '2023江苏省青少年体育锦标赛' : '2023年冬季室内马拉松挑战赛',
|
||||
status: Math.floor(Math.random() * 3) + 1,
|
||||
date: `2023.${Math.floor(Math.random() * 12) + 1}.${Math.floor(Math.random() * 28) + 1}`,
|
||||
endDate: `2023.${Math.floor(Math.random() * 12) + 1}.${Math.floor(Math.random() * 28) + 1}`,
|
||||
image: `https://picsum.photos/800/450?random=${id + 100}`,
|
||||
price: randomPrice,
|
||||
participants: randomParticipants,
|
||||
location: locations[Math.floor(Math.random() * locations.length)]
|
||||
};
|
||||
});
|
||||
|
||||
relatedList.value = [...relatedList.value, ...mockData];
|
||||
|
||||
// 模拟无更多数据
|
||||
if (relatedPage.value >= 2) {
|
||||
hasMoreRelated.value = false;
|
||||
} else {
|
||||
relatedPage.value++;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取相关推荐失败', error);
|
||||
} finally {
|
||||
relatedLoading.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 加载更多相关推荐
|
||||
const loadMoreRelated = () => {
|
||||
if (relatedLoading.value === 'loading' || !hasMoreRelated.value) return;
|
||||
getRelatedList();
|
||||
};
|
||||
|
||||
// 切换选项卡
|
||||
const switchTab = (tab) => {
|
||||
activeTab.value = tab;
|
||||
};
|
||||
|
||||
// 打开PDF预览
|
||||
const previewPdf = (file) => {
|
||||
currentFile.value = file;
|
||||
@@ -229,101 +148,13 @@ const closePdfPreview = () => {
|
||||
showPdfPreview.value = false;
|
||||
};
|
||||
|
||||
// 打开报名表单
|
||||
const openRegistrationForm = () => {
|
||||
// showRegistrationForm.value = true;
|
||||
function openRegistrationForm() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/activity/registration-form/index'
|
||||
url: '/pages/activity/registration-form/index?id=' + actId.value
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
// 关闭报名表单
|
||||
const closeRegistrationForm = () => {
|
||||
showRegistrationForm.value = false;
|
||||
};
|
||||
|
||||
// 添加参赛人员
|
||||
const addParticipant = () => {
|
||||
registration.participants.push({
|
||||
name: '',
|
||||
gender: '男',
|
||||
position: '',
|
||||
idNumber: '',
|
||||
phone: '',
|
||||
accommodation: false
|
||||
});
|
||||
};
|
||||
|
||||
// 移除参赛人员
|
||||
const removeParticipant = (index) => {
|
||||
if (registration.participants.length > 1) {
|
||||
registration.participants.splice(index, 1);
|
||||
} else {
|
||||
Toast({message: '至少需要一名参赛人员', theme: 'warning'});
|
||||
}
|
||||
};
|
||||
|
||||
// 提交报名信息
|
||||
const submitRegistration = () => {
|
||||
// 检查是否同意承诺书
|
||||
if (!registration.agreementChecked) {
|
||||
Toast({message: '请阅读并同意参赛承诺书', theme: 'warning'});
|
||||
return;
|
||||
}
|
||||
|
||||
// 这里可以添加表单验证逻辑
|
||||
|
||||
// 模拟提交成功
|
||||
Toast({message: '报名成功!', theme: 'success'});
|
||||
closeRegistrationForm();
|
||||
};
|
||||
|
||||
// 分享
|
||||
const handleShare = () => {
|
||||
Toast({message: '分享功能开发中', theme: 'warning'});
|
||||
};
|
||||
|
||||
// 切换到首页
|
||||
const navigateToHome = () => {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
};
|
||||
|
||||
// 状态标签文字
|
||||
const getStatusText = (status) => {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return '报名中';
|
||||
case 2:
|
||||
return '已结束';
|
||||
case 3:
|
||||
return '即将开始';
|
||||
default:
|
||||
return '未知状态';
|
||||
}
|
||||
};
|
||||
|
||||
// 报名或预约
|
||||
const handleSignup = () => {
|
||||
if (detailData.value.status === 2) {
|
||||
Toast({message: '活动已结束', theme: 'warning'});
|
||||
return;
|
||||
}
|
||||
|
||||
if (detailData.value.status === 1) {
|
||||
Toast({message: '报名成功', theme: 'success'});
|
||||
} else {
|
||||
Toast({message: '预约提醒成功', theme: 'success'});
|
||||
}
|
||||
};
|
||||
|
||||
// 跳转到详情页
|
||||
const navigateToDetail = (id) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/detail/index?id=${id}`
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -332,7 +163,7 @@ const navigateToDetail = (id) => {
|
||||
<template v-if="detailData">
|
||||
<!-- 顶部图片 -->
|
||||
<view class="event-header">
|
||||
<image :src="detailData.banner" mode="aspectFill" class="event-cover"/>
|
||||
<image :src="detailData.cover" mode="aspectFill" class="event-cover"/>
|
||||
</view>
|
||||
|
||||
<!-- 活动标题卡片 -->
|
||||
@@ -403,13 +234,13 @@ const navigateToDetail = (id) => {
|
||||
|
||||
<t-tabs default-value="detail">
|
||||
<t-tab-panel value="detail" label="详细信息">
|
||||
<view class="detail-text">{{ detailData.desc }}</view>
|
||||
<view class="detail-text" v-html="detailData.content"></view>
|
||||
</t-tab-panel>
|
||||
<t-tab-panel value="events" label="比赛项目">
|
||||
<view class="event-table-mobile">
|
||||
<view
|
||||
class="project-card"
|
||||
v-for="(item, index) in detailData.competitions"
|
||||
v-for="(item, index) in detailData.items"
|
||||
:key="index"
|
||||
>
|
||||
<view class="project-header">
|
||||
@@ -419,11 +250,11 @@ const navigateToDetail = (id) => {
|
||||
<view class="project-details">
|
||||
<view class="detail-item">
|
||||
<view class="detail-label">活动形式</view>
|
||||
<view class="detail-content">{{ item.format }}</view>
|
||||
<view class="detail-content">{{ item.form }}</view>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<view class="detail-label">评分规则</view>
|
||||
<view class="detail-content">{{ item.rules }}</view>
|
||||
<view class="detail-content">{{ item.rule }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -459,238 +290,6 @@ const navigateToDetail = (id) => {
|
||||
立即报名
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 报名表单 -->
|
||||
<t-popup
|
||||
v-model:visible="showRegistrationForm"
|
||||
placement="center"
|
||||
:close-on-overlay-click="true"
|
||||
:prevent-scroll-through="true"
|
||||
:show-overlay="true"
|
||||
class="registration-dialog"
|
||||
style="width: 100%"
|
||||
>
|
||||
<view class="registration-container">
|
||||
<view class="registration-header">
|
||||
<view class="registration-title">活动报名</view>
|
||||
<view class="registration-close" @click="closeRegistrationForm">
|
||||
<t-icon name="close"/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="registration-content" :scroll-y="true">
|
||||
<view class="form-block">
|
||||
<view class="form-block-title">
|
||||
<t-icon name="user-circle"/>
|
||||
单位信息
|
||||
</view>
|
||||
|
||||
<view class="form-field">
|
||||
<text class="field-label">单位名称
|
||||
<text class="required-mark">*</text>
|
||||
</text>
|
||||
<input
|
||||
type="text"
|
||||
class="field-input"
|
||||
placeholder="请输入单位名称"
|
||||
v-model="registration.organization"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-row">
|
||||
<view class="field-col">
|
||||
<view class="form-field">
|
||||
<text class="field-label">联系人
|
||||
<text class="required-mark">*</text>
|
||||
</text>
|
||||
<input
|
||||
type="text"
|
||||
class="field-input"
|
||||
placeholder="请输入姓名"
|
||||
v-model="registration.contactName"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="field-col">
|
||||
<view class="form-field">
|
||||
<text class="field-label">联系电话
|
||||
<text class="required-mark">*</text>
|
||||
</text>
|
||||
<input
|
||||
type="text"
|
||||
class="field-input"
|
||||
placeholder="请输入手机号"
|
||||
v-model="registration.contactPhone"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-block">
|
||||
<view class="form-block-title">
|
||||
<t-icon name="usergroup"/>
|
||||
参赛人员
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="participant-card"
|
||||
v-for="(participant, index) in registration.participants"
|
||||
:key="index"
|
||||
>
|
||||
<view class="participant-header">
|
||||
<view class="participant-title">
|
||||
<text>{{ index + 1 }}</text>
|
||||
参赛人员信息
|
||||
</view>
|
||||
<view
|
||||
class="remove-participant"
|
||||
v-if="registration.participants.length > 1"
|
||||
@click="removeParticipant(index)"
|
||||
>
|
||||
删除
|
||||
<t-icon name="close-circle" size="16px"/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-field">
|
||||
<text class="field-label">姓名
|
||||
<text class="required-mark">*</text>
|
||||
</text>
|
||||
<input
|
||||
type="text"
|
||||
class="field-input"
|
||||
placeholder="请输入姓名"
|
||||
v-model="participant.name"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-field-horizontal">
|
||||
<text class="field-label-horizontal">性别
|
||||
<text class="required-mark">*</text>
|
||||
</text>
|
||||
<view class="field-content">
|
||||
<view class="radio-buttons">
|
||||
<view
|
||||
class="radio-button"
|
||||
:class="{ active: participant.gender === '男' }"
|
||||
@click="participant.gender = '男'"
|
||||
>
|
||||
<t-icon name="check-circle" v-if="participant.gender === '男'"/>
|
||||
<t-icon name="circle" v-else/>
|
||||
<text>男</text>
|
||||
</view>
|
||||
<view
|
||||
class="radio-button"
|
||||
:class="{ active: participant.gender === '女' }"
|
||||
@click="participant.gender = '女'"
|
||||
>
|
||||
<t-icon name="check-circle" v-if="participant.gender === '女'"/>
|
||||
<t-icon name="circle" v-else/>
|
||||
<text>女</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-field">
|
||||
<text class="field-label">职务</text>
|
||||
<input
|
||||
type="text"
|
||||
class="field-input"
|
||||
placeholder="请输入职务"
|
||||
v-model="participant.position"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-row">
|
||||
<view class="field-col">
|
||||
<view class="form-field">
|
||||
<text class="field-label">身份证号
|
||||
<text class="required-mark">*</text>
|
||||
</text>
|
||||
<input
|
||||
type="text"
|
||||
class="field-input"
|
||||
placeholder="请输入身份证号"
|
||||
v-model="participant.idNumber"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="field-col">
|
||||
<view class="form-field">
|
||||
<text class="field-label">联系电话
|
||||
<text class="required-mark">*</text>
|
||||
</text>
|
||||
<input
|
||||
type="text"
|
||||
class="field-input"
|
||||
placeholder="请输入手机号"
|
||||
v-model="participant.phone"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-field-horizontal">
|
||||
<text class="field-label-horizontal">是否住宿</text>
|
||||
<view class="field-content">
|
||||
<view class="radio-buttons">
|
||||
<view
|
||||
class="radio-button"
|
||||
:class="{ active: participant.accommodation }"
|
||||
@click="participant.accommodation = true"
|
||||
>
|
||||
<t-icon name="check-circle" v-if="participant.accommodation"/>
|
||||
<t-icon name="circle" v-else/>
|
||||
<text>是</text>
|
||||
</view>
|
||||
<view
|
||||
class="radio-button"
|
||||
:class="{ active: !participant.accommodation }"
|
||||
@click="participant.accommodation = false"
|
||||
>
|
||||
<t-icon name="check-circle" v-if="!participant.accommodation"/>
|
||||
<t-icon name="circle" v-else/>
|
||||
<text>否</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="add-participant" @click="addParticipant">
|
||||
<t-icon name="add-circle"/>
|
||||
添加参赛人员
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<t-input label="标签文字" layout="vertical" placeholder="请输入姓名"></t-input>
|
||||
|
||||
</scroll-view>
|
||||
|
||||
<view class="registration-footer">
|
||||
<view class="agreement-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="registration.agreementChecked"
|
||||
/>
|
||||
<label>我已阅读并同意
|
||||
<text class="agreement-link">《参赛承诺书》</text>
|
||||
</label>
|
||||
</view>
|
||||
<t-button
|
||||
block
|
||||
theme="primary"
|
||||
size="large"
|
||||
shape="round"
|
||||
@click="submitRegistration"
|
||||
>
|
||||
提交报名
|
||||
</t-button>
|
||||
</view>
|
||||
</view>
|
||||
</t-popup>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
@@ -1113,268 +712,4 @@ const navigateToDetail = (id) => {
|
||||
box-shadow: 0 2px 8px rgba(231, 76, 60, 0.3);
|
||||
}
|
||||
|
||||
/* 报名表单样式 */
|
||||
.registration-dialog {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.registration-container {
|
||||
background: white;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.registration-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
background-color: #e74c3c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.registration-title {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.registration-close {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.registration-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.form-block {
|
||||
padding: 20px 16px;
|
||||
border-bottom: 10px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.form-block-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 16px;
|
||||
color: #333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.form-block-title :deep(i) {
|
||||
margin-right: 8px;
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-field:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 左右布局表单 */
|
||||
.form-field-horizontal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-field-horizontal:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.field-label-horizontal {
|
||||
width: 80px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.field-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.field-input {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ddd;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
background: transparent;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.field-input:focus {
|
||||
border-color: #e74c3c;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.field-input::placeholder {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.field-col {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.radio-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.radio-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
flex: none;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.radio-button.active {
|
||||
border-color: #e74c3c;
|
||||
background-color: rgba(231, 76, 60, 0.05);
|
||||
}
|
||||
|
||||
.radio-button :deep(i) {
|
||||
font-size: 18px;
|
||||
margin-right: 8px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.radio-button.active :deep(i) {
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
.participant-card {
|
||||
background: white;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
border-left: 3px solid #e74c3c;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.participant-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.participant-title {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.participant-title text {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: #e74c3c;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
font-size: 14px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.remove-participant {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.add-participant {
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
color: #e74c3c;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.add-participant :deep(i) {
|
||||
margin-right: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.registration-footer {
|
||||
padding: 16px;
|
||||
background-color: white;
|
||||
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.required-mark {
|
||||
color: #e74c3c;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.agreement-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.agreement-checkbox input[type="checkbox"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 8px;
|
||||
accent-color: #e74c3c;
|
||||
}
|
||||
|
||||
.agreement-checkbox label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.registration-container {
|
||||
max-width: 500px;
|
||||
max-height: 90vh;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.registration-header {
|
||||
border-radius: 12px 12px 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user