Pārlūkot izejas kodu

feat: 创建分类

runningwater 4 mēneši atpakaļ
vecāks
revīzija
79abe57834

+ 86 - 0
app/http/controllers/api/v1/categories_controller.go

@@ -0,0 +1,86 @@
+package v1
+
+import (
+	"github.com/runningwater/gohub/app/models/category"
+	"github.com/runningwater/gohub/app/requests"
+	"github.com/runningwater/gohub/pkg/response"
+
+	"github.com/gin-gonic/gin"
+)
+
+type CategoriesController struct {
+	BaseApiController
+}
+
+func (ctrl *CategoriesController) Store(c *gin.Context) {
+
+	request := requests.CategoryRequest{}
+	if ok := requests.Validate(c, &request, requests.CategorySave); !ok {
+		return
+	}
+
+	categoryModel := category.Category{
+		Name:        request.Name,
+		Description: request.Description,
+	}
+	categoryModel.Create()
+	if categoryModel.ID > 0 {
+		response.Created(c, categoryModel)
+	} else {
+		response.Abort500(c, "创建失败,请稍后尝试~")
+	}
+}
+
+// func (ctrl *CategoriesController) Update(c *gin.Context) {
+//
+//     categoryModel := category.Get(c.Param("id"))
+//     if categoryModel.ID == 0 {
+//         response.Abort404(c)
+//         return
+//     }
+//
+//     if ok := policies.CanModifyCategory(c, categoryModel); !ok {
+//         response.Abort403(c)
+//         return
+//     }
+//
+//     request := requests.CategoryRequest{}
+//     bindOk, errs := requests.Validate(c, &request, requests.CategorySave)
+//     if !bindOk {
+//         return
+//     }
+//     if len(errs) > 0 {
+//         response.ValidationError(c, errs)
+//         return
+//     }
+//
+//     categoryModel.FieldName = request.FieldName
+//     rowsAffected := categoryModel.Save()
+//     if rowsAffected > 0 {
+//         response.Data(c, categoryModel)
+//     } else {
+//         response.Abort500(c, "更新失败,请稍后尝试~")
+//     }
+// }
+//
+// func (ctrl *CategoriesController) Delete(c *gin.Context) {
+//
+//     categoryModel := category.Get(c.Param("id"))
+//     if categoryModel.ID == 0 {
+//         response.Abort404(c)
+//         return
+//     }
+//
+//     if ok := policies.CanModifyCategory(c, categoryModel); !ok {
+//         response.Abort403(c)
+//         return
+//     }
+//
+//     rowsAffected := categoryModel.Delete()
+//     if rowsAffected > 0 {
+//         response.Success(c)
+//         return
+//     }
+//
+//     response.Abort500(c, "删除失败,请稍后尝试~")
+// }

+ 32 - 0
app/requests/category_request.go

@@ -0,0 +1,32 @@
+package requests
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/thedevsaddam/govalidator"
+)
+
+type CategoryRequest struct {
+	Name        string `valid:"name" json:"name"`
+	Description string `valid:"description" json:"description,omitempty"`
+}
+
+func CategorySave(data any, c *gin.Context) map[string][]string {
+
+	rules := govalidator.MapData{
+		"name":        []string{"required", "min_cn:2", "max_cn:8", "not_exists:categories,name"},
+		"description": []string{"min_cn:3", "max_cn:255"},
+	}
+	messages := govalidator.MapData{
+		"name": []string{
+			"required:名称为必填项",
+			"min_cn:名称长度需至少 2 个字",
+			"max_cn:名称长度不能超过 8 个字",
+			"not_exists:名称已存在",
+		},
+		"description": []string{
+			"min_cn:描述长度需至少 3 个字",
+			"max_cn:描述长度不能超过 255 个字",
+		},
+	}
+	return validate(data, rules, messages)
+}

+ 32 - 1
app/requests/validators/custom_rules.go

@@ -3,10 +3,13 @@ package validators
 import (
 	"errors"
 	"fmt"
+	"strconv"
 	"strings"
+	"unicode/utf8"
 
-	"github.com/runningwater/gohub/pkg/database"
 	"github.com/thedevsaddam/govalidator"
+
+	"github.com/runningwater/gohub/pkg/database"
 )
 
 func init() {
@@ -56,4 +59,32 @@ func init() {
 		return nil
 
 	})
+
+	// max_cn:8 中文最多 8 个字
+	govalidator.AddCustomRule("max_cn", func(field string, rule string, message string, value any) error {
+		valueLen := utf8.RuneCountInString(value.(string))
+		maxLen, _ := strconv.Atoi(strings.TrimPrefix(rule, "max_cn:"))
+		if valueLen > maxLen {
+			// 如果有自定义错误消息的话,使用自定义消息
+			if message != "" {
+				return errors.New(message)
+			}
+			return fmt.Errorf("%v 长度不能超过 %v 个字", field, maxLen)
+		}
+		return nil
+	})
+
+	// min_cn:8 中文长度最少 8 个字
+	govalidator.AddCustomRule("min_cn", func(field string, rule string, message string, value any) error {
+		valueLen := utf8.RuneCountInString(value.(string))
+		minLen, _ := strconv.Atoi(strings.TrimPrefix(rule, "min_cn:"))
+		if valueLen < minLen {
+			// 如果有自定义错误消息的话,使用自定义消息
+			if message != "" {
+				return errors.New(message)
+			}
+			return fmt.Errorf("%v 长度不能小于 %v 个字", field, minLen)
+		}
+		return nil
+	})
 }

+ 11 - 1
gohub.http

@@ -94,4 +94,14 @@ Authorization: Bearer {{access_token}}
 
 
 ### users
-GET {{base_url}}/v1/users HTTP/1.1
+GET {{base_url}}/v1/users HTTP/1.1
+
+### 创建分类
+POST {{base_url}}/v1/categories HTTP/1.1
+Authorization: Bearer {{access_token}}
+Content-Type: application/json
+
+{
+    "name": "分类1",
+    "description": "分类1描述"
+}

+ 1 - 1
http-client.env.json

@@ -1,6 +1,6 @@
 {
   "dev": {
     "base_url": "http://127.0.0.1:3000",
-    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMSIsInVzZXJfbmFtZSI6InN1bW1lciIsImV4cGlyZV90aW1lIjoxNzU3NzMyNTk3LCJpc3MiOiJHb2h1YiIsInN1YiI6IjEiLCJhdWQiOlsic3VtbWVyIl0sImV4cCI6MTc1NzczMjU5NywibmJmIjoxNzUyNTQ4NTk3LCJpYXQiOjE3NTI1NDg1OTd9.4bE5RE1saBymOUuMewdAUKmy5U6AKM_tc4hQyH9lrk4"
+    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMSIsInVzZXJfbmFtZSI6InN1bW1lciIsImV4cGlyZV90aW1lIjoxNzU3ODE2NDI3LCJpc3MiOiJHb2h1YiIsInN1YiI6IjEiLCJhdWQiOlsic3VtbWVyIl0sImV4cCI6MTc1NzgxNjQyNywibmJmIjoxNzUyNjMyNDI3LCJpYXQiOjE3NTI2MzI0Mjd9.9tYiBN5J4PVblgM1vk09s8sPq2Hqsvm5YimJcV19iaw"
   }
 }

+ 1 - 1
pkg/console/console.go

@@ -43,5 +43,5 @@ func ExitIf(err error) {
 }
 
 func colorOut(msg, color string) {
-	fmt.Fprintln(os.Stdout, ansi.Color(msg, color))
+	_, _ = fmt.Fprintln(os.Stdout, ansi.Color(msg, color))
 }

+ 1 - 1
pkg/migrate/migrator.go

@@ -24,7 +24,7 @@ func (m *Migrator) createMigrationsTable() {
 
 	if !m.Migrator.HasTable(&migration) {
 		// 如果表不存在,则创建表
-		if err := m.DB.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci").AutoMigrate(&migration); err != nil {
+		if err := m.DB.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci").Migrator().CreateTable(&migration); err != nil {
 			console.ExitIf(err)
 			return
 		}

+ 6 - 1
routes/api.go

@@ -18,7 +18,6 @@ func RegisterAPIRoutes(router *gin.Engine) {
 	// 作为参考 Github API 每小时最多 60 个请求(根据 IP)。
 	// 测试时,可以调高一点。
 	v1.Use(middlewares.LimitIP("200-H"))
-
 	{
 		uc := new(controllers.UsersController)
 
@@ -59,5 +58,11 @@ func RegisterAPIRoutes(router *gin.Engine) {
 		{
 			userGroup.GET("", uc.Index)
 		}
+
+		cgc := new(controllers.CategoriesController)
+		categoryGroup := v1.Group("/categories")
+		{
+			categoryGroup.POST("", middlewares.AuthJWT(), cgc.Store)
+		}
 	}
 }