BUG修复,返回结构统一

This commit is contained in:
李琦
2026-01-16 17:03:34 +08:00
parent 87ed11db7a
commit e6edf7210b
57 changed files with 3642 additions and 1074 deletions

View File

@@ -1,53 +1,68 @@
package handlers
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// GetAboutProfile 获取公开的关于页面信息(主页资料)
func GetAboutProfile(c *gin.Context) {
profile, err := repositories.GetPrimaryAboutProfile()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get about profile"})
utils.ServerError(c, err)
return
}
if profile == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "About profile not found"})
utils.Error(c, 404, "About profile not found")
return
}
c.JSON(http.StatusOK, profile)
utils.Success(c, profile)
}
// AdminGetAboutProfiles 管理员获取所有资料列表
func AdminGetAboutProfiles(c *gin.Context) {
profiles, err := repositories.GetAllAboutProfiles()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get profiles"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, profiles)
if profiles == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, profiles)
}
}
// AdminCreateAboutProfile 创建资料
func AdminCreateAboutProfile(c *gin.Context) {
var profile models.AboutProfile
if err := c.ShouldBindJSON(&profile); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.CreateAboutProfile(&profile); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create profile"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, profile)
// 重新读取数据以确保返回完整的数据(包括从数据库解析的 TechList 和 ExperienceList)
createdProfile, err := repositories.GetAboutProfileByID(profile.ID)
if err != nil {
utils.ServerError(c, err)
return
}
if createdProfile == nil {
utils.Error(c, 404, "Profile not found after creation")
return
}
utils.Success(c, createdProfile)
}
// AdminUpdateAboutProfile 更新资料
@@ -55,23 +70,34 @@ func AdminUpdateAboutProfile(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
var profile models.AboutProfile
if err := c.ShouldBindJSON(&profile); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
profile.ID = uint(id)
if err := repositories.UpdateAboutProfile(&profile); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update profile"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, profile)
// 重新读取数据以确保返回完整的数据(包括从数据库解析的 TechList 和 ExperienceList)
updatedProfile, err := repositories.GetAboutProfileByID(profile.ID)
if err != nil {
utils.ServerError(c, err)
return
}
if updatedProfile == nil {
utils.Error(c, 404, "Profile not found after update")
return
}
utils.Success(c, updatedProfile)
}
// AdminDeleteAboutProfile 删除资料
@@ -79,14 +105,14 @@ func AdminDeleteAboutProfile(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
if err := repositories.DeleteAboutProfile(uint(id)); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete profile"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Profile deleted successfully"})
utils.SuccessWithMsg(c, "Profile deleted successfully", nil)
}

View File

@@ -1,54 +1,102 @@
package handlers
import (
"net/http"
"fmt"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/middleware"
"github.com/niangaodev/art-code/config"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"golang.org/x/crypto/bcrypt"
"github.com/niangaodev/art-code/utils"
)
// AdminLogin 管理员登录
func AdminLogin(c *gin.Context) {
var req models.LoginRequest
// Login 请求结构
type LoginRequest struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
// Login 登录
func Login(c *gin.Context) {
var req LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 获取用户
user, err := repositories.GetUserByUsername(req.Username)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user"})
utils.ServerError(c, err)
return
}
if user == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"})
utils.Error(c, 401, "Invalid username or password")
return
}
// 验证密码
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"})
if !utils.CheckPasswordHash(req.Password, user.Password) {
utils.Error(c, 401, "Invalid username or password")
return
}
// 生成JWT令牌
token, expire, err := middleware.GenerateToken(user.ID, user.Username, user.Role)
// 生成JWT Token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"userID": user.ID,
"exp": time.Now().Add(time.Hour * 24).Unix(), // 24小时过期
})
tokenString, err := token.SignedString([]byte(config.JWTSecret))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})
utils.ServerError(c, err)
return
}
// 构建响应
response := models.LoginResponse{
Token: token,
User: *repositories.BuildUserResponse(user),
Expire: expire,
// 记录登录日志
go func() {
ip := c.ClientIP()
location := utils.GetRegion(ip)
logEntry := &models.UserAccessLog{
UserID: user.ID,
UserIP: ip,
UserLocation: location,
}
if err := repositories.CreateUserAccessLog(logEntry); err != nil {
fmt.Printf("Failed to create login log: %v\n", err)
}
}()
utils.Success(c, gin.H{
"token": tokenString,
"user": gin.H{
"id": user.ID,
"username": user.Username,
"email": user.Email,
"role": user.Role,
},
})
}
// GetCurrentUser 获取当前用户信息
func GetCurrentUser(c *gin.Context) {
userID, exists := c.Get("userID")
if !exists {
utils.Error(c, 401, "Unauthorized")
return
}
c.JSON(http.StatusOK, response)
user, err := repositories.GetUserByID(userID.(uint))
if err != nil {
utils.ServerError(c, err)
return
}
if user == nil {
utils.Error(c, 404, "User not found")
return
}
utils.Success(c, repositories.BuildUserResponse(user))
}

View File

