初始化

This commit is contained in:
李琦
2026-01-15 13:51:44 +08:00
commit b7b6d3e39e
156 changed files with 38913 additions and 0 deletions

54
server/handlers/auth.go Normal file
View File

@@ -0,0 +1,54 @@
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/middleware"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"golang.org/x/crypto/bcrypt"
)
// AdminLogin 管理员登录
func AdminLogin(c *gin.Context) {
var req models.LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 获取用户
user, err := repositories.GetUserByUsername(req.Username)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user"})
return
}
if user == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "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"})
return
}
// 生成JWT令牌
token, expire, err := middleware.GenerateToken(user.ID, user.Username, user.Role)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})
return
}
// 构建响应
response := models.LoginResponse{
Token: token,
User: *repositories.BuildUserResponse(user),
Expire: expire,
}
c.JSON(http.StatusOK, response)
}

View File

@@ -0,0 +1,46 @@
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/repositories"
)
// 仪表盘数据处理函数
func AdminGetDashboardStats(c *gin.Context) {
// 获取统计数据
userCount, err := repositories.GetUserCount()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user count"})
return
}
postCount, err := repositories.GetPostCount()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get post count"})
return
}
workCount, err := repositories.GetWorkCount()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get work count"})
return
}
snippetCount, err := repositories.GetSnippetCount()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get snippet count"})
return
}
// 构建响应
stats := gin.H{
"users": userCount,
"posts": postCount,
"works": workCount,
"snippets": snippetCount,
}
c.JSON(http.StatusOK, stats)
}

81
server/handlers/log.go Normal file
View File

@@ -0,0 +1,81 @@
package handlers
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/repositories"
)
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"})
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 = "📋"
}
// 构建活动文本描述
text := fmt.Sprintf("%s %s", log.Method, log.Path)
activities = append(activities, gin.H{
"id": log.ID,
"icon": icon,
"text": text,
"time": log.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
c.JSON(http.StatusOK, activities)
}
// 获取操作日志列表
func AdminGetOperationLogs(c *gin.Context) {
// 获取分页参数
page := 1
pageSize := 10
// 从查询参数中获取分页信息
if c.Query("page") != "" {
c.ShouldBindQuery(&page)
}
if c.Query("pageSize") != "" {
c.ShouldBindQuery(&pageSize)
}
// 获取操作日志
logs, total, err := repositories.GetOperationLogs(page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get operation logs"})
return
}
c.JSON(http.StatusOK, gin.H{
"list": repositories.BuildOperationLogsResponse(logs),
"total": total,
"page": page,
"size": pageSize,
})
}

182
server/handlers/post.go Normal file
View File

@@ -0,0 +1,182 @@
package handlers
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
)
// 获取博客文章列表
func GetPosts(c *gin.Context) {
// 从数据库获取所有博客文章
posts, err := repositories.GetPosts()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch posts"})
return
}
// 构建响应
responses := repositories.BuildPostsResponse(posts)
c.JSON(http.StatusOK, responses)
}
func GetPost(c *gin.Context) {
id := c.Param("id")
// 从数据库获取博客文章
post, err := repositories.GetPostByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch post"})
return
}
if post == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Post not found"})
return
}
// 构建响应,包含内容
response := repositories.BuildPostResponse(post, true)
c.JSON(http.StatusOK, 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()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get posts"})
return
}
c.JSON(http.StatusOK, repositories.BuildPostsResponse(posts))
}
// 创建文章
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"})
return
}
// 创建文章
if err := repositories.CreatePost(&post); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create post"})
return
}
// 保存历史记录
userID, _ := c.Get("userID")
if err := repositories.SavePostHistory(&post, userID.(uint)); err != nil {
log.Printf("Error saving post history: %v", err)
}
c.JSON(http.StatusOK, gin.H{"message": "Post created successfully"})
}
// 更新文章
func AdminUpdatePost(c *gin.Context) {
postID := c.Param("id")
var post models.Post
if err := c.ShouldBindJSON(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 设置文章ID
post.ID = postID
// 更新文章
if err := repositories.UpdatePost(&post); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update post"})
return
}
// 保存历史记录
userID, _ := c.Get("userID")
if err := repositories.SavePostHistory(&post, userID.(uint)); err != nil {
log.Printf("Error saving post history: %v", err)
}
c.JSON(http.StatusOK, gin.H{"message": "Post updated successfully"})
}
// 删除文章
func AdminDeletePost(c *gin.Context) {
postID := c.Param("id")
// 删除文章
if err := repositories.DeletePost(postID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete post"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Post deleted successfully"})
}
// 获取文章历史记录
func AdminGetPostHistory(c *gin.Context) {
postID := c.Param("id")
history, err := repositories.GetPostHistory(postID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get post history"})
return
}
c.JSON(http.StatusOK, repositories.BuildPostHistoryResponses(history))
}
// 获取指定版本的文章历史记录
func AdminGetPostHistoryByVersion(c *gin.Context) {
postID := c.Param("id")
version := c.Param("version")
// 转换版本号为uint
var versionUint uint
_, err := fmt.Sscanf(version, "%d", &versionUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid version"})
return
}
history, err := repositories.GetPostHistoryByVersion(postID, versionUint)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get post history"})
return
}
if history == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "History not found"})
return
}
c.JSON(http.StatusOK, repositories.BuildPostHistoryResponse(history))
}

