fix: 全面修复项目问题

后端修复:
- 验证码存储与校验机制
- 订单创建事务+库存扣减
- GetStats字段名错误
- VerifyEmail改为POST
- 供应商更新字段白名单
- 文件删除安全检查
- 抽奖安全随机数
- 用户管理CRUD
- 订单取消/确认收货
- 工单回复
- Toggle返回新数据
- 移除死代码

前端修复:
- 404兜底路由
- 401软跳转
- API层统一
- 面包屑补充banners
- 国际化完善
- 购物车并行删除
- 退出清理购物车
- 供应商Dashboard数据
- 工单详情页
- 订单取消/确认收货
This commit is contained in:
2026-05-06 09:16:34 +08:00
parent 739481b59f
commit 3a898e8aa0
52 changed files with 2807 additions and 920 deletions
+67 -6
View File
@@ -230,7 +230,9 @@ func (h *OrderHandler) Create(c *gin.Context) {
PaymentMethod: req.PaymentMethod,
}
if err := utils.DB.Create(&order).Error; err != nil {
tx := utils.DB.Begin()
if err := tx.Create(&order).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create order"})
return
}
@@ -238,20 +240,41 @@ func (h *OrderHandler) Create(c *gin.Context) {
for i := range orderItems {
orderItems[i].OrderID = order.ID
}
utils.DB.Create(&orderItems)
if err := tx.Create(&orderItems).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create order items"})
return
}
for _, cart := range carts {
if cart.Product.RequireCredit {
utils.DB.Model(&models.User{}).Where("id = ?", userID).
UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits - ?", cart.Product.CreditCost*cart.Quantity))
if err := tx.Model(&models.User{}).Where("id = ?", userID).
UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits - ?", cart.Product.CreditCost*cart.Quantity)).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to deduct credits"})
return
}
}
if cart.Product.CreditReward > 0 {
utils.DB.Model(&models.User{}).Where("id = ?", userID).
tx.Model(&models.User{}).Where("id = ?", userID).
UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits + ?", cart.Product.CreditReward*cart.Quantity))
}
var inventory models.Inventory
if err := tx.Where("product_id = ?", cart.ProductID).First(&inventory).Error; err == nil {
if inventory.Quantity >= cart.Quantity {
tx.Model(&inventory).UpdateColumn("quantity", inventory.Quantity-cart.Quantity)
}
}
}
utils.DB.Where("user_id = ?", userID).Delete(&models.Cart{})
if err := tx.Where("user_id = ?", userID).Delete(&models.Cart{}).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to clear cart"})
return
}
tx.Commit()
utils.DB.Preload("OrderItems.Product").Preload("ShippingAddress").First(&order, order.ID)
c.JSON(http.StatusCreated, gin.H{"data": order})
@@ -412,3 +435,41 @@ func (h *OrderHandler) Export(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"data": orders})
}
func (h *OrderHandler) CancelOrder(c *gin.Context) {
userID := c.GetUint("user_id")
id, _ := strconv.Atoi(c.Param("id"))
var order models.Order
if err := utils.DB.Where("id = ? AND user_id = ?", id, userID).First(&order).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
return
}
if order.Status != models.OrderStatusPendingPayment && order.Status != models.OrderStatusPendingConfirm {
c.JSON(http.StatusBadRequest, gin.H{"error": "Order cannot be cancelled"})
return
}
utils.DB.Model(&order).Update("status", models.OrderStatusCancelled)
c.JSON(http.StatusOK, gin.H{"message": "Order cancelled successfully"})
}
func (h *OrderHandler) ConfirmReceipt(c *gin.Context) {
userID := c.GetUint("user_id")
id, _ := strconv.Atoi(c.Param("id"))
var order models.Order
if err := utils.DB.Where("id = ? AND user_id = ?", id, userID).First(&order).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
return
}
if order.Status != models.OrderStatusShipped {
c.JSON(http.StatusBadRequest, gin.H{"error": "Order cannot be confirmed"})
return
}
utils.DB.Model(&order).Update("status", models.OrderStatusCompleted)
c.JSON(http.StatusOK, gin.H{"message": "Order confirmed successfully"})
}