feat: 删除JSP视图层,完善评价和通知系统,新增拼团模块
- 删除所有 JSP 页面(20个文件),前端完全迁移至 Vue 3 SPA - 完善评价系统:ReviewDialog 组件、用户评价历史页、评价状态检查API - 新增通知系统:Notification 实体/仓库/服务/控制器,NotificationCenter 接入真实API - 新增拼团模块:GroupBuying 全套后端和前端页面 - 修复 review check API 参数双重包装导致请求格式错误 - 修复通知 API 路径缺少 /api 前缀和响应格式处理 - MessageListenerService 集成 NotificationService 创建持久化通知 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import type {
|
||||
CartItem,
|
||||
FlashSale,
|
||||
GroupBuying,
|
||||
GroupBuyingGroup,
|
||||
Order,
|
||||
OrderAddress,
|
||||
PageResponse,
|
||||
@@ -285,3 +287,69 @@ export const normalizeAdminProduct = (product: Record<string, any>): AdminProduc
|
||||
viewCount: toNumber(product.viewCount),
|
||||
rating: toNumber(product.rating),
|
||||
})
|
||||
|
||||
export const mapGroupBuyingStatus = (status: number | string): GroupBuying['status'] => {
|
||||
const value = typeof status === 'string' ? status : toNumber(status)
|
||||
if (value === 'DRAFT' || value === 0) return 'DRAFT'
|
||||
if (value === 'UPCOMING' || value === 1) return 'UPCOMING'
|
||||
if (value === 'ACTIVE' || value === 2) return 'ACTIVE'
|
||||
if (value === 'ENDED' || value === 3) return 'ENDED'
|
||||
return 'DRAFT'
|
||||
}
|
||||
|
||||
export const mapGroupStatus = (status: number | string): GroupBuyingGroup['status'] => {
|
||||
const value = typeof status === 'string' ? status : toNumber(status)
|
||||
if (value === 'FORMING' || value === 1) return 'FORMING'
|
||||
if (value === 'SUCCESS' || value === 2) return 'SUCCESS'
|
||||
if (value === 'FAILED' || value === 3) return 'FAILED'
|
||||
return 'FORMING'
|
||||
}
|
||||
|
||||
export const normalizeGroupBuying = (gb: Record<string, any>): GroupBuying => ({
|
||||
id: toNumber(gb.id),
|
||||
productId: toNumber(gb.productId),
|
||||
productName: toString(gb.productName),
|
||||
productImageUrl: resolveImageUrl(toString(gb.productImageUrl, '')),
|
||||
productPrice: toNumber(gb.productPrice),
|
||||
groupPrice: toNumber(gb.groupPrice),
|
||||
requiredMembers: toNumber(gb.requiredMembers, 2),
|
||||
durationMinutes: toNumber(gb.durationMinutes, 1440),
|
||||
totalStock: toNumber(gb.totalStock),
|
||||
remainingStock: toNumber(gb.remainingStock),
|
||||
maxPerUser: toNumber(gb.maxPerUser, 1),
|
||||
status: mapGroupBuyingStatus(gb.status),
|
||||
statusDescription: toString(gb.statusDescription),
|
||||
startTime: toIsoLikeString(gb.startTime),
|
||||
endTime: toIsoLikeString(gb.endTime),
|
||||
createdAt: toIsoLikeString(gb.createdAt),
|
||||
updatedAt: toIsoLikeString(gb.updatedAt || gb.createdAt),
|
||||
activeGroupCount: toNumber(gb.activeGroupCount),
|
||||
discount: toNumber(gb.discount),
|
||||
})
|
||||
|
||||
export const normalizeGroupBuyingGroup = (group: Record<string, any>): GroupBuyingGroup => ({
|
||||
id: toNumber(group.id),
|
||||
groupNo: toString(group.groupNo),
|
||||
groupBuyingId: toNumber(group.groupBuyingId),
|
||||
leaderUserId: toNumber(group.leaderUserId),
|
||||
leaderUsername: toString(group.leaderUsername),
|
||||
requiredMembers: toNumber(group.requiredMembers, 2),
|
||||
currentMembers: toNumber(group.currentMembers, 1),
|
||||
status: mapGroupStatus(group.status),
|
||||
statusDescription: toString(group.statusDescription),
|
||||
expireTime: toIsoLikeString(group.expireTime),
|
||||
createdAt: toIsoLikeString(group.createdAt),
|
||||
completedAt: group.completedAt ? toIsoLikeString(group.completedAt) : undefined,
|
||||
members: Array.isArray(group.members)
|
||||
? group.members.map((m: Record<string, any>) => ({
|
||||
id: toNumber(m.id),
|
||||
userId: toNumber(m.userId),
|
||||
username: toString(m.username),
|
||||
avatar: resolveImageUrl(toString(m.avatar, '')),
|
||||
orderId: m.orderId ? toNumber(m.orderId) : undefined,
|
||||
status: toNumber(m.status),
|
||||
joinedAt: toIsoLikeString(m.joinedAt),
|
||||
}))
|
||||
: [],
|
||||
groupBuying: group.groupBuying ? normalizeGroupBuying(group.groupBuying) : undefined,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user