package service import ( "crypto/md5" "encoding/hex" "encoding/json" "fmt" "gorm.io/datatypes" "io" "net/http" "psi/database" "psi/models" systemReq "psi/models/request" systemRes "psi/models/response" "strconv" "strings" "time" ) type BookService struct{} // GetBookInfo 获取图书信息 func (s *BookService) GetBookInfo(req systemReq.BookRequest) (*systemRes.ESBook, error) { // 调用ES接口 isbn := req.Isbn apiURL := fmt.Sprintf("https://book.center.yushutx.com/api/es/searchByISBNtoPsi?isbn=%s", isbn) resp, err := http.Get(apiURL) if err != nil { return nil, fmt.Errorf("[ERROR] 请求 ES 接口失败:%v\n", err) } body, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil { return nil, fmt.Errorf("[ERROR] 读取响应失败:%v\n", err) } var esResp systemRes.GetEsBookResponse if err := json.Unmarshal(body, &esResp); err != nil { return nil, fmt.Errorf("[ERROR] 解析响应失败:%v\n", err) } // 如果ES接口没有返回数据,返回空对象 if esResp.Data.BookName.Value == "" && esResp.Data.ISBN == "" { return nil, nil } return &esResp.Data, nil } func (s *BookService) GetSuitBook(req systemReq.BookRequest) (*systemRes.SuitBookResponse, error) { var books []models.BookInfo if err := database.DB.Where("isbn = ? AND type IN (2, 3)", req.Isbn).Find(&books).Error; err != nil { return nil, fmt.Errorf("[ERROR] 查询书籍信息失败:%v\n", err) } if len(books) == 0 { return nil, nil } response := &systemRes.SuitBookResponse{ WithFid: make([]models.BookInfo, 0), WithoutFid: make([]models.BookInfo, 0), } for _, book := range books { if book.Fid == 0 { response.WithoutFid = append(response.WithoutFid, book) } else { response.WithFid = append(response.WithFid, book) } } return response, nil } func (s *BookService) GetProCode(req systemReq.GetCodeRequest) (string, error) { input := req.BookName + req.Author + req.Publisher hash := md5.Sum([]byte(input)) hexStr := hex.EncodeToString(hash[:]) code := hexStr[:20] return strings.ToUpper(code), nil } func (s *BookService) SyncBook(req systemReq.AddBookRequest) (int64, string, error) { if req.Fid == 0 { var existingBook models.BookInfo err := database.DB.Where("fid = 0 AND isbn = ?", req.Isbn).First(&existingBook).Error if err == nil { return existingBook.ID, fmt.Sprintf("%s-%s", req.Isbn, req.FIsbn), nil } } bookID, err := s.doBook(req) if err != nil { return 0, "", fmt.Errorf("[ERROR] 保存书籍信息失败:%v\n", err) } return bookID, fmt.Sprintf("%s-%s", req.Isbn, req.FIsbn), nil } // GetNoIsbnBook 获取无书号书籍 func (s *BookService) GetNoIsbnBook(req systemReq.GetNoIsbnBookRequest) (*systemRes.NoIsbnBookResponse, error) { query := database.DB.Model(&models.BookInfo{}).Where("type = ?", 4) if req.BookName != "" { query = query.Where("book_name LIKE ?", "%"+req.BookName+"%") } if req.Author != "" { query = query.Where("author LIKE ?", "%"+req.Author+"%") } if req.Publisher != "" { query = query.Where("publishing LIKE ?", "%"+req.Publisher+"%") } var total int64 if err := query.Count(&total).Error; err != nil { return nil, fmt.Errorf("查询无书号书总数失败: %v", err) } var books []models.BookInfo if err := query.Order("id DESC").Find(&books).Error; err != nil { return nil, fmt.Errorf("查询无书号书列表失败: %v", err) } if books == nil { books = make([]models.BookInfo, 0) } return &systemRes.NoIsbnBookResponse{ Total: total, List: books, }, nil } func (s *BookService) doBook(data systemReq.AddBookRequest) (int64, error) { var liveImage datatypes.JSON if len(data.LiveImage) > 0 { jsonBytes, _ := json.Marshal(data.LiveImage) liveImage = jsonBytes } else { liveImage = datatypes.JSON("[]") } catIdByJson := datatypes.JSON(`{"xian_yu_cat_id": "", "kong_fu_zi_cat_id": "", "pin_duo_duo_cat_id": ""}`) if data.CatID != "" { var catObj map[string]string if err := json.Unmarshal([]byte(data.CatID), &catObj); err == nil { filtered := make(map[string]string) for k, v := range catObj { if strings.TrimSpace(v) != "" { filtered[k] = v } } if len(filtered) > 0 { filteredBytes, _ := json.Marshal(filtered) catIdByJson = filteredBytes } } } // publication_time 兼容秒级和毫秒级时间戳,格式化为 "年-月" var publicationDate string if data.PublicationTime > 0 { ts := data.PublicationTime if ts > 1e12 { // 毫秒级时间戳 ts /= 1000 } publicationDate = time.Unix(ts, 0).Format("2006-01") } book := models.BookInfo{ Fid: data.Fid, Type: data.Type, ISBN: data.Isbn, FISBN: data.FIsbn, BookName: data.BookName, FBookName: data.FBookName, Author: data.Author, Publishing: data.Publisher, PublicationTime: data.PublicationTime, PublicationDate: publicationDate, Binding: data.BindingLayout, PagesCount: data.PageCount, WordsCount: data.WordCount, Format: data.BookFormat, Price: data.FixPrice, CatID: catIdByJson, LiveImage: liveImage, } bookID, err := s.createBook(book) if err != nil { return 0, err } return bookID, nil } func (s *BookService) createBook(book models.BookInfo) (int64, error) { if err := database.DB.Create(&book).Error; err != nil { return 0, fmt.Errorf("创建书籍信息失败:%w", err) } return book.ID, nil } func (s *BookService) parseIntOrString(value string) int { value = strings.TrimSpace(value) if value == "" { return 0 } intVal, err := strconv.Atoi(value) if err != nil { return 0 } return intVal }