145
server/handlers/role.go Normal file
View File

@@ -0,0 +1,145 @@
package handlers
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
)
// 获取角色列表
func AdminGetRoles(c *gin.Context) {
roles, err := repositories.GetRoles()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get roles"})
return
}
c.JSON(http.StatusOK, repositories.BuildRolesResponse(roles))
}
// 创建角色
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"})
return
}
// 创建角色
if err := repositories.CreateRole(&role); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create role"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role created successfully"})
}
// 更新角色
func AdminUpdateRole(c *gin.Context) {
roleID := c.Param("id")
var role models.Role
if err := c.ShouldBindJSON(&role); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 转换角色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"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role updated successfully"})
}
// 删除角色
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"})
return
}
// 删除角色
if err := repositories.DeleteRole(idUint); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete role"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role deleted successfully"})
}
// 获取所有权限列表
func AdminGetPermissions(c *gin.Context) {
permissions, err := repositories.GetPermissions()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get permissions"})
return
}
c.JSON(http.StatusOK, repositories.BuildPermissionsResponse(permissions))
}
// 更新角色权限请求结构
type UpdateRolePermissionsRequest struct {
PermissionIDs []uint `json:"permissionIds" binding:"required"`
}
// 更新角色的权限
func AdminUpdateRolePermissions(c *gin.Context) {
roleIDStr := c.Param("id")
// 转换角色ID
var roleID uint
id, err := strconv.ParseUint(roleIDStr, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid role ID"})
return
}
roleID = uint(id)
// 绑定请求数据
var req UpdateRolePermissionsRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request format"})
return
}
// 检查角色是否存在
role, err := repositories.GetRoleByID(roleID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to check role existence"})
return
}
if role == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "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"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Role permissions updated successfully"})
}

54
server/handlers/runner.go Normal file
View File

@@ -0,0 +1,54 @@
package handlers
import (
"context"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/runner"
)
type RunCodeRequest struct {
Language string `json:"language" binding:"required"`
Code string `json:"code" binding:"required"`
}
func RunCode(c *gin.Context) {
var req RunCodeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 对于前端语言,直接返回代码供前端渲染,或者提示不支持后端执行
switch req.Language {
case "html", "vue", "react", "css":
c.JSON(http.StatusOK, gin.H{
"output": req.Code, // 或者返回 "Client-side rendering only"
"isClient": true,
})
return
}
// 获取运行器
r, err := runner.GetRunner(req.Language)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 设置超时上下文 (例如 5 秒)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// 执行代码
result, err := r.Run(ctx, req.Code)
if err != nil {
// 运行错误(如无法启动进程)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}

View File

@@ -0,0 +1,67 @@
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
)
// 获取系统配置列表
func AdminGetSettings(c *gin.Context) {
settings, err := repositories.GetSettings()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get settings"})
return
}
c.JSON(http.StatusOK, repositories.BuildSettingsResponse(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"})
return
}
// 更新系统配置
if err := repositories.UpdateSetting(&setting); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update setting"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Setting updated successfully"})
}
// 创建系统配置
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"})
return
}
// 创建系统配置
if err := repositories.CreateSetting(&setting); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create setting"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Setting created successfully"})
}
// 删除系统配置
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"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Setting deleted successfully"})
}

106
server/handlers/snippet.go Normal file
View File

@@ -0,0 +1,106 @@
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
)
// 获取代码片段列表
func GetSnippets(c *gin.Context) {
// 从数据库获取所有代码片段
snippets, err := repositories.GetSnippets()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch snippets"})
return
}
// 构建响应
responses := repositories.BuildSnippetsResponse(snippets)
c.JSON(http.StatusOK, responses)
}
func GetSnippet(c *gin.Context) {
id := c.Param("id")
// 从数据库获取代码片段
snippet, err := repositories.GetSnippetByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch snippet"})
return
}
if snippet == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Snippet not found"})
return
}
// 构建响应
response := repositories.BuildSnippetResponse(snippet)
c.JSON(http.StatusOK, response)
}
// 获取代码片段列表 (Admin)
func AdminGetSnippets(c *gin.Context) {
snippets, err := repositories.GetSnippets()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get snippets"})
return
}
c.JSON(http.StatusOK, repositories.BuildSnippetsResponse(snippets))
}
// 创建代码片段
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"})
return
}
// 创建代码片段
if err := repositories.CreateSnippet(&snippet); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create snippet"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Snippet created successfully"})
}
// 更新代码片段
func AdminUpdateSnippet(c *gin.Context) {
snippetID := c.Param("id")
var snippet models.Snippet
if err := c.ShouldBindJSON(&snippet); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 设置代码片段ID
snippet.ID = snippetID
// 更新代码片段
if err := repositories.UpdateSnippet(&snippet); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update snippet"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Snippet updated successfully"})
}
// 删除代码片段
func AdminDeleteSnippet(c *gin.Context) {
snippetID := c.Param("id")
// 删除代码片段
if err := repositories.DeleteSnippet(snippetID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete snippet"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Snippet deleted successfully"})
}

