完成这5个接口 查询接口的查询条件要所有属性

// 获取商品反射列表
// 获取商品反射详情
// 创建商品反射
// 更新商品反射
// 删除商品反射
This commit is contained in:
Administrator 2026-06-17 16:08:16 +08:00
parent d0e9a0fa82
commit 934ef9334c
5 changed files with 697 additions and 1 deletions

View File

@ -1,3 +1,146 @@
package controllers package controllers
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"psi/constant"
"psi/models/request"
systemRes "psi/models/response"
"psi/service"
"psi/utils"
)
var productBookService = &service.ProductBookService{}
type ProductBookApi struct{} type ProductBookApi struct{}
// List 获取商品反射列表
func (r *ProductBookApi) List(c *gin.Context) {
var req request.GetProductBookListRequest
if err := c.ShouldBind(&req); err != nil {
utils.ErrorLog(constant.LoggerChannelRequest, logrus.Fields(gin.H{
"source": "获取商品反射列表请求参数异常",
"err_msg": err.Error(),
}))
systemRes.FailWithValidateMessage("参数错误: "+err.Error(), c)
return
}
result, err := productBookService.List(req)
if err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "获取商品反射列表异常", err, c, req)
return
}
systemRes.OkWithDetailed(result, "获取成功", c)
}
// Detail 获取商品反射详情
func (r *ProductBookApi) Detail(c *gin.Context) {
id := c.Query("id")
isbn := c.Query("isbn")
if id == "" || isbn == "" {
utils.ErrorLog(constant.LoggerChannelRequest, logrus.Fields(gin.H{
"source": "获取商品反射详情请求参数异常",
"err_msg": "id和isbn不能为空",
}))
systemRes.FailWithValidateMessage("参数错误: id和isbn不能为空", c)
return
}
var idInt int64
if _, err := fmt.Sscanf(id, "%d", &idInt); err != nil || idInt <= 0 {
utils.ErrorLog(constant.LoggerChannelRequest, logrus.Fields(gin.H{
"source": "获取商品反射详情请求参数异常",
"err_msg": "ID格式错误",
}))
systemRes.FailWithValidateMessage("参数错误: ID格式不正确", c)
return
}
result, err := productBookService.Detail(idInt, isbn)
if err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "获取商品反射详情异常", err, c, gin.H{"id": idInt, "isbn": isbn})
return
}
systemRes.OkWithDetailed(result, "获取成功", c)
}
// Create 创建商品反射
func (r *ProductBookApi) Create(c *gin.Context) {
var req request.ProductBookRequest
if err := c.ShouldBind(&req); err != nil {
utils.ErrorLog(constant.LoggerChannelRequest, logrus.Fields(gin.H{
"source": "创建商品反射请求参数异常",
"err_msg": err.Error(),
}))
systemRes.FailWithValidateMessage("参数错误: "+err.Error(), c)
return
}
id, err := productBookService.Create(req)
if err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "创建商品反射异常", err, c, req)
return
}
systemRes.OkWithDetailed(gin.H{"id": id}, "创建成功", c)
}
// Update 更新商品反射
func (r *ProductBookApi) Update(c *gin.Context) {
var req request.ProductBookRequest
if err := c.ShouldBind(&req); err != nil {
utils.ErrorLog(constant.LoggerChannelRequest, logrus.Fields(gin.H{
"source": "更新商品反射请求参数异常",
"err_msg": err.Error(),
}))
systemRes.FailWithValidateMessage("参数错误: "+err.Error(), c)
return
}
if err := productBookService.Update(req); err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "更新商品反射异常", err, c, req)
return
}
systemRes.OkWithMessage("更新成功", c)
}
// Del 删除商品反射
func (r *ProductBookApi) Del(c *gin.Context) {
id := c.Query("id")
isbn := c.Query("isbn")
if id == "" || isbn == "" {
utils.ErrorLog(constant.LoggerChannelRequest, logrus.Fields(gin.H{
"source": "删除商品反射请求参数异常",
"err_msg": "id和isbn不能为空",
}))
systemRes.FailWithValidateMessage("参数错误: id和isbn不能为空", c)
return
}
var idInt int64
if _, err := fmt.Sscanf(id, "%d", &idInt); err != nil || idInt <= 0 {
utils.ErrorLog(constant.LoggerChannelRequest, logrus.Fields(gin.H{
"source": "删除商品反射请求参数异常",
"err_msg": "ID格式错误",
}))
systemRes.FailWithValidateMessage("参数错误: ID格式不正确", c)
return
}
if err := productBookService.Del(idInt, isbn); err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "删除商品反射异常", err, c, gin.H{"id": idInt, "isbn": isbn})
return
}
systemRes.OkWithMessage("删除成功", c)
}

