generated from kedaya_haitao/template
This commit is contained in:
parent
a3f7314ece
commit
00e4f26d71
@ -15,19 +15,17 @@ import (
|
||||
"github.com/gofiber/fiber/v3/middleware/cors"
|
||||
"github.com/gofiber/fiber/v3/middleware/recover"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
glog.Info(">>> BEGIN INIT<<<")
|
||||
logrus.Info(">>> BEGIN INIT<<<")
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt)
|
||||
defer cancel()
|
||||
// 初始化数据库
|
||||
db, err := database.InitDefaultDatabase()
|
||||
if err != nil {
|
||||
glog.Fatalf("init database failed: %v", err)
|
||||
logrus.Fatalf("init database failed: %v", err)
|
||||
}
|
||||
|
||||
client, err := dw_sdk.InitDefaultDWClient()
|
||||
@ -59,6 +57,6 @@ func main() {
|
||||
EnablePrintRoutes: true,
|
||||
GracefulContext: ctx,
|
||||
}); err != nil {
|
||||
glog.Warningf("service over: %v", err)
|
||||
logrus.Warningf("service over: %v", err)
|
||||
}
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -8,7 +8,6 @@ require (
|
||||
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20250329125718-37b1ee0b6a4b
|
||||
gitea.timerzz.com/kedaya_haitao/dw-sdk v0.0.0-20240904075121-552ef11ea87c
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.4
|
||||
github.com/golang/glog v1.2.2
|
||||
github.com/samber/lo v1.49.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/xuri/excelize/v2 v2.9.0
|
||||
@ -50,6 +49,7 @@ require (
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
||||
golang.org/x/arch v0.9.0 // indirect
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/image v0.25.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
|
6
go.sum
6
go.sum
@ -25,8 +25,6 @@ github.com/gofiber/schema v1.2.0 h1:j+ZRrNnUa/0ZuWrn/6kAtAufEr4jCJ+JuTURAMxNSZg=
|
||||
github.com/gofiber/schema v1.2.0/go.mod h1:YYwj01w3hVfaNjhtJzaqetymL56VW642YS3qZPhuE6c=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.7 h1:NnHFrRHvhrufPABdWajcKZejz9HnCWmT/asoxRsiEbQ=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.7/go.mod h1:J/M03s+HMdZdvhAeyh76xT72IfVqBzuz/OJkrMa7cwU=
|
||||
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
|
||||
github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
@ -112,8 +110,8 @@ golang.org/x/arch v0.9.0 h1:ub9TgUInamJ8mrZIGlBG6/4TqWeMszd4N8lNorbrr6k=
|
||||
golang.org/x/arch v0.9.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
|
||||
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -57,16 +57,15 @@ func (s *Tools) CoachOutletExcel(c fiber.Ctx) error {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "导出工具未初始化")
|
||||
}
|
||||
|
||||
// 设置文件名和响应头
|
||||
fileName := fmt.Sprintf("coach_outlet_%s.xlsx", providerId)
|
||||
c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
|
||||
c.Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
|
||||
// 直接将Excel数据写入响应
|
||||
if err := s.export.ExportCheapProduct(providerId, c); err != nil {
|
||||
fileName, err := s.export.ExportCheapProduct(providerId)
|
||||
if err != nil {
|
||||
logrus.Errorf("导出Coach Outlet商品数据失败: %v", err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("导出失败: %v", err))
|
||||
}
|
||||
// 设置文件名和响应头
|
||||
c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
|
||||
c.Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
|
||||
return nil
|
||||
return c.SendFile(fileName)
|
||||
}
|
||||
|
@ -5,14 +5,12 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.timerzz.com/kedaya_haitao/common/structs/storage"
|
||||
"gitea.timerzz.com/kedaya_haitao/common/structs/utils"
|
||||
v2 "gitea.timerzz.com/kedaya_haitao/common/structs/v2"
|
||||
dw_sdk "gitea.timerzz.com/kedaya_haitao/dw-sdk"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/samber/lo"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/xuri/excelize/v2"
|
||||
@ -37,19 +35,23 @@ func NewExporter(storage *storage.Storage, dw *dw_sdk.Client) (e *Exporter, err
|
||||
}
|
||||
|
||||
// ExportCheapProduct 导出价格较低的商品数据到Excel,直接写入到HTTP响应
|
||||
func (e *Exporter) ExportCheapProduct(providerId string, c fiber.Ctx) error {
|
||||
func (e *Exporter) ExportCheapProduct(providerId string) (string, error) {
|
||||
// 创建Excel文件
|
||||
f := excelize.NewFile()
|
||||
defer f.Close()
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// 创建工作表
|
||||
|
||||
sheetName := providerId
|
||||
_, err := f.NewSheet(sheetName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建工作表失败: %w", err)
|
||||
return "", fmt.Errorf("创建工作表失败: %w", err)
|
||||
}
|
||||
_ = f.DeleteSheet("Sheet1") // 删除默认的Sheet1
|
||||
|
||||
// 确定查询的供应商ID
|
||||
var cheapId, otherId string
|
||||
cheapId = providerId
|
||||
@ -70,47 +72,47 @@ func (e *Exporter) ExportCheapProduct(providerId string, c fiber.Ctx) error {
|
||||
Where("pa1.cost->>'finalPrice' <= pa2.cost->>'finalPrice'").
|
||||
FindInBatches(&articles, 20, func(tx *gorm.DB, batch int) error {
|
||||
for _, article := range articles {
|
||||
// 更新DW价格(如果需要)
|
||||
dwSeller, idx, exist := lo.FindIndexOf(article.Sellers, func(seller v2.SellerArticle) bool {
|
||||
return seller.SellerId == "dw-normal"
|
||||
pArticle, _ := lo.Find(article.Providers, func(p v2.ProviderArticle) bool {
|
||||
return p.ProviderId == v2.ProviderId(cheapId)
|
||||
})
|
||||
if exist && dwSeller.Sell.CreatedAt.Before(time.Now().AddDate(0, 0, -1)) {
|
||||
// 如果已经是一天前的数据,那么就要更新下
|
||||
dwSeller = e.pullDwPrice(dwSeller)
|
||||
article.Sellers[idx] = dwSeller
|
||||
}
|
||||
if pArticle.Cost.OriginalPrice != 0 {
|
||||
// 更新DW价格(如果需要)
|
||||
dwSeller, idx, exist := lo.FindIndexOf(article.Sellers, func(seller v2.SellerArticle) bool {
|
||||
return seller.SellerId == "dw-normal"
|
||||
})
|
||||
if exist && dwSeller.Sell.CreatedAt.Before(time.Now().AddDate(0, 0, -1)) {
|
||||
// 如果已经是一天前的数据,那么就要更新下
|
||||
dwSeller = e.pullDwPrice(dwSeller)
|
||||
article.Sellers[idx] = dwSeller
|
||||
}
|
||||
|
||||
// 计算利润率
|
||||
utils.ProfitRate(article)
|
||||
// 计算利润率
|
||||
utils.ProfitRate(article)
|
||||
|
||||
// 添加到Excel
|
||||
rowIndex++
|
||||
if err = addRow(f, sheetName, rowIndex, article); err != nil {
|
||||
logrus.Errorf("添加行失败: %v", err)
|
||||
continue
|
||||
// 添加到Excel
|
||||
rowIndex++
|
||||
if err = addRow(f, sheetName, rowIndex, article); err != nil {
|
||||
logrus.Errorf("添加行失败: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}).Error
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询数据失败: %w", err)
|
||||
return "", fmt.Errorf("查询数据失败: %w", err)
|
||||
}
|
||||
|
||||
// 保存Excel文件
|
||||
filename := fmt.Sprintf("coach_outlet_%s.xlsx", providerId)
|
||||
|
||||
if err = f.SaveAs(filename); err != nil {
|
||||
return fmt.Errorf("保存Excel文件失败: %w", err)
|
||||
}
|
||||
|
||||
// 直接将Excel文件写入到HTTP响应
|
||||
if err = f.Write(c.Response().BodyWriter()); err != nil {
|
||||
return fmt.Errorf("写入Excel数据失败: %w", err)
|
||||
return "", fmt.Errorf("保存Excel文件失败: %w", err)
|
||||
}
|
||||
|
||||
logrus.Infof("成功导出 %d 条数据", rowIndex-1)
|
||||
return nil
|
||||
return filename, nil
|
||||
}
|
||||
|
||||
// 设置标题行
|
||||
@ -172,11 +174,13 @@ func addRow(f *excelize.File, sheetName string, rowIndex int, article *v2.Articl
|
||||
cell, _ := excelize.CoordinatesToCellName(i+1, rowIndex)
|
||||
_ = f.SetCellValue(sheetName, cell, value)
|
||||
}
|
||||
|
||||
// 设置行高以适应图片
|
||||
_ = f.SetRowHeight(sheetName, rowIndex, 80)
|
||||
|
||||
// 处理图片
|
||||
linkCell, _ := excelize.CoordinatesToCellName(1, rowIndex)
|
||||
_ = f.SetCellHyperLink(sheetName, linkCell, caProvider.Link, "External")
|
||||
|
||||
if len(article.Image) > 0 {
|
||||
imgCell, _ := excelize.CoordinatesToCellName(2, rowIndex)
|
||||
|
||||
@ -188,8 +192,8 @@ func addRow(f *excelize.File, sheetName string, rowIndex int, article *v2.Articl
|
||||
_ = f.SetCellValue(sheetName, imgCell, article.Image)
|
||||
} else {
|
||||
// 添加图片到Excel
|
||||
if err := f.AddPictureFromBytes(sheetName, imgCell, &excelize.Picture{
|
||||
Extension: getImageExtension(article.Image),
|
||||
if err = f.AddPictureFromBytes(sheetName, imgCell, &excelize.Picture{
|
||||
Extension: ".jpg",
|
||||
File: imgData,
|
||||
Format: &excelize.GraphicOptions{
|
||||
AutoFit: true,
|
||||
@ -202,6 +206,7 @@ func addRow(f *excelize.File, sheetName string, rowIndex int, article *v2.Articl
|
||||
// 如果添加失败,显示URL
|
||||
_ = f.SetCellValue(sheetName, imgCell, article.Image)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,31 +241,6 @@ func downloadImage(url string) ([]byte, error) {
|
||||
return imgData, nil
|
||||
}
|
||||
|
||||
// getImageExtension 从URL获取图片扩展名
|
||||
func getImageExtension(url string) string {
|
||||
// 默认扩展名
|
||||
ext := ".jpg"
|
||||
|
||||
// 从URL中提取扩展名
|
||||
if strings.Contains(url, ".") {
|
||||
parts := strings.Split(url, ".")
|
||||
lastPart := parts[len(parts)-1]
|
||||
|
||||
// 处理可能的查询参数
|
||||
if strings.Contains(lastPart, "?") {
|
||||
lastPart = strings.Split(lastPart, "?")[0]
|
||||
}
|
||||
|
||||
// 常见图片扩展名
|
||||
switch strings.ToLower(lastPart) {
|
||||
case "jpg", "jpeg", "png", "gif", "bmp", "webp":
|
||||
ext = "." + strings.ToLower(lastPart)
|
||||
}
|
||||
}
|
||||
|
||||
return ext
|
||||
}
|
||||
|
||||
func (e *Exporter) pullDwPrice(sArticle v2.SellerArticle) v2.SellerArticle {
|
||||
skuId, _ := strconv.Atoi(sArticle.SkuID)
|
||||
resp, err := e.dw.NormalBidClient().LowestPrice(skuId)
|
||||
|
Loading…
x
Reference in New Issue
Block a user