132
server/handlers/tag.go Normal file
View File

@@ -0,0 +1,132 @@
package handlers
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
)
// 获取标签列表
func GetTags(c *gin.Context) {
// 从数据库获取所有标签
tags, err := repositories.GetTags()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch tags"})
return
}
// 构建响应
responses := repositories.BuildTagsResponse(tags)
c.JSON(http.StatusOK, responses)
}
func GetTag(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
}
// 从数据库获取标签
tag, err := repositories.GetTagByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch tag"})
return
}
if tag == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Tag not found"})
return
}
// 构建响应
response := repositories.BuildTagResponse(tag)
c.JSON(http.StatusOK, response)
}
// 获取标签列表 (Admin)
func AdminGetTags(c *gin.Context) {
// 从数据库获取所有标签
tags, err := repositories.GetTags()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get tags"})
return
}
c.JSON(http.StatusOK, 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"})
return
}
// 创建标签
if err := repositories.CreateTag(&tag); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create tag"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Tag created successfully"})
}
// 更新标签
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"})
return
}
// 转换标签ID为uint
var idUint uint
_, err := fmt.Sscanf(tagID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid tag ID"})
return
}
// 设置标签ID
tag.ID = idUint
// 更新标签
if err := repositories.UpdateTag(&tag); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update tag"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Tag updated successfully"})
}
// 删除标签
func AdminDeleteTag(c *gin.Context) {
tagID := c.Param("id")
// 转换标签ID为uint
var idUint uint
_, err := fmt.Sscanf(tagID, "%d", &idUint)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid tag ID"})
return
}
// 删除标签
if err := repositories.DeleteTag(idUint); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete tag"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Tag deleted successfully"})
}

129
server/handlers/user.go Normal file
View File

@@ -0,0 +1,129 @@
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"
)
// GetUsers 获取所有用户
func AdminGetUsers(c *gin.Context) {
users, err := repositories.GetUsers()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get users"})
return
}
c.JSON(http.StatusOK, repositories.BuildUsersResponse(users))
}
// 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 创建用户
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"})
return
}
// 设置默认密码并使用bcrypt哈希
defaultPassword := "admin123"
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(defaultPassword), bcrypt.DefaultCost)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"})
return
}
user.PasswordHash = string(hashedPassword)
// 创建用户
if err := repositories.CreateUser(&user); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "User created successfully"})
}
// UpdateUser 更新用户
func AdminUpdateUser(c *gin.Context) {
userID := c.Param("id")
var user models.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 转换用户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
}
// 设置用户ID
user.ID = idUint
// 更新用户
if err := repositories.UpdateUser(&user); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "User updated successfully"})
}
// DeleteUser 删除用户
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"})
return
}
// 删除用户
if err := repositories.DeleteUser(idUint); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete user"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "User deleted successfully"})
}

130
server/handlers/work.go Normal file
View File

@@ -0,0 +1,130 @@
package handlers
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
)
// 获取作品列表
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) {
id := c.Param("id")
// 从数据库获取作品
work, err := repositories.GetWorkByID(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch work"})
return
}
if work == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Work not found"})
return
}
// 构建响应
response, err := repositories.BuildWorkResponse(work)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to build work response"})
return
}
c.JSON(http.StatusOK, response)
}
// 获取作品列表 (Admin)
func AdminGetWorks(c *gin.Context) {
works, err := repositories.GetWorks()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get 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 AdminCreateWork(c *gin.Context) {
var work models.Work
if err := c.ShouldBindJSON(&work); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 创建作品
if err := repositories.CreateWork(&work); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create work"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Work created successfully"})
}
// 更新作品
func AdminUpdateWork(c *gin.Context) {
workID := c.Param("id")
var work models.Work
if err := c.ShouldBindJSON(&work); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}
// 设置作品ID
work.ID = workID
// 更新作品
if err := repositories.UpdateWork(&work); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update work"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Work updated successfully"})
}
// 删除作品
func AdminDeleteWork(c *gin.Context) {
workID := c.Param("id")
// 删除作品
if err := repositories.DeleteWork(workID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete work"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Work deleted successfully"})
}