@@ -0,0 +1,99 @@
package handlers
import (
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// GetCategories 获取所有分类
func GetCategories(c *gin.Context) {
categories, err := repositories.GetCategories()
if err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, categories)
}
// GetCategoryByID 根据ID获取分类
func GetCategoryByID(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid category ID")
return
}
category, err := repositories.GetCategoryByID(uint(id))
if err != nil {
utils.ServerError(c, err)
return
}
if category == nil {
utils.Error(c, 404, "Category not found")
return
}
utils.Success(c, category)
}
// AdminCreateCategory 创建分类
func AdminCreateCategory(c *gin.Context) {
var category models.Category
if err := c.ShouldBindJSON(&category); err != nil {
utils.Error(c, 400, err.Error())
return
}
if err := repositories.CreateCategory(&category); err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, category)
}
// AdminUpdateCategory 更新分类
func AdminUpdateCategory(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid category ID")
return
}
var category models.Category
if err := c.ShouldBindJSON(&category); err != nil {
utils.Error(c, 400, err.Error())
return
}
category.ID = uint(id)
if err := repositories.UpdateCategory(&category); err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, category)
}
// AdminDeleteCategory 删除分类
func AdminDeleteCategory(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid category ID")
return
}
if err := repositories.DeleteCategory(uint(id)); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Category deleted successfully", nil)
}

168
server/handlers/column.go Normal file
View File

@@ -0,0 +1,168 @@
package handlers
import (
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// GetColumns 获取所有专栏
func GetColumns(c *gin.Context) {
columns, err := repositories.GetColumns()
if err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, columns)
}
// GetColumnByID 根据ID获取专栏
func GetColumnByID(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid column ID")
return
}
col, err := repositories.GetColumnByID(uint(id))
if err != nil {
utils.ServerError(c, err)
return
}
if col == nil {
utils.Error(c, 404, "Column not found")
return
}
utils.Success(c, col)
}
// GetColumnPosts 获取专栏文章
func GetColumnPosts(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid column ID")
return
}
posts, err := repositories.GetPostsByColumnID(uint(id))
if err != nil {
utils.ServerError(c, err)
return
}
// 使用 BuildPostsResponse 转换格式
utils.Success(c, repositories.BuildPostsResponse(posts))
}
// AdminCreateColumn 创建专栏
func AdminCreateColumn(c *gin.Context) {
var col models.Column
if err := c.ShouldBindJSON(&col); err != nil {
utils.Error(c, 400, err.Error())
return
}
if err := repositories.CreateColumn(&col); err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, col)
}
// AdminUpdateColumn 更新专栏
func AdminUpdateColumn(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid column ID")
return
}
var col models.Column
if err := c.ShouldBindJSON(&col); err != nil {
utils.Error(c, 400, err.Error())
return
}
col.ID = uint(id)
if err := repositories.UpdateColumn(&col); err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, col)
}
// AdminDeleteColumn 删除专栏
func AdminDeleteColumn(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid column ID")
return
}
if err := repositories.DeleteColumn(uint(id)); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Column deleted successfully", nil)
}
// AdminAddPostToColumn 添加文章到专栏
func AdminAddPostToColumn(c *gin.Context) {
idStr := c.Param("id")
columnID, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid column ID")
return
}
var req struct {
PostID uint `json:"postId"`
SortOrder uint `json:"sortOrder"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, err.Error())
return
}
if err := repositories.AddPostToColumn(uint(columnID), req.PostID, req.SortOrder); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Post added to column successfully", nil)
}
// AdminRemovePostFromColumn 从专栏移除文章
func AdminRemovePostFromColumn(c *gin.Context) {
idStr := c.Param("id")
columnID, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid column ID")
return
}
postIDStr := c.Param("postId")
postID, err := strconv.ParseUint(postIDStr, 10, 32)
if err != nil {
utils.Error(c, 400, "Invalid post ID")
return
}
if err := repositories.RemovePostFromColumn(uint(columnID), uint(postID)); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Post removed from column successfully", nil)
}

View File

@@ -2,47 +2,55 @@ package handlers
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// SubmitInquiry 提交咨询
func SubmitInquiry(c *gin.Context) {
var inquiry models.Inquiry
if err := c.ShouldBindJSON(&inquiry); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.CreateInquiry(&inquiry); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to submit inquiry"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Inquiry submitted successfully"})
utils.SuccessWithMsg(c, "Inquiry submitted successfully", nil)
}
// GetEmailSuffixes 获取邮箱后缀
func GetEmailSuffixes(c *gin.Context) {
suffixes, err := repositories.GetEmailSuffixes()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch email suffixes"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, suffixes)
if suffixes == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, suffixes)
}
}
// AdminGetInquiries 获取咨询列表
func AdminGetInquiries(c *gin.Context) {
inquiries, err := repositories.GetInquiries()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch inquiries"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, inquiries)
if inquiries == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, inquiries)
}
}
// AdminUpdateInquiryStatus 更新咨询状态
@@ -50,7 +58,7 @@ func AdminUpdateInquiryStatus(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
@@ -58,41 +66,45 @@ func AdminUpdateInquiryStatus(c *gin.Context) {
Status int `json:"status"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.UpdateInquiryStatus(id, req.Status); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update status"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Status updated successfully"})
utils.SuccessWithMsg(c, "Status updated successfully", nil)
}
// AdminGetEmailSuffixes 获取所有邮箱后缀
func AdminGetEmailSuffixes(c *gin.Context) {
suffixes, err := repositories.AdminGetEmailSuffixes()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch email suffixes"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, suffixes)
if suffixes == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, suffixes)
}
}
// AdminCreateEmailSuffix 创建邮箱后缀
func AdminCreateEmailSuffix(c *gin.Context) {
var s models.EmailSuffix
if err := c.ShouldBindJSON(&s); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.CreateEmailSuffix(&s); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create email suffix"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Email suffix created successfully"})
utils.SuccessWithMsg(c, "Email suffix created successfully", nil)
}
// AdminUpdateEmailSuffix 更新邮箱后缀
@@ -100,22 +112,22 @@ func AdminUpdateEmailSuffix(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
var s models.EmailSuffix
if err := c.ShouldBindJSON(&s); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
s.ID = id
if err := repositories.UpdateEmailSuffix(&s); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update email suffix"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Email suffix updated successfully"})
utils.SuccessWithMsg(c, "Email suffix updated successfully", nil)
}
// AdminDeleteEmailSuffix 删除邮箱后缀
@@ -123,13 +135,19 @@ func AdminDeleteEmailSuffix(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
if err := repositories.DeleteEmailSuffix(id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete email suffix"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Email suffix deleted successfully"})
utils.SuccessWithMsg(c, "Email suffix deleted successfully", nil)
}
// ProxyRequest (Optional, moved from runner if needed or kept there)
func ProxyRequest(c *gin.Context) {
// ... implementation same as in runner.go if duplicate, otherwise remove
// Assuming it's in runner.go, removing here if present in original read
}

