|
|
@@ -1,720 +0,0 @@
|
|
|
-<template>
|
|
|
- <view class="container">
|
|
|
- <!-- 加载状态 -->
|
|
|
- <view v-if="loading" class="loading-wrap">
|
|
|
- <view class="loading-spinner"></view>
|
|
|
- <text class="loading-text">加载中...</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 错误状态 -->
|
|
|
- <view v-else-if="error" class="error-wrap">
|
|
|
- <text class="error-icon">📋</text>
|
|
|
- <text class="error-text">{{ errorMsg }}</text>
|
|
|
- <button class="retry-btn" @click="loadDetail(activityId)">重新加载</button>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 活动内容 -->
|
|
|
- <scroll-view v-else-if="activity.id" scroll-y class="content">
|
|
|
- <!-- 封面图 -->
|
|
|
- <image
|
|
|
- v-if="activity.coverImage"
|
|
|
- class="cover"
|
|
|
- :src="activity.coverImage"
|
|
|
- mode="widthFix"
|
|
|
- />
|
|
|
- <image v-else class="cover placeholder-cover" src="/static/default-activity.png" mode="aspectFill" />
|
|
|
-
|
|
|
- <view class="info-section">
|
|
|
- <text class="activity-title">{{ activity.title }}</text>
|
|
|
-
|
|
|
- <!-- 活动状态标签 -->
|
|
|
- <view class="status-row">
|
|
|
- <text class="status-tag" :class="'status-' + (activity.status || 'upcoming')">{{ statusText(activity.status) }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 活动元信息 -->
|
|
|
- <view class="meta-list">
|
|
|
- <view class="meta-item" v-if="activity.startTime">
|
|
|
- <text class="meta-icon">🕐</text>
|
|
|
- <text class="meta-text">{{ formatDate(activity.startTime) }}{{ activity.endTime ? ' ~ ' + formatDate(activity.endTime) : '' }}</text>
|
|
|
- </view>
|
|
|
- <view class="meta-item" v-if="activity.endTime && activity.requireRegistration === 1">
|
|
|
- <text class="meta-icon">⏰</text>
|
|
|
- <text class="meta-text">报名截止: {{ formatDate(activity.endTime) }}</text>
|
|
|
- </view>
|
|
|
- <view class="meta-item" v-if="activity.location">
|
|
|
- <text class="meta-icon">📍</text>
|
|
|
- <text class="meta-text">{{ activity.location }}</text>
|
|
|
- </view>
|
|
|
- <view class="meta-item" v-if="activity.maxParticipants">
|
|
|
- <text class="meta-icon">👥</text>
|
|
|
- <text class="meta-text">{{ activity.currentParticipants || 0 }} / {{ activity.maxParticipants }} 人</text>
|
|
|
- </view>
|
|
|
- <view class="meta-item">
|
|
|
- <text class="meta-icon">💰</text>
|
|
|
- <view class="meta-text" v-if="activity.memberPrice && activity.memberPrice > 0 && activity.memberPrice < activity.price">
|
|
|
- <text>会员价 ¥{{ activity.memberPrice }} 普通价 ¥{{ activity.price }}</text>
|
|
|
- </view>
|
|
|
- <text class="meta-text" v-else>{{ activity.priceLabel || (activity.price > 0 ? '¥' + activity.price : '免费') }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 活动简介 -->
|
|
|
- <view class="desc-section" v-if="activity.description">
|
|
|
- <text class="section-title">活动介绍</text>
|
|
|
- <mp-html :content="activity.description" />
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 付费不退费说明 -->
|
|
|
- <view class="refund-notice" v-if="hasPrice">
|
|
|
- <text class="refund-notice-icon">⚠️</text>
|
|
|
- <text class="refund-notice-text">本活动为付费活动,报名成功后不支持退费</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 底部操作栏 -->
|
|
|
- <view class="bottom-bar">
|
|
|
- <view class="price-info">
|
|
|
- <text class="bottom-type">活动</text>
|
|
|
- <text class="bottom-vendor" v-if="activity.vendorName">{{ activity.vendorName }}</text>
|
|
|
- </view>
|
|
|
- <view class="action-btns">
|
|
|
- <view class="poster-btn" @click="generatePoster">
|
|
|
- <text class="poster-btn-icon">🖼</text>
|
|
|
- <text class="poster-btn-text">海报</text>
|
|
|
- </view>
|
|
|
- <!-- 未报名 → 显示报名按钮 -->
|
|
|
- <button
|
|
|
- v-if="!registrationStatus && activity.requireRegistration !== 0"
|
|
|
- class="btn-register"
|
|
|
- :class="{ 'btn-register-loading': registrationLoading || paying }"
|
|
|
- :disabled="registrationLoading || paying"
|
|
|
- @click="onRegister"
|
|
|
- >
|
|
|
- <text v-if="registrationLoading">报名中...</text>
|
|
|
- <text v-else-if="paying">支付中...</text>
|
|
|
- <text v-else-if="hasPrice">¥{{ activity.price }} 立即报名</text>
|
|
|
- <text v-else>立即报名</text>
|
|
|
- </button>
|
|
|
-
|
|
|
- <!-- 已报名(pending 待审核) -->
|
|
|
- <button
|
|
|
- v-if="registrationStatus === 'pending'"
|
|
|
- class="btn-register-done"
|
|
|
- disabled
|
|
|
- >
|
|
|
- <text>审核中</text>
|
|
|
- </button>
|
|
|
-
|
|
|
- <!-- 已报名(approved)→ 显示"已报名" + "签到" -->
|
|
|
- <template v-if="registrationStatus === 'approved'">
|
|
|
- <button
|
|
|
- class="btn-registered"
|
|
|
- :disabled="registrationLoading"
|
|
|
- @click="onCancelRegistration"
|
|
|
- >
|
|
|
- <text>已报名</text>
|
|
|
- </button>
|
|
|
- <button
|
|
|
- class="btn-checkin"
|
|
|
- :class="{ 'btn-checkin-done': checkinDone, 'btn-checkin-loading': checkinLoading }"
|
|
|
- :disabled="checkinLoading || checkinDone"
|
|
|
- @click="onCheckin"
|
|
|
- >
|
|
|
- <text v-if="checkinLoading">签到中...</text>
|
|
|
- <text v-else-if="checkinDone && activity.requireCheckinReview === 1">已签到待审核</text>
|
|
|
- <text v-else-if="checkinDone">已签到 ✓</text>
|
|
|
- <text v-else>签到</text>
|
|
|
- </button>
|
|
|
- <text v-if="activity.requireCheckinReview === 1 && !checkinDone" class="checkin-review-hint">签到需要管理员审核</text>
|
|
|
- </template>
|
|
|
-
|
|
|
- <!-- 已签到(无报名流程的活动) -->
|
|
|
- <button
|
|
|
- v-if="registrationStatus === 'approved' && checkinDone"
|
|
|
- class="btn-checkin btn-checkin-done"
|
|
|
- disabled
|
|
|
- >
|
|
|
- <text>已签到 ✓</text>
|
|
|
- </button>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </scroll-view>
|
|
|
-
|
|
|
- <!-- 空状态 -->
|
|
|
- <view v-else class="empty-wrap">
|
|
|
- <text class="empty-text">活动不存在或已下架</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <ContentSharePoster
|
|
|
- :show="showPoster"
|
|
|
- :title="activity.title"
|
|
|
- :coverImage="activity.coverImage"
|
|
|
- :qrCodeBase64="posterQrCode"
|
|
|
- typeLabel="活动推荐"
|
|
|
- @close="showPoster = false"
|
|
|
- />
|
|
|
- </view>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import { getActivityDetail, activityCheckin, registerActivity, getMyActivityRegistrations, cancelActivityRegistration, getShareQrCode } from '@/utils/api.js'
|
|
|
-import ContentSharePoster from '@/components/ContentSharePoster.vue'
|
|
|
-import MpHtml from '@/components/mp-html/mp-html.vue'
|
|
|
-
|
|
|
-var WEEKDAYS = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
|
|
-
|
|
|
-export default {
|
|
|
- components: { ContentSharePoster, MpHtml },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- activityId: null,
|
|
|
- activity: {},
|
|
|
- loading: false,
|
|
|
- error: false,
|
|
|
- errorMsg: '',
|
|
|
- checkinLoading: false,
|
|
|
- checkinDone: false,
|
|
|
- checkinPoints: 0,
|
|
|
- showPoster: false,
|
|
|
- posterQrCode: '',
|
|
|
- // 报名相关
|
|
|
- registrationStatus: '', // '' | 'pending' | 'approved'
|
|
|
- registrationLoading: false,
|
|
|
- registrationId: null,
|
|
|
- paying: false
|
|
|
- }
|
|
|
- },
|
|
|
- computed: {
|
|
|
- hasPrice: function() {
|
|
|
- return this.activity && this.activity.price > 0
|
|
|
- }
|
|
|
- },
|
|
|
- onLoad: function(options) {
|
|
|
- if (options && options.id) {
|
|
|
- this.activityId = options.id
|
|
|
- this.loadDetail(options.id)
|
|
|
- } else {
|
|
|
- this.error = true
|
|
|
- this.errorMsg = '缺少活动ID'
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否已经签到(从路由参数获取)
|
|
|
- if (options && options.checkinDone === '1') {
|
|
|
- this.checkinDone = true
|
|
|
- }
|
|
|
- },
|
|
|
- methods: {
|
|
|
- async generatePoster() {
|
|
|
- if (!this.activity.id) return
|
|
|
- uni.showLoading({ title: '生成海报中...' })
|
|
|
- try {
|
|
|
- var page = 'pages/discover/activity-detail/activity-detail'
|
|
|
- var scene = 'id=' + this.activity.id
|
|
|
- var res = await getShareQrCode(page, scene)
|
|
|
- if (res && res.data) {
|
|
|
- this.posterQrCode = res.data.qrCodeBase64 || ''
|
|
|
- this.showPoster = true
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- uni.showToast({ title: '生成失败', icon: 'none' })
|
|
|
- } finally {
|
|
|
- uni.hideLoading()
|
|
|
- }
|
|
|
- },
|
|
|
- // ===== 工具方法 =====
|
|
|
- formatDate: function(dateStr) {
|
|
|
- if (!dateStr) return ''
|
|
|
- var d = new Date(dateStr.replace(/-/g, '/'))
|
|
|
- if (isNaN(d.getTime())) return dateStr
|
|
|
- var year = d.getFullYear()
|
|
|
- var month = d.getMonth() + 1
|
|
|
- var day = d.getDate()
|
|
|
- var hour = d.getHours()
|
|
|
- var minute = d.getMinutes()
|
|
|
- var ampm = hour < 12 ? '上午' : '下午'
|
|
|
- var h12 = hour % 12
|
|
|
- if (h12 === 0) h12 = 12
|
|
|
- var minStr = minute < 10 ? '0' + minute : minute
|
|
|
- return year + '年' + month + '月' + day + '日 ' + ampm + h12 + ':' + minStr
|
|
|
- },
|
|
|
-
|
|
|
- // ===== 数据加载 =====
|
|
|
- loadDetail: function(id) {
|
|
|
- var self = this
|
|
|
- self.loading = true
|
|
|
- self.error = false
|
|
|
- getActivityDetail(id).then(function(res) {
|
|
|
- self.loading = false
|
|
|
- if (res && res.code === 200 && res.data) {
|
|
|
- self.activity = res.data
|
|
|
- // 加载详情后检查报名状态
|
|
|
- self.loadRegistrationStatus(id)
|
|
|
- } else {
|
|
|
- self.error = true
|
|
|
- self.errorMsg = (res && res.message) || '加载失败'
|
|
|
- }
|
|
|
- }).catch(function(err) {
|
|
|
- self.loading = false
|
|
|
- self.error = true
|
|
|
- self.errorMsg = '网络异常,请稍后重试'
|
|
|
- })
|
|
|
- },
|
|
|
- statusText: function(status) {
|
|
|
- var map = { draft: '草稿', published: '进行中', ended: '已结束' }
|
|
|
- return map[status] || '未知'
|
|
|
- },
|
|
|
-
|
|
|
- // ===== 报名相关 =====
|
|
|
- loadRegistrationStatus: function(activityId) {
|
|
|
- var self = this
|
|
|
- var childId = uni.getStorageSync('currentChildId')
|
|
|
- if (!childId) return
|
|
|
-
|
|
|
- getMyActivityRegistrations({ id: activityId, childId: childId, page: 1, size: 10 }).then(function(res) {
|
|
|
- var records, i, reg
|
|
|
- if (res && res.code === 200 && res.data) {
|
|
|
- records = res.data.records || []
|
|
|
- for (i = 0; i < records.length; i++) {
|
|
|
- reg = records[i]
|
|
|
- if (String(reg.activityId) === String(activityId)) {
|
|
|
- self.registrationStatus = reg.status || 'pending'
|
|
|
- self.registrationId = reg.id
|
|
|
- if (reg.checkinTime) {
|
|
|
- self.checkinDone = true
|
|
|
- }
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }).catch(function(err) {
|
|
|
- // 静默失败,不阻塞页面
|
|
|
- })
|
|
|
- },
|
|
|
- onRegister: function() {
|
|
|
- var self = this
|
|
|
- if (self.registrationLoading || self.paying) return
|
|
|
-
|
|
|
- var childId = uni.getStorageSync('currentChildId')
|
|
|
- if (!childId) {
|
|
|
- uni.showToast({ title: '请选择孩子身份', icon: 'none' })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 付费活动 → 先确认支付
|
|
|
- if (self.hasPrice) {
|
|
|
- uni.showModal({
|
|
|
- title: '确认报名',
|
|
|
- content: '该活动需支付 ¥' + self.activity.price + ',报名成功后不支持退费。是否继续?',
|
|
|
- confirmText: '确认支付',
|
|
|
- cancelText: '再想想',
|
|
|
- success: function(confirmRes) {
|
|
|
- if (confirmRes.confirm) {
|
|
|
- self.doRegister(childId)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- // 免费活动 → 直接报名
|
|
|
- uni.showModal({
|
|
|
- title: '确认报名',
|
|
|
- content: '确认报名该活动?',
|
|
|
- confirmText: '立即报名',
|
|
|
- cancelText: '再想想',
|
|
|
- success: function(confirmRes) {
|
|
|
- if (confirmRes.confirm) {
|
|
|
- self.doRegister(childId)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- },
|
|
|
- doRegister: function(childId) {
|
|
|
- var self = this
|
|
|
- self.registrationLoading = true
|
|
|
-
|
|
|
- // 付费活动模拟支付等待
|
|
|
- if (self.hasPrice) {
|
|
|
- self.paying = true
|
|
|
- }
|
|
|
-
|
|
|
- registerActivity({ id: self.activity.id, childId: childId }).then(function(res) {
|
|
|
- var msg
|
|
|
- self.registrationLoading = false
|
|
|
- self.paying = false
|
|
|
- if (res && res.code === 200) {
|
|
|
- self.registrationStatus = 'pending'
|
|
|
- self.registrationId = res.data && res.data.id
|
|
|
- uni.showToast({ title: '报名成功', icon: 'success' })
|
|
|
- // 重新加载详情获取最新人数
|
|
|
- self.loadDetail(self.activityId)
|
|
|
- } else {
|
|
|
- msg = (res && res.message) || '报名失败'
|
|
|
- uni.showToast({ title: msg, icon: 'none' })
|
|
|
- }
|
|
|
- }).catch(function(err) {
|
|
|
- self.registrationLoading = false
|
|
|
- self.paying = false
|
|
|
- uni.showToast({ title: '网络异常', icon: 'none' })
|
|
|
- })
|
|
|
- },
|
|
|
- onCancelRegistration: function() {
|
|
|
- var self = this
|
|
|
- if (self.registrationLoading) return
|
|
|
-
|
|
|
- uni.showModal({
|
|
|
- title: '取消报名',
|
|
|
- content: '确定取消报名?',
|
|
|
- confirmText: '确认取消',
|
|
|
- confirmColor: '#EF4444',
|
|
|
- success: function(confirmRes) {
|
|
|
- if (confirmRes.confirm) {
|
|
|
- self.doCancelRegistration()
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- doCancelRegistration: function() {
|
|
|
- var self = this
|
|
|
- self.registrationLoading = true
|
|
|
- cancelActivityRegistration({ id: self.activity.id, childId: uni.getStorageSync('currentChildId') }).then(function(res) {
|
|
|
- var msg
|
|
|
- self.registrationLoading = false
|
|
|
- if (res && res.code === 200) {
|
|
|
- self.registrationStatus = ''
|
|
|
- self.registrationId = null
|
|
|
- uni.showToast({ title: '已取消报名', icon: 'success' })
|
|
|
- // 重新加载详情
|
|
|
- self.loadDetail(self.activityId)
|
|
|
- } else {
|
|
|
- msg = (res && res.message) || '取消失败'
|
|
|
- uni.showToast({ title: msg, icon: 'none' })
|
|
|
- }
|
|
|
- }).catch(function(err) {
|
|
|
- self.registrationLoading = false
|
|
|
- uni.showToast({ title: '网络异常', icon: 'none' })
|
|
|
- })
|
|
|
- },
|
|
|
-
|
|
|
- // ===== 签到相关 =====
|
|
|
- onCheckin: function() {
|
|
|
- var self = this
|
|
|
- if (self.checkinLoading || self.checkinDone) return
|
|
|
-
|
|
|
- // 检查活动是否已开始(只有进行中状态才能签到)
|
|
|
- if (self.activity.status !== 'published') {
|
|
|
- uni.showToast({ title: '活动尚未开始,无法签到', icon: 'none' })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- var childId = uni.getStorageSync('currentChildId')
|
|
|
- if (!childId) {
|
|
|
- uni.showToast({ title: '请选择孩子身份', icon: 'none' })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- self.checkinLoading = true
|
|
|
- activityCheckin({ id: self.activity.id, childId: childId }).then(function(res) {
|
|
|
- var msg
|
|
|
- self.checkinLoading = false
|
|
|
- if (res && res.code === 200 && res.data) {
|
|
|
- if (res.data.alreadyCompleted) {
|
|
|
- self.checkinDone = true
|
|
|
- uni.showToast({ title: '已签到', icon: 'success' })
|
|
|
- } else if (res.data.pointsEarned && res.data.pointsEarned > 0) {
|
|
|
- self.checkinDone = true
|
|
|
- self.checkinPoints = res.data.pointsEarned
|
|
|
- uni.showToast({ title: '签到成功 +' + res.data.pointsEarned + '积分', icon: 'success' })
|
|
|
- } else {
|
|
|
- self.checkinDone = true
|
|
|
- uni.showToast({ title: '签到成功', icon: 'success' })
|
|
|
- }
|
|
|
- } else {
|
|
|
- msg = (res && res.message) || '签到失败'
|
|
|
- uni.showToast({ title: msg, icon: 'none' })
|
|
|
- }
|
|
|
- }).catch(function(err) {
|
|
|
- self.checkinLoading = false
|
|
|
- uni.showToast({ title: '网络异常', icon: 'none' })
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.container {
|
|
|
- min-height: 100vh;
|
|
|
- background: #FFF7ED;
|
|
|
-}
|
|
|
-
|
|
|
-/* 加载 / 错误 / 空状态 */
|
|
|
-.loading-wrap,
|
|
|
-.error-wrap,
|
|
|
-.empty-wrap {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 120rpx 40rpx;
|
|
|
-}
|
|
|
-.loading-spinner {
|
|
|
- width: 60rpx;
|
|
|
- height: 60rpx;
|
|
|
- border: 4rpx solid #FDE68A;
|
|
|
- border-top-color: #F97316;
|
|
|
- border-radius: 50%;
|
|
|
- animation: spin 0.8s linear infinite;
|
|
|
- margin-bottom: 20rpx;
|
|
|
-}
|
|
|
-@keyframes spin {
|
|
|
- to { transform: rotate(360deg); }
|
|
|
-}
|
|
|
-.loading-text,
|
|
|
-.error-text,
|
|
|
-.empty-text {
|
|
|
- font-size: 28rpx;
|
|
|
- color: #999;
|
|
|
- margin-bottom: 20rpx;
|
|
|
-}
|
|
|
-.error-icon {
|
|
|
- font-size: 60rpx;
|
|
|
- margin-bottom: 16rpx;
|
|
|
-}
|
|
|
-.retry-btn {
|
|
|
- background: #F97316;
|
|
|
- color: #fff;
|
|
|
- border: none;
|
|
|
- border-radius: 40rpx;
|
|
|
- padding: 12rpx 40rpx;
|
|
|
- font-size: 26rpx;
|
|
|
- line-height: 1.5;
|
|
|
-}
|
|
|
-
|
|
|
-/* 内容区 */
|
|
|
-.content {
|
|
|
- height: 100vh;
|
|
|
- padding-bottom: 120rpx;
|
|
|
-}
|
|
|
-.cover {
|
|
|
- width: 100%;
|
|
|
- display: block;
|
|
|
-}
|
|
|
-.placeholder-cover {
|
|
|
- height: 400rpx;
|
|
|
- background: #f0f0f0;
|
|
|
-}
|
|
|
-
|
|
|
-/* 信息区 */
|
|
|
-.info-section {
|
|
|
- padding: 30rpx;
|
|
|
-}
|
|
|
-.activity-title {
|
|
|
- font-size: 36rpx;
|
|
|
- font-weight: bold;
|
|
|
- color: #1f2937;
|
|
|
- line-height: 1.4;
|
|
|
-}
|
|
|
-.status-row {
|
|
|
- margin-top: 16rpx;
|
|
|
-}
|
|
|
-.status-tag {
|
|
|
- display: inline-block;
|
|
|
- font-size: 22rpx;
|
|
|
- padding: 4rpx 16rpx;
|
|
|
- border-radius: 8rpx;
|
|
|
-}
|
|
|
-.status-draft { background: #F5F5F5; color: #999; }
|
|
|
-.status-published { background: #F0FDF4; color: #22C55E; }
|
|
|
-.status-ended { background: #F5F5F5; color: #999; }
|
|
|
-.status-upcoming { background: #FFF7ED; color: #F97316; }
|
|
|
-
|
|
|
-/* 元信息列表 */
|
|
|
-.meta-list {
|
|
|
- margin-top: 24rpx;
|
|
|
- background: #fff;
|
|
|
- border-radius: 16rpx;
|
|
|
- padding: 24rpx;
|
|
|
-}
|
|
|
-.meta-item {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 16rpx;
|
|
|
-}
|
|
|
-.meta-item:last-child {
|
|
|
- margin-bottom: 0;
|
|
|
-}
|
|
|
-.meta-icon {
|
|
|
- font-size: 28rpx;
|
|
|
- margin-right: 12rpx;
|
|
|
- width: 32rpx;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-.meta-text {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #4b5563;
|
|
|
- flex: 1;
|
|
|
- line-height: 1.4;
|
|
|
-}
|
|
|
-
|
|
|
-/* 活动介绍 */
|
|
|
-.desc-section {
|
|
|
- margin-top: 30rpx;
|
|
|
- background: #fff;
|
|
|
- border-radius: 16rpx;
|
|
|
- padding: 24rpx;
|
|
|
-}
|
|
|
-.section-title {
|
|
|
- font-size: 28rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #1f2937;
|
|
|
- display: block;
|
|
|
- margin-bottom: 12rpx;
|
|
|
-}
|
|
|
-.desc-text {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #4b5563;
|
|
|
- line-height: 1.6;
|
|
|
-}
|
|
|
-
|
|
|
-/* 付费不退费说明 */
|
|
|
-.refund-notice {
|
|
|
- margin-top: 20rpx;
|
|
|
- background: #FEF2F2;
|
|
|
- border: 2rpx solid #FECACA;
|
|
|
- border-radius: 12rpx;
|
|
|
- padding: 16rpx 20rpx;
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-.refund-notice-icon {
|
|
|
- font-size: 24rpx;
|
|
|
- margin-right: 10rpx;
|
|
|
- flex-shrink: 0;
|
|
|
-}
|
|
|
-.refund-notice-text {
|
|
|
- font-size: 24rpx;
|
|
|
- color: #DC2626;
|
|
|
- line-height: 1.4;
|
|
|
-}
|
|
|
-
|
|
|
-/* 底部操作栏 */
|
|
|
-.bottom-bar {
|
|
|
- position: fixed;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- bottom: 0;
|
|
|
- background: #fff;
|
|
|
- padding: 20rpx 30rpx;
|
|
|
- padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- box-shadow: 0 -2rpx 12rpx rgba(0,0,0,0.06);
|
|
|
-}
|
|
|
-.price-info {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
-}
|
|
|
-.bottom-type {
|
|
|
- font-size: 22rpx;
|
|
|
- color: #999;
|
|
|
-}
|
|
|
-.bottom-vendor {
|
|
|
- font-size: 22rpx;
|
|
|
- color: #999;
|
|
|
- margin-top: 4rpx;
|
|
|
-}
|
|
|
-.action-btns {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- gap: 16rpx;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-.poster-btn {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 8rpx 16rpx;
|
|
|
-}
|
|
|
-.poster-btn-icon { font-size: 36rpx; }
|
|
|
-.poster-btn-text { font-size: 20rpx; color: #64748B; }
|
|
|
-
|
|
|
-/* 报名按钮 */
|
|
|
-.btn-register {
|
|
|
- background: linear-gradient(135deg, #F97316, #FB923C);
|
|
|
- color: #fff;
|
|
|
- border: none;
|
|
|
- border-radius: 40rpx;
|
|
|
- padding: 16rpx 48rpx;
|
|
|
- font-size: 28rpx;
|
|
|
- font-weight: 600;
|
|
|
- line-height: 1.5;
|
|
|
- min-width: 160rpx;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-.btn-register:active {
|
|
|
- opacity: 0.85;
|
|
|
-}
|
|
|
-.btn-register-loading {
|
|
|
- opacity: 0.7;
|
|
|
-}
|
|
|
-
|
|
|
-/* 已报名(待审核) */
|
|
|
-.btn-register-done {
|
|
|
- background: #9CA3AF;
|
|
|
- color: #fff;
|
|
|
- border: none;
|
|
|
- border-radius: 40rpx;
|
|
|
- padding: 16rpx 48rpx;
|
|
|
- font-size: 28rpx;
|
|
|
- font-weight: 600;
|
|
|
- line-height: 1.5;
|
|
|
- min-width: 160rpx;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-
|
|
|
-/* 已报名(可取消) */
|
|
|
-.btn-registered {
|
|
|
- background: #F3F4F6;
|
|
|
- color: #4B5563;
|
|
|
- border: 2rpx solid #D1D5DB;
|
|
|
- border-radius: 40rpx;
|
|
|
- padding: 14rpx 36rpx;
|
|
|
- font-size: 26rpx;
|
|
|
- font-weight: 500;
|
|
|
- line-height: 1.5;
|
|
|
- min-width: 120rpx;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-.btn-registered:active {
|
|
|
- opacity: 0.7;
|
|
|
-}
|
|
|
-
|
|
|
-/* 签到按钮 */
|
|
|
-.btn-checkin {
|
|
|
- background: linear-gradient(135deg, #F97316, #FB923C);
|
|
|
- color: #fff;
|
|
|
- border: none;
|
|
|
- border-radius: 40rpx;
|
|
|
- padding: 16rpx 48rpx;
|
|
|
- font-size: 28rpx;
|
|
|
- font-weight: 600;
|
|
|
- line-height: 1.5;
|
|
|
- min-width: 160rpx;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-.btn-checkin:active {
|
|
|
- opacity: 0.85;
|
|
|
-}
|
|
|
-.btn-checkin-done {
|
|
|
- background: #22C55E;
|
|
|
-}
|
|
|
-.btn-checkin-loading {
|
|
|
- opacity: 0.7;
|
|
|
-}
|
|
|
-</style>
|