refactor(export): 统一导出内容

This commit is contained in:
Mr.Li 2023-01-30 18:32:16 +08:00
parent 372c126cac
commit d024627ab2
9 changed files with 606 additions and 0 deletions

18
cmd/main.go Normal file
View File

@ -0,0 +1,18 @@
package main
func main() {
}
//分块获取数据
//获取关联表单数据
//组装数据
//将数据写入excel中
//更具切割参数,计算拆分文件序号
//并发读写数据的能力
//控制内存使用、cpu使用

14
data/conn.go Normal file
View File

@ -0,0 +1,14 @@
package data
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func Conn() *gorm.DB {
conn, err := gorm.Open(mysql.Open("root:root@tcp(192.168.6.74:3307)/new_sys?charset=utf8mb4&parseTime=True"))
if err != nil {
panic("数据库连接失败")
}
return conn
}

86
data/order.go Normal file
View File

@ -0,0 +1,86 @@
package data
import (
"context"
"gorm.io/gorm"
"time"
)
type Reseller struct {
Id int64 `gorm:"primaryKey;column:id"`
Name string
}
func (o Reseller) TableName() string {
return "reseller"
}
type OrderItem struct {
OrderNumber string `gorm:"primaryKey;column:order_order_number"`
OursProductId int
OursProductTitle string
}
func (o OrderItem) TableName() string {
return "order_item"
}
type OrderRemark struct {
OrderNumber string `gorm:"primaryKey;column:order_number"`
Remark string
}
func (o OrderRemark) TableName() string {
return "order_remark"
}
type Order struct {
OrderNumber string `gorm:"primaryKey;column:order_number"`
ResellerId int64
ResellerOrderNumber string
Amount float32
Account string
Quantity int
Status int
PayStatus int
CreateTime int64
FinishTime int64
Item OrderItem `gorm:"foreignkey:order_order_number;references:order_number"`
Remark OrderRemark `gorm:"foreignkey:order_number;references:order_number"`
Reseller Reseller `gorm:"foreignkey:id;references:reseller_id"`
}
func (o Order) TableName() string {
return "order"
}
type OrderRepo struct {
db *gorm.DB
}
func NewOrderRepo(db *gorm.DB) *OrderRepo {
return &OrderRepo{
db: db,
}
}
func (repo OrderRepo) List(ctx context.Context, begin, end time.Time, limit int, last string) ([]Order, error) {
var orders []Order
db := repo.db.WithContext(ctx).Debug().
Preload("Reseller").
Preload("Item").
Preload("Remark").
Where("create_time BETWEEN ? AND ?", begin.Unix(), end.Unix())
if last != "" {
db.Where("order_number > ?", last)
}
result := db.Order("create_time,order_number").
Limit(limit).
Find(&orders)
if result.Error != nil {
return nil, result.Error
}
return orders, nil
}

21
data/order_test.go Normal file
View File

@ -0,0 +1,21 @@
package data
import (
"context"
"fmt"
"testing"
"time"
)
func orderRepo() *OrderRepo {
db := Conn()
return NewOrderRepo(db)
}
func TestOrderRepo_List(t *testing.T) {
repo := orderRepo()
begin := time.Date(2022, 10, 1, 0, 0, 0, 0, time.Local)
end := time.Date(2022, 12, 1, 0, 0, 0, 0, time.Local)
orders, err := repo.List(context.Background(), begin, end, 10, "123")
fmt.Println(err)
fmt.Printf("%+v\n", orders)
}

7
export/entity.go Normal file
View File

@ -0,0 +1,7 @@
package export
type Entity interface {
Title() []string
Size() int
Data() []interface{}
}

129
export/excel.go Normal file
View File

@ -0,0 +1,129 @@
package export
import (
"errors"
"fmt"
"github.com/tealeg/xlsx/v3"
"os"
)
const sheet_name = "sheet_1"
type Export struct {
index int
count int //总数
row int //当前执行的数据行
limit int //导出限制
path string
isNew bool
titles []string
file *xlsx.File
sheet *xlsx.Sheet
}
func NewExport(path string, limit int) *Export {
return &Export{
path: path,
limit: limit,
}
}
func (e *Export) Title(titles []string) error {
if e.file == nil || e.sheet == nil {
return errors.New("没有执行open方法")
}
if titles != nil {
e.titles = titles
}
if e.titles != nil && e.isNew {
row := e.sheet.AddRow()
row.WriteSlice(e.titles, -1)
}
return nil
}
func (e *Export) fileName() string {
return fmt.Sprintf(e.path, e.index)
}
func (e *Export) slice() {
e.row++
if e.row > e.limit {
e.row = 0
e.reset()
}
}
func (e *Export) reset() {
e.Save()
e.index++
e.Open()
e.Title(nil)
e.slice()
}
func (e *Export) Export(data Entity) error {
if e.file == nil || e.sheet == nil {
return errors.New("没有执行open方法")
}
e.count = data.Size()
for _, order := range data.Data() {
e.slice()
row := e.sheet.AddRow()
row.WriteStruct(order, -1)
}
return nil
}
func (e *Export) Open() error {
path := e.fileName()
exist, err := e.isFielExist(path)
if err != nil {
return err
}
if exist {
e.isNew = false
if e.file, err = xlsx.OpenFile(path); err != nil {
return err
}
} else {
e.isNew = true
e.file = xlsx.NewFile()
}
var ok bool
e.sheet, ok = e.file.Sheet[sheet_name]
if !ok {
e.sheet, err = e.file.AddSheet(sheet_name)
if err != nil {
return err
}
} else {
//需要处理偏移数据
e.row = e.sheet.MaxRow - 1
}
return nil
}
func (e *Export) isFielExist(file string) (bool, error) {
_, err := os.Stat(file)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func (e *Export) Save() error {
return e.file.Save(e.fileName())
}

226
export/excel_test.go Normal file
View File

@ -0,0 +1,226 @@
package export
import (
"fmt"
"lsxd_excel/data"
"os"
"testing"
)
func TestExport_Export(t *testing.T) {
dir, _ := os.Getwd()
path := dir + "/aa_%d.xlsx"
e := NewExport(path, 4)
err := e.Open()
fmt.Println(err)
data := NewOrder([]data.Order{
{
OrderNumber: "123451",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123452",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123453",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123454",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123455",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123456",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123457",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123458",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
{
OrderNumber: "123459",
Reseller: data.Reseller{
Id: 23456,
Name: "分销商名称",
},
ResellerOrderNumber: "123456448",
Amount: 12.22,
Account: "13512345678",
Quantity: 1,
Status: 1,
PayStatus: 1,
CreateTime: 1672744984,
FinishTime: 1672744984,
Item: data.OrderItem{
OursProductId: 101,
OursProductTitle: "商品名称",
},
Remark: data.OrderRemark{
Remark: "备注信息",
},
},
})
err = e.Title(data.Title())
fmt.Println(err)
err = e.Export(data)
fmt.Println(err)
err = e.Save()
fmt.Println(err)
}

83
export/order.go Normal file
View File

@ -0,0 +1,83 @@
package export
import (
"lsxd_excel/data"
"time"
)
type Order struct {
OrderNumber string
ResellerId int64
ResellerName string
ResellerOrderNumber string
Amount float32
Account string
Quantity int
Status int
PayStatus int
OursProductId int
OursProductTitle string
Remark string
CreateTime string
FinishTime string
}
func TransformOrder(order data.Order) *Order {
return &Order{
OrderNumber: order.OrderNumber,
ResellerId: order.ResellerId,
ResellerName: order.Reseller.Name,
ResellerOrderNumber: order.ResellerOrderNumber,
Amount: order.Amount,
Account: order.Account,
Quantity: order.Quantity,
Status: order.Status,
PayStatus: order.PayStatus,
CreateTime: time.Unix(order.CreateTime, 0).Format("2006-01-02 15:04:05"),
FinishTime: time.Unix(order.FinishTime, 0).Format("2006-01-02 15:04:05"),
OursProductId: order.Item.OursProductId,
OursProductTitle: order.Item.OursProductTitle,
Remark: order.Remark.Remark,
}
}
func NewOrder(data []data.Order) Orders {
o := make([]*Order, len(data))
for i, v := range data {
o[i] = TransformOrder(v)
}
return o
}
type Orders []*Order
func (o Orders) Title() []string {
return []string{
"订单号",
"分销商ID",
"分销商名称",
"分销商订单号",
"总价",
"充值账号",
"数量",
"状态",
"支付状态",
"商品编号",
"商品名称",
"备注",
"创建时间",
"完成时间",
}
}
func (o Orders) Size() int {
return len(o)
}
func (o Orders) Data() []interface{} {
d := make([]interface{}, o.Size())
for i, v := range o {
d[i] = v
}
return d
}

22
go.mod Normal file
View File

@ -0,0 +1,22 @@
module excel_export
go 1.18
require (
github.com/frankban/quicktest v1.11.2 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/google/btree v1.0.0 // indirect
github.com/google/go-cmp v0.5.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/kr/text v0.1.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa // indirect
github.com/tealeg/xlsx/v3 v3.2.4 // direct
golang.org/x/text v0.3.3 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
gorm.io/driver/mysql v1.4.5 // direct
gorm.io/gorm v1.24.3 // direct
)