diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e7587b3..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "files.associations": { - "iostream": "cpp", - "ostream": "cpp", - "iosfwd": "cpp", - "xstring": "cpp" - } -} \ No newline at end of file diff --git a/controller/controller.go b/controller/controller.go index c57ea94..401f191 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -3,6 +3,7 @@ package controller import ( "yitao/service" + "github.com/iris-contrib/middleware/jwt" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/core/router" "github.com/kataras/iris/v12/mvc" @@ -38,3 +39,13 @@ func registerController(root string, controller ControllerInterface) { ) router.Handle(controller) } + +func GetUidFromCtx(ctx iris.Context) uint { + // 从 jwt 中获取 uid + if token, ok := ctx.Values().Get("jwt").(*jwt.Token); ok { + // Use the token if needed + uid := uint(token.Claims.(jwt.MapClaims)["uid"].(float64)) + return uid + } + return 0 +} diff --git a/controller/file_controller.go b/controller/file_controller.go index fcf6a98..a25b58b 100644 --- a/controller/file_controller.go +++ b/controller/file_controller.go @@ -44,7 +44,7 @@ func (c *FileController) UploadItemImg() mvc.Result { if !util.FileIsImage(file.SystemPath) { // 文件不是图片文件 util.DeleteFile(file.SystemPath) - c.Service.File.SetFileStatus(file.ID, model.FileStatusDelete) + c.Service.File.SetFileState(file.ID, model.FileStateDelete) return ecode.File(ecode.FILE_TYPE_ERR).Response() } diff --git a/controller/item_controller.go b/controller/item_controller.go index 4bedc41..8fe8d64 100644 --- a/controller/item_controller.go +++ b/controller/item_controller.go @@ -19,6 +19,7 @@ func (c *ItemController) BeforeActivation(b mvc.BeforeActivation) { // 管理员接口 { b.Handle("POST", "/oper/create", "Create", middleware.JwtMiddleware.Serve) + b.Handle("DELETE", "/oper/delete", "Delete", middleware.JwtMiddleware.Serve) //b.Handle("POST", "/admin/update", "Update", middleware.JwtMiddleware.Serve, middleware.AdminMiddleware) //b.Handle("POST", "/admin/delete", "Delete", middleware.JwtMiddleware.Serve, middleware.AdminMiddleware) } @@ -55,7 +56,14 @@ func (c *ItemController) Create() mvc.Result { return e.Response() } - item, e := c.Service.Item.CreateItem(create_item_param.Itemname, create_item_param.Desc, create_item_param.Types, create_item_param.Img, create_item_param.Price) + // 验证图片文件是否存在 + _, e = c.Service.File.GetFileId(create_item_param.Img) + if e.Error() { + return e.Response() + } + + uid := GetUidFromCtx(c.Ctx) + item, e := c.Service.Item.CreateItem(uid, create_item_param.Itemname, create_item_param.Desc, create_item_param.Types, create_item_param.Img, create_item_param.Price) if e.Error() { return e.Response() } @@ -64,3 +72,25 @@ func (c *ItemController) Create() mvc.Result { Object: item, } } + +// @Summary 删除商品 +// @Description 删除商品接口 +// @Tags item api +// @Accept json +// @Produce json +// @Param deleteItemParam body validate.DeleteItemParam true "商品信息" +// @Success 200 {object} map[string]interface{} "{"msg": "商品操作成功"}" +// @Failure 400 {object} map[string]interface{} "{"msg": "错误信息","code":0}" +// @Router /api/item/oper/delete [delete] +func (c *ItemController) Delete() mvc.Result { + e := ecode.OK() + deleteItemParam := new(validate.DeleteItemParam) + e = validate.ReadJSON(c.Ctx, deleteItemParam) + if e.Error() { + return e.Response() + } + + uid := GetUidFromCtx(c.Ctx) + c.Service.Item.DeleteItem(uid, 1) + return e.Response() +} diff --git a/docs/docs.go b/docs/docs.go index 59ee9ce..91a9e78 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -343,6 +343,48 @@ const docTemplate = `{ } } }, + "/api/item/oper/delete": { + "delete": { + "description": "删除商品接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "item api" + ], + "summary": "删除商品", + "parameters": [ + { + "description": "商品信息", + "name": "deleteItemParam", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/validate.DeleteItemParam" + } + } + ], + "responses": { + "200": { + "description": "{\"msg\": \"商品操作成功\"}", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "{\"msg\": \"错误信息\",\"code\":0}", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, "/api/user/auth/login": { "post": { "description": "the 用户登录接口", @@ -450,7 +492,7 @@ const docTemplate = `{ "price": { "type": "integer" }, - "states": { + "state": { "type": "string" }, "typeString": { @@ -462,6 +504,9 @@ const docTemplate = `{ "type": "integer" } }, + "uid": { + "type": "integer" + }, "updatedAt": { "type": "string" } @@ -509,6 +554,18 @@ const docTemplate = `{ } } }, + "validate.DeleteItemParam": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "example": 1 + } + } + }, "validate.LoginParam": { "type": "object", "required": [ diff --git a/docs/swagger.json b/docs/swagger.json index ae1bed0..86b233e 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -337,6 +337,48 @@ } } }, + "/api/item/oper/delete": { + "delete": { + "description": "删除商品接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "item api" + ], + "summary": "删除商品", + "parameters": [ + { + "description": "商品信息", + "name": "deleteItemParam", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/validate.DeleteItemParam" + } + } + ], + "responses": { + "200": { + "description": "{\"msg\": \"商品操作成功\"}", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "{\"msg\": \"错误信息\",\"code\":0}", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, "/api/user/auth/login": { "post": { "description": "the 用户登录接口", @@ -444,7 +486,7 @@ "price": { "type": "integer" }, - "states": { + "state": { "type": "string" }, "typeString": { @@ -456,6 +498,9 @@ "type": "integer" } }, + "uid": { + "type": "integer" + }, "updatedAt": { "type": "string" } @@ -503,6 +548,18 @@ } } }, + "validate.DeleteItemParam": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "example": 1 + } + } + }, "validate.LoginParam": { "type": "object", "required": [ diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 68b7b5d..a76567e 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -14,7 +14,7 @@ definitions: type: string price: type: integer - states: + state: type: string typeString: type: string @@ -22,6 +22,8 @@ definitions: items: type: integer type: array + uid: + type: integer updatedAt: type: string type: object @@ -57,6 +59,14 @@ definitions: - price - types type: object + validate.DeleteItemParam: + properties: + id: + example: 1 + type: integer + required: + - id + type: object validate.LoginParam: properties: captcha_data: @@ -331,6 +341,34 @@ paths: summary: 创建商品 tags: - item api + /api/item/oper/delete: + delete: + consumes: + - application/json + description: 删除商品接口 + parameters: + - description: 商品信息 + in: body + name: deleteItemParam + required: true + schema: + $ref: '#/definitions/validate.DeleteItemParam' + produces: + - application/json + responses: + "200": + description: '{"msg": "商品操作成功"}' + schema: + additionalProperties: true + type: object + "400": + description: '{"msg": "错误信息","code":0}' + schema: + additionalProperties: true + type: object + summary: 删除商品 + tags: + - item api /api/user/auth/login: post: consumes: diff --git a/ecode/item_ecode.go b/ecode/item_ecode.go new file mode 100644 index 0000000..5b72983 --- /dev/null +++ b/ecode/item_ecode.go @@ -0,0 +1,20 @@ +package ecode + +const ( + ITEM_OK = iota + ITEM_NOT_FOUND + ITEM_PERMISSION_DENIED +) + +var ITEM_MSG = map[int]string{ + ITEM_OK: "商品操作成功", + ITEM_NOT_FOUND: "商品不存在", + ITEM_PERMISSION_DENIED: "操作权限不足", +} + +func Item(id int) *Ecode { + code := new(Ecode) + code.Code = id + code.Msg = ITEM_MSG[id] + return code +} diff --git a/model/file_model.go b/model/file_model.go index 9f503bc..a4805c4 100644 --- a/model/file_model.go +++ b/model/file_model.go @@ -3,8 +3,8 @@ package model const ( FileTypeItemImg = "item-img" - FileStatusNormal = "normal" - FileStatusDelete = "delete" + FileStateNormal = "normal" + FileStateDelete = "delete" ) type FileModel struct { @@ -15,7 +15,8 @@ type FileModel struct { Url string SystemPath string Key string - Status string + State string + Uid uint } func (f *FileModel) TableName() string { diff --git a/model/item_model.go b/model/item_model.go index cf23993..f268878 100644 --- a/model/item_model.go +++ b/model/item_model.go @@ -8,6 +8,7 @@ import ( const ( ItemStateOnSale = "onsale" + ItemStateDelete = "delete" ) // type 是外部输入的 []int 类型,需要转换成 string 类型存储到数据库 @@ -19,7 +20,8 @@ type ItemModel struct { Price int Desc string Img string - States string + State string + Uid uint } func (m *ItemModel) TableName() string { diff --git a/model/user_model.go b/model/user_model.go index 40be22c..5d4ade9 100644 --- a/model/user_model.go +++ b/model/user_model.go @@ -3,8 +3,8 @@ package model type UserStatus string const ( - UserStatusPending UserStatus = "pending" - UserStatusComfirmed UserStatus = "confirmed" + UserStatePending UserStatus = "pending" + UserStateComfirmed UserStatus = "confirmed" ) type UserModel struct { @@ -13,7 +13,7 @@ type UserModel struct { Username string Passhash string Secret string - Status UserStatus `gorm:"type:enum('pending', 'confirmed')"` + State UserStatus `gorm:"type:enum('pending', 'confirmed')"` IsAdmin bool `gorm:"default:false"` } diff --git a/service/file_service.go b/service/file_service.go index 003a633..65d14b1 100644 --- a/service/file_service.go +++ b/service/file_service.go @@ -16,7 +16,7 @@ func (s *FileService) UploadItemImg(header *multipart.FileHeader) (*model.FileMo file.Name = header.Filename file.Key = util.RandString(12) file.Size = header.Size - file.Status = model.FileStatusNormal + file.State = model.FileStateNormal file.Url = "/upload/item/img/" + file.Key + ".jpg" file.SystemPath = "./public" + file.Url model.DB.Create(file) @@ -25,13 +25,23 @@ func (s *FileService) UploadItemImg(header *multipart.FileHeader) (*model.FileMo } // 设置文件状态 -func (s *FileService) SetFileStatus(id uint, status string) *ecode.Ecode { +func (s *FileService) SetFileState(id uint, status string) *ecode.Ecode { file := new(model.FileModel) model.DB.First(file, id) if file.ID == 0 { return ecode.File(ecode.FILE_NOT_FOUND) } - file.Status = status + file.State = status model.DB.Save(file) return ecode.OK() } + +// 获取文件Id +func (s *FileService) GetFileId(key string) (uint, *ecode.Ecode) { + file := new(model.FileModel) + model.DB.Where("`key`=?", key).Where("status=?", model.FileStateNormal).First(file) + if file.ID == 0 { + return 0, ecode.File(ecode.FILE_NOT_FOUND) + } + return file.ID, ecode.OK() +} diff --git a/service/item_service.go b/service/item_service.go index 8de4fb1..b8c5811 100644 --- a/service/item_service.go +++ b/service/item_service.go @@ -7,7 +7,7 @@ import ( type ItemService struct{} -func (s *ItemService) CreateItem(itemname string, desc string, types []int, img string, price int) (item *model.ItemModel, e *ecode.Ecode) { +func (s *ItemService) CreateItem(uid uint, itemname string, desc string, types []int, img string, price int) (item *model.ItemModel, e *ecode.Ecode) { item = new(model.ItemModel) e = ecode.OK() item.Itemname = itemname @@ -15,7 +15,21 @@ func (s *ItemService) CreateItem(itemname string, desc string, types []int, img item.Types = types item.Img = img item.Price = price - item.States = model.ItemStateOnSale + item.State = model.ItemStateOnSale + item.Uid = uid model.DB.Create(item) return } + +func (s *ItemService) DeleteItem(uid uint, item_id uint) *ecode.Ecode { + item := new(model.ItemModel) + model.DB.Where("id=?", item_id).First(item) + if item.Uid != uid { + return ecode.Item(ecode.ITEM_PERMISSION_DENIED) + } + // 将商品状态设置为删除 + item.State = model.ItemStateDelete + model.DB.Save(item) + + return ecode.OK() +} diff --git a/service/user_service.go b/service/user_service.go index 5d8cc68..7ee3f30 100644 --- a/service/user_service.go +++ b/service/user_service.go @@ -35,7 +35,7 @@ func (u *UserService) AuthSignup(username string, password string) (user *model. user.Username = username user.Secret = util.RandString(16) user.Passhash = util.MD5(user.Secret + password + user.Secret) - user.Status = model.UserStatusComfirmed + user.State = model.UserStateComfirmed model.DB.Create(user) return } diff --git a/validate/item_validate.go b/validate/item_validate.go index 93175f2..6d9d386 100644 --- a/validate/item_validate.go +++ b/validate/item_validate.go @@ -10,3 +10,7 @@ type CreateItemParam struct { // @description 商品类型,可以有多个类型,请用数组传过来,类型id请使用 /item/types 接口获取 Types []int `json:"types" validate:"required" example:"1,2"` } + +type DeleteItemParam struct { + Id uint `json:"id" validate:"required" example:"1"` +}