国外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.

399 lines
9.7 KiB

2 days ago
  1. <template>
  2. <view class="activity-page">
  3. <!-- 搜索栏和一级Tab合并容器 -->
  4. <view class="search-section">
  5. <view class="search-bar">
  6. <uv-icon name="search" size="18" color="#999"></uv-icon>
  7. <input type="text" placeholder="搜索活动名称" class="search-input" v-model="searchKeyword" />
  8. </view>
  9. <!-- 一级Tab当前活动/往期活动 移到搜索容器内 -->
  10. <view class="primary-tabs">
  11. <view
  12. class="primary-tab-item"
  13. :class="{ active: primaryActiveTab === 'current' }"
  14. @click="switchPrimaryTab('current')"
  15. >
  16. 当前活动
  17. </view>
  18. <view
  19. class="primary-tab-item"
  20. :class="{ active: primaryActiveTab === 'past' }"
  21. @click="switchPrimaryTab('past')"
  22. >
  23. 往期活动
  24. </view>
  25. </view>
  26. </view>
  27. <!-- 二级Tab使用uv-tabs组件 -->
  28. <view class="secondary-tabs">
  29. <uv-tabs
  30. :list="secondaryTabs"
  31. :current="secondaryActiveIndex"
  32. @change="switchSecondaryTab"
  33. lineColor="#007AFF"
  34. activeColor="#007AFF"
  35. inactiveColor="#666"
  36. :lineWidth="30"
  37. :lineHeight="3"
  38. itemStyle="padding: 10px 20px;"
  39. ></uv-tabs>
  40. </view>
  41. <!-- 活动列表 -->
  42. <view class="activity-list">
  43. <view
  44. class="activity-item"
  45. v-for="(item, index) in filteredActivities"
  46. :key="index"
  47. @click="goToActivityDetail(item)"
  48. >
  49. <!-- 活动图片 -->
  50. <view class="activity-image">
  51. <image :src="item.image" mode="aspectFill" class="image"></image>
  52. </view>
  53. <!-- 活动信息 -->
  54. <view class="activity-info">
  55. <view class="title-row">
  56. <!-- 活动标签 -->
  57. <view class="activity-tag" :style="{ backgroundColor: item.tagColor }">
  58. {{ item.tag }}
  59. </view>
  60. <view class="activity-title">{{ item.title }}</view>
  61. </view>
  62. <view class="activity-location">
  63. <uv-icon name="map-fill" size="14" color="#999"></uv-icon>
  64. <text class="location-text">{{ item.location }}</text>
  65. </view>
  66. <view class="activity-time">
  67. <uv-icon name="calendar" size="14" color="#999"></uv-icon>
  68. <text class="time-text">{{ item.time }}</text>
  69. </view>
  70. <view class="activity-participants">
  71. <uv-icon name="account-fill" size="14" color="#999"></uv-icon>
  72. <text class="participants-text">报名人数{{ item.participants }}/{{ item.maxParticipants }}</text>
  73. </view>
  74. </view>
  75. <!-- 报名按钮 -->
  76. <view class="activity-action">
  77. <uv-button type="primary" size="mini" shape="circle" :text="item.isFullOrExpired ? '已结束' : '报名中'" :disabled="item.isFullOrExpired" @click.stop="signUpActivity(item)"></uv-button>
  78. </view>
  79. </view>
  80. </view>
  81. <!-- 空状态 -->
  82. <view class="empty-state" v-if="filteredActivities.length === 0">
  83. <uv-empty mode="data" text="暂无活动数据"></uv-empty>
  84. </view>
  85. </view>
  86. </template>
  87. <script>
  88. export default {
  89. data() {
  90. return {
  91. searchKeyword: '',
  92. primaryActiveTab: 'current', // current: 当前活动, past: 往期活动
  93. secondaryActiveIndex: 0,
  94. secondaryTabs: [
  95. { name: '全部' },
  96. { name: '品牌项目' },
  97. { name: '公益活动' },
  98. { name: '培训活动' }
  99. ],
  100. // 模拟活动数据
  101. activities: [
  102. {
  103. id: 1,
  104. title: '关爱自闭症儿童活动',
  105. location: '长沙市雨花区时代阳光大道国际人才2145',
  106. time: '2025/08/1-2025/09/01',
  107. participants: 12,
  108. maxParticipants: 30,
  109. image: '/static/bannerImage.png',
  110. tag: '30分',
  111. tagColor: '#007AFF',
  112. category: 'charity', // all, brand, charity, training
  113. status: 'current', // current, past
  114. isFullOrExpired: false
  115. },
  116. {
  117. id: 2,
  118. title: '社区环保志愿服务',
  119. location: '长沙市岳麓区梅溪湖国际新城',
  120. time: '2025/07/15-2025/07/20',
  121. participants: 25,
  122. maxParticipants: 40,
  123. image: '/static/bannerImage.png',
  124. tag: '20分',
  125. tagColor: '#52C41A',
  126. category: 'charity',
  127. status: 'current',
  128. isFullOrExpired: false
  129. },
  130. {
  131. id: 3,
  132. title: '青少年编程培训',
  133. location: '长沙市开福区万达广场',
  134. time: '2025/06/01-2025/06/30',
  135. participants: 30,
  136. maxParticipants: 30,
  137. image: '/static/bannerImage.png',
  138. tag: '50分',
  139. tagColor: '#FF6B35',
  140. category: 'training',
  141. status: 'past',
  142. isFullOrExpired: true
  143. },
  144. {
  145. id: 4,
  146. title: '品牌推广活动',
  147. location: '长沙市天心区IFS国金中心',
  148. time: '2025/05/10-2025/05/15',
  149. participants: 18,
  150. maxParticipants: 25,
  151. image: '/static/bannerImage.png',
  152. tag: '40分',
  153. tagColor: '#722ED1',
  154. category: 'brand',
  155. status: 'past',
  156. isFullOrExpired: true
  157. }
  158. ]
  159. }
  160. },
  161. computed: {
  162. filteredActivities() {
  163. let filtered = this.activities;
  164. // 根据一级tab筛选
  165. filtered = filtered.filter(item => item.status === this.primaryActiveTab);
  166. // 根据二级tab筛选
  167. const categoryMap = {
  168. 0: 'all',
  169. 1: 'brand',
  170. 2: 'charity',
  171. 3: 'training'
  172. };
  173. const selectedCategory = categoryMap[this.secondaryActiveIndex];
  174. if (selectedCategory !== 'all') {
  175. filtered = filtered.filter(item => item.category === selectedCategory);
  176. }
  177. // 根据搜索关键词筛选
  178. if (this.searchKeyword.trim()) {
  179. filtered = filtered.filter(item =>
  180. item.title.toLowerCase().includes(this.searchKeyword.toLowerCase())
  181. );
  182. }
  183. return filtered;
  184. }
  185. },
  186. methods: {
  187. // 切换一级tab
  188. switchPrimaryTab(tab) {
  189. this.primaryActiveTab = tab;
  190. },
  191. // 切换二级tab
  192. switchSecondaryTab(index) {
  193. this.secondaryActiveIndex = index;
  194. },
  195. // 跳转到活动详情
  196. goToActivityDetail(activity) {
  197. uni.navigateTo({
  198. url: `/subPages/index/activityDetail?id=${activity.id}`
  199. });
  200. },
  201. // 报名活动
  202. signUpActivity(item) {
  203. if (item.isFullOrExpired) {
  204. uni.showToast({
  205. title: '活动已结束',
  206. icon: 'none'
  207. });
  208. return;
  209. }
  210. uni.navigateTo({
  211. url: `/subPages/index/activityDetail?id=${item.id}`
  212. });
  213. }
  214. },
  215. onLoad() {
  216. // 页面加载时的初始化逻辑
  217. console.log('活动页面加载完成');
  218. }
  219. }
  220. </script>
  221. <style lang="scss" scoped>
  222. .activity-page {
  223. background-color: #f5f5f5;
  224. min-height: 100vh;
  225. }
  226. // 搜索栏样式 - 修改为包含一级Tab
  227. .search-section {
  228. height: 350rpx;
  229. background: linear-gradient(180deg,#1488db, #98b5f1);
  230. padding-top: 180rpx; /* 使用padding-top避免margin塌陷 */
  231. box-sizing: border-box; /* 确保padding包含在高度内 */
  232. }
  233. .search-bar {
  234. background-color: white;
  235. border-radius: 50rpx;
  236. padding: 20rpx 30rpx;
  237. display: flex;
  238. align-items: center;
  239. gap: 20rpx;
  240. width: 85%;
  241. margin: 0 auto ; /* 移除margin-top,只保留左右居中和下边距 */
  242. }
  243. .search-input {
  244. flex: 1;
  245. font-size: 28rpx;
  246. color: #333;
  247. &::placeholder {
  248. color: #999;
  249. }
  250. }
  251. // 一级Tab样式 - 调整为在蓝色背景内
  252. .primary-tabs {
  253. display: flex;
  254. padding: 0 20rpx;
  255. margin-bottom: 20rpx;
  256. }
  257. .primary-tab-item {
  258. flex: 1;
  259. text-align: center;
  260. padding: 20rpx 0;
  261. font-size: 32rpx;
  262. color: #000000; /* 白色半透明 */
  263. position: relative;
  264. &.active {
  265. color: white; /* 激活状态为纯白色 */
  266. font-weight: 600;
  267. &::after {
  268. content: '';
  269. position: absolute;
  270. bottom: 0;
  271. left: 50%;
  272. transform: translateX(-50%);
  273. width: 100rpx;
  274. height: 6rpx;
  275. background-color: white; /* 下划线改为白色 */
  276. border-radius: 3rpx;
  277. }
  278. }
  279. }
  280. // 二级Tab样式 - 保持不变
  281. .secondary-tabs {
  282. background-color: white;
  283. border-bottom: 1px solid #f0f0f0;
  284. }
  285. // 活动列表样式
  286. .activity-list {
  287. padding: 20rpx;
  288. }
  289. .activity-item {
  290. background-color: white;
  291. border-radius: 12rpx;
  292. margin-bottom: 30rpx;
  293. padding: 20rpx;
  294. display: flex;
  295. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
  296. }
  297. .activity-image {
  298. width: 180rpx;
  299. height: 180rpx;
  300. border-radius: 8rpx;
  301. overflow: hidden;
  302. flex-shrink: 0;
  303. margin-right: 20rpx;
  304. }
  305. .image {
  306. width: 100%;
  307. height: 100%;
  308. }
  309. .activity-info {
  310. flex: 1;
  311. display: flex;
  312. flex-direction: column;
  313. justify-content: space-between;
  314. }
  315. .title-row {
  316. display: flex;
  317. align-items: center;
  318. margin-bottom: 10rpx;
  319. }
  320. .activity-tag {
  321. width: 31px;
  322. height: 20px;
  323. background: #218cdd;
  324. border-radius: 3.5px;
  325. margin-right: 7rpx;
  326. display: flex;
  327. align-items: center;
  328. justify-content: center;
  329. font-size: 18rpx;
  330. color: white;
  331. font-weight: 600;
  332. }
  333. .activity-title {
  334. font-size: 28rpx;
  335. font-weight: bold;
  336. color: #333;
  337. line-height: 1.4;
  338. }
  339. .activity-location,
  340. .activity-time,
  341. .activity-participants {
  342. display: flex;
  343. align-items: center;
  344. margin-bottom: 6rpx;
  345. .location-text,
  346. .time-text,
  347. .participants-text {
  348. font-size: 24rpx;
  349. color: #666;
  350. margin-left: 6rpx;
  351. }
  352. }
  353. .activity-action {
  354. display: flex;
  355. align-items: flex-end;
  356. padding-bottom: 10rpx;
  357. }
  358. // 空状态样式
  359. .empty-state {
  360. padding: 100rpx 40rpx;
  361. }
  362. </style>