Files
toutoukan/controllers/article/createarticle.go
2025-09-24 01:07:21 +08:00

138 lines
4.1 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 article
import (
"net/http"
"time"
"toutoukan/init/databaseInit"
"github.com/gin-gonic/gin"
)
// OptionItem 选项子结构
type OptionItem struct {
Content string `json:"content" binding:"required,min=1,max=200"` // 选项内容
SortOrder int `json:"sort_order" binding:"required,min=0"` // 排序值
}
// CreateArticleRequest 创建文章的请求参数结构
type CreateArticleRequest struct {
PublishUserID string `json:"publish_user_id" binding:"required,min=1,max=40"`
Title string `json:"title" binding:"required,min=1,max=255"`
VoteType string `json:"vote_type" binding:"required,min=1,max=60"`
EndTime time.Time `json:"end_time" binding:"required"`
Options []OptionItem `json:"options" binding:"required,min=1,max=3"`
}
// 数据库文章记录结构体(与表结构完全对应)
type ArticleList struct {
ArticleID int64 `gorm:"column:articleId;primaryKey;autoIncrement"` // 明确主键和自增
PublishUserID string `gorm:"column:publish_user_id"`
Title string `gorm:"column:title"`
VoteType string `gorm:"column:vote_type"`
EndTime time.Time `gorm:"column:end_time"`
IsEnded bool `gorm:"column:is_ended"`
TotalVotersNum int `gorm:"column:total_voters_num"`
CreateTime time.Time `gorm:"column:create_time"`
}
// 自定义表名(如果结构体名与表名不一致)
func (ArticleList) TableName() string {
return "article_list"
}
// CreateArticle 创建文章(包含选项)
func CreateArticle(c *gin.Context) {
var req CreateArticleRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "参数解析失败",
"detail": err.Error(),
})
return
}
tx := databaseInit.UserDB.Begin()
if tx.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "开启事务失败: " + tx.Error.Error()})
return
}
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 1. 创建文章主记录
newArticle := ArticleList{
PublishUserID: req.PublishUserID,
Title: req.Title,
VoteType: req.VoteType,
EndTime: req.EndTime,
IsEnded: false,
TotalVotersNum: 0,
CreateTime: time.Now(),
}
// 插入文章并获取ID使用GORM的Create方法自动填充自增ID
if err := tx.Create(&newArticle).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建文章失败: " + err.Error()})
return
}
// 验证文章ID是否有效必须大于0
if newArticle.ArticleID <= 0 {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法获取文章ID创建失败"})
return
}
// 2. 批量创建选项确保vote_article_id正确关联
var options []map[string]interface{}
for _, opt := range req.Options {
options = append(options, map[string]interface{}{
"vote_article_id": newArticle.ArticleID, // 使用刚创建的文章ID
"option_content": opt.Content,
"option_votes_num": 0,
"sort_order": opt.SortOrder,
})
}
// 插入选项前先验证文章ID是否存在额外保险
var count int64
if err := tx.Model(&ArticleList{}).Where("articleId = ?", newArticle.ArticleID).Count(&count).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "验证文章ID失败: " + err.Error()})
return
}
if count == 0 {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "文章ID不存在外键约束失败"})
return
}
// 批量插入选项
if err := tx.Table("article_options").CreateInBatches(options, len(options)).Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建选项失败: " + err.Error()})
return
}
// 提交事务
if err := tx.Commit().Error; err != nil {
tx.Rollback()
c.JSON(http.StatusInternalServerError, gin.H{"error": "提交数据失败: " + err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "文章及选项创建成功",
"data": gin.H{
"article_id": newArticle.ArticleID,
"option_count": len(req.Options),
},
})
}