ActivityHistoryPage.vue
8.69 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
<template>
<div class="activity-history-page w-full min-h-screen bg-[#F7F8FA] relative pb-[140px]">
<!-- Header Banner -->
<div class="w-full relative h-[180px] overflow-hidden">
<img :src="historyBg" class="w-full h-full object-cover" alt="History Banner" />
<div class="absolute inset-0 flex flex-col justify-center items-center text-center px-4">
<h1 class="text-[#FFDD01] text-3xl font-bold mb-2 tracking-wider drop-shadow-md mt-3">{{ recordDate }}</h1>
<h2 class="text-white text-2xl font-bold mb-4 tracking-wider drop-shadow-md">您的活动历史</h2>
<div class="w-full max-w-md rounded-lg px-4 py-2"
style="background: linear-gradient(96deg, rgba(82,88,254,0) 0%, #5258FE 47%, rgba(92,106,241,0) 100%);">
<p class="text-white text-xs leading-tight opacity-90">
查看并确认您参与的星球活动记录,<br>
如果有缺失,点击没找到我的星球活动,进行补充
</p>
</div>
</div>
</div>
<!-- Filter Bar -->
<div class="bg-white px-4 py-3 flex justify-between items-center sticky top-0 z-20 shadow-sm">
<span class="text-[#333] font-medium text-sm">活动记录</span>
<div class="flex items-center text-[#666] text-sm">
<span>{{ activities.length }}条</span>
</div>
</div>
<!-- List -->
<div class="px-4 py-4 space-y-4">
<div v-for="item in activities" :key="item.id"
class="bg-white rounded-xl py-4 pr-4 pl-0 shadow-sm relative overflow-hidden flex">
<!-- Blue Marker (Absolute or Flex) -->
<!-- Based on image, it is sticking to the left edge but inside the card padding area potentially, or flush left -->
<!-- Looking at image, it is flush left to the card container -->
<div class="w-1 h-4 bg-[#0052D9] rounded-r-sm mt-1 shrink-0 self-start"></div>
<div class="pl-3 flex-1">
<h3 class="text-[#333] font-bold text-base leading-snug">
{{ item.title }}
</h3>
<div class="border-t border-dashed border-gray-200 my-3"></div>
<div class="flex justify-between items-center text-xs text-[#666] mb-2">
<span>单价: ¥{{ item.price.toFixed(2) }}/人</span>
<span>人数: {{ item.count }}</span>
</div>
<div class="flex justify-between items-center text-xs text-[#666] mb-4">
<span>下单时间: {{ item.date }}</span>
<span class="text-[#FF3B30] font-bold">实付金额: ¥{{ item.total.toFixed(0) }}</span>
</div>
<div class="flex justify-end">
<van-button size="small" plain color="#0052D9" class="!rounded-full !px-4 !h-[28px] !text-xs"
@click="handleGeneratePoster(item)">
生成活动海报
</van-button>
</div>
</div>
</div>
</div>
<!-- Fixed Bottom Buttons -->
<div v-if="!userInfo.has_activity_registration"
class="fixed bottom-0 left-0 right-0 bg-white/60 backdrop-blur-md p-4 pb-8 z-30 shadow-[0_-2px_10px_rgba(0,0,0,0.05)]">
<van-button block color="#0052D9" class="!rounded-lg !mb-3 !h-[44px] !text-base !font-bold"
@click="handleCollectCoins">
收集星球币
</van-button>
<van-button block plain color="#0052D9" class="!rounded-lg !h-[44px] !text-base !font-medium"
@click="showMissingPopup = true">
<template #icon>
<van-icon name="question-o" class="mr-1" />
</template>
没找到我的星球活动
</van-button>
</div>
<!-- Missing Activity Popup -->
<van-popup v-model:show="showMissingPopup" round position="bottom" :style="{ height: '60%' }" class="flex flex-col">
<div class="p-4 flex-1 flex flex-col">
<h3 class="text-center font-bold text-lg mb-6 text-[#333]">补充活动信息</h3>
<div class="flex-1 bg-[#F7F8FA] rounded-lg p-3 mb-6">
<textarea v-model="missingInfo"
class="w-full h-full bg-transparent border-none outline-none resize-none text-sm text-[#333] placeholder:text-[#999]"
placeholder="请把缺失的星球活动,补充在这里,留下活动的名称、时间、地点、参加人数等信息"></textarea>
</div>
<van-button block color="#0052D9" class="!rounded-lg !h-[44px] !text-base !font-bold"
@click="handleSubmitMissing">
提交
</van-button>
</div>
</van-popup>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useTitle } from '@vueuse/core'
import { showToast } from 'vant'
import { userInfoAPI, searchOldActivityAPI } from '@/api/recall_users'
import { oldActivityBatchActivityRegistrationAPI } from '@/api/points'
const historyBg = 'https://cdn.ipadbiz.cn/mlaj/recall/img/history_bg@2x.png'
const router = useRouter()
useTitle('活动历史')
const activities = ref([])
// State
const showMissingPopup = ref(false)
const missingInfo = ref('')
// 处理生成海报
const handleGeneratePoster = (item) => {
router.push({ path: '/recall/poster', query: { id: item.id, stu_uid: item.stu_uid, campaign_id: item.campaign_id } })
// showToast('生成海报: ' + item.title)
}
const handleCollectCoins = async () => {
// 从缓存获取用户信息
const cachedUserInfo = localStorage.getItem('cached_user_info')
if (cachedUserInfo) {
const userInfo = JSON.parse(cachedUserInfo)
// 调用积分接口
const res = await oldActivityBatchActivityRegistrationAPI({
name: userInfo.name || '',
mobile: userInfo.phone || '',
idcard: userInfo.idCard || '',
old_activity_data: campaign_info.value
})
if (res.code) {
showToast({
message: '收集星球币成功',
icon: 'success'
})
router.push({ path: '/recall/points' })
} else {
showToast({
message: '收集星球币失败',
icon: 'error'
})
}
}
}
const handleSubmitMissing = () => {
if (!missingInfo.value.trim()) {
showToast('请输入活动信息')
return
}
// TODO: Submit to API
showToast({
message: '感谢您为我们找回偏轨的星球活动',
icon: 'success'
})
showMissingPopup.value = false
missingInfo.value = ''
}
const userInfo = ref({});
const campaign_info = ref([]);
// 记录日期
const recordDate = ref('')
onMounted(async () => {
// 从缓存获取用户信息
const cachedUserInfo = localStorage.getItem('cached_user_info')
if (cachedUserInfo) {
const userInfo = JSON.parse(cachedUserInfo)
if (userInfo.name && userInfo.phone && userInfo.idCard) {
// 通过用户信息获取活动历史信息
const activityRes = await searchOldActivityAPI({
name: userInfo.name,
mobile: userInfo.phone,
idcard: userInfo.idCard
})
if (activityRes.code) {
// 获取历史列表数据
const campaign_info = activityRes.data?.campaign_info || []
if (campaign_info.length) {
campaign_info.value = campaign_info;
activities.value = campaign_info.map(item => ({
id: item.campaign_id || 0,
stu_uid: item.stu_uid || '',
title: item.campaign_name || '',
price: item.fee_stu || 0,
count: item.stu_cnt || 0,
date: item.create_time?.substring(0, 10) || '',
total: item.fee_stu * item.stu_cnt || 0
}))
// 遍历日期把列表date字段从小到大排序, 获取到其中日期段 比如 2020-2025
const sortedDates = activities.value.map(item => item.date).sort((a, b) => new Date(a) - new Date(b))
recordDate.value = sortedDates[0]?.substring(0, 4) + '-' + sortedDates[sortedDates.length - 1]?.substring(0, 4) || ''
}
}
}
} else {
// 如果是收集完成没有缓存字段的情况, 直接查接口
const activityRes = await searchOldActivityAPI()
if (activityRes.code) {
// 获取历史列表数据
const campaign_info = activityRes.data?.campaign_info || []
if (campaign_info.length) {
activities.value = campaign_info.map(item => ({
id: item.campaign_id || 0,
stu_uid: item.stu_uid || '',
title: item.campaign_name || '',
price: item.fee_stu || 0,
count: item.stu_cnt || 0,
date: item.create_time?.substring(0, 10) || '',
total: item.fee_stu * item.stu_cnt || 0
}))
}
}
}
// 获取用户信息
const userInfoRes = await userInfoAPI()
if (userInfoRes.code) {
userInfo.value = userInfoRes.data.user || {};
}
})
</script>
<style lang="less" scoped>
// Custom Scrollbar hide for cleaner look if needed
::-webkit-scrollbar {
width: 0px;
background: transparent;
}
</style>