新增了删除商品接口

This commit is contained in:
wzj 2024-11-09 16:36:28 +08:00
parent 0a55c9742c
commit da9cbc2156
15 changed files with 262 additions and 26 deletions

View File

@ -1,8 +0,0 @@
{
"files.associations": {
"iostream": "cpp",
"ostream": "cpp",
"iosfwd": "cpp",
"xstring": "cpp"
}
}

View File

@ -3,6 +3,7 @@ package controller
import ( import (
"yitao/service" "yitao/service"
"github.com/iris-contrib/middleware/jwt"
"github.com/kataras/iris/v12" "github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/core/router" "github.com/kataras/iris/v12/core/router"
"github.com/kataras/iris/v12/mvc" "github.com/kataras/iris/v12/mvc"
@ -38,3 +39,13 @@ func registerController(root string, controller ControllerInterface) {
) )
router.Handle(controller) 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
}

View File

@ -44,7 +44,7 @@ func (c *FileController) UploadItemImg() mvc.Result {
if !util.FileIsImage(file.SystemPath) { if !util.FileIsImage(file.SystemPath) {
// 文件不是图片文件 // 文件不是图片文件
util.DeleteFile(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() return ecode.File(ecode.FILE_TYPE_ERR).Response()
} }

View File

@ -19,6 +19,7 @@ func (c *ItemController) BeforeActivation(b mvc.BeforeActivation) {
// 管理员接口 // 管理员接口
{ {
b.Handle("POST", "/oper/create", "Create", middleware.JwtMiddleware.Serve) 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/update", "Update", middleware.JwtMiddleware.Serve, middleware.AdminMiddleware)
//b.Handle("POST", "/admin/delete", "Delete", 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() 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() { if e.Error() {
return e.Response() return e.Response()
} }
@ -64,3 +72,25 @@ func (c *ItemController) Create() mvc.Result {
Object: item, 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()
}

View File

@ -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": { "/api/user/auth/login": {
"post": { "post": {
"description": "the 用户登录接口", "description": "the 用户登录接口",
@ -450,7 +492,7 @@ const docTemplate = `{
"price": { "price": {
"type": "integer" "type": "integer"
}, },
"states": { "state": {
"type": "string" "type": "string"
}, },
"typeString": { "typeString": {
@ -462,6 +504,9 @@ const docTemplate = `{
"type": "integer" "type": "integer"
} }
}, },
"uid": {
"type": "integer"
},
"updatedAt": { "updatedAt": {
"type": "string" "type": "string"
} }
@ -509,6 +554,18 @@ const docTemplate = `{
} }
} }
}, },
"validate.DeleteItemParam": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"example": 1
}
}
},
"validate.LoginParam": { "validate.LoginParam": {
"type": "object", "type": "object",
"required": [ "required": [

View File

@ -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": { "/api/user/auth/login": {
"post": { "post": {
"description": "the 用户登录接口", "description": "the 用户登录接口",
@ -444,7 +486,7 @@
"price": { "price": {
"type": "integer" "type": "integer"
}, },
"states": { "state": {
"type": "string" "type": "string"
}, },
"typeString": { "typeString": {
@ -456,6 +498,9 @@
"type": "integer" "type": "integer"
} }
}, },
"uid": {
"type": "integer"
},
"updatedAt": { "updatedAt": {
"type": "string" "type": "string"
} }
@ -503,6 +548,18 @@
} }
} }
}, },
"validate.DeleteItemParam": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"example": 1
}
}
},
"validate.LoginParam": { "validate.LoginParam": {
"type": "object", "type": "object",
"required": [ "required": [

View File

@ -14,7 +14,7 @@ definitions:
type: string type: string
price: price:
type: integer type: integer
states: state:
type: string type: string
typeString: typeString:
type: string type: string
@ -22,6 +22,8 @@ definitions:
items: items:
type: integer type: integer
type: array type: array
uid:
type: integer
updatedAt: updatedAt:
type: string type: string
type: object type: object
@ -57,6 +59,14 @@ definitions:
- price - price
- types - types
type: object type: object
validate.DeleteItemParam:
properties:
id:
example: 1
type: integer
required:
- id
type: object
validate.LoginParam: validate.LoginParam:
properties: properties:
captcha_data: captcha_data:
@ -331,6 +341,34 @@ paths:
summary: 创建商品 summary: 创建商品
tags: tags:
- item api - 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: /api/user/auth/login:
post: post:
consumes: consumes:

20
ecode/item_ecode.go Normal file
View File

@ -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
}

View File

@ -3,8 +3,8 @@ package model
const ( const (
FileTypeItemImg = "item-img" FileTypeItemImg = "item-img"
FileStatusNormal = "normal" FileStateNormal = "normal"
FileStatusDelete = "delete" FileStateDelete = "delete"
) )
type FileModel struct { type FileModel struct {
@ -15,7 +15,8 @@ type FileModel struct {
Url string Url string
SystemPath string SystemPath string
Key string Key string
Status string State string
Uid uint
} }
func (f *FileModel) TableName() string { func (f *FileModel) TableName() string {

View File

@ -8,6 +8,7 @@ import (
const ( const (
ItemStateOnSale = "onsale" ItemStateOnSale = "onsale"
ItemStateDelete = "delete"
) )
// type 是外部输入的 []int 类型,需要转换成 string 类型存储到数据库 // type 是外部输入的 []int 类型,需要转换成 string 类型存储到数据库
@ -19,7 +20,8 @@ type ItemModel struct {
Price int Price int
Desc string Desc string
Img string Img string
States string State string
Uid uint
} }
func (m *ItemModel) TableName() string { func (m *ItemModel) TableName() string {

View File

@ -3,8 +3,8 @@ package model
type UserStatus string type UserStatus string
const ( const (
UserStatusPending UserStatus = "pending" UserStatePending UserStatus = "pending"
UserStatusComfirmed UserStatus = "confirmed" UserStateComfirmed UserStatus = "confirmed"
) )
type UserModel struct { type UserModel struct {
@ -13,7 +13,7 @@ type UserModel struct {
Username string Username string
Passhash string Passhash string
Secret string Secret string
Status UserStatus `gorm:"type:enum('pending', 'confirmed')"` State UserStatus `gorm:"type:enum('pending', 'confirmed')"`
IsAdmin bool `gorm:"default:false"` IsAdmin bool `gorm:"default:false"`
} }

View File

@ -16,7 +16,7 @@ func (s *FileService) UploadItemImg(header *multipart.FileHeader) (*model.FileMo
file.Name = header.Filename file.Name = header.Filename
file.Key = util.RandString(12) file.Key = util.RandString(12)
file.Size = header.Size file.Size = header.Size
file.Status = model.FileStatusNormal file.State = model.FileStateNormal
file.Url = "/upload/item/img/" + file.Key + ".jpg" file.Url = "/upload/item/img/" + file.Key + ".jpg"
file.SystemPath = "./public" + file.Url file.SystemPath = "./public" + file.Url
model.DB.Create(file) 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) file := new(model.FileModel)
model.DB.First(file, id) model.DB.First(file, id)
if file.ID == 0 { if file.ID == 0 {
return ecode.File(ecode.FILE_NOT_FOUND) return ecode.File(ecode.FILE_NOT_FOUND)
} }
file.Status = status file.State = status
model.DB.Save(file) model.DB.Save(file)
return ecode.OK() 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()
}

View File

@ -7,7 +7,7 @@ import (
type ItemService struct{} 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) item = new(model.ItemModel)
e = ecode.OK() e = ecode.OK()
item.Itemname = itemname item.Itemname = itemname
@ -15,7 +15,21 @@ func (s *ItemService) CreateItem(itemname string, desc string, types []int, img
item.Types = types item.Types = types
item.Img = img item.Img = img
item.Price = price item.Price = price
item.States = model.ItemStateOnSale item.State = model.ItemStateOnSale
item.Uid = uid
model.DB.Create(item) model.DB.Create(item)
return 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()
}

View File

@ -35,7 +35,7 @@ func (u *UserService) AuthSignup(username string, password string) (user *model.
user.Username = username user.Username = username
user.Secret = util.RandString(16) user.Secret = util.RandString(16)
user.Passhash = util.MD5(user.Secret + password + user.Secret) user.Passhash = util.MD5(user.Secret + password + user.Secret)
user.Status = model.UserStatusComfirmed user.State = model.UserStateComfirmed
model.DB.Create(user) model.DB.Create(user)
return return
} }

View File

@ -10,3 +10,7 @@ type CreateItemParam struct {
// @description 商品类型可以有多个类型请用数组传过来类型id请使用 /item/types 接口获取 // @description 商品类型可以有多个类型请用数组传过来类型id请使用 /item/types 接口获取
Types []int `json:"types" validate:"required" example:"1,2"` Types []int `json:"types" validate:"required" example:"1,2"`
} }
type DeleteItemParam struct {
Id uint `json:"id" validate:"required" example:"1"`
}