View File

@ -0,0 +1,81 @@
package request
// ProductBookRequest 创建/更新商品反射请求
type ProductBookRequest struct {
ID int64 `form:"id"` // 商品ID(更新时必填)
CategoryID int64 `form:"category_id"` // 分类ID
AboutId int64 `form:"about_id"` // 关联ID(租户ID)
WarehouseID int64 `form:"warehouse_id"` // 仓库ID
WarehouseName string `form:"warehouse_name"` // 仓库名称
LocationID int64 `form:"location_id"` // 货位ID
LocationName string `form:"location_name"` // 货位名称
StandardProductID int64 `form:"standard_product_id"` // 关联标品ID
Fid int64 `form:"fid"` // 父级ID
Type int8 `form:"type"` // 类型 1正常 2套装书 3一号多书 4无书号
ISBN string `form:"isbn" binding:"required"` // ISBN
FISBN string `form:"f_isbn"` // FISBN
BookName string `form:"book_name"` // 书名
FBookName string `form:"f_book_name"` // 副书名
Author string `form:"author"` // 作者
Publishing string `form:"publishing"` // 出版社
PublicationTime int64 `form:"publication_time"` // 出版日期时间戳
Binding string `form:"binding"` // 装帧
PagesCount int64 `form:"pages_count"` // 页数
WordsCount int64 `form:"words_count"` // 字数
Format int64 `form:"format"` // 开本
CatID string `form:"cat_id"` // 类目json字符串
Name string `form:"name"` // 商品名称
Appearance int64 `form:"appearance"` // 品相
Barcode string `form:"barcode"` // 条码
Price int64 `form:"price"` // 价格
SalePrice int64 `form:"sale_price"` // 书价
Cost int64 `form:"cost"` // 最低运费
LiveImage []string `form:"live_image[]"` // 实拍图数组
IsBatchManaged int8 `form:"is_batch_managed"` // 是否批次管理
IsShelfLifeManaged int8 `form:"is_shelf_life_managed"` // 是否效期管理
Status int8 `form:"status"` // 状态
}
// GetProductBookListRequest 获取商品反射列表请求
type GetProductBookListRequest struct {
Page int `form:"page"` // 页码
PageSize int `form:"page_size"` // 每页数量
ID int64 `form:"id"` // 商品ID
CategoryID int64 `form:"category_id"` // 分类ID
AboutId int64 `form:"about_id"` // 关联ID
WarehouseID int64 `form:"warehouse_id"` // 仓库ID
WarehouseName string `form:"warehouse_name"` // 仓库名称
LocationID int64 `form:"location_id"` // 货位ID
LocationName string `form:"location_name"` // 货位名称
StandardProductID int64 `form:"standard_product_id"` // 关联标品ID
Fid int64 `form:"fid"` // 父级ID
Type *int8 `form:"type"` // 类型
ISBN string `form:"isbn"` // ISBN
FISBN string `form:"f_isbn"` // FISBN
BookName string `form:"book_name"` // 书名
FBookName string `form:"f_book_name"` // 副书名
Author string `form:"author"` // 作者
Publishing string `form:"publishing"` // 出版社
PublicationTime int64 `form:"publication_time"` // 出版日期
Binding string `form:"binding"` // 装帧
PagesCount int64 `form:"pages_count"` // 页数
WordsCount int64 `form:"words_count"` // 字数
Format int64 `form:"format"` // 开本
Name string `form:"name"` // 商品名称
Appearance int64 `form:"appearance"` // 品相
Barcode string `form:"barcode"` // 条码
Price int64 `form:"price"` // 价格
SalePrice int64 `form:"sale_price"` // 书价
Cost int64 `form:"cost"` // 最低运费
IsBatchManaged *int8 `form:"is_batch_managed"` // 批次管理
IsShelfLifeManaged *int8 `form:"is_shelf_life_managed"` // 效期管理
Status *int8 `form:"status"` // 状态
StartCreatedAt int64 `form:"start_created_at"` // 创建时间开始
EndCreatedAt int64 `form:"end_created_at"` // 创建时间结束
Keyword string `form:"keyword"` // 关键词(搜索书名/作者/ISBN)
}
// DeleteProductBookRequest 删除商品反射请求
type DeleteProductBookRequest struct {
ID int64 `form:"id" binding:"required"` // 商品ID
}

View File

@ -0,0 +1,102 @@
package response
import (
"encoding/json"
"psi/models"
)
// ProductBookListResponse 商品反射列表响应
type ProductBookListResponse struct {
List []ProductBookItem `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
// ProductBookItem 商品反射项
type ProductBookItem struct {
ID int64 `json:"id"`
CategoryID int64 `json:"category_id"`
AboutId int64 `json:"about_id"`
WarehouseID int64 `json:"warehouse_id"`
WarehouseName string `json:"warehouse_name"`
LocationID int64 `json:"location_id"`
LocationName string `json:"location_name"`
StandardProductID int64 `json:"standard_product_id"`
Fid int64 `json:"fid"`
Type int8 `json:"type"`
ISBN string `json:"isbn"`
FISBN string `json:"f_isbn"`
BookName string `json:"book_name"`
FBookName string `json:"f_book_name"`
Author string `json:"author"`
Publishing string `json:"publishing"`
PublicationTime int64 `json:"publication_time"`
Binding string `json:"binding"`
PagesCount int64 `json:"pages_count"`
WordsCount int64 `json:"words_count"`
Format int64 `json:"format"`
CatID interface{} `json:"cat_id"`
Name string `json:"name"`
Appearance int64 `json:"appearance"`
Barcode string `json:"barcode"`
Price int64 `json:"price"`
SalePrice int64 `json:"sale_price"`
Cost int64 `json:"cost"`
LiveImage []string `json:"live_image"`
IsBatchManaged int8 `json:"is_batch_managed"`
IsShelfLifeManaged int8 `json:"is_shelf_life_managed"`
Status int8 `json:"status"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
// ConvertProductBookToItem 转换模型为响应项
func ConvertProductBookToItem(book models.ProductBook) ProductBookItem {
var liveImage []string
if len(book.LiveImage) > 0 {
json.Unmarshal(book.LiveImage, &liveImage)
}
var catID interface{}
if len(book.CatID) > 0 {
json.Unmarshal(book.CatID, &catID)
}
return ProductBookItem{
ID: book.ID,
CategoryID: book.CategoryID,
AboutId: book.AboutId,
WarehouseID: book.WarehouseID,
WarehouseName: book.WarehouseName,
LocationID: book.LocationID,
LocationName: book.LocationName,
StandardProductID: book.StandardProductID,
Fid: book.Fid,
Type: book.Type,
ISBN: book.ISBN,
FISBN: book.FISBN,
BookName: book.BookName,
FBookName: book.FBookName,
Author: book.Author,
Publishing: book.Publishing,
PublicationTime: book.PublicationTime,
Binding: book.Binding,
PagesCount: book.PagesCount,
WordsCount: book.WordsCount,
Format: book.Format,
CatID: catID,
Name: book.Name,
Appearance: book.Appearance,
Barcode: book.Barcode,
Price: book.Price,
SalePrice: book.SalePrice,
Cost: book.Cost,
LiveImage: liveImage,
IsBatchManaged: book.IsBatchManaged,
IsShelfLifeManaged: book.IsShelfLifeManaged,
Status: book.Status,
CreatedAt: book.CreatedAt,
UpdatedAt: book.UpdatedAt,
}
}

View File

@ -82,7 +82,7 @@ func initRouter() (r *gin.Engine) {
public.POST("/product/pushToShop", productApi.PushProductToShop) // 推送商品到店铺 public.POST("/product/pushToShop", productApi.PushProductToShop) // 推送商品到店铺
// 商品反射 // 商品反射
public.GET("/product_book/list", productBookApi.List) // 获取商品反射列表 public.GET("/product_book/list", productBookApi.List) // 获取商品反射列表
public.GET("/product_book/list", productBookApi.Detail) // 获取商品反射详情 public.GET("/product_book/detail", productBookApi.Detail) // 获取商品反射详情
public.POST("/product_book/create", productBookApi.Create) // 创建商品反射 public.POST("/product_book/create", productBookApi.Create) // 创建商品反射
public.POST("/product_book/update", productBookApi.Update) // 更新商品反射 public.POST("/product_book/update", productBookApi.Update) // 更新商品反射
public.GET("/product_book/del", productBookApi.Del) // 删除商品反射 public.GET("/product_book/del", productBookApi.Del) // 删除商品反射

370
service/product_book.go Normal file
View File

@ -0,0 +1,370 @@
package service
import (
"encoding/json"
"fmt"
"gorm.io/datatypes"
"psi/database"
"psi/models"
systemReq "psi/models/request"
systemRes "psi/models/response"
"psi/utils"
"time"
)
type ProductBookService struct{}
// List 获取商品反射列表
func (s *ProductBookService) List(req systemReq.GetProductBookListRequest) (*systemRes.ProductBookListResponse, error) {
db := database.DB
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
// 根据ISBN确定分表
tableName := "product_book_00"
if req.ISBN != "" {
tableName = models.ProductBookTableName(req.ISBN)
} else if req.Barcode != "" {
tableName = models.ProductBookTableName(req.Barcode)
}
query := db.Table(tableName).Where("is_del = ?", 0)
// 添加查询条件
if req.ID > 0 {
query = query.Where("id = ?", req.ID)
}
if req.CategoryID > 0 {
query = query.Where("category_id = ?", req.CategoryID)
}
if req.AboutId > 0 {
query = query.Where("about_id = ?", req.AboutId)
}
if req.WarehouseID > 0 {
query = query.Where("warehouse_id = ?", req.WarehouseID)
}
if req.WarehouseName != "" {
query = query.Where("warehouse_name LIKE ?", "%"+req.WarehouseName+"%")
}
if req.LocationID > 0 {
query = query.Where("location_id = ?", req.LocationID)
}
if req.LocationName != "" {
query = query.Where("location_name LIKE ?", "%"+req.LocationName+"%")
}
if req.StandardProductID > 0 {
query = query.Where("standard_product_id = ?", req.StandardProductID)
}
if req.Fid > 0 {
query = query.Where("fid = ?", req.Fid)
}
if req.Type != nil {
query = query.Where("type = ?", *req.Type)
}
if req.ISBN != "" {
query = query.Where("isbn = ?", req.ISBN)
}
if req.FISBN != "" {
query = query.Where("f_isbn = ?", req.FISBN)
}
if req.BookName != "" {
query = query.Where("book_name LIKE ?", "%"+req.BookName+"%")
}
if req.FBookName != "" {
query = query.Where("f_book_name LIKE ?", "%"+req.FBookName+"%")
}
if req.Author != "" {
query = query.Where("author LIKE ?", "%"+req.Author+"%")
}
if req.Publishing != "" {
query = query.Where("publishing LIKE ?", "%"+req.Publishing+"%")
}
if req.PublicationTime > 0 {
query = query.Where("publication_time = ?", req.PublicationTime)
}
if req.Binding != "" {
query = query.Where("binding = ?", req.Binding)
}
if req.PagesCount > 0 {
query = query.Where("pages_count = ?", req.PagesCount)
}
if req.WordsCount > 0 {
query = query.Where("words_count = ?", req.WordsCount)
}
if req.Format > 0 {
query = query.Where("format = ?", req.Format)
}
if req.Name != "" {
query = query.Where("name LIKE ?", "%"+req.Name+"%")
}
if req.Appearance > 0 {
query = query.Where("appearance = ?", req.Appearance)
}
if req.Barcode != "" {
query = query.Where("barcode = ?", req.Barcode)
}
if req.Price > 0 {
query = query.Where("price = ?", req.Price)
}
if req.SalePrice > 0 {
query = query.Where("sale_price = ?", req.SalePrice)
}
if req.Cost > 0 {
query = query.Where("cost = ?", req.Cost)
}
if req.IsBatchManaged != nil {
query = query.Where("is_batch_managed = ?", *req.IsBatchManaged)
}
if req.IsShelfLifeManaged != nil {
query = query.Where("is_shelf_life_managed = ?", *req.IsShelfLifeManaged)
}
if req.Status != nil {
query = query.Where("status = ?", *req.Status)
}
if req.StartCreatedAt > 0 {
query = query.Where("created_at >= ?", req.StartCreatedAt)
}
if req.EndCreatedAt > 0 {
query = query.Where("created_at <= ?", req.EndCreatedAt)
}
if req.Keyword != "" {
query = query.Where("(book_name LIKE ? OR author LIKE ? OR isbn LIKE ? OR barcode LIKE ?)",
"%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%")
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
var books []models.ProductBook
offset := (req.Page - 1) * req.PageSize
if err := query.Order("created_at DESC").Offset(offset).Limit(req.PageSize).Find(&books).Error; err != nil {
return nil, utils.NewError("查询列表失败")
}
items := make([]systemRes.ProductBookItem, 0, len(books))
for _, book := range books {
items = append(items, systemRes.ConvertProductBookToItem(book))
}
return &systemRes.ProductBookListResponse{
List: items,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// Detail 获取商品反射详情
func (s *ProductBookService) Detail(id int64, isbn string) (*systemRes.ProductBookItem, error) {
db := database.DB
// 根据ISBN确定分表
tableName := models.ProductBookTableName(isbn)
var book models.ProductBook
if err := db.Table(tableName).Where("id = ? AND is_del = ?", id, 0).First(&book).Error; err != nil {
return nil, utils.NewError("商品不存在")
}
item := systemRes.ConvertProductBookToItem(book)
return &item, nil
}
// Create 创建商品反射
func (s *ProductBookService) Create(req systemReq.ProductBookRequest) (int64, error) {
db := database.DB
now := time.Now().Unix()
// 解析LiveImage
var liveImage datatypes.JSON
if len(req.LiveImage) > 0 {
jsonBytes, _ := json.Marshal(req.LiveImage)
liveImage = jsonBytes
} else {
liveImage = datatypes.JSON("[]")
}
// 解析CatID
var catID datatypes.JSON
if req.CatID != "" {
catID = datatypes.JSON(req.CatID)
} else {
catID = datatypes.JSON("{}")
}
// 根据ISBN确定分表
tableName := models.ProductBookTableName(req.ISBN)
book := models.ProductBook{
CategoryID: req.CategoryID,
AboutId: req.AboutId,
WarehouseID: req.WarehouseID,
WarehouseName: req.WarehouseName,
LocationID: req.LocationID,
LocationName: req.LocationName,
StandardProductID: req.StandardProductID,
Fid: req.Fid,
Type: req.Type,
ISBN: req.ISBN,
FISBN: req.FISBN,
BookName: req.BookName,
FBookName: req.FBookName,
Author: req.Author,
Publishing: req.Publishing,
PublicationTime: req.PublicationTime,
Binding: req.Binding,
PagesCount: req.PagesCount,
WordsCount: req.WordsCount,
Format: req.Format,
CatID: catID,
Name: req.Name,
Appearance: req.Appearance,
Barcode: req.Barcode,
Price: req.Price,
SalePrice: req.SalePrice,
Cost: req.Cost,
LiveImage: liveImage,
IsBatchManaged: req.IsBatchManaged,
IsShelfLifeManaged: req.IsShelfLifeManaged,
Status: req.Status,
CreatedAt: now,
UpdatedAt: now,
IsDel: 0,
}
if err := db.Table(tableName).Create(&book).Error; err != nil {
return 0, fmt.Errorf("创建商品反射失败: %w", err)
}
return book.ID, nil
}
// Update 更新商品反射
func (s *ProductBookService) Update(req systemReq.ProductBookRequest) error {
db := database.DB
if req.ID == 0 {
return utils.NewError("商品ID不能为空")
}
now := time.Now().Unix()
// 先查询获取ISBN以确定分表
var existingBook models.ProductBook
// 如果提供了ISBN,直接使用;否则需要遍历所有分表查找
tableName := ""
if req.ISBN != "" {
tableName = models.ProductBookTableName(req.ISBN)
if err := db.Table(tableName).Where("id = ? AND is_del = ?", req.ID, 0).First(&existingBook).Error; err != nil {
return utils.NewError("商品不存在")
}
} else {
// 遍历所有分表查找
allTables := models.ProductBookAllTableNames()
found := false
for _, tName := range allTables {
if err := db.Table(tName).Where("id = ? AND is_del = ?", req.ID, 0).First(&existingBook).Error; err == nil {
tableName = tName
found = true
break
}
}
if !found {
return utils.NewError("商品不存在")
}
}
// 解析LiveImage
var liveImage datatypes.JSON
if len(req.LiveImage) > 0 {
jsonBytes, _ := json.Marshal(req.LiveImage)
liveImage = jsonBytes
} else {
liveImage = existingBook.LiveImage
}
// 解析CatID
var catID datatypes.JSON
if req.CatID != "" {
catID = datatypes.JSON(req.CatID)
} else {
catID = existingBook.CatID
}
updates := map[string]interface{}{
"category_id": req.CategoryID,
"about_id": req.AboutId,
"warehouse_id": req.WarehouseID,
"warehouse_name": req.WarehouseName,
"location_id": req.LocationID,
"location_name": req.LocationName,
"standard_product_id": req.StandardProductID,
"fid": req.Fid,
"type": req.Type,
"f_isbn": req.FISBN,
"book_name": req.BookName,
"f_book_name": req.FBookName,
"author": req.Author,
"publishing": req.Publishing,
"publication_time": req.PublicationTime,
"binding": req.Binding,
"pages_count": req.PagesCount,
"words_count": req.WordsCount,
"format": req.Format,
"cat_id": catID,
"name": req.Name,
"appearance": req.Appearance,
"barcode": req.Barcode,
"price": req.Price,
"sale_price": req.SalePrice,
"cost": req.Cost,
"live_image": liveImage,
"is_batch_managed": req.IsBatchManaged,
"is_shelf_life_managed": req.IsShelfLifeManaged,
"status": req.Status,
"updated_at": now,
}
if err := db.Table(tableName).Model(&existingBook).Updates(updates).Error; err != nil {
return fmt.Errorf("更新商品反射失败: %w", err)
}
return nil
}
// Del 删除商品反射(逻辑删除)
func (s *ProductBookService) Del(id int64, isbn string) error {
db := database.DB
if id == 0 {
return utils.NewError("商品ID不能为空")
}
now := time.Now().Unix()
// 根据ISBN确定分表
tableName := models.ProductBookTableName(isbn)
var book models.ProductBook
if err := db.Table(tableName).Where("id = ? AND is_del = ?", id, 0).First(&book).Error; err != nil {
return utils.NewError("商品不存在")
}
if err := db.Table(tableName).Model(&book).Updates(map[string]interface{}{
"is_del": 1,
"updated_at": now,
}).Error; err != nil {
return fmt.Errorf("删除商品反射失败: %w", err)
}
return nil
}