ActivityListTestPage.vue
4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<template>
<div class="pb-safe min-h-screen bg-gray-50">
<!-- 顶部导航栏 -->
<van-nav-bar fixed placeholder z-index="50" class="nav-bar">
<template #left>
<van-icon name="arrow-left" size="22" color="#333" />
</template>
<template #title>
<span class="text-lg font-medium text-gray-800">最新活动</span>
</template>
<template #right>
<van-icon name="ellipsis" size="22" color="#333" />
</template>
</van-nav-bar>
<!-- 筛选栏 -->
<div
class="sticky top-[46px] z-40 flex items-center justify-between bg-white px-3 py-2 shadow-sm"
>
<div class="flex items-center gap-6">
<!-- 全部 -->
<div class="relative text-[15px] font-bold text-gray-900">
全部
<div
class="absolute -bottom-2 left-1/2 h-[3px] w-4 -translate-x-1/2 rounded-full bg-gray-800"
></div>
</div>
<!-- 活动地点 -->
<div class="flex items-center gap-1 text-[14px] text-gray-600">
<span>活动地点</span>
<van-icon name="play" class="rotate-90 text-[10px] text-gray-400" />
</div>
<!-- 活动状态 -->
<div class="flex items-center gap-1 text-[14px] text-gray-600">
<span>活动状态</span>
<van-icon name="play" class="rotate-90 text-[10px] text-gray-400" />
</div>
</div>
<!-- 筛选图标 -->
<van-icon name="filter-o" size="18" color="#333" />
</div>
<!-- 活动列表 -->
<div class="space-y-3 p-3">
<div
v-for="item in activityList"
:key="item.id"
class="flex gap-3 rounded-xl bg-white p-3 shadow-sm transition-transform active:scale-[0.99]"
>
<!-- 左侧封面图 -->
<div
class="relative h-[100px] w-[100px] flex-shrink-0 overflow-hidden rounded-lg bg-gray-100"
>
<img
:src="getOptimizedImage(item.imageUrl)"
:alt="item.title"
class="h-full w-full object-cover"
/>
</div>
<!-- 右侧内容 -->
<div class="flex flex-1 flex-col justify-between py-0.5">
<!-- 标题 -->
<h3 class="line-clamp-2 text-[15px] font-bold leading-snug text-gray-900">
{{ item.fullTitle }}
</h3>
<!-- 信息区域 -->
<div class="space-y-1.5">
<!-- 地点与状态 -->
<div class="flex items-center gap-2">
<span class="text-xs text-gray-500">地点: {{ item.location }}</span>
<span
class="rounded border px-1.5 py-0.5 text-[10px]"
:class="getStatusStyle(item.status)"
>
{{ item.status }}
</span>
</div>
<!-- 时间 -->
<div class="text-xs text-gray-400">时间: {{ item.period }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { activities } from '@/utils/mockData'
/**
* 处理图片链接,如果是指定CDN域名则添加压缩参数
* @param {string} url - 图片链接
* @returns {string} - 处理后的链接
*/
const getOptimizedImage = url => {
if (!url) return ''
if (url.includes('cdn.ipadbiz.cn')) {
// 检查是否已有参数
return url.includes('?')
? `${url}&imageMogr2/thumbnail/200x/strip/quality/70`
: `${url}?imageMogr2/thumbnail/200x/strip/quality/70`
}
return url
}
// 处理活动数据,拼接标题
const activityList = computed(() =>
activities.map(item => ({
...item,
fullTitle: item.subtitle ? `${item.title} ${item.subtitle}` : item.title,
}))
)
/**
* 获取状态样式
* @param {string} status - 状态文本
* @returns {string} - Tailwind 类名
*/
const getStatusStyle = status => {
if (status === '活动中') {
return 'bg-blue-50 text-blue-500 border-blue-100'
}
if (status === '进行中' || status === '即将开始') {
return 'bg-orange-50 text-orange-500 border-orange-100'
}
return 'bg-gray-50 text-gray-500 border-gray-100'
}
</script>
<style lang="less" scoped>
// 自定义导航栏样式以匹配设计图
:deep(.van-nav-bar) {
--van-nav-bar-height: 46px;
.van-nav-bar__content {
height: 46px;
}
}
// 隐藏滚动条但保持滚动
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.hide-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>