优化选品中心代码结构

This commit is contained in:
unknown 2026-03-13 13:49:09 +08:00
parent 8130d83dba
commit fe34007bd8
8 changed files with 1999 additions and 66 deletions

237
controller/book.go Normal file
View File

@ -0,0 +1,237 @@
package controller
import (
"centerBook/es"
"centerBook/model/request"
"centerBook/model/response"
"centerBook/service"
"fmt"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// BookController 图书控制器
type BookController struct {
bookService *service.BookService
}
// NewBookController 创建图书控制器实例
func NewBookController(bookService *service.BookService) *BookController {
return &BookController{
bookService: bookService,
}
}
// SearchBookBaseInfoHandler 搜索图书基础信息 Handler
func (b *BookController) SearchBookBaseInfoHandler(c *gin.Context) {
// 绑定请求参数
var req request.BookSearchRequest
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 设置默认值
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
if req.PerPage > 0 {
req.PageSize = req.PerPage
} else {
req.PageSize = 10
}
}
// 调用服务层查询
list, total, err := b.bookService.SearchBookBaseInfo(&req)
if err != nil {
fmt.Printf("[ERROR] SearchBookBaseInfo failed: %v\n", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// 转换为响应格式
responseList := make([]es.ESBookResponse, 0, len(list))
for _, book := range list {
responseList = append(responseList, book.ConvertToResponse())
}
// DEBUG: 打印响应数据摘要
fmt.Printf("[DEBUG] Response Info => total=%d page=%d pageSize=%d returnCount=%d\n",
total, req.Page, req.PageSize, len(responseList))
// 返回标准响应格式
resp := response.NewBookSearchResponse(req.Page, req.PageSize, total, responseList)
c.JSON(http.StatusOK, resp)
}
// AddBookToESHandler 根据ISBN查询ES中是否存在不存在则新增数据,存在则根据参数更新 Handler
func (b *BookController) AddBookToESHandler(c *gin.Context) {
var req es.ESBook
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "参数解析错误",
"message": err.Error(),
})
return
}
if req.ISBN == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "ISBN不能为空",
})
return
}
// 调用服务层处理
result, err := b.bookService.AddBookToESHandler(c.Request.Context(), &req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "处理失败",
"details": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"data": result.Book.ConvertToResponse(),
"source": result.Source,
})
}
// UpdateBookFieldsByISBNHandler 根据 ISBN 更新图书字段 Handler
func (b *BookController) UpdateBookFieldsByISBNHandler(c *gin.Context) {
// 绑定请求参数
var req request.BookUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "请求参数错误",
"details": err.Error(),
})
return
}
isbn := strings.TrimSpace(req.ISBN)
if isbn == "" {
c.JSON(400, gin.H{
"error": "ISBN不能为空",
})
return
}
if len(req.Data) == 0 {
c.JSON(400, gin.H{
"error": "至少提供一个要更新的字段",
})
return
}
// 调用服务层处理
result, err := b.bookService.UpdateBookFieldsByISBN(&req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "更新失败",
"details": err.Error(),
})
return
}
// 返回标准响应
resp := response.NewUpdateBookResponse(result.ISBN, result.Updated, result.Fields)
c.JSON(http.StatusOK, resp)
}
// UpdateBookCatIdByISBNHandler 根据 ISBN 更新图书字段 Handler
func (b *BookController) UpdateBookCatIdByISBNHandler(c *gin.Context) {
// 绑定请求参数
var req request.BookUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "请求参数错误",
"details": err.Error(),
})
return
}
isbn := strings.TrimSpace(req.ISBN)
if isbn == "" {
c.JSON(400, gin.H{
"error": "ISBN不能为空",
})
return
}
if len(req.Data) == 0 {
c.JSON(400, gin.H{
"error": "至少提供一个要更新的字段",
})
return
}
// 调用服务层处理
result, err := b.bookService.UpdateBookCatIdByISBNHandler(&req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "更新失败",
"details": err.Error(),
})
return
}
// 返回标准响应
resp := response.NewUpdateBookResponse(result.ISBN, result.Updated, result.Fields)
c.JSON(http.StatusOK, resp)
}
// DeleteBookHandler 删除图书
func (b *BookController) DeleteBookHandler(c *gin.Context) {
// 绑定请求参数
var req request.BookDelByIsbnRequest
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "请求参数错误",
"details": err.Error(),
})
return
}
// 调用服务层处理
err := b.bookService.DeleteBookByISBN(&req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "删除失败",
"details": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}
// DeleteBookByIDHandler 根据ID删除图书的HTTP处理器
func (b *BookController) DeleteBookByIDHandler(c *gin.Context) {
// 绑定请求参数
var req request.BookDelByIdRequest
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "请求参数错误",
"details": err.Error(),
})
return
}
// 调用服务层处理
err := b.bookService.DeleteBookByID(&req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "删除失败",
"details": err.Error(),
})
return
}
c.JSON(200, gin.H{
"code": 200,
"message": "删除成功",
"data": gin.H{
"id": req.ID,
"deleted": true,
},
})
}

