14 changed files with 1182 additions and 102 deletions
@ -0,0 +1,242 @@ |
|||
<template> |
|||
<div class="gift-records"> |
|||
<div class="flex justify-between items-center mb-4"> |
|||
<h3 class="text-lg font-bold">赠品记录</h3> |
|||
<el-button type="primary" @click="refreshRecords">刷新</el-button> |
|||
</div> |
|||
|
|||
<!-- 加载状态 --> |
|||
<div v-if="loading" class="text-center py-8"> |
|||
<el-icon class="is-loading mr-2"><Loading /></el-icon> |
|||
加载中... |
|||
</div> |
|||
|
|||
<!-- 空状态 --> |
|||
<div v-else-if="!giftRecords || giftRecords.length === 0" class="text-center py-8 text-gray-500"> |
|||
<el-icon class="text-4xl mb-2"><Box /></el-icon> |
|||
<p>暂无赠品记录</p> |
|||
</div> |
|||
|
|||
<!-- 赠品记录列表 --> |
|||
<div v-else class="gift-records-list"> |
|||
<el-card |
|||
v-for="record in giftRecords" |
|||
:key="record.id" |
|||
class="mb-4 gift-record-card" |
|||
shadow="hover" |
|||
> |
|||
<div class="flex justify-between items-start"> |
|||
<div class="flex-1"> |
|||
<div class="flex items-center mb-2"> |
|||
<h4 class="font-bold text-lg mr-3">{{ record.gift_name }}</h4> |
|||
<el-tag |
|||
:type="getStatusTagType(record.gift_status)" |
|||
size="small" |
|||
> |
|||
{{ record.gift_status_text }} |
|||
</el-tag> |
|||
</div> |
|||
|
|||
<div class="grid grid-cols-2 gap-4 text-sm text-gray-600"> |
|||
<div> |
|||
<span class="font-medium">赠品类型:</span> |
|||
<el-tag size="small" type="info">{{ record.gift_type_text }}</el-tag> |
|||
</div> |
|||
<div> |
|||
<span class="font-medium">赠送人:</span> |
|||
{{ record.giver_name }} |
|||
<span v-if="record.giver_phone" class="text-gray-500">({{ record.giver_phone }})</span> |
|||
</div> |
|||
<div> |
|||
<span class="font-medium">发放时间:</span> |
|||
{{ record.gift_time_formatted }} |
|||
</div> |
|||
<div v-if="record.use_time_formatted"> |
|||
<span class="font-medium">使用时间:</span> |
|||
{{ record.use_time_formatted }} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="text-right text-sm text-gray-500"> |
|||
创建时间:{{ record.create_time }} |
|||
</div> |
|||
</div> |
|||
</el-card> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, onMounted, defineProps } from 'vue' |
|||
import { Loading, Box } from '@element-plus/icons-vue' |
|||
import { getGiftRecordList } from '@/app/api/customer_resources' |
|||
|
|||
const props = defineProps({ |
|||
customer_resource_id: { |
|||
type: [String, Number], |
|||
required: true |
|||
} |
|||
}) |
|||
|
|||
const loading = ref(false) |
|||
const giftRecords = ref([]) |
|||
|
|||
// 获取赠品记录列表 |
|||
const fetchGiftRecords = async () => { |
|||
if (!props.customer_resource_id) return |
|||
|
|||
loading.value = true |
|||
try { |
|||
const response = await getGiftRecordList({ |
|||
resource_id: props.customer_resource_id |
|||
}) |
|||
|
|||
if (response.code === 1) { |
|||
giftRecords.value = response.data || [] |
|||
} else { |
|||
console.error('获取赠品记录失败:', response.msg) |
|||
giftRecords.value = [] |
|||
} |
|||
} catch (error) { |
|||
console.error('获取赠品记录异常:', error) |
|||
giftRecords.value = [] |
|||
} finally { |
|||
loading.value = false |
|||
} |
|||
} |
|||
|
|||
// 刷新记录 |
|||
const refreshRecords = () => { |
|||
fetchGiftRecords() |
|||
} |
|||
|
|||
// 获取状态标签类型 |
|||
const getStatusTagType = (status) => { |
|||
switch (status) { |
|||
case 0: return 'info' // 已失效 |
|||
case 1: return 'success' // 可使用 |
|||
case 2: return 'warning' // 已使用 |
|||
default: return 'info' |
|||
} |
|||
} |
|||
|
|||
// 组件挂载时获取数据 |
|||
onMounted(() => { |
|||
fetchGiftRecords() |
|||
}) |
|||
|
|||
// 监听customer_resource_id变化 |
|||
import { watch } from 'vue' |
|||
watch(() => props.customer_resource_id, (newId) => { |
|||
if (newId) { |
|||
fetchGiftRecords() |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.gift-records { |
|||
padding: 16px; |
|||
} |
|||
|
|||
.gift-record-card { |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.gift-record-card:hover { |
|||
transform: translateY(-2px); |
|||
} |
|||
|
|||
.grid { |
|||
display: grid; |
|||
} |
|||
|
|||
.grid-cols-2 { |
|||
grid-template-columns: repeat(2, minmax(0, 1fr)); |
|||
} |
|||
|
|||
.gap-4 { |
|||
gap: 1rem; |
|||
} |
|||
|
|||
.text-gray-500 { |
|||
color: #6b7280; |
|||
} |
|||
|
|||
.text-gray-600 { |
|||
color: #4b5563; |
|||
} |
|||
|
|||
.font-medium { |
|||
font-weight: 500; |
|||
} |
|||
|
|||
.font-bold { |
|||
font-weight: 700; |
|||
} |
|||
|
|||
.text-lg { |
|||
font-size: 1.125rem; |
|||
line-height: 1.75rem; |
|||
} |
|||
|
|||
.text-sm { |
|||
font-size: 0.875rem; |
|||
line-height: 1.25rem; |
|||
} |
|||
|
|||
.text-4xl { |
|||
font-size: 2.25rem; |
|||
line-height: 2.5rem; |
|||
} |
|||
|
|||
.mb-2 { |
|||
margin-bottom: 0.5rem; |
|||
} |
|||
|
|||
.mb-4 { |
|||
margin-bottom: 1rem; |
|||
} |
|||
|
|||
.mr-2 { |
|||
margin-right: 0.5rem; |
|||
} |
|||
|
|||
.mr-3 { |
|||
margin-right: 0.75rem; |
|||
} |
|||
|
|||
.py-8 { |
|||
padding-top: 2rem; |
|||
padding-bottom: 2rem; |
|||
} |
|||
|
|||
.text-center { |
|||
text-align: center; |
|||
} |
|||
|
|||
.text-right { |
|||
text-align: right; |
|||
} |
|||
|
|||
.flex { |
|||
display: flex; |
|||
} |
|||
|
|||
.flex-1 { |
|||
flex: 1 1 0%; |
|||
} |
|||
|
|||
.items-center { |
|||
align-items: center; |
|||
} |
|||
|
|||
.items-start { |
|||
align-items: flex-start; |
|||
} |
|||
|
|||
.justify-between { |
|||
justify-content: space-between; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,155 @@ |
|||
<!--赠品记录卡片组件--> |
|||
<template> |
|||
<view class="gift-record-card"> |
|||
<view class="gift-header"> |
|||
<view class="gift-name">{{ record.gift_name }}</view> |
|||
<view class="gift-status" :class="getStatusClass(record.gift_status)"> |
|||
{{ record.gift_status_text }} |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="gift-info"> |
|||
<view class="info-row"> |
|||
<text class="info-label">赠品类型:</text> |
|||
<text class="info-value">{{ record.gift_type_text }}</text> |
|||
</view> |
|||
<view class="info-row"> |
|||
<text class="info-label">获得时间:</text> |
|||
<text class="info-value">{{ formatTime(record.gift_time_formatted) }}</text> |
|||
</view> |
|||
<view class="info-row" v-if="record.giver_name"> |
|||
<text class="info-label">赠送人:</text> |
|||
<text class="info-value">{{ record.giver_name }}</text> |
|||
</view> |
|||
<view class="info-row" v-if="record.use_time_formatted"> |
|||
<text class="info-label">使用时间:</text> |
|||
<text class="info-value">{{ formatTime(record.use_time_formatted) }}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'GiftRecordCard', |
|||
props: { |
|||
record: { |
|||
type: Object, |
|||
required: true |
|||
} |
|||
}, |
|||
methods: { |
|||
formatTime(timeStr) { |
|||
if (!timeStr) return '未知时间' |
|||
|
|||
try { |
|||
// 如果有工具方法则使用,否则使用内置格式化 |
|||
if (this.$util && this.$util.formatToDateTime) { |
|||
return this.$util.formatToDateTime(timeStr, 'Y-m-d H:i') |
|||
} |
|||
|
|||
// 内置格式化方法 |
|||
if (timeStr.includes('-')) { |
|||
const date = new Date(timeStr) |
|||
const year = date.getFullYear() |
|||
const month = String(date.getMonth() + 1).padStart(2, '0') |
|||
const day = String(date.getDate()).padStart(2, '0') |
|||
const hours = String(date.getHours()).padStart(2, '0') |
|||
const minutes = String(date.getMinutes()).padStart(2, '0') |
|||
return `${year}-${month}-${day} ${hours}:${minutes}` |
|||
} |
|||
|
|||
return timeStr |
|||
} catch (error) { |
|||
console.error('时间格式化失败:', error) |
|||
return timeStr |
|||
} |
|||
}, |
|||
|
|||
getStatusClass(status) { |
|||
const statusMap = { |
|||
0: 'status-expired', // 已失效 |
|||
1: 'status-available', // 可使用 |
|||
2: 'status-used' // 已使用 |
|||
} |
|||
return statusMap[status] || 'status-unknown' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.gift-record-card { |
|||
background: #fff; |
|||
border-radius: 16rpx; |
|||
padding: 32rpx; |
|||
margin-bottom: 24rpx; |
|||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06); |
|||
} |
|||
|
|||
.gift-header { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
margin-bottom: 24rpx; |
|||
|
|||
.gift-name { |
|||
font-size: 32rpx; |
|||
font-weight: 600; |
|||
color: #333; |
|||
flex: 1; |
|||
} |
|||
|
|||
.gift-status { |
|||
padding: 8rpx 16rpx; |
|||
border-radius: 8rpx; |
|||
font-size: 24rpx; |
|||
font-weight: 500; |
|||
|
|||
&.status-available { |
|||
background: #E8F5E8; |
|||
color: #52C41A; |
|||
} |
|||
|
|||
&.status-used { |
|||
background: #F0F0F0; |
|||
color: #8C8C8C; |
|||
} |
|||
|
|||
&.status-expired { |
|||
background: #FFF2F0; |
|||
color: #FF4D4F; |
|||
} |
|||
|
|||
&.status-unknown { |
|||
background: #F6F6F6; |
|||
color: #999; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.gift-info { |
|||
.info-row { |
|||
display: flex; |
|||
align-items: center; |
|||
margin-bottom: 16rpx; |
|||
|
|||
&:last-child { |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
.info-label { |
|||
font-size: 28rpx; |
|||
color: #999; |
|||
width: 160rpx; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.info-value { |
|||
font-size: 28rpx; |
|||
color: #333; |
|||
flex: 1; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue