根因:publishFlashSale() 只做了缓存预热,从未调用 updateStatus() 将状态从1(未开始)更新为2(进行中),导致发布后UI无变化, 且活动无法被"进行中"查询找到。 修复内容: - publishFlashSale() 添加 updateStatus(id, 2) 和缓存更新 - 简化 getFlashSaleList 状态查询,直接按 status 字段过滤 - 新增 findByStatus 仓库方法 - 前后端全面支持 PAUSED(status=4) 状态 - 修复管理后台"恢复"按钮错误显示在"已结束"状态上 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
165 lines
5.1 KiB
TypeScript
165 lines
5.1 KiB
TypeScript
import { request } from '../request'
|
|
import type { ApiResponse, FlashSale, PageParams, PageResponse } from '@/types/api'
|
|
import { mapOrderStatus, normalizeFlashSale, normalizePage } from '@/utils/normalizers'
|
|
|
|
const flashSaleStatusToCode = (status?: string) => {
|
|
if (status === 'UPCOMING') return 1
|
|
if (status === 'ACTIVE') return 2
|
|
if (status === 'ENDED') return 3
|
|
if (status === 'PAUSED') return 4
|
|
return undefined
|
|
}
|
|
|
|
const flashSaleSortField = (sort?: string) => {
|
|
if (sort === 'flashPrice') return 'flashPrice'
|
|
if (sort === 'endTime') return 'endTime'
|
|
return 'startTime'
|
|
}
|
|
|
|
export const flashsaleApi = {
|
|
// 获取秒杀活动统计信息(即将开始/正在进行/我的参与/抢购成功)
|
|
getStatistics(): Promise<ApiResponse<{ upcoming: number; active: number; participated: number; success: number }>> {
|
|
return request.get('/api/flashsale/statistics')
|
|
},
|
|
|
|
// 获取秒杀活动列表
|
|
getList(params?: PageParams & { status?: string }): Promise<ApiResponse<PageResponse<FlashSale>>> {
|
|
return request.post<ApiResponse<Record<string, any>>>('/api/flashsale/list', {
|
|
status: flashSaleStatusToCode(params?.status),
|
|
page: params?.page ?? 0,
|
|
size: params?.size ?? 10,
|
|
sortBy: flashSaleSortField(params?.sort),
|
|
sortDirection: params?.order || 'asc',
|
|
}).then((res) => ({
|
|
...res,
|
|
data: normalizePage(res.data, normalizeFlashSale),
|
|
}))
|
|
},
|
|
|
|
// 获取正在进行的秒杀活动
|
|
getActive(limit?: number): Promise<ApiResponse<FlashSale[]>> {
|
|
return request.get<ApiResponse<any[]>>('/api/flashsale/active').then((res) => ({
|
|
...res,
|
|
data: (Array.isArray(res.data) ? res.data : [])
|
|
.map((item) => normalizeFlashSale(item))
|
|
.slice(0, limit ?? Number.MAX_SAFE_INTEGER),
|
|
}))
|
|
},
|
|
|
|
// 获取秒杀活动详情
|
|
getDetail(id: number): Promise<ApiResponse<FlashSale>> {
|
|
return request.get<ApiResponse<any>>(`/api/flashsale/${id}`).then((res) => ({
|
|
...res,
|
|
data: normalizeFlashSale(res.data),
|
|
}))
|
|
},
|
|
|
|
// 参与秒杀
|
|
participate(data: {
|
|
flashSaleId: number;
|
|
quantity: number;
|
|
timestamp?: number;
|
|
}): Promise<ApiResponse<{ orderId: number }>> {
|
|
return request.post<ApiResponse<any>>('/api/flashsale/participate', data).then((res) => ({
|
|
...res,
|
|
data: {
|
|
orderId: Number(res.data?.orderId || res.data?.id || 0),
|
|
},
|
|
}))
|
|
},
|
|
|
|
// 获取用户参与记录
|
|
getUserRecords(): Promise<ApiResponse<any[]>> {
|
|
return request.post<ApiResponse<Record<string, any>>>('/api/order/my-orders', {
|
|
orderType: 2,
|
|
page: 0,
|
|
size: 100,
|
|
sortBy: 'createdAt',
|
|
sortDirection: 'desc',
|
|
}).then((res) => {
|
|
const content = Array.isArray(res.data?.content) ? res.data.content : []
|
|
return {
|
|
...res,
|
|
data: content.map((item: Record<string, any>) => ({
|
|
id: item.id,
|
|
success: mapOrderStatus(item.status) !== 'CANCELLED',
|
|
status: item.status,
|
|
})),
|
|
}
|
|
})
|
|
},
|
|
|
|
// 检查用户是否可以参与
|
|
checkEligibility(flashSaleId: number): Promise<ApiResponse<{
|
|
eligible: boolean;
|
|
reason?: string;
|
|
remainingQuota?: number;
|
|
}>> {
|
|
return this.getDetail(flashSaleId).then((res) => {
|
|
const eligible = res.data.status === 'ACTIVE' && res.data.remainingStock > 0
|
|
return {
|
|
code: 0,
|
|
success: true,
|
|
message: '检查成功',
|
|
data: {
|
|
eligible,
|
|
reason: eligible ? '' : '活动未开始、已结束或库存不足',
|
|
remainingQuota: res.data.limitPerUser,
|
|
},
|
|
}
|
|
})
|
|
},
|
|
|
|
create(data: {
|
|
productId: number
|
|
flashPrice: number
|
|
flashStock: number
|
|
startTime: string
|
|
endTime: string
|
|
}): Promise<ApiResponse<FlashSale>> {
|
|
return request.post<ApiResponse<any>>('/api/flashsale/create', data).then((res) => ({
|
|
...res,
|
|
data: normalizeFlashSale(res.data),
|
|
}))
|
|
},
|
|
|
|
update(id: number, data: Record<string, unknown>): Promise<ApiResponse<FlashSale>> {
|
|
return request.put<ApiResponse<any>>(`/api/flashsale/${id}`, data).then((res) => ({
|
|
...res,
|
|
data: normalizeFlashSale(res.data),
|
|
}))
|
|
},
|
|
|
|
delete(id: number): Promise<ApiResponse> {
|
|
return request.delete(`/api/flashsale/${id}`)
|
|
},
|
|
|
|
publish(id: number): Promise<ApiResponse<FlashSale>> {
|
|
return request.post<ApiResponse<any>>(`/api/flashsale/${id}/publish`).then((res) => ({
|
|
...res,
|
|
data: normalizeFlashSale(res.data),
|
|
}))
|
|
},
|
|
|
|
pause(id: number): Promise<ApiResponse<FlashSale>> {
|
|
return request.post<ApiResponse<any>>(`/api/flashsale/${id}/pause`).then((res) => ({
|
|
...res,
|
|
data: normalizeFlashSale(res.data),
|
|
}))
|
|
},
|
|
|
|
resume(id: number): Promise<ApiResponse<FlashSale>> {
|
|
return request.post<ApiResponse<any>>(`/api/flashsale/${id}/resume`).then((res) => ({
|
|
...res,
|
|
data: normalizeFlashSale(res.data),
|
|
}))
|
|
},
|
|
|
|
end(id: number): Promise<ApiResponse<FlashSale>> {
|
|
return request.post<ApiResponse<any>>(`/api/flashsale/${id}/end`).then((res) => ({
|
|
...res,
|
|
data: normalizeFlashSale(res.data),
|
|
}))
|
|
},
|
|
}
|