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:
@@ -0,0 +1,98 @@
|
||||
package com.org.flashsalesystem.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "group_buying")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class GroupBuying {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "product_id", nullable = false)
|
||||
private Long productId;
|
||||
|
||||
@Column(name = "group_price", nullable = false, precision = 10, scale = 2)
|
||||
private BigDecimal groupPrice;
|
||||
|
||||
@Column(name = "required_members", nullable = false)
|
||||
private Integer requiredMembers = 2;
|
||||
|
||||
@Column(name = "duration_minutes", nullable = false)
|
||||
private Integer durationMinutes = 1440;
|
||||
|
||||
@Column(name = "total_stock", nullable = false)
|
||||
private Integer totalStock;
|
||||
|
||||
@Column(name = "remaining_stock", nullable = false)
|
||||
private Integer remainingStock;
|
||||
|
||||
@Column(name = "max_per_user", nullable = false)
|
||||
private Integer maxPerUser = 1;
|
||||
|
||||
/**
|
||||
* 状态:0-草稿 1-未开始 2-进行中 3-已结束
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private Integer status = 0;
|
||||
|
||||
@Column(name = "start_time", nullable = false)
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Column(name = "end_time", nullable = false)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Column(name = "created_at", nullable = false, updatable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "product_id", insertable = false, updatable = false)
|
||||
private Product product;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
createdAt = LocalDateTime.now();
|
||||
updatedAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
protected void onUpdate() {
|
||||
updatedAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return now.isAfter(startTime) && now.isBefore(endTime) && status == 2;
|
||||
}
|
||||
|
||||
public enum GroupBuyingStatus {
|
||||
DRAFT(0, "草稿"),
|
||||
PENDING(1, "未开始"),
|
||||
ACTIVE(2, "进行中"),
|
||||
ENDED(3, "已结束");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
GroupBuyingStatus(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCode() { return code; }
|
||||
public String getDescription() { return description; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.org.flashsalesystem.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "group_buying_group")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class GroupBuyingGroup {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "group_no", nullable = false, unique = true, length = 64)
|
||||
private String groupNo;
|
||||
|
||||
@Column(name = "group_buying_id", nullable = false)
|
||||
private Long groupBuyingId;
|
||||
|
||||
@Column(name = "leader_user_id", nullable = false)
|
||||
private Long leaderUserId;
|
||||
|
||||
@Column(name = "required_members", nullable = false)
|
||||
private Integer requiredMembers;
|
||||
|
||||
@Column(name = "current_members", nullable = false)
|
||||
private Integer currentMembers = 1;
|
||||
|
||||
/**
|
||||
* 状态:1-拼团中 2-已成团 3-已失败(超时)
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private Integer status = 1;
|
||||
|
||||
@Column(name = "expire_time", nullable = false)
|
||||
private LocalDateTime expireTime;
|
||||
|
||||
@Column(name = "created_at", nullable = false, updatable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Column(name = "completed_at")
|
||||
private LocalDateTime completedAt;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "group_buying_id", insertable = false, updatable = false)
|
||||
private GroupBuying groupBuying;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "leader_user_id", insertable = false, updatable = false)
|
||||
private User leader;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
createdAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public enum GroupStatus {
|
||||
FORMING(1, "拼团中"),
|
||||
SUCCESS(2, "已成团"),
|
||||
FAILED(3, "已失败");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
GroupStatus(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCode() { return code; }
|
||||
public String getDescription() { return description; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.org.flashsalesystem.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "group_buying_member", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "uk_group_user", columnNames = {"group_id", "user_id"})
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class GroupBuyingMember {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "group_id", nullable = false)
|
||||
private Long groupId;
|
||||
|
||||
@Column(name = "user_id", nullable = false)
|
||||
private Long userId;
|
||||
|
||||
@Column(name = "order_id")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 状态:1-已加入 2-已成团 3-已退出
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private Integer status = 1;
|
||||
|
||||
@Column(name = "joined_at", nullable = false, updatable = false)
|
||||
private LocalDateTime joinedAt;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "group_id", insertable = false, updatable = false)
|
||||
private GroupBuyingGroup group;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "user_id", insertable = false, updatable = false)
|
||||
private User user;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
joinedAt = LocalDateTime.now();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.org.flashsalesystem.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "notifications", indexes = {
|
||||
@Index(name = "idx_notification_user_read", columnList = "user_id, is_read"),
|
||||
@Index(name = "idx_notification_user_created", columnList = "user_id, created_at")
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Notification {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "user_id", nullable = false)
|
||||
private Long userId;
|
||||
|
||||
@Column(nullable = false, length = 32)
|
||||
private String type;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "TEXT")
|
||||
private String message;
|
||||
|
||||
@Column(length = 255)
|
||||
private String link;
|
||||
|
||||
@Column(name = "is_read", nullable = false)
|
||||
private Boolean read = false;
|
||||
|
||||
@Column(name = "created_at", nullable = false, updatable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
createdAt = LocalDateTime.now();
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,12 @@ public class Order {
|
||||
@Column(name = "product_id", nullable = false)
|
||||
private Long productId;
|
||||
|
||||
@Column(name = "flash_sale_id")
|
||||
private Long flashSaleId;
|
||||
|
||||
@Column(name = "group_buying_group_id")
|
||||
private Long groupBuyingGroupId;
|
||||
|
||||
@Min(value = 1, message = "商品数量必须大于0")
|
||||
@Column(nullable = false)
|
||||
private Integer quantity;
|
||||
@@ -145,7 +151,8 @@ public class Order {
|
||||
*/
|
||||
public enum OrderType {
|
||||
NORMAL(1, "普通订单"),
|
||||
FLASH_SALE(2, "秒杀订单");
|
||||
FLASH_SALE(2, "秒杀订单"),
|
||||
GROUP_BUYING(3, "拼团订单");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
Reference in New Issue
Block a user