优化页面、修复BUG

This commit is contained in:
李琦
2026-06-25 16:57:06 +08:00
parent d5ff40e4d3
commit 20fb0e3203
31 changed files with 2032 additions and 754 deletions

View File

@@ -11,6 +11,29 @@ import (
"github.com/niangaodev/art-code/utils"
)
func trySavePostHistory(c *gin.Context, postID uint) bool {
userID, _ := c.Get("userID")
modifiedBy, ok := userID.(uint)
if !ok {
log.Printf("Error saving post history for post %d: invalid userID", postID)
return false
}
saved, err := repositories.GetPostByIDAdmin(postID)
if err != nil {
log.Printf("Error saving post history for post %d: reload failed: %v", postID, err)
return false
}
if saved == nil {
log.Printf("Error saving post history for post %d: post not found after save", postID)
return false
}
if err := repositories.SavePostHistory(saved, modifiedBy); err != nil {
log.Printf("Error saving post history for post %d: %v", postID, err)
return false
}
return true
}
// 获取博客文章列表 (前台)
func GetPosts(c *gin.Context) {
// 获取查询参数
@@ -252,15 +275,9 @@ func AdminCreatePost(c *gin.Context) {
return
}
// 保存历史记录
userID, _ := c.Get("userID")
if saved, err := repositories.GetPostByIDAdmin(post.ID); err == nil && saved != nil {
if err := repositories.SavePostHistory(saved, userID.(uint)); err != nil {
log.Printf("Error saving post history: %v", err)
}
}
historySaved := trySavePostHistory(c, post.ID)
utils.SuccessWithMsg(c, "Post created successfully", gin.H{"id": post.ID})
utils.SuccessWithMsg(c, "Post created successfully", gin.H{"id": post.ID, "historySaved": historySaved})
}
// 更新文章
@@ -287,15 +304,9 @@ func AdminUpdatePost(c *gin.Context) {
return
}
// 保存历史记录
userID, _ := c.Get("userID")
if saved, err := repositories.GetPostByIDAdmin(postID); err == nil && saved != nil {
if err := repositories.SavePostHistory(saved, userID.(uint)); err != nil {
log.Printf("Error saving post history: %v", err)
}
}
historySaved := trySavePostHistory(c, postID)
utils.SuccessWithMsg(c, "Post updated successfully", nil)
utils.SuccessWithMsg(c, "Post updated successfully", gin.H{"historySaved": historySaved})
}
// 更新文章关联关系(只更新分类、专栏、标签,不更新内容)
@@ -323,12 +334,9 @@ func AdminUpdatePostRelations(c *gin.Context) {
return
}
userID, _ := c.Get("userID")
if saved, err := repositories.GetPostByIDAdmin(postID); err == nil && saved != nil {
_ = repositories.SavePostHistory(saved, userID.(uint))
}
historySaved := trySavePostHistory(c, postID)
utils.SuccessWithMsg(c, "Post relations updated successfully", nil)
utils.SuccessWithMsg(c, "Post relations updated successfully", gin.H{"historySaved": historySaved})
}
// 切换文章发布状态
@@ -353,12 +361,9 @@ func AdminTogglePostStatus(c *gin.Context) {
return
}
userID, _ := c.Get("userID")
if saved, err := repositories.GetPostByIDAdmin(postID); err == nil && saved != nil {
_ = repositories.SavePostHistory(saved, userID.(uint))
}
historySaved := trySavePostHistory(c, postID)
utils.SuccessWithMsg(c, "Post status updated successfully", nil)
utils.SuccessWithMsg(c, "Post status updated successfully", gin.H{"historySaved": historySaved})
}
// 删除文章

View File

@@ -9,6 +9,36 @@ import (
"github.com/niangaodev/art-code/utils"
)
func parseSnippetID(c *gin.Context) (uint, bool) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil || id == 0 {
utils.Error(c, 400, "Invalid snippet ID")
return 0, false
}
return uint(id), true
}
type snippetPayload struct {
Title string `json:"title"`
Code string `json:"code"`
Type string `json:"type"`
CodeTypeID uint `json:"codeTypeId"`
Description string `json:"description"`
PostIDs []uint `json:"postIds"`
}
func (p *snippetPayload) toSnippet(id uint) models.Snippet {
return models.Snippet{
ID: id,
Title: p.Title,
Code: p.Code,
Type: p.Type,
CodeTypeID: p.CodeTypeID,
Description: p.Description,
}
}
// GetSnippets 获取所有代码片段
func GetSnippets(c *gin.Context) {
snippets, err := repositories.GetSnippets()
@@ -17,7 +47,6 @@ func GetSnippets(c *gin.Context) {
return
}
// 构建响应
responses := repositories.BuildSnippetsResponse(snippets)
if responses == nil {
utils.Success(c, []interface{}{})
@@ -27,8 +56,11 @@ func GetSnippets(c *gin.Context) {
}
func GetSnippet(c *gin.Context) {
id := c.Param("id")
// 从数据库获取代码片段
id, ok := parseSnippetID(c)
if !ok {
return
}
snippet, err := repositories.GetSnippetByID(id)
if err != nil {
utils.ServerError(c, err)
@@ -40,10 +72,7 @@ func GetSnippet(c *gin.Context) {
return
}
// 构建响应
response := repositories.BuildSnippetResponse(snippet)
utils.Success(c, response)
utils.Success(c, repositories.BuildSnippetResponse(snippet))
}
// AdminGetSnippets 获取代码片段列表 (后台)
@@ -73,12 +102,13 @@ func AdminGetSnippets(c *gin.Context) {
// AdminCreateSnippet 创建代码片段
func AdminCreateSnippet(c *gin.Context) {
var snippet models.Snippet
if err := c.ShouldBindJSON(&snippet); err != nil {
var payload snippetPayload
if err := c.ShouldBindJSON(&payload); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
snippet := payload.toSnippet(0)
syncSnippetTypeFromCodeType(&snippet)
if err := repositories.CreateSnippet(&snippet); err != nil {
@@ -86,20 +116,28 @@ func AdminCreateSnippet(c *gin.Context) {
return
}
if err := repositories.ReplaceSnippetPosts(snippet.ID, payload.PostIDs); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Snippet created successfully", gin.H{"id": snippet.ID})
}
// AdminUpdateSnippet 更新代码片段
func AdminUpdateSnippet(c *gin.Context) {
idStr := c.Param("id")
id, ok := parseSnippetID(c)
if !ok {
return
}
var snippet models.Snippet
if err := c.ShouldBindJSON(&snippet); err != nil {
var payload snippetPayload
if err := c.ShouldBindJSON(&payload); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
snippet.ID = idStr
snippet := payload.toSnippet(id)
syncSnippetTypeFromCodeType(&snippet)
if err := repositories.UpdateSnippet(&snippet); err != nil {
@@ -107,6 +145,11 @@ func AdminUpdateSnippet(c *gin.Context) {
return
}
if err := repositories.ReplaceSnippetPosts(snippet.ID, payload.PostIDs); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Snippet updated successfully", nil)
}
@@ -122,9 +165,12 @@ func syncSnippetTypeFromCodeType(snippet *models.Snippet) {
// AdminDeleteSnippet 删除代码片段
func AdminDeleteSnippet(c *gin.Context) {
idStr := c.Param("id")
id, ok := parseSnippetID(c)
if !ok {
return
}
if err := repositories.DeleteSnippet(idStr); err != nil {
if err := repositories.DeleteSnippet(id); err != nil {
utils.ServerError(c, err)
return
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/niangaodev/art-code/config"
"github.com/niangaodev/art-code/handlers"
"github.com/niangaodev/art-code/middleware"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
@@ -21,6 +22,8 @@ func main() {
// 运行数据库迁移 (Convert Datetime to BigInt)
// repositories.MigrateToBigInt() // 已禁用自动迁移
repositories.MigratePostHistoryFields()
repositories.MigratePostSnippets()
// 初始化ip2region (如果文件不存在,将降级为普通IP记录)
// 函数会自动从环境变量或可执行文件目录查找 ip2region.xdb

View File

@@ -54,20 +54,21 @@ func (p *Post) BeforeUpdate(tx *gorm.DB) error {
// PostResponse 博客文章响应模型
type PostResponse struct {
ID uint `json:"id"`
Title string `json:"title"`
CategoryID uint `json:"categoryId"`
CategoryName string `json:"categoryName"`
CategorySlug string `json:"categorySlug"`
ColumnID *uint `json:"columnId,omitempty"`
ColumnName string `json:"columnName,omitempty"`
ColumnSlug string `json:"columnSlug,omitempty"`
Date string `json:"date"`
Excerpt string `json:"excerpt,omitempty"`
Content *string `json:"content,omitempty"` // 使用指针类型,当 includeContent=true 时总是设置
Tags []Tag `json:"tags,omitempty"`
IsPublished int `json:"isPublished,omitempty"`
ReadCount uint `json:"readCount,omitempty"`
ID uint `json:"id"`
Title string `json:"title"`
CategoryID uint `json:"categoryId"`
CategoryName string `json:"categoryName"`
CategorySlug string `json:"categorySlug"`
ColumnID *uint `json:"columnId,omitempty"`
ColumnName string `json:"columnName,omitempty"`
ColumnSlug string `json:"columnSlug,omitempty"`
Date string `json:"date"`
Excerpt string `json:"excerpt,omitempty"`
Content *string `json:"content,omitempty"` // 使用指针类型,当 includeContent=true 时总是设置
Tags []Tag `json:"tags,omitempty"`
IsPublished int `json:"isPublished,omitempty"`
ReadCount uint `json:"readCount,omitempty"`
Snippets []SnippetBrief `json:"snippets,omitempty"`
}
// PostHistory 文章历史记录模型

View File

@@ -0,0 +1,27 @@
package models
// PostSnippet 文章与代码片段关联
type PostSnippet struct {
PostID uint `json:"postId" gorm:"primaryKey;column:post_id"`
SnippetID uint `json:"snippetId" gorm:"primaryKey;column:snippet_id"`
SortOrder uint `json:"sortOrder" gorm:"column:sort_order;default:0"`
CreatedAt int64 `json:"createdAt" gorm:"column:created_at;default:0"`
}
func (PostSnippet) TableName() string {
return "post_snippets"
}
// PostBrief 文章简要信息
type PostBrief struct {
ID uint `json:"id"`
Title string `json:"title"`
}
// SnippetBrief 代码片段简要信息
type SnippetBrief struct {
ID uint `json:"id"`
Title string `json:"title"`
Type string `json:"type"`
CodeType *CodeTypeResponse `json:"codeType,omitempty"`
}

View File

@@ -8,7 +8,7 @@ import (
// Snippet 代码片段模型
type Snippet struct {
ID string `json:"id" gorm:"primaryKey;column:id"`
ID uint `json:"id" gorm:"primaryKey;column:id;autoIncrement"`
Title string `json:"title" gorm:"column:title"`
Code string `json:"code" gorm:"column:code;type:text"`
Type string `json:"type" gorm:"column:type"`
@@ -48,7 +48,7 @@ func (s *Snippet) BeforeUpdate(tx *gorm.DB) error {
// SnippetResponse 代码片段响应模型
type SnippetResponse struct {
ID string `json:"id"`
ID uint `json:"id"`
Title string `json:"title"`
Code string `json:"code"`
Type string `json:"type"`
@@ -56,4 +56,5 @@ type SnippetResponse struct {
CodeType *CodeTypeResponse `json:"codeType,omitempty"`
Description string `json:"description,omitempty"`
ViewCount uint `json:"viewCount,omitempty"`
Posts []PostBrief `json:"posts,omitempty"`
}

View File

@@ -31,12 +31,12 @@ CREATE TABLE `about_profiles` (
`wechat` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '',
`tech_stack` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT 'JSON string or comma separated list',
`experiences` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT 'JSON string of experience list',
`is_primary` tinyint(1) NULL DEFAULT 0,
`is_primary` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否主展示资料(0否 1是)',
`created_at` bigint NOT NULL DEFAULT 0,
`updated_at` bigint NOT NULL DEFAULT 0,
`deleted_at` bigint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '关于页个人资料表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for access_logs
@@ -310,8 +310,8 @@ CREATE TABLE `posts` (
`column_id` int UNSIGNED NULL DEFAULT NULL COMMENT '专栏ID(可选)',
`excerpt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '文章摘要',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文章内容',
`read_count` int UNSIGNED NULL DEFAULT 0 COMMENT '阅读量',
`is_published` tinyint(1) NULL DEFAULT 1 COMMENT '是否已发布(0:草稿,1:已发布)',
`read_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '阅读量',
`is_published` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否已发布(0:草稿,1:已发布)',
`deleted_at` bigint NOT NULL DEFAULT 0,
`created_at` bigint NOT NULL DEFAULT 0,
`updated_at` bigint NOT NULL DEFAULT 0,
@@ -388,7 +388,7 @@ CREATE TABLE `settings` (
-- ----------------------------
DROP TABLE IF EXISTS `code_types`;
CREATE TABLE `code_types` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '类型名称',
`category` tinyint NOT NULL DEFAULT 0 COMMENT '0前端 1后端 2其他',
`deleted_at` bigint NOT NULL DEFAULT 0,
@@ -403,13 +403,13 @@ CREATE TABLE `code_types` (
-- ----------------------------
DROP TABLE IF EXISTS `snippets`;
CREATE TABLE `snippets` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '代码片段唯一标识',
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '代码片段ID',
`title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '代码片段标题',
`code` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '代码内容',
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '代码类型(如:javascript、css、html等)',
`code_type_id` bigint UNSIGNED NULL DEFAULT NULL COMMENT '代码类型ID',
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '代码片段描述',
`view_count` int UNSIGNED NULL DEFAULT 0 COMMENT '查看次数',
`view_count` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '查看次数',
`deleted_at` bigint NOT NULL DEFAULT 0,
`created_at` bigint NOT NULL DEFAULT 0,
`updated_at` bigint NOT NULL DEFAULT 0,
@@ -549,4 +549,18 @@ CREATE TABLE `works` (
INDEX `idx_is_featured`(`is_featured` ASC) USING BTREE COMMENT '按精选状态查询索引'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '作品表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for post_snippets
-- ----------------------------
DROP TABLE IF EXISTS `post_snippets`;
CREATE TABLE `post_snippets` (
`post_id` int UNSIGNED NOT NULL COMMENT '文章ID',
`snippet_id` bigint UNSIGNED NOT NULL COMMENT '代码片段ID',
`sort_order` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序(越小越靠前)',
`created_at` bigint NOT NULL DEFAULT 0 COMMENT '创建时间(Unix秒)',
PRIMARY KEY (`post_id`, `snippet_id`) USING BTREE,
INDEX `idx_snippet_id`(`snippet_id` ASC) USING BTREE,
INDEX `idx_sort_order`(`sort_order` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文章代码片段关联表' ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -112,3 +112,47 @@ func execSQL(query string) {
log.Printf("SQL Error: %v | Query: %s", err, query)
}
}
// MigratePostHistoryFields adds column_id and tag_ids to post_history if missing.
func MigratePostHistoryFields() {
if !columnExists("post_history", "column_id") {
log.Printf("Adding post_history.column_id...")
execSQL("ALTER TABLE `post_history` ADD COLUMN `column_id` INT UNSIGNED NULL AFTER `category_id`")
}
if !columnExists("post_history", "tag_ids") {
log.Printf("Adding post_history.tag_ids...")
execSQL("ALTER TABLE `post_history` ADD COLUMN `tag_ids` JSON NULL COMMENT '标签ID快照' AFTER `column_id`")
}
}
func tableExists(tableName string) bool {
var count int64
err := config.DB.Raw(`
SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name = ?
`, tableName).Scan(&count).Error
if err != nil {
log.Printf("Error checking table %s: %v", tableName, err)
return false
}
return count > 0
}
// MigratePostSnippets creates post_snippets junction table if missing.
func MigratePostSnippets() {
if tableExists("post_snippets") {
return
}
log.Printf("Creating post_snippets table...")
execSQL(`CREATE TABLE post_snippets (
post_id INT UNSIGNED NOT NULL COMMENT '文章ID',
snippet_id BIGINT UNSIGNED NOT NULL COMMENT '代码片段ID',
sort_order INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序(越小越靠前)',
created_at BIGINT NOT NULL DEFAULT 0 COMMENT '创建时间(Unix秒)',
PRIMARY KEY (post_id, snippet_id),
INDEX idx_snippet_id (snippet_id),
INDEX idx_sort_order (sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文章代码片段关联表'`)
}

View File

@@ -391,6 +391,10 @@ func BuildPostResponse(post *models.Post, includeContent bool) *models.PostRespo
response.Content = &content
}
if snippets, err := GetSnippetsByPostID(post.ID); err == nil && len(snippets) > 0 {
response.Snippets = snippets
}
return response
}

View File

@@ -0,0 +1,132 @@
package repositories
import (
"log"
"time"
"github.com/niangaodev/art-code/config"
"github.com/niangaodev/art-code/models"
"gorm.io/gorm"
)
// ReplaceSnippetPosts 全量替换代码片段关联的文章
func ReplaceSnippetPosts(snippetID uint, postIDs []uint) error {
return config.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("snippet_id = ?", snippetID).Delete(&models.PostSnippet{}).Error; err != nil {
log.Printf("Error clearing snippet posts: %v", err)
return err
}
if len(postIDs) == 0 {
return nil
}
now := time.Now().Unix()
for i, postID := range postIDs {
row := models.PostSnippet{
PostID: postID,
SnippetID: snippetID,
SortOrder: uint(i),
CreatedAt: now,
}
if err := tx.Create(&row).Error; err != nil {
log.Printf("Error creating post_snippet: %v", err)
return err
}
}
return nil
})
}
// GetPostsBySnippetID 获取代码片段关联的文章
func GetPostsBySnippetID(snippetID uint) ([]models.PostBrief, error) {
var posts []models.Post
err := config.DB.Table("posts").
Select("posts.id, posts.title").
Joins("INNER JOIN post_snippets ps ON ps.post_id = posts.id").
Where("ps.snippet_id = ? AND posts.deleted_at = ?", snippetID, 0).
Order("ps.sort_order ASC, ps.created_at ASC").
Find(&posts).Error
if err != nil {
log.Printf("Error getting posts by snippet ID: %v", err)
return nil, err
}
result := make([]models.PostBrief, 0, len(posts))
for _, p := range posts {
result = append(result, models.PostBrief{ID: p.ID, Title: p.Title})
}
return result, nil
}
// GetSnippetsByPostID 获取文章关联的代码片段(不含完整 code)
func GetSnippetsByPostID(postID uint) ([]models.SnippetBrief, error) {
var snippets []models.Snippet
err := config.DB.Table("snippets").
Select("snippets.id, snippets.title, snippets.type, snippets.code_type_id").
Joins("INNER JOIN post_snippets ps ON ps.snippet_id = snippets.id").
Where("ps.post_id = ? AND snippets.deleted_at = ?", postID, 0).
Order("ps.sort_order ASC, ps.created_at ASC").
Find(&snippets).Error
if err != nil {
log.Printf("Error getting snippets by post ID: %v", err)
return nil, err
}
result := make([]models.SnippetBrief, 0, len(snippets))
for _, s := range snippets {
brief := models.SnippetBrief{
ID: s.ID,
Title: s.Title,
Type: s.Type,
}
if ct := GetCodeTypeForSnippet(&s); ct != nil {
r := BuildCodeTypeResponse(ct)
brief.CodeType = &r
if brief.Type == "" {
brief.Type = ct.Name
}
}
result = append(result, brief)
}
return result, nil
}
// GetPostsBySnippetIDs 批量获取多个片段关联的文章
func GetPostsBySnippetIDs(snippetIDs []uint) map[uint][]models.PostBrief {
result := make(map[uint][]models.PostBrief)
if len(snippetIDs) == 0 {
return result
}
type row struct {
SnippetID uint
PostID uint
Title string
SortOrder uint
}
var rows []row
err := config.DB.Table("post_snippets ps").
Select("ps.snippet_id, ps.post_id, p.title, ps.sort_order").
Joins("INNER JOIN posts p ON p.id = ps.post_id").
Where("ps.snippet_id IN ? AND p.deleted_at = ?", snippetIDs, 0).
Order("ps.sort_order ASC, ps.created_at ASC").
Scan(&rows).Error
if err != nil {
log.Printf("Error batch getting posts by snippet IDs: %v", err)
return result
}
for _, r := range rows {
result[r.SnippetID] = append(result[r.SnippetID], models.PostBrief{ID: r.PostID, Title: r.Title})
}
return result
}
// GetPostIDsBySnippetID 获取片段关联的文章 ID 列表(后台编辑用)
func GetPostIDsBySnippetID(snippetID uint) ([]uint, error) {
var ids []uint
err := config.DB.Model(&models.PostSnippet{}).
Where("snippet_id = ?", snippetID).
Order("sort_order ASC, created_at ASC").
Pluck("post_id", &ids).Error
if err != nil {
log.Printf("Error getting post IDs by snippet ID: %v", err)
return nil, err
}
return ids, nil
}

View File

@@ -24,7 +24,7 @@ func GetSnippets() ([]models.Snippet, error) {
}
// GetSnippetByID 根据ID获取代码片段
func GetSnippetByID(id string) (*models.Snippet, error) {
func GetSnippetByID(id uint) (*models.Snippet, error) {
var snippet models.Snippet
err := config.DB.Model(&models.Snippet{}).
Where("id = ? AND deleted_at = ?", id, 0).
@@ -47,6 +47,10 @@ func GetSnippetByID(id string) (*models.Snippet, error) {
// BuildSnippetResponse 构建代码片段响应
func BuildSnippetResponse(snippet *models.Snippet) *models.SnippetResponse {
return BuildSnippetResponseWithPosts(snippet, nil)
}
func BuildSnippetResponseWithPosts(snippet *models.Snippet, posts []models.PostBrief) *models.SnippetResponse {
resp := &models.SnippetResponse{
ID: snippet.ID,
Title: snippet.Title,
@@ -63,14 +67,27 @@ func BuildSnippetResponse(snippet *models.Snippet) *models.SnippetResponse {
resp.Type = ct.Name
}
}
if posts != nil {
resp.Posts = posts
} else if posts, err := GetPostsBySnippetID(snippet.ID); err == nil && len(posts) > 0 {
resp.Posts = posts
}
return resp
}
// BuildSnippetsResponse 构建代码片段列表响应
func BuildSnippetsResponse(snippets []models.Snippet) []models.SnippetResponse {
if len(snippets) == 0 {
return []models.SnippetResponse{}
}
ids := make([]uint, len(snippets))
for i, s := range snippets {
ids[i] = s.ID
}
postsMap := GetPostsBySnippetIDs(ids)
var responses []models.SnippetResponse
for _, snippet := range snippets {
responses = append(responses, *BuildSnippetResponse(&snippet))
responses = append(responses, *BuildSnippetResponseWithPosts(&snippet, postsMap[snippet.ID]))
}
return responses
}
@@ -105,7 +122,7 @@ func UpdateSnippet(snippet *models.Snippet) error {
}
// DeleteSnippet 删除代码片段 (Soft Delete)
func DeleteSnippet(id string) error {
func DeleteSnippet(id uint) error {
err := config.DB.Model(&models.Snippet{}).
Where("id = ?", id).
Update("deleted_at", time.Now().Unix()).Error