清除数据

This commit is contained in:
2026-05-06 23:30:54 +08:00
parent 17a5734d67
commit d16fc36264
149 changed files with 6691 additions and 5575 deletions

View File

@@ -0,0 +1,286 @@
<template>
<div class="flashsale-page">
<div class="container mx-auto px-4 py-8">
<!-- 页面标题 -->
<div class="mb-8">
<h1 class="text-3xl font-bold mb-2 flex items-center">
<el-icon class="page-icon mr-2">
<Lightning/>
</el-icon>
限时活动
</h1>
<p class="text-gray-600">限时抢购先到先得</p>
</div>
<!-- 筛选栏 -->
<div class="bg-white rounded-lg shadow-sm p-4 mb-6">
<div class="flex flex-wrap gap-4 items-center">
<!-- 状态筛选 -->
<el-radio-group v-model="filters.status" @change="loadFlashSales">
<el-radio-button label="">全部</el-radio-button>
<el-radio-button label="UPCOMING">即将开始</el-radio-button>
<el-radio-button label="ACTIVE">进行中</el-radio-button>
<el-radio-button label="ENDED">已结束</el-radio-button>
</el-radio-group>
<!-- 排序 -->
<el-select
v-model="filters.sort"
placeholder="排序方式"
style="width: 150px"
@change="loadFlashSales"
>
<el-option label="开始时间" value="startTime"/>
<el-option label="结束时间" value="endTime"/>
<el-option label="价格从低到高" value="flashPrice"/>
<el-option label="折扣力度" value="discount"/>
</el-select>
<!-- 搜索 -->
<el-input
v-model="filters.keyword"
clearable
placeholder="搜索商品名称"
style="width: 200px"
@keyup.enter="loadFlashSales"
>
<template #suffix>
<el-icon class="cursor-pointer" @click="loadFlashSales">
<Search/>
</el-icon>
</template>
</el-input>
<!-- 刷新按钮 -->
<el-button @click="handleRefresh">
<el-icon class="mr-1">
<Refresh/>
</el-icon>
刷新
</el-button>
</div>
</div>
<!-- 统计信息 -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div class="stat-card tone-1">
<div class="stat-value">{{ statistics.upcoming }}</div>
<div class="stat-label">即将开始</div>
<el-icon :size="30" class="stat-icon">
<Clock/>
</el-icon>
</div>
<div class="stat-card tone-2">
<div class="stat-value">{{ statistics.active }}</div>
<div class="stat-label">正在进行</div>
<el-icon :size="30" class="stat-icon">
<Lightning/>
</el-icon>
</div>
<div class="stat-card tone-3">
<div class="stat-value">{{ statistics.participated }}</div>
<div class="stat-label">我的参与</div>
<el-icon :size="30" class="stat-icon">
<Trophy/>
</el-icon>
</div>
<div class="stat-card tone-4">
<div class="stat-value">{{ statistics.success }}</div>
<div class="stat-label">抢购成功</div>
<el-icon :size="30" class="stat-icon">
<SuccessFilled/>
</el-icon>
</div>
</div>
<!-- 限时活动列表 -->
<div v-if="loading" class="text-center py-12">
<el-icon :size="40" class="animate-spin">
<Loading/>
</el-icon>
<p class="mt-2 text-gray-500">加载中...</p>
</div>
<div v-else-if="flashSales.length === 0" class="text-center py-12">
<el-empty description="暂无限时活动"/>
</div>
<div v-else>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
<FlashSaleCard
v-for="item in flashSales"
:key="item.id"
:data="item"
@participate="handleParticipate"
@refresh="loadFlashSales"
/>
</div>
<!-- 分页 -->
<div class="mt-8 flex justify-center">
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.size"
:page-sizes="[12, 24, 36, 48]"
:total="pagination.total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="loadFlashSales"
@current-change="loadFlashSales"
/>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {ref, reactive, onMounted} from 'vue'
import {useRouter} from 'vue-router'
import {ElMessage, ElMessageBox} from 'element-plus'
import FlashSaleCard from '@/components/business/FlashSaleCard.vue'
import {flashsaleApi} from '@/api/modules/flashsale'
import {useUserStore} from '@/stores/user'
import type {FlashSale} from '@/types/api'
const router = useRouter()
const userStore = useUserStore()
// 数据状态
const loading = ref(false)
const flashSales = ref<FlashSale[]>([])
// 筛选条件
const filters = reactive({
status: '',
sort: 'startTime',
keyword: ''
})
// 分页
const pagination = reactive({
page: 1,
size: 12,
total: 0
})
// 统计信息
const statistics = reactive({
upcoming: 0,
active: 0,
participated: 0,
success: 0
})
// 加载限时活动
const loadFlashSales = async () => {
loading.value = true
try {
const res = await flashsaleApi.getList({
...filters,
page: pagination.page - 1,
size: pagination.size
})
if (res.success) {
flashSales.value = res.data.content
pagination.total = res.data.totalElements
}
} catch (error) {
console.error('加载限时活动失败:', error)
} finally {
loading.value = false
}
}
// 加载统计信息(从后端获取真实数据)
const loadStatistics = async () => {
try {
const res = await flashsaleApi.getStatistics()
if (res.success) {
statistics.upcoming = res.data.upcoming ?? 0
statistics.active = res.data.active ?? 0
statistics.participated = res.data.participated ?? 0
statistics.success = res.data.success ?? 0
}
} catch (error) {
console.error('加载统计信息失败:', error)
}
}
// 参与限时
const handleParticipate = async (flashSaleId: number) => {
if (!userStore.isLoggedIn) {
ElMessage.warning('请先登录')
router.push('/login')
return
}
// 先检查资格
try {
const res = await flashsaleApi.checkEligibility(flashSaleId)
if (res.success && res.data.eligible) {
// 确认对话框
await ElMessageBox.confirm(
'确定要参与这个限时活动吗?',
'提示',
{
confirmButtonText: '立即抢购',
cancelButtonText: '取消',
type: 'warning',
}
)
// 跳转到详情页参与
router.push(`/flashsale/${flashSaleId}`)
} else {
ElMessage.warning(res.data.reason || '您暂时无法参与此活动')
}
} catch (error) {
// 用户取消或错误
}
}
// 刷新
const handleRefresh = () => {
loadFlashSales()
loadStatistics()
ElMessage.success('已刷新')
}
onMounted(() => {
loadFlashSales()
loadStatistics()
})
</script>
<style lang="scss" scoped>
.flashsale-page {
min-height: calc(100vh - 60px);
background: transparent;
}
.page-icon {
color: #44443f;
}
.stat-card {
@apply relative overflow-hidden rounded-lg p-4;
background: #fffaf2;
color: #171715;
border: 1px solid #d8cebf;
box-shadow: 0 10px 24px rgba(23, 22, 20, 0.04);
.stat-value {
@apply text-2xl font-bold;
}
.stat-label {
@apply text-sm mt-1;
}
.stat-icon {
@apply absolute right-4 bottom-4;
opacity: 0.2;
}
}
</style>