View File

@ -1,58 +1,58 @@
package controller package controller
import ( //import (
"centerBook/util/esClient" // "centerBook/util/esClient"
"centerBook/util/pdd" // "centerBook/util/pdd"
"centerBook/util/redisClient" // "centerBook/util/redisClient"
"context" // "context"
"log" // "log"
) //)
//
// 推测pddCatId类目 //// 推测pddCatId类目
func getPddCatId() { //func getPddCatId() {
//
ctx := context.Background() // ctx := context.Background()
// 为两个数据库创建命名客户端 // // 为两个数据库创建命名客户端
redisClient.AddClient("db4", "36.212.20.113", "j8nZ4jra2E", 4) // redisClient.AddClient("db4", "36.212.20.113", "j8nZ4jra2E", 4)
redisClient.AddClient("db14", "36.212.20.113", "j8nZ4jra2E", 14) // redisClient.AddClient("db14", "36.212.20.113", "j8nZ4jra2E", 14)
//
// 从 db4 获取数据示例 // // 从 db4 获取数据示例
db4Client, err := redisClient.GetClientByName("db4") // db4Client, err := redisClient.GetClientByName("db4")
if err == nil { // if err == nil {
// 示例:获取键为 "key1" 的值 // // 示例:获取键为 "key1" 的值
val, err := db4Client.Get(ctx, "1995373681100910593").Result() // val, err := db4Client.Get(ctx, "1995373681100910593").Result()
if err == nil { // if err == nil {
log.Println(val) // log.Println(val)
} // }
} // }
//
bookName := "" // bookName := ""
//
instance, err := pdd.GetPddInstance() // instance, err := pdd.GetPddInstance()
if err != nil { // if err != nil {
return // return
} // }
instance.PddGoodsOuterCatMappingGet("", "15543", "书籍/杂志/报纸", "书籍 "+bookName) // instance.PddGoodsOuterCatMappingGet("", "15543", "书籍/杂志/报纸", "书籍 "+bookName)
//
// 从 db14 获取数据示例 // // 从 db14 获取数据示例
db14Client, err := redisClient.GetClientByName("db14") // db14Client, err := redisClient.GetClientByName("db14")
if err == nil { // if err == nil {
// 示例:获取键为 "key2" 的值 // // 示例:获取键为 "key2" 的值
val, err := db14Client.Get(ctx, "key2").Result() // val, err := db14Client.Get(ctx, "key2").Result()
if err == nil { // if err == nil {
// 处理获取到的值 // // 处理获取到的值
} // }
} // }
//
} //}
//
// connectES 连接到 Elasticsearch //// connectES 连接到 Elasticsearch
func connectES(addresses []string, username, password string) (*esClient.ESClient, error) { //func connectES(addresses []string, username, password string) (*esClient.ESClient, error) {
return esClient.NewESClient(addresses, username, password) // return esClient.NewESClient(addresses, username, password)
} //}
//
// connectRedis 连接到 Redis //// connectRedis 连接到 Redis
func connectRedis(addr, password string, db int) { //func connectRedis(addr, password string, db int) {
redisClient.InitRedis(addr, password, db) // redisClient.InitRedis(addr, password, db)
redisClient.GetClient() // redisClient.GetClient()
} //}

View File

@ -5,6 +5,7 @@ import (
"bytes" "bytes"
"centerBook/image" "centerBook/image"
"centerBook/kongfz" "centerBook/kongfz"
"centerBook/model/request"
"centerBook/tail" "centerBook/tail"
"centerBook/util/redisClient" "centerBook/util/redisClient"
"context" "context"
@ -245,6 +246,10 @@ type ESBook struct {
IsIllegal int `json:"is_illegal,omitempty"` // 是否非法 示例 000000 IsIllegal int `json:"is_illegal,omitempty"` // 是否非法 示例 000000
IsReturn int `json:"is_return,omitempty"` // 是否为驳回 示例 0 否 1 是 IsReturn int `json:"is_return,omitempty"` // 是否为驳回 示例 0 否 1 是
IsFilter string `json:"is_filter,omitempty"` // 过滤字段 IsFilter string `json:"is_filter,omitempty"` // 过滤字段
PageCount NumberOrString `json:"page_count"` // 页数
WordCount NumberOrString `json:"word_count"` // 字数
BookFormat NumberOrString `json:"book_format"` // 多少开
CatId request.CatIdObject `json:"cat_id"` // 类目
} }
// AddBookRequest 用于 Service 方法的入参 // AddBookRequest 用于 Service 方法的入参
@ -1935,6 +1940,10 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
if err != nil { if err != nil {
return nil, 0, fmt.Errorf("复制响应数据失败: %v", err) return nil, 0, fmt.Errorf("复制响应数据失败: %v", err)
} }
err = writer.Flush()
if err != nil {
return nil, 0, fmt.Errorf("刷新缓冲区失败:%v", err)
}
rawData := buf.Bytes() rawData := buf.Bytes()
//rawData, err := io.ReadAll(res.Body) //rawData, err := io.ReadAll(res.Body)
if err != nil { if err != nil {
@ -2575,6 +2584,7 @@ func (svc *ESSearchService) UpdateBookFieldsByISBNHandler(c *gin.Context) {
// 先确认 ISBN 是否存在 // 先确认 ISBN 是否存在
book, err := svc.SearchBookByISBN(isbn) book, err := svc.SearchBookByISBN(isbn)
fmt.Println("book:", book)
if err != nil { if err != nil {
c.JSON(500, gin.H{ c.JSON(500, gin.H{
"error": "查询ES失败", "error": "查询ES失败",
@ -2641,7 +2651,7 @@ func (svc *ESSearchService) UpdateBookFieldsByISBN(
params := make(map[string]interface{}) params := make(map[string]interface{})
allowedFields := map[string]bool{ allowedFields := map[string]bool{
"book_name": true, //"book_name": true,
"book_pic": true, "book_pic": true,
"book_pic_s": true, "book_pic_s": true,
"book_pic_b": true, "book_pic_b": true,
@ -2670,6 +2680,9 @@ func (svc *ESSearchService) UpdateBookFieldsByISBN(
"is_return": true, "is_return": true,
"is_filter": true, "is_filter": true,
"update_time": true, "update_time": true,
"page_count": true,
"word_count": true,
"book_format": true,
} }
for field, value := range data { for field, value := range data {
@ -2680,7 +2693,7 @@ func (svc *ESSearchService) UpdateBookFieldsByISBN(
fmt.Sprintf("ctx._source.%s = params.%s;", field, field)) fmt.Sprintf("ctx._source.%s = params.%s;", field, field))
params[field] = value params[field] = value
} }
fmt.Println("scriptParts:", scriptParts)
if len(scriptParts) == 0 { if len(scriptParts) == 0 {
return 0, fmt.Errorf("没有有效的字段可更新") return 0, fmt.Errorf("没有有效的字段可更新")
} }
@ -2697,7 +2710,6 @@ func (svc *ESSearchService) UpdateBookFieldsByISBN(
}, },
}, },
} }
payload, _ := json.Marshal(body) payload, _ := json.Marshal(body)
res, err := svc.ES.Client.UpdateByQuery( res, err := svc.ES.Client.UpdateByQuery(
@ -2711,6 +2723,11 @@ func (svc *ESSearchService) UpdateBookFieldsByISBN(
} }
defer res.Body.Close() defer res.Body.Close()
if res.IsError() {
errorBody := res.String()
log.Printf("[UpdateBookFieldsByISBN] ES 返回错误 | status=%s | body=%s", res.Status(), errorBody)
return 0, fmt.Errorf("ES 返回错误:%s, 详细信息:%s", res.Status(), errorBody)
}
if res.IsError() { if res.IsError() {
return 0, fmt.Errorf("ES返回错误: %s", res.String()) return 0, fmt.Errorf("ES返回错误: %s", res.String())
} }

37
main.go
View File

@ -2,6 +2,8 @@ package main
import ( import (
"bytes" "bytes"
"centerBook/controller"
"centerBook/service"
"context" "context"
"crypto/md5" "crypto/md5"
"database/sql" "database/sql"
@ -193,7 +195,9 @@ func main() {
esService := es.NewESSearchService(esClient) esService := es.NewESSearchService(esClient)
redisClient.AddClient("db4", "36.212.20.113:7963", "j8nZ4jra2E", 4) redisClient.AddClient("db4", "36.212.12.247:6379", "long6166@@", 2)
redisClient.AddClient("db1", "36.212.12.247:6379", "long6166@@", 1)
//redisClient.AddClient("test", "127.0.0.1:6379", "", 0)
// =================================================================== // ===================================================================
// 3. 初始化IP日志路径 // 3. 初始化IP日志路径
@ -293,13 +297,32 @@ func main() {
// ISBN 模糊搜索 // ISBN 模糊搜索
r.GET("/api/es/searchByISBNLike", esService.SearchBooksHandler) r.GET("/api/es/searchByISBNLike", esService.SearchBooksHandler)
// ISBN 精确搜索 // ISBN 精确搜索
r.GET("/api/es/searchByISBN", esService.SearchBookByISBNHandler) r.GET("/api/es/searchByISBN", esService.SearchBookByISBNHandler) //1
// 书名搜索 // 书名搜索
r.GET("/api/es/searchByBookName", esService.SearchBookByBookNameHandler) r.GET("/api/es/searchByBookName", esService.SearchBookByBookNameHandler)
// 全字段搜索 // 全字段搜索
r.GET("/api/es/searchAll", esService.SearchBooksAllFieldsHandler) r.GET("/api/es/searchAll", esService.SearchBooksAllFieldsHandler)
// 根据条件查询 ES 图书信息 // 根据条件查询 ES 图书信息
r.GET("/api/es/getBookBaseInfoES", esService.SearchBookBaseInfoESHandler) //r.GET("/api/es/getBookBaseInfoES", esService.SearchBookBaseInfoESHandler) //1
//------------------------------------------------------------------------
// 初始化控制器 新
bookSearchService := service.NewBookService(esClient)
bookController := controller.NewBookController(bookSearchService)
// 根据条件查询 ES 图书信息
r.GET("/api/es/getBookBaseInfoES", bookController.SearchBookBaseInfoHandler)
// 新增根据ISBN查询ES中是否存在不存在则新增数据,存在则根据参数更新
//r.POST("/api/es/addBookToES", bookController.AddBookToESHandler)
// 更新根据ISBN通用更新图书字段
r.POST("/api/es/updateBookFieldsByISBN", bookController.UpdateBookFieldsByISBNHandler)
// 更新根据ISBN通用更新图书字段
r.POST("/api/es/updateBookCatIdByISBN", bookController.UpdateBookCatIdByISBNHandler)
// 删除根据ISBN删除ES数据
r.GET("/api/es/DeleteBookByISBN", bookController.DeleteBookHandler)
// 新增根据ID删除ES数据
r.GET("/api/es/DeleteBookByID", bookController.DeleteBookByIDHandler)
//------------------------------------------------------------------------
// 新:核价软件用批量获取 // 新:核价软件用批量获取
r.GET("/api/es/batchGetBookBaseInfoES", esService.BatchGetBookBaseInfoESHandler) r.GET("/api/es/batchGetBookBaseInfoES", esService.BatchGetBookBaseInfoESHandler)
// 多条件高级搜索 // 多条件高级搜索
@ -313,9 +336,9 @@ func main() {
// 新增根据ISBN更新图书的is_suit字段 // 新增根据ISBN更新图书的is_suit字段
r.POST("/api/es/updateBookSuitByISBN", esService.UpdateBookSuitByISBNHandler) r.POST("/api/es/updateBookSuitByISBN", esService.UpdateBookSuitByISBNHandler)
// 新增根据ISBN通用更新图书字段 // 新增根据ISBN通用更新图书字段
r.POST("/api/es/updateBookFieldsByISBN", esService.UpdateBookFieldsByISBNHandler) //r.POST("/api/es/updateBookFieldsByISBN", esService.UpdateBookFieldsByISBNHandler) //1
// 新增根据ISBN查询ES中是否存在不存在则新增数据,存在则根据参数更新 // 新增根据ISBN查询ES中是否存在不存在则新增数据,存在则根据参数更新
r.POST("/api/es/addBookToES", esService.AddBookToESHandler) r.POST("/api/es/addBookToES", esService.AddBookToESHandler) //1
// 新增:完整插入接口,支持所有字段, // 新增:完整插入接口,支持所有字段,
r.POST("/api/es/addBookFullToES", esService.AddBookFullToESHandler) r.POST("/api/es/addBookFullToES", esService.AddBookFullToESHandler)
// 新增:批量插入接口,支持同时插入多本图书 // 新增:批量插入接口,支持同时插入多本图书
@ -324,9 +347,9 @@ func main() {
r.GET("/api/es/checkBookExists", esService.CheckBookExistsByISBNHandler) r.GET("/api/es/checkBookExists", esService.CheckBookExistsByISBNHandler)
r.POST("/api/es/checkBookExists", esService.CheckBookExistsByISBNHandler) r.POST("/api/es/checkBookExists", esService.CheckBookExistsByISBNHandler)
// 删除根据ISBN删除ES数据 // 删除根据ISBN删除ES数据
r.GET("/api/es/DeleteBookByISBN", esService.DeleteBookHandler) //r.GET("/api/es/DeleteBookByISBN", esService.DeleteBookHandler) //1
// 新增根据ID删除ES数据 // 新增根据ID删除ES数据
r.GET("/api/es/DeleteBookByID", esService.DeleteBookByIDHandler) //r.GET("/api/es/DeleteBookByID", esService.DeleteBookByIDHandler) //1
// 新增:检查书名是否包含套装关键字 // 新增:检查书名是否包含套装关键字
r.GET("/api/es/checkBookSuit", esService.CheckBookSuitHandler) r.GET("/api/es/checkBookSuit", esService.CheckBookSuitHandler)

90
model/request/book.go Normal file
View File

@ -0,0 +1,90 @@
package request
// BookSearchRequest ES 搜索图书请求参数
type BookSearchRequest struct {
Page int `form:"page"` // 页码
PageSize int `form:"pageSize"` // 每页数量
PerPage int `form:"per_page"` // 每页数量 (兼容字段)
SaleSelect string `form:"saleSelect"` // 销量筛选类型
PicType string `form:"picType"` // 图片类型
ShopType string `form:"shopType"` // 店铺类型
BookName string `form:"book_name"` // 书名
BookPic string `form:"book_pic"` // 图片筛选
ISBN string `form:"isbn"` // ISBN
Author string `form:"author"` // 作者
Category string `form:"category"` // 分类
CategoryType string `form:"categoryType"` // ISBN分类类型
Publisher string `form:"publisher"` // 出版社
PublicationTime string `form:"publication_time"` // 出版时间
BindingLayout string `form:"binding_layout"` // 装帧
FixPrice string `form:"fix_price"` // 定价
IsSuit string `form:"isSuit"` // 是否套装
IsReturn string `form:"is_return"` // 是否驳回
IsFilter string `form:"is_filter"` // 过滤字段
BuyCounts string `form:"buy_counts"` // 购买次数
SellCounts string `form:"sell_counts"` // 在售数量
DaySale7 string `form:"day_sale_7"` // 7 天销量
DaySale15 string `form:"day_sale_15"` // 15 天销量
DaySale30 string `form:"day_sale_30"` // 30 天销量
DaySale60 string `form:"day_sale_60"` // 60 天销量
DaySale90 string `form:"day_sale_90"` // 90 天销量
DaySale180 string `form:"day_sale_180"` // 180 天销量
DaySale365 string `form:"day_sale_365"` // 365 天销量
ThisYearSale string `form:"this_year_sale"` // 今年销量
LastYearSale string `form:"last_year_sale"` // 去年销量
TotalSaleRange string `form:"totalSale_range"` // 总销量范围
ID string `form:"id"` // ID
}
// BookUpdateRequest 更新图书请求参数
type BookUpdateRequest struct {
ISBN string `json:"isbn" binding:"required"`
Data map[string]interface{} `json:"data" binding:"required"`
}
// BookDelByIsbnRequest 更新图书请求参数
type BookDelByIsbnRequest struct {
ISBN string `json:"isbn" form:"isbn" binding:"required"`
}
// BookDelByIdRequest 更新图书请求参数
type BookDelByIdRequest struct {
ID string `json:"id" form:"id" binding:"required"`
}
// BookInfo 书籍信息结构
type BookInfo struct {
Isbn string `json:"isbn"` // ISBN
BookName string `json:"book_name"` // 书名
Author string `json:"author"` // 作者
Publishing string `json:"publishing"` // 出版社
PublicationDate string `json:"publication_date"` // 出版时间
Binding string `json:"binding"` // 装帧
PagesCount int64 `json:"pages_count"` // 页数
WordsCount int64 `json:"words_count"` // 字数
Format int64 `json:"format"` // 开本
ImageObject *ImageObject `json:"image_object"` // 图片
Price int64 `json:"price"` // 售价
CatIdObject CatIdObject `json:"cat_id"` // 分类
}
// ImageObject 图片对象结构
type ImageObject struct {
CarouselUrlArray []string `json:"carousel_url_array"` // 轮播图
WhiteBackgroundUrl string `json:"white_background_url"` // 白底图
DetailUrlObject DetailImageObject `json:"detail_url_object"` // 详情对象
DefaultImageUrl string `json:"default_image_url"` // 默认图
}
type CatIdObject struct {
PinDuoDuoCatId string `json:"pin_duo_duo_cat_id"` // 拼多多分类 ID
KongFuZiCatId string `json:"kong_fu_zi_cat_id"` // 孔夫子分类 ID
XianYuCatId string `json:"xian_yu_cat_id"` // 闲鱼分类 ID
}
type DetailImageObject struct {
IntroductionUrl []string `json:"introduction_url"` // 简介图
CatalogueUrl []string `json:"catalogue_url"` // 目录图
LiveShootingUrl []string `json:"live_shooting_url"` // 实拍图
OtherUrl []string `json:"other_url"` // 其他图
}

48
model/response/book.go Normal file
View File

@ -0,0 +1,48 @@
package response
import "centerBook/es"
// BookSearchResponse 图书搜索响应
type BookSearchResponse struct {
CurrentPage int `json:"current_page"`
Data []es.ESBookResponse `json:"data"`
PerPage int `json:"per_page"`
Total int `json:"total"`
}
// NewBookSearchResponse 创建图书搜索响应
func NewBookSearchResponse(page, pageSize, total int, data []es.ESBookResponse) *BookSearchResponse {
return &BookSearchResponse{
CurrentPage: page,
Data: data,
PerPage: pageSize,
Total: total,
}
}
// UpdateBookResponse 更新图书响应
type UpdateBookResponse struct {
Code int `json:"code"`
Message string `json:"message"`
ISBN string `json:"isbn"`
Updated int `json:"updated"`
FieldsUpdated int `json:"fields_updated"`
UpdatedFields []string `json:"updated_fields"`
}
// NewUpdateBookResponse 创建更新图书响应
func NewUpdateBookResponse(isbn string, updated int, fields map[string]interface{}) *UpdateBookResponse {
fieldsList := make([]string, 0, len(fields))
for k := range fields {
fieldsList = append(fieldsList, k)
}
return &UpdateBookResponse{
Code: 200,
Message: "success",
ISBN: isbn,
Updated: updated,
FieldsUpdated: len(fields),
UpdatedFields: fieldsList,
}
}

1471
service/book.go Normal file

File diff suppressed because it is too large Load Diff

47
util/common.go Normal file
View File

@ -0,0 +1,47 @@
package util
import (
"fmt"
"strings"
"time"
)
// ParsePublicationTime 支持的格式:"2013-12", "2013", "2013-12-25", "2013 年 12 月" 等
func ParsePublicationTime(timeStr string) int64 {
if timeStr == "" {
return 0
}
// 清理字符串中的空格和特殊字符
timeStr = strings.TrimSpace(timeStr)
timeStr = strings.ReplaceAll(timeStr, "年", "-")
timeStr = strings.ReplaceAll(timeStr, "月", "")
timeStr = strings.TrimSpace(timeStr)
// 定义多种可能的日期格式
formats := []string{
"2006-1", // "2013-12"
"2006-01", // "2013-12" (补零)
"2006", // "2013"
"2006-1-2", // "2013-12-25"
"2006-01-02", // "2013-12-25" (补零)
}
var t time.Time
var err error
for _, format := range formats {
t, err = time.ParseInLocation(format, timeStr, time.Local)
if err == nil {
break
}
}
// 如果所有格式都失败,返回 0
if err != nil {
fmt.Printf("出版时间解析失败:%s\n", timeStr)
return 0
}
return t.Unix()
}