Files
asset_assistant/backend/src/logic4country/update.go
2025-11-26 16:28:37 +08:00

233 lines
6.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package logic4country
import (
"asset_assistant/db"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.uber.org/zap"
)
// UpdateRequest 更新请求参数结构
type UpdateRequest struct {
CountryID string `json:"country_id" binding:"required"` // 国家ID必填
Name string `json:"name"` // 国家名称,可选
Code string `json:"code"` // 国家代码,可选
Flag string `json:"flag"` // 国旗信息,可选(新增字段)
}
// UpdateResponse 更新响应结构
type UpdateResponse struct {
Success bool `json:"success"` // 操作是否成功
Message string `json:"message"` // 提示信息
}
// UpdateHandler 更新逻辑
func UpdateHandler(c *gin.Context) {
startTime := time.Now()
// 获取或生成请求ID
reqID := c.Request.Header.Get("X-UpdateRequest-ID")
if reqID == "" {
reqID = uuid.New().String()
zap.L().Debug("✨ 生成新的请求ID", zap.String("req_id", reqID))
}
// 记录请求接收日志
zap.L().Info("📥 收到国家更新请求",
zap.String("req_id", reqID),
zap.String("path", c.Request.URL.Path),
zap.String("method", c.Request.Method),
)
var req UpdateRequest
// 绑定并验证请求参数主要验证country_id必填
if err := c.ShouldBindJSON(&req); err != nil {
zap.L().Warn("⚠️ 请求参数验证失败",
zap.String("req_id", reqID),
zap.Error(err),
)
c.JSON(http.StatusBadRequest, UpdateResponse{
Success: false,
Message: "请求参数错误country_id为必填项",
})
return
}
// 验证name、code和flag不能同时为空
if req.Name == "" && req.Code == "" && req.Flag == "" {
zap.L().Warn("⚠️ 请求参数验证失败",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.String("reason", "name、code和flag不能同时为空"),
)
c.JSON(http.StatusBadRequest, UpdateResponse{
Success: false,
Message: "请求参数错误name、code和flag不能同时为空",
})
return
}
zap.L().Debug("✅ 请求参数验证通过",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.String("name", req.Name),
zap.String("code", req.Code),
zap.String("flag", req.Flag), // 新增国旗参数日志
)
// 开启数据库事务
tx, err := db.DB.Begin()
if err != nil {
zap.L().Error("❌ 事务开启失败",
zap.String("req_id", reqID),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, UpdateResponse{
Success: false,
Message: "系统错误,请稍后重试",
})
return
}
// 延迟处理panic情况
defer func() {
if r := recover(); r != nil {
if err := tx.Rollback(); err != nil {
zap.L().Error("💥 panic后事务回滚失败",
zap.String("req_id", reqID),
zap.Error(err),
)
}
zap.L().Error("💥 事务处理发生panic",
zap.String("req_id", reqID),
zap.Any("recover", r),
)
c.JSON(http.StatusInternalServerError, UpdateResponse{
Success: false,
Message: "系统错误,请稍后重试",
})
}
}()
// 如果name不为空更新name表
if req.Name != "" {
_, err = tx.Exec("UPDATE country_name SET name = $1, updated_at = CURRENT_TIMESTAMP WHERE country_id = $2", req.Name, req.CountryID)
if err != nil {
tx.Rollback()
zap.L().Error("❌ country_name表更新失败",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, UpdateResponse{
Success: false,
Message: "更新名称信息失败",
})
return
}
zap.L().Debug("📝 name表更新成功",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
)
}
// 如果code不为空更新code表
if req.Code != "" {
_, err = tx.Exec("UPDATE country_code SET code = $1, updated_at = CURRENT_TIMESTAMP WHERE country_id = $2", req.Code, req.CountryID)
if err != nil {
tx.Rollback()
zap.L().Error("❌ country_code表更新失败",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, UpdateResponse{
Success: false,
Message: "更新代码信息失败",
})
return
}
zap.L().Debug("📝 code表更新成功",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
)
}
// 新增如果flag不为空更新flag表
if req.Flag != "" {
// 先检查是否存在国旗记录
var flagExists bool
err = tx.QueryRow("SELECT EXISTS(SELECT 1 FROM country_flag WHERE country_id = $1 AND deleted = FALSE)", req.CountryID).Scan(&flagExists)
if err != nil {
tx.Rollback()
zap.L().Error("❌ 检查国旗记录存在性失败",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, UpdateResponse{
Success: false,
Message: "检查国旗信息失败",
})
return
}
if flagExists {
// 存在则更新
_, err = tx.Exec("UPDATE country_flag SET flag = $1, updated_at = CURRENT_TIMESTAMP WHERE country_id = $2", req.Flag, req.CountryID)
} else {
// 不存在则插入新记录
_, err = tx.Exec("INSERT INTO country_flag (country_id, flag) VALUES ($1, $2)", req.CountryID, req.Flag)
}
if err != nil {
tx.Rollback()
zap.L().Error("❌ country_flag表更新/插入失败",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, UpdateResponse{
Success: false,
Message: "更新国旗信息失败",
})
return
}
zap.L().Debug("📝 flag表更新/插入成功",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
)
}
// 提交事务
if err := tx.Commit(); err != nil {
tx.Rollback()
zap.L().Error("❌ 事务提交失败",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, UpdateResponse{
Success: false,
Message: "数据提交失败,请稍后重试",
})
return
}
// 记录请求处理耗时
duration := time.Since(startTime)
zap.L().Info("✅ 国家更新请求处理完成",
zap.String("req_id", reqID),
zap.String("country_id", req.CountryID),
zap.Duration("duration", duration),
)
// 返回成功响应
c.JSON(http.StatusOK, UpdateResponse{
Success: true,
Message: "更新成功",
})
}