国外MOSE官网
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

405 lines
10 KiB

2 days ago
  1. <template>
  2. <view class="activity-detail">
  3. <!-- 轮播图 -->
  4. <view class="banner-container">
  5. <swiper class="banner-swiper" height="450rpx" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="500">
  6. <swiper-item v-for="(image, index) in bannerImages" :key="index">
  7. <image class="banner-image" :src="image" mode="aspectFill"></image>
  8. </swiper-item>
  9. </swiper>
  10. </view>
  11. <!-- 活动信息 -->
  12. <view class="activity-info">
  13. <!-- 活动标题和标签 -->
  14. <view class="title-section">
  15. <view class="activity-badge">
  16. <text class="badge-text">{{ activityData.duration }}</text>
  17. </view>
  18. <text class="activity-title">{{ activityData.title }}</text>
  19. </view>
  20. <!-- 活动详细信息 -->
  21. <view class="info-section">
  22. <view class="info-item">
  23. <uv-icon name="calendar" size="16" color="#666"></uv-icon>
  24. <text class="info-label">活动时间</text>
  25. <text class="info-value">{{ activityData.time }}</text>
  26. </view>
  27. <view class="info-item">
  28. <uv-icon name="clock" size="16" color="#666"></uv-icon>
  29. <text class="info-label">报名时间</text>
  30. <text class="info-value">{{ activityData.registrationTime }}</text>
  31. </view>
  32. <view class="info-item">
  33. <uv-icon name="account-fill" size="16" color="#666"></uv-icon>
  34. <text class="info-label">联系人</text>
  35. <text class="info-value">{{ activityData.contact }}</text>
  36. </view>
  37. <view class="info-item">
  38. <uv-icon name="phone" size="16" color="#666"></uv-icon>
  39. <text class="info-label">取消规则</text>
  40. <text class="info-value">{{ activityData.cancelRule }}</text>
  41. </view>
  42. <view class="info-item">
  43. <uv-icon name="map-fill" size="16" color="#666"></uv-icon>
  44. <text class="info-label">活动地点</text>
  45. <text class="info-value">{{ activityData.location }}</text>
  46. </view>
  47. </view>
  48. <!-- 活动详情 -->
  49. <view class="detail-section">
  50. <view class="section-title">
  51. <text class="title-text">活动详情</text>
  52. </view>
  53. <view class="detail-content">
  54. <text class="detail-text" v-for="(item, index) in activityData.details" :key="index">
  55. {{ index + 1 }}. {{ item }}
  56. </text>
  57. </view>
  58. </view>
  59. <!-- 活动图集 -->
  60. <view class="gallery-section">
  61. <view class="section-title">
  62. <text class="title-text">活动图集</text>
  63. </view>
  64. <view class="gallery-grid">
  65. <image
  66. v-for="(image, index) in activityData.gallery"
  67. :key="index"
  68. class="gallery-image"
  69. :src="image"
  70. mode="aspectFill"
  71. @click="previewImage(image, activityData.gallery)"
  72. ></image>
  73. </view>
  74. </view>
  75. </view>
  76. <!-- 固定底部操作栏 -->
  77. <view class="bottom-action">
  78. <view class="action-left">
  79. <view class="action-item" @click="shareActivity">
  80. <uv-icon name="share" size="24" color="#000"></uv-icon>
  81. <text class="action-text">分享</text>
  82. </view>
  83. <view class="action-item" @click="collectActivity">
  84. <uv-icon name="heart-fill" size="24" :color="isCollected ? '#ff4757' : '#999'"></uv-icon>
  85. <text class="action-text">收藏</text>
  86. </view>
  87. <view class="action-item">
  88. <text class="participants-count">
  89. <text :style="{'color': activityData.registeredCount >= activityData.maxCount ? '#999' : '#1488DB'}">{{ activityData.registeredCount }}</text>
  90. /{{ activityData.maxCount }}</text>
  91. <text class="action-text">已报名</text>
  92. </view>
  93. </view>
  94. <view class="action-right">
  95. <!-- 未签到状态 -->
  96. <uv-button
  97. v-if="status === 'unsigned'"
  98. type="primary"
  99. size="normal"
  100. text="扫码签到"
  101. shape="circle"
  102. @click="scanQRCode"
  103. ></uv-button>
  104. <!-- 已签到状态 -->
  105. <uv-button
  106. v-else-if="status === 'signed'"
  107. type="success"
  108. size="normal"
  109. text="已签到"
  110. shape="circle"
  111. :disabled="true"
  112. ></uv-button>
  113. <!-- 系统取消状态 -->
  114. <uv-button
  115. v-else-if="status === 'cancelled'"
  116. type="error"
  117. size="normal"
  118. text="系统取消"
  119. shape="circle"
  120. :disabled="true"
  121. ></uv-button>
  122. </view>
  123. </view>
  124. </view>
  125. </template>
  126. <script>
  127. export default {
  128. data() {
  129. return {
  130. isCollected: false,
  131. status: 'unsigned', // unsigned: 未签到, signed: 已签到, cancelled: 系统取消
  132. bannerImages: [
  133. '/static/bannerImage.png',
  134. '/static/bannerImage.png',
  135. '/static/bannerImage.png'
  136. ],
  137. activityData: {
  138. title: '关爱自闭症儿童活动',
  139. duration: '30积分',
  140. time: '2025-06-12 14:30',
  141. registrationTime: '2025-06-01 14:30——2025-09-01 14:30',
  142. contact: '柳老师 (13256484512)',
  143. cancelRule: '报名随时可取消',
  144. location: '长沙市雨花区时代阳光大夏国际大厅2145',
  145. registeredCount: 9,
  146. maxCount: 30,
  147. details: [
  148. '身体健康,热爱志愿服务工作,富有责任感和奉献精神',
  149. '遵纪守法,思想上进,作风正派,服从安排',
  150. '年龄在60岁以下,具备广告宣传理能力'
  151. ],
  152. gallery: [
  153. '/static/bannerImage.png',
  154. '/static/bannerImage.png',
  155. '/static/bannerImage.png',
  156. '/static/bannerImage.png'
  157. ]
  158. }
  159. }
  160. },
  161. onLoad(options) {
  162. if (options.id) {
  163. this.loadActivityDetail(options.id)
  164. }
  165. if (options.status) {
  166. this.status = options.status
  167. }
  168. },
  169. methods: {
  170. loadActivityDetail(id) {
  171. // 根据ID加载活动详情
  172. console.log('加载活动详情:', id)
  173. },
  174. previewImage(current, urls) {
  175. uni.previewImage({
  176. current: current,
  177. urls: urls
  178. })
  179. },
  180. shareActivity() {
  181. uni.showToast({
  182. title: '分享功能',
  183. icon: 'none'
  184. })
  185. },
  186. collectActivity() {
  187. this.isCollected = !this.isCollected
  188. uni.showToast({
  189. title: this.isCollected ? '收藏成功' : '取消收藏',
  190. icon: 'none'
  191. })
  192. },
  193. scanQRCode() {
  194. // 扫码签到功能
  195. uni.scanCode({
  196. success: (res) => {
  197. console.log('扫码结果:', res)
  198. // 这里可以调用签到API
  199. this.status = 'signed'
  200. uni.showToast({
  201. title: '签到成功',
  202. icon: 'success'
  203. })
  204. },
  205. fail: (err) => {
  206. console.log('扫码失败:', err)
  207. uni.showToast({
  208. title: '扫码失败',
  209. icon: 'none'
  210. })
  211. }
  212. })
  213. }
  214. }
  215. }
  216. </script>
  217. <style lang="scss" scoped>
  218. .activity-detail {
  219. min-height: 100vh;
  220. background: #f8f8f8;
  221. padding-bottom: 120rpx;
  222. .banner-container {
  223. width: 100%;
  224. height: 450rpx;
  225. .banner-swiper {
  226. width: 100%;
  227. height: 100%;
  228. .banner-image {
  229. width: 100%;
  230. height: 100%;
  231. }
  232. }
  233. }
  234. .activity-info {
  235. background: #ffffff;
  236. margin: 20rpx;
  237. border-radius: 16rpx;
  238. padding: 30rpx;
  239. .title-section {
  240. display: flex;
  241. align-items: center;
  242. margin-bottom: 30rpx;
  243. .activity-badge {
  244. background: #218CDD;
  245. border-radius: 8rpx;
  246. padding: 4rpx 10rpx;
  247. margin-right: 16rpx;
  248. .badge-text {
  249. color: #ffffff;
  250. font-size: 24rpx;
  251. font-weight: 500;
  252. }
  253. }
  254. .activity-title {
  255. font-size: 36rpx;
  256. font-weight: bold;
  257. color: #333333;
  258. flex: 1;
  259. }
  260. }
  261. .info-section {
  262. background: #F3F7F8;
  263. margin-bottom: 40rpx;
  264. border: 2rpx dashed #F3F7F8;
  265. .info-item {
  266. display: flex;
  267. align-items: center;
  268. margin-bottom: 20rpx;
  269. &:last-child {
  270. margin-bottom: 0;
  271. }
  272. .info-label {
  273. font-size: 28rpx;
  274. color: #999999;
  275. margin-left: 12rpx;
  276. margin-right: 8rpx;
  277. }
  278. .info-value {
  279. font-size: 28rpx;
  280. color: #999999;
  281. flex: 1;
  282. }
  283. }
  284. }
  285. .detail-section {
  286. margin-bottom: 40rpx;
  287. .section-title {
  288. margin-bottom: 20rpx;
  289. .title-text {
  290. font-size: 32rpx;
  291. font-weight: bold;
  292. color: #333333;
  293. }
  294. }
  295. .detail-content {
  296. .detail-text {
  297. display: block;
  298. font-size: 28rpx;
  299. color: #666666;
  300. line-height: 1.6;
  301. margin-bottom: 16rpx;
  302. &:last-child {
  303. margin-bottom: 0;
  304. }
  305. }
  306. }
  307. }
  308. .gallery-section {
  309. .section-title {
  310. margin-bottom: 20rpx;
  311. .title-text {
  312. font-size: 32rpx;
  313. font-weight: bold;
  314. color: #333333;
  315. }
  316. }
  317. .gallery-grid {
  318. display: grid;
  319. grid-template-columns: repeat(2, 1fr);
  320. gap: 16rpx;
  321. .gallery-image {
  322. width: 100%;
  323. height: 200rpx;
  324. border-radius: 12rpx;
  325. }
  326. }
  327. }
  328. }
  329. .bottom-action {
  330. position: fixed;
  331. bottom: 0;
  332. left: 0;
  333. right: 0;
  334. background: #ffffff;
  335. padding: 20rpx 30rpx;
  336. border-top: 1rpx solid #eeeeee;
  337. display: flex;
  338. align-items: center;
  339. justify-content: space-between;
  340. z-index: 100;
  341. .action-left {
  342. display: flex;
  343. align-items: center;
  344. gap: 100rpx;
  345. .action-item {
  346. display: flex;
  347. flex-direction: column;
  348. align-items: center;
  349. gap: 8rpx;
  350. .action-text {
  351. font-size: 22rpx;
  352. color: #000;
  353. }
  354. .participants-count {
  355. font-size: 24rpx;
  356. color: #333333;
  357. }
  358. }
  359. }
  360. .action-right {
  361. flex-shrink: 0;
  362. }
  363. }
  364. }
  365. </style>