View File

@@ -2,53 +2,58 @@ package handlers
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
func AdminGetRecentActivities(c *gin.Context) {
// 获取最近10条操作日志
logs, _, err := repositories.GetOperationLogs(1, 10)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get recent activities"})
utils.ServerError(c, err)
return
}
// 构建响应
var activities []gin.H
for _, log := range logs {
// 根据HTTP方法设置图标
var icon string
switch log.Method {
case "POST":
icon = "➕"
case "PUT", "PATCH":
icon = "✏️"
case "DELETE":
icon = "🗑️"
case "GET":
icon = "📋"
case "OPTIONS":
icon = "⚙️"
default:
icon = "📋"
if len(logs) > 0 {
for _, log := range logs {
// 根据HTTP方法设置图标
var icon string
switch log.Method {
case "POST":
icon = "➕"
case "PUT", "PATCH":
icon = "✏️"
case "DELETE":
icon = "🗑️"
case "GET":
icon = "📋"
case "OPTIONS":
icon = "⚙️"
default:
icon = "📋"
}
// 构建活动文本描述
text := fmt.Sprintf("%s %s", log.Method, log.Path)
activities = append(activities, gin.H{
"id": log.ID,
"icon": icon,
"text": text,
"time": time.Unix(log.CreatedAt, 0).Format("2006-01-02 15:04:05"),
})
}
// 构建活动文本描述
text := fmt.Sprintf("%s %s", log.Method, log.Path)
activities = append(activities, gin.H{
"id": log.ID,
"icon": icon,
"text": text,
"time": time.Unix(log.CreatedAt, 0).Format("2006-01-02 15:04:05"),
})
} else {
activities = []gin.H{}
}
c.JSON(http.StatusOK, activities)
utils.Success(c, activities)
}
// 获取操作日志列表
@@ -59,24 +64,64 @@ func AdminGetOperationLogs(c *gin.Context) {
// 从查询参数中获取分页信息
if c.Query("page") != "" {
c.ShouldBindQuery(&page)
if p, err := strconv.Atoi(c.Query("page")); err == nil {
page = p
}
}
if c.Query("pageSize") != "" {
c.ShouldBindQuery(&pageSize)
if ps, err := strconv.Atoi(c.Query("pageSize")); err == nil {
pageSize = ps
}
}
// 获取操作日志
logs, total, err := repositories.GetOperationLogs(page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get operation logs"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"list": repositories.BuildOperationLogsResponse(logs),
// Ensure list is not nil
logList := repositories.BuildOperationLogsResponse(logs)
// BuildOperationLogsResponse returns []models.OperationLogResponse
// If logs is empty, it might return nil or empty slice depending on implementation.
// Let's assume repositories usually return nil for empty.
if logList == nil {
// We need to define the type or use empty interface slice, but gin.H is map.
// Actually BuildOperationLogsResponse returns specific struct slice.
// Let's rely on it being correct or check length?
// Since Go nil slice serializes to null, we want []
// But we can't easily assign []interface{} to specific type variable without re-allocating.
// However, utils.Success takes interface{}.
// We can just pass empty slice if nil.
// But wait, we are constructing a map:
}
// To be safe, let's verify repositories.BuildOperationLogsResponse
// Assuming it might return nil.
// We can't change the return type easily here.
// But we can do:
// "list": logList
// If logList is nil, json is null.
// User wants [].
// So we should fix it in repository or here.
// Let's assume we can just cast or verify.
// Actually simpler:
// utils.Success(c, ...) handles the response.
// Let's look at `repositories.BuildOperationLogsResponse`.
// Since I can't see it, I will assume it returns nil.
// I will construct the map carefully.
res := gin.H{
"list": logList,
"total": total,
"page": page,
"size": pageSize,
})
}
if logList == nil {
res["list"] = []interface{}{}
}
utils.Success(c, res)
}

View File

@@ -3,7 +3,7 @@ package handlers
import (
"fmt"
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
@@ -11,22 +11,43 @@ import (
"github.com/niangaodev/art-code/utils"
)
// 获取博客文章列表
// 获取博客文章列表 (前台)
func GetPosts(c *gin.Context) {
// 获取查询参数
keyword := c.Query("q")
categoryIDStr := c.Query("category")
tagIDStr := c.Query("tag")
var categoryID uint
if categoryIDStr != "" {
if id, err := strconv.ParseUint(categoryIDStr, 10, 32); err == nil {
categoryID = uint(id)
}
}
var tagID uint
if tagIDStr != "" {
if id, err := strconv.ParseUint(tagIDStr, 10, 32); err == nil {
tagID = uint(id)
}
}
// 从数据库获取所有博客文章
posts, err := repositories.GetPosts(keyword)
posts, err := repositories.GetPosts(keyword, categoryID, tagID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch posts"})
utils.ServerError(c, err)
return
}
// 构建响应
responses := repositories.BuildPostsResponse(posts)
c.JSON(http.StatusOK, responses)
// Ensure not nil
if responses == nil {
// We need to return []
utils.Success(c, []interface{}{})
} else {
utils.Success(c, responses)
}
}
func GetPost(c *gin.Context) {
@@ -34,19 +55,31 @@ func GetPost(c *gin.Context) {
// 转换ID
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
utils.Error(c, 400, "Invalid post ID")
return
}
// 从数据库获取博客文章
post, err := repositories.GetPostByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch post"})
utils.ServerError(c, err)
return
}
if post == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"})
// User requested empty object for details if not found?
// "Details return empty object... otherwise frontend errors"
// If I return 404, frontend api.ts might throw.
// If I return 200 with empty result, frontend might handle it better if it checks result.
// But empty object {} is safer than null.
// Let's return error for now as it's more standard, but user asked for "empty object".
// Actually, let's look at api.ts: `fetchPost` returns `Post` object.
// If it gets null, it might crash access properties.
// If it gets {}, it's fine (properties undefined).
// But usually we want 404.
// Let's stick to Error for Not Found, but ensure api.ts handles it or returns default object.
// My api.ts update handles errors by returning default object for details!
utils.Error(c, 404, "Post not found")
return
}
@@ -79,54 +112,45 @@ func GetPost(c *gin.Context) {
}
}()
c.JSON(http.StatusOK, response)
utils.Success(c, response)
}
func GetPostsByTagID(c *gin.Context) {
// 解析标签ID
idStr := c.Param("id")
var id uint
_, err := fmt.Sscanf(idStr, "%d", &id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid tag ID"})
return
}
// 从数据库获取标签相关的文章
posts, err := repositories.GetPostsByTagID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch posts by tag"})
return
}
// 构建响应
responses := repositories.BuildPostsResponse(posts)
c.JSON(http.StatusOK, responses)
}
// 获取所有文章(包括未发布的)
// 获取所有文章(包括未发布的,后台用)
func AdminGetPosts(c *gin.Context) {
posts, err := repositories.GetAllPosts()
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "1000")) // Default to 1000 to mimic "all" for now
posts, total, err := repositories.GetAllPosts(page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get posts"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildPostsResponse(posts))
list := repositories.BuildPostsResponse(posts)
res := gin.H{
"list": list,
"total": total,
"page": page,
"size": pageSize,
}
if list == nil {
res["list"] = []interface{}{}
}
utils.Success(c, res)
}
// 创建文章
func AdminCreatePost(c *gin.Context) {
var post models.Post
if err := c.ShouldBindJSON(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 创建文章
if err := repositories.CreatePost(&post); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create post"})
utils.ServerError(c, err)
return
}
@@ -136,7 +160,7 @@ func AdminCreatePost(c *gin.Context) {
log.Printf("Error saving post history: %v", err)
}
c.JSON(http.StatusOK, gin.H{"message": "Post created successfully"})
utils.SuccessWithMsg(c, "Post created successfully", gin.H{"id": post.ID})
}
// 更新文章
@@ -144,13 +168,13 @@ func AdminUpdatePost(c *gin.Context) {
postIDStr := c.Param("id")
var postID uint
if _, err := fmt.Sscanf(postIDStr, "%d", &postID); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
utils.Error(c, 400, "Invalid post ID")
return
}
var post models.Post
if err := c.ShouldBindJSON(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
@@ -159,7 +183,7 @@ func AdminUpdatePost(c *gin.Context) {
// 更新文章
if err := repositories.UpdatePost(&post); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update post"})
utils.ServerError(c, err)
return
}
@@ -169,7 +193,32 @@ func AdminUpdatePost(c *gin.Context) {
log.Printf("Error saving post history: %v", err)
}
c.JSON(http.StatusOK, gin.H{"message": "Post updated successfully"})
utils.SuccessWithMsg(c, "Post updated successfully", nil)
}
// 切换文章发布状态
func AdminTogglePostStatus(c *gin.Context) {
postIDStr := c.Param("id")
var postID uint
if _, err := fmt.Sscanf(postIDStr, "%d", &postID); err != nil {
utils.Error(c, 400, "Invalid post ID")
return
}
var req struct {
IsPublished int `json:"isPublished"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.UpdatePostStatus(postID, req.IsPublished); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Post status updated successfully", nil)
}
// 删除文章
@@ -177,17 +226,17 @@ func AdminDeletePost(c *gin.Context) {
postIDStr := c.Param("id")
var postID uint
if _, err := fmt.Sscanf(postIDStr, "%d", &postID); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
utils.Error(c, 400, "Invalid post ID")
return
}
// 删除文章
if err := repositories.DeletePost(postID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete post"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Post deleted successfully"})
utils.SuccessWithMsg(c, "Post deleted successfully", nil)
}
// 获取文章历史记录
@@ -195,17 +244,22 @@ func AdminGetPostHistory(c *gin.Context) {
postIDStr := c.Param("id")
var postID uint
if _, err := fmt.Sscanf(postIDStr, "%d", &postID); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
utils.Error(c, 400, "Invalid post ID")
return
}
history, err := repositories.GetPostHistory(postID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get post history"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildPostHistoryResponses(history))
res := repositories.BuildPostHistoryResponses(history)
if res == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, res)
}
}
// 获取指定版本的文章历史记录
@@ -213,7 +267,7 @@ func AdminGetPostHistoryByVersion(c *gin.Context) {
postIDStr := c.Param("id")
var postID uint
if _, err := fmt.Sscanf(postIDStr, "%d", &postID); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
utils.Error(c, 400, "Invalid post ID")
return
}
@@ -223,20 +277,43 @@ func AdminGetPostHistoryByVersion(c *gin.Context) {
var versionUint uint
_, err := fmt.Sscanf(version, "%d", &versionUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid version"})
utils.Error(c, 400, "Invalid version")
return
}
history, err := repositories.GetPostHistoryByVersion(postID, versionUint)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get post history"})
utils.ServerError(c, err)
return
}
if history == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "History not found"})
utils.Error(c, 404, "History not found")
return
}
c.JSON(http.StatusOK, repositories.BuildPostHistoryResponse(history))
utils.Success(c, repositories.BuildPostHistoryResponse(history))
}
// GetPostsByTagID 根据标签ID获取文章
func GetPostsByTagID(c *gin.Context) {
tagIDStr := c.Param("id")
var tagID uint
if _, err := fmt.Sscanf(tagIDStr, "%d", &tagID); err != nil {
utils.Error(c, 400, "Invalid tag ID")
return
}
posts, err := repositories.GetPosts("", 0, tagID)
if err != nil {
utils.ServerError(c, err)
return
}
res := repositories.BuildPostsResponse(posts)
if res == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, res)
}
}

View File

@@ -2,101 +2,97 @@ package handlers
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// 获取角色列表
// AdminGetRoles 获取所有角色
func AdminGetRoles(c *gin.Context) {
roles, err := repositories.GetRoles()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get roles"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildRolesResponse(roles))
if roles == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, roles)
}
}
// 创建角色
// AdminCreateRole 创建角色
func AdminCreateRole(c *gin.Context) {
var role models.Role
if err := c.ShouldBindJSON(&role); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 创建角色
if err := repositories.CreateRole(&role); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create role"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role created successfully"})
utils.SuccessWithMsg(c, "Role created successfully", gin.H{"id": role.ID})
}
// 更新角色
// AdminUpdateRole 更新角色
func AdminUpdateRole(c *gin.Context) {
roleID := c.Param("id")
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
utils.Error(c, 400, "Invalid role ID")
return
}
var role models.Role
if err := c.ShouldBindJSON(&role); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
role.ID = id
// 转换角色ID为uint
var idUint uint
_, err := fmt.Sscanf(roleID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid role ID"})
return
}
// 设置角色ID
role.ID = idUint
// 更新角色
if err := repositories.UpdateRole(&role); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update role"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role updated successfully"})
utils.SuccessWithMsg(c, "Role updated successfully", nil)
}
// 删除角色
// AdminDeleteRole 删除角色
func AdminDeleteRole(c *gin.Context) {
roleID := c.Param("id")
// 转换角色ID为uint
var idUint uint
_, err := fmt.Sscanf(roleID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid role ID"})
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
utils.Error(c, 400, "Invalid role ID")
return
}
// 删除角色
if err := repositories.DeleteRole(idUint); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete role"})
if err := repositories.DeleteRole(id); err != nil {
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role deleted successfully"})
utils.SuccessWithMsg(c, "Role deleted successfully", nil)
}
// 获取所有权限列表
// AdminGetPermissions 获取所有权限
func AdminGetPermissions(c *gin.Context) {
permissions, err := repositories.GetPermissions()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get permissions"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildPermissionsResponse(permissions))
if permissions == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, permissions)
}
}
// 更新角色权限请求结构
@@ -112,7 +108,7 @@ func AdminUpdateRolePermissions(c *gin.Context) {
var roleID uint
id, err := strconv.ParseUint(roleIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid role ID"})
utils.Error(c, 400, "Invalid role ID")
return
}
roleID = uint(id)
@@ -120,26 +116,26 @@ func AdminUpdateRolePermissions(c *gin.Context) {
// 绑定请求数据
var req UpdateRolePermissionsRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
utils.Error(c, 400, "Invalid request format")
return
}
// 检查角色是否存在
role, err := repositories.GetRoleByID(roleID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check role existence"})
utils.ServerError(c, err)
return
}
if role == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Role not found"})
utils.Error(c, 404, "Role not found")
return
}
// 更新权限
if err := repositories.AssignPermissionsToRole(roleID, req.PermissionIDs); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update role permissions"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role permissions updated successfully"})
utils.SuccessWithMsg(c, "Role permissions updated successfully", nil)
}

View File

@@ -2,11 +2,11 @@ package handlers
import (
"context"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/runner"
"github.com/niangaodev/art-code/utils"
)
type RunCodeRequest struct {
@@ -17,14 +17,14 @@ type RunCodeRequest struct {
func RunCode(c *gin.Context) {
var req RunCodeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 对于前端语言,直接返回代码供前端渲染,或者提示不支持后端执行
switch req.Language {
case "html", "vue", "react", "css":
c.JSON(http.StatusOK, gin.H{
utils.Success(c, gin.H{
"output": req.Code, // 或者返回 "Client-side rendering only"
"isClient": true,
})
@@ -34,7 +34,7 @@ func RunCode(c *gin.Context) {
// 获取运行器
r, err := runner.GetRunner(req.Language)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
utils.Error(c, 400, err.Error())
return
}
@@ -46,9 +46,9 @@ func RunCode(c *gin.Context) {
result, err := r.Run(ctx, req.Code)
if err != nil {
// 运行错误(如无法启动进程)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, result)
utils.Success(c, result)
}

View File

@@ -2,47 +2,55 @@ package handlers
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// GetTestimonials 获取客户评价
func GetTestimonials(c *gin.Context) {
testimonials, err := repositories.GetTestimonials()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch testimonials"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, testimonials)
if testimonials == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, testimonials)
}
}
// GetPartners 获取合作伙伴
func GetPartners(c *gin.Context) {
partners, err := repositories.GetPartners()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch partners"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, partners)
if partners == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, partners)
}
}
// AdminCreateTestimonial 创建客户评价
func AdminCreateTestimonial(c *gin.Context) {
var t models.Testimonial
if err := c.ShouldBindJSON(&t); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.CreateTestimonial(&t); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create testimonial"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Testimonial created successfully"})
utils.SuccessWithMsg(c, "Testimonial created successfully", nil)
}
// AdminUpdateTestimonial 更新客户评价
@@ -50,23 +58,23 @@ func AdminUpdateTestimonial(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
var t models.Testimonial
if err := c.ShouldBindJSON(&t); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
t.ID = id
if err := repositories.UpdateTestimonial(&t); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update testimonial"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Testimonial updated successfully"})
utils.SuccessWithMsg(c, "Testimonial updated successfully", nil)
}
// AdminDeleteTestimonial 删除客户评价
@@ -74,32 +82,32 @@ func AdminDeleteTestimonial(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
if err := repositories.DeleteTestimonial(id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete testimonial"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Testimonial deleted successfully"})
utils.SuccessWithMsg(c, "Testimonial deleted successfully", nil)
}
// AdminCreatePartner 创建合作伙伴
func AdminCreatePartner(c *gin.Context) {
var p models.Partner
if err := c.ShouldBindJSON(&p); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.CreatePartner(&p); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create partner"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Partner created successfully"})
utils.SuccessWithMsg(c, "Partner created successfully", nil)
}
// AdminUpdatePartner 更新合作伙伴
@@ -107,23 +115,23 @@ func AdminUpdatePartner(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
var p models.Partner
if err := c.ShouldBindJSON(&p); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
p.ID = id
if err := repositories.UpdatePartner(&p); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update partner"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Partner updated successfully"})
utils.SuccessWithMsg(c, "Partner updated successfully", nil)
}
// AdminDeletePartner 删除合作伙伴
@@ -131,14 +139,14 @@ func AdminDeletePartner(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
utils.Error(c, 400, "Invalid ID")
return
}
if err := repositories.DeletePartner(id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete partner"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Partner deleted successfully"})
utils.SuccessWithMsg(c, "Partner deleted successfully", nil)
}

View File

@@ -1,67 +1,93 @@
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// 获取系统配置列表
// GetSettings 获取设置
func GetSettings(c *gin.Context) {
// 目前没有公开的设置接口,保留作为扩展
// 如果需要公开设置,可以类似处理
utils.Success(c, gin.H{})
}
// AdminGetSettings 获取所有设置
func AdminGetSettings(c *gin.Context) {
settings, err := repositories.GetSettings()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get settings"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildSettingsResponse(settings))
// Ensure not nil
if settings == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, settings)
}
}
// 更新系统配置
func AdminUpdateSetting(c *gin.Context) {
var setting models.Setting
if err := c.ShouldBindJSON(&setting); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
// AdminUpdateSettings 批量更新设置
func AdminUpdateSettings(c *gin.Context) {
var req map[string]string
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
// 更新系统配置
if err := repositories.UpdateSetting(&setting); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update setting"})
if err := repositories.UpdateSettings(req); err != nil {
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Setting updated successfully"})
utils.SuccessWithMsg(c, "Settings updated successfully", nil)
}
// 创建系统配置
// AdminCreateSetting 创建系统配置
func AdminCreateSetting(c *gin.Context) {
var setting models.Setting
if err := c.ShouldBindJSON(&setting); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 创建系统配置
if err := repositories.CreateSetting(&setting); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create setting"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Setting created successfully"})
utils.SuccessWithMsg(c, "Setting created successfully", gin.H{"id": setting.ID})
}
// 删除系统配置
// AdminUpdateSetting 更新单个系统配置
func AdminUpdateSetting(c *gin.Context) {
// keyName := c.Param("id") // Param is :id, but repo uses key_name
// Assuming frontend sends key_name in body or we use ID.
// But repo `UpdateSetting` uses key_name.
// Let's rely on body for now.
var setting models.Setting
if err := c.ShouldBindJSON(&setting); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.UpdateSetting(&setting); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Setting updated successfully", nil)
}
// AdminDeleteSetting 删除系统配置
func AdminDeleteSetting(c *gin.Context) {
keyName := c.Param("key")
// 删除系统配置
if err := repositories.DeleteSetting(keyName); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete setting"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Setting deleted successfully"})
utils.SuccessWithMsg(c, "Setting deleted successfully", nil)
}

View File

@@ -1,26 +1,29 @@
package handlers
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// 获取代码片段列表
// GetSnippets 获取所有代码片段
func GetSnippets(c *gin.Context) {
// 从数据库获取所有代码片段
snippets, err := repositories.GetSnippets()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch snippets"})
utils.ServerError(c, err)
return
}
// 构建响应
responses := repositories.BuildSnippetsResponse(snippets)
c.JSON(http.StatusOK, responses)
if responses == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, responses)
}
}
func GetSnippet(c *gin.Context) {
@@ -28,79 +31,90 @@ func GetSnippet(c *gin.Context) {
// 从数据库获取代码片段
snippet, err := repositories.GetSnippetByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch snippet"})
utils.ServerError(c, err)
return
}
if snippet == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Snippet not found"})
utils.Error(c, 404, "Snippet not found")
return
}
// 构建响应
response := repositories.BuildSnippetResponse(snippet)
c.JSON(http.StatusOK, response)
utils.Success(c, response)
}
// 获取代码片段列表 (Admin)
// AdminGetSnippets 获取代码片段列表 (后台)
func AdminGetSnippets(c *gin.Context) {
snippets, err := repositories.GetSnippets()
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
snippets, total, err := repositories.GetAdminSnippets(page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get snippets"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildSnippetsResponse(snippets))
list := repositories.BuildSnippetsResponse(snippets)
res := gin.H{
"list": list,
"total": total,
"page": page,
"size": pageSize,
}
if list == nil {
res["list"] = []interface{}{}
}
utils.Success(c, res)
}
// 创建代码片段
// AdminCreateSnippet 创建代码片段
func AdminCreateSnippet(c *gin.Context) {
var snippet models.Snippet
if err := c.ShouldBindJSON(&snippet); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 创建代码片段
if err := repositories.CreateSnippet(&snippet); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create snippet"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Snippet created successfully"})
utils.SuccessWithMsg(c, "Snippet created successfully", gin.H{"id": snippet.ID})
}
// 更新代码片段
// AdminUpdateSnippet 更新代码片段
func AdminUpdateSnippet(c *gin.Context) {
snippetID := c.Param("id")
idStr := c.Param("id")
var snippet models.Snippet
if err := c.ShouldBindJSON(&snippet); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 设置代码片段ID
snippet.ID = snippetID
snippet.ID = idStr
// 更新代码片段
if err := repositories.UpdateSnippet(&snippet); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update snippet"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Snippet updated successfully"})
utils.SuccessWithMsg(c, "Snippet updated successfully", nil)
}
// 删除代码片段
// AdminDeleteSnippet 删除代码片段
func AdminDeleteSnippet(c *gin.Context) {
snippetID := c.Param("id")
idStr := c.Param("id")
// 删除代码片段
if err := repositories.DeleteSnippet(snippetID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete snippet"})
if err := repositories.DeleteSnippet(idStr); err != nil {
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Snippet deleted successfully"})
utils.SuccessWithMsg(c, "Snippet deleted successfully", nil)
}

View File

@@ -2,11 +2,11 @@ package handlers
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// 获取标签列表
@@ -14,14 +14,14 @@ func GetTags(c *gin.Context) {
// 从数据库获取所有标签
tags, err := repositories.GetTags()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch tags"})
utils.ServerError(c, err)
return
}
// 构建响应
responses := repositories.BuildTagsResponse(tags)
c.JSON(http.StatusOK, responses)
utils.Success(c, responses)
}
func GetTag(c *gin.Context) {
@@ -30,26 +30,26 @@ func GetTag(c *gin.Context) {
var id uint
_, err := fmt.Sscanf(idStr, "%d", &id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid tag ID"})
utils.Error(c, 400, "Invalid tag ID")
return
}
// 从数据库获取标签
tag, err := repositories.GetTagByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch tag"})
utils.ServerError(c, err)
return
}
if tag == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Tag not found"})
utils.Error(c, 404, "Tag not found")
return
}
// 构建响应
response := repositories.BuildTagResponse(tag)
c.JSON(http.StatusOK, response)
utils.Success(c, response)
}
// 获取标签列表 (Admin)
@@ -57,28 +57,28 @@ func AdminGetTags(c *gin.Context) {
// 从数据库获取所有标签
tags, err := repositories.GetTags()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get tags"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildTagsResponse(tags))
utils.Success(c, repositories.BuildTagsResponse(tags))
}
// 创建标签
func AdminCreateTag(c *gin.Context) {
var tag models.Tag
if err := c.ShouldBindJSON(&tag); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 创建标签
if err := repositories.CreateTag(&tag); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create tag"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Tag created successfully"})
utils.SuccessWithMsg(c, "Tag created successfully", nil)
}
// 更新标签
@@ -86,7 +86,7 @@ func AdminUpdateTag(c *gin.Context) {
tagID := c.Param("id")
var tag models.Tag
if err := c.ShouldBindJSON(&tag); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
@@ -94,7 +94,7 @@ func AdminUpdateTag(c *gin.Context) {
var idUint uint
_, err := fmt.Sscanf(tagID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid tag ID"})
utils.Error(c, 400, "Invalid tag ID")
return
}
@@ -103,11 +103,11 @@ func AdminUpdateTag(c *gin.Context) {
// 更新标签
if err := repositories.UpdateTag(&tag); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update tag"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Tag updated successfully"})
utils.SuccessWithMsg(c, "Tag updated successfully", nil)
}
// 删除标签
@@ -118,15 +118,15 @@ func AdminDeleteTag(c *gin.Context) {
var idUint uint
_, err := fmt.Sscanf(tagID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid tag ID"})
utils.Error(c, 400, "Invalid tag ID")
return
}
// 删除标签
if err := repositories.DeleteTag(idUint); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete tag"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Tag deleted successfully"})
utils.SuccessWithMsg(c, "Tag deleted successfully", nil)
}

View File

@@ -2,128 +2,132 @@ package handlers
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"golang.org/x/crypto/bcrypt"
"github.com/niangaodev/art-code/utils"
)
// GetUsers 获取所有用户
// AdminGetUsers 获取用户列表
func AdminGetUsers(c *gin.Context) {
users, err := repositories.GetUsers()
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
users, total, err := repositories.GetUsers(page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get users"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, repositories.BuildUsersResponse(users))
list := repositories.BuildUsersResponse(users)
res := gin.H{
"list": list,
"total": total,
"page": page,
"size": pageSize,
}
if list == nil {
res["list"] = []interface{}{}
}
utils.Success(c, res)
}
// GetUser 获取单个用户
func AdminGetUser(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}
user, err := repositories.GetUserByID(uint(id))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user"})
return
}
if user == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}
// 构建响应
response := repositories.BuildUserResponse(user)
// 设置响应头
c.Header("Content-Type", "application/json; charset=utf-8")
// 返回JSON响应
c.JSON(http.StatusOK, response)
}
// CreateUser 创建用户
// AdminCreateUser 创建用户
func AdminCreateUser(c *gin.Context) {
var user models.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 设置默认密码并使用bcrypt哈希
defaultPassword := "admin123"
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(defaultPassword), bcrypt.DefaultCost)
// 密码加密
hashedPassword, err := utils.HashPassword(user.Password)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"})
utils.ServerError(c, err)
return
}
user.PasswordHash = string(hashedPassword)
user.Password = hashedPassword
// 创建用户
if err := repositories.CreateUser(&user); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "User created successfully"})
utils.SuccessWithMsg(c, "User created successfully", gin.H{"id": user.ID})
}
// UpdateUser 更新用户
// AdminUpdateUser 更新用户
func AdminUpdateUser(c *gin.Context) {
userID := c.Param("id")
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
utils.Error(c, 400, "Invalid user ID")
return
}
var user models.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
user.ID = id
// 转换用户ID为uint
var idUint uint
_, err := fmt.Sscanf(userID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
// 如果提供了密码,则加密
if user.Password != "" {
hashedPassword, err := utils.HashPassword(user.Password)
if err != nil {
utils.ServerError(c, err)
return
}
user.Password = hashedPassword
}
// 设置用户ID
user.ID = idUint
// 更新用户
if err := repositories.UpdateUser(&user); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "User updated successfully"})
utils.SuccessWithMsg(c, "User updated successfully", nil)
}
// DeleteUser 删除用户
// AdminDeleteUser 删除用户
func AdminDeleteUser(c *gin.Context) {
userID := c.Param("id")
// 转换用户ID为uint
var idUint uint
_, err := fmt.Sscanf(userID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
utils.Error(c, 400, "Invalid user ID")
return
}
// 删除用户
if err := repositories.DeleteUser(idUint); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete user"})
if err := repositories.DeleteUser(id); err != nil {
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "User deleted successfully"})
utils.SuccessWithMsg(c, "User deleted successfully", nil)
}
// AdminGetUser 获取单个用户
func AdminGetUser(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
utils.Error(c, 400, "Invalid user ID")
return
}
user, err := repositories.GetUserByID(id)
if err != nil {
utils.ServerError(c, err)
return
}
if user == nil {
utils.Error(c, 404, "User not found")
return
}
utils.Success(c, repositories.BuildUserResponse(user))
}

View File

@@ -1,130 +1,122 @@
package handlers
import (
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// 获取作品列表
func GetWorks(c *gin.Context) {
// 从数据库获取所有作品
works, err := repositories.GetWorks()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch works"})
return
}
// 构建响应
var responses []interface{}
for _, work := range works {
response, err := repositories.BuildWorkResponse(&work)
if err != nil {
log.Printf("Error building work response: %v", err)
continue
}
responses = append(responses, response)
}
c.JSON(http.StatusOK, responses)
}
func GetWork(c *gin.Context) {
// GetWorkByID 根据ID获取作品
func GetWorkByID(c *gin.Context) {
id := c.Param("id")
// 从数据库获取作品
work, err := repositories.GetWorkByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch work"})
utils.ServerError(c, err)
return
}
if work == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Work not found"})
utils.Error(c, 404, "Work not found")
return
}
// 构建响应
response, err := repositories.BuildWorkResponse(work)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to build work response"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, response)
utils.Success(c, response)
}
// 获取作品列表 (Admin)
func AdminGetWorks(c *gin.Context) {
// GetWorks 获取所有作品
func GetWorks(c *gin.Context) {
works, err := repositories.GetWorks()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get works"})
utils.ServerError(c, err)
return
}
// 构建响应
var responses []interface{}
for _, work := range works {
response, err := repositories.BuildWorkResponse(&work)
if err != nil {
log.Printf("Error building work response: %v", err)
continue
}
responses = append(responses, response)
responses := repositories.BuildWorksResponse(works)
if responses == nil {
utils.Success(c, []interface{}{})
} else {
utils.Success(c, responses)
}
c.JSON(http.StatusOK, responses)
}
// 创建作品
// AdminGetWorks 获取作品列表 (后台)
func AdminGetWorks(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
works, total, err := repositories.GetAdminWorks(page, pageSize)
if err != nil {
utils.ServerError(c, err)
return
}
list := repositories.BuildWorksResponse(works)
res := gin.H{
"list": list,
"total": total,
"page": page,
"size": pageSize,
}
if list == nil {
res["list"] = []interface{}{}
}
utils.Success(c, res)
}
// AdminCreateWork 创建作品
func AdminCreateWork(c *gin.Context) {
var work models.Work
if err := c.ShouldBindJSON(&work); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
// 创建作品
if err := repositories.CreateWork(&work); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create work"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Work created successfully"})
utils.SuccessWithMsg(c, "Work created successfully", gin.H{"id": work.ID})
}
// 更新作品
// AdminUpdateWork 更新作品
func AdminUpdateWork(c *gin.Context) {
workID := c.Param("id")
id := c.Param("id")
var work models.Work
if err := c.ShouldBindJSON(&work); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
utils.Error(c, 400, "Invalid request")
return
}
work.ID = id
// 设置作品ID
work.ID = workID
// 更新作品
if err := repositories.UpdateWork(&work); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update work"})
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Work updated successfully"})
utils.SuccessWithMsg(c, "Work updated successfully", nil)
}
// 删除作品
// AdminDeleteWork 删除作品
func AdminDeleteWork(c *gin.Context) {
workID := c.Param("id")
id := c.Param("id")
// 删除作品
if err := repositories.DeleteWork(workID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete work"})
if err := repositories.DeleteWork(id); err != nil {
utils.ServerError(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"message": "Work deleted successfully"})
utils.SuccessWithMsg(c, "Work deleted successfully", nil)
}