diff --git a/export.go b/export.go index 8c29e91..003eb9c 100644 --- a/export.go +++ b/export.go @@ -3,13 +3,17 @@ package excel_export import ( "encoding/json" "fmt" + "gitea.cdlsxd.cn/self-tools/l_excel_export/export_err" "gitea.cdlsxd.cn/self-tools/l_excel_export/pkg" "gitea.cdlsxd.cn/self-tools/l_excel_export/types" - "time" - - "gitea.cdlsxd.cn/self-tools/l_excel_export/export_err" "github.com/xuri/excelize/v2" + + "io" + "math" + "net/http" "os" + "sort" + "time" ) type ExportExcel struct { @@ -25,19 +29,17 @@ type ExportExcel struct { header []interface{} } -func NewExport(config *Config, opts ...Option) (*ExportExcel, error) { - export := &ExportExcel{ - config: config, - } +func NewExport(opts ...Option) *ExportExcel { + e := &ExportExcel{} for _, opt := range opts { - opt(export) // 应用选项 + opt(e) // 应用选项 } - err := export.check() - return export, err + e.initJobName() + return e } -func (e *ExportExcel) Run() (taskId string, err error) { - err = e.init() +func (e *ExportExcel) Run(config *Config) (taskId string, err error) { + err = e.init(config) if err != nil { return } @@ -66,6 +68,81 @@ func (e *ExportExcel) Run() (taskId string, err error) { return e.task.TaskId, nil } +func (e *ExportExcel) TaskInfo(task_id string) (task *types.Task, err error) { + + e.logPath, err = pkg.DefaultLogPath(e.jobName) + + if err != nil { + return nil, err + } + e.task = &types.Task{ + TaskId: task_id, + } + + taskInfo, err := os.ReadFile(e.logFile()) + if err != nil { + return nil, err + } + _ = json.Unmarshal(taskInfo, e.task) + return e.task, nil +} + +func (e *ExportExcel) DownloadExcel(w http.ResponseWriter, task_id string) (err error) { + task, err := e.TaskInfo(task_id) + if err != nil { + return err + } + _, exist := os.Stat(task.Url) + if exist != nil { + return fmt.Errorf("文件不存在") + } + + file, err := os.Open(task.Url) + if err != nil { + return err + } + defer file.Close() + payload, err := io.ReadAll(file) + if err != nil { + return err + } + // 设置HTTP响应头 + // 打开为预览 + //ctx.Response().Header().Set("Content-Type", "image/png") + // 打开为下载 + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", "attachment; filename="+task.Url) + // 将结果写入 + _, err = w.Write(payload) + return +} + +func (e *ExportExcel) TaskHis(page int, num int) (res *types.ResPage, err error) { + var data []*types.Task + e.logPath, err = pkg.DefaultLogPath(e.jobName) + if err != nil { + return res, err + } + + entries := e.SortLogFileWithStatus() + count := len(entries) + + begin := (page - 1) * num + entEnd := begin + num + if count < entEnd { + entEnd = count + } + data = entries[begin:entEnd] + + return &types.ResPage{ + Page: page, + Limit: num, + Total: count, + Data: data, + LastPage: int(math.Ceil(float64(count) / float64(num))), + }, nil +} + func (e *ExportExcel) run(f *excelize.File) (err error) { index, err := f.NewStreamWriter(e.getSheetName()) @@ -106,17 +183,22 @@ func (e *ExportExcel) getUrl() string { return fmt.Sprintf("%s/%s_%s%s", e.config.SavePath, e.config.FileName, e.task.TaskId, e.config.Ext) } -func (e *ExportExcel) init() error { - e.task = &types.Task{ - TaskId: pkg.CreateTaskId(), - Process: 0, - Url: "", - Ctime: time.Now().Format(time.DateTime), - Ftime: "", - Status: Init, - FileAddr: "", +func (e *ExportExcel) init(config *Config) error { + e.config = config + + err := e.check() + if err != nil { + return err } - err := e.updateTask() + e.task = &types.Task{ + TaskId: pkg.CreateTaskId(), + Process: 0, + Url: "", + Ctime: time.Now().Format(time.DateTime), + Ftime: "", + Status: Init, + } + err = e.updateTask() if err != nil { return err } @@ -195,9 +277,7 @@ func (e *ExportExcel) path() string { } func (e *ExportExcel) check() (err error) { - if len(e.jobName) == 0 { - e.jobName = time.Now().Format("default") - } + if e.config.SavePath == "" && e.saveFunc == nil { return export_err.ErrNotSetSaveWay } @@ -209,9 +289,40 @@ func (e *ExportExcel) check() (err error) { return } +func (e *ExportExcel) initJobName() { + if len(e.jobName) == 0 { + e.jobName = "default" + } +} + func (e *ExportExcel) getSheetName() string { if len(e.sheetName) == 0 { e.sheetName = "Sheet1" } return e.sheetName } + +func (e *ExportExcel) SortLogFileWithStatus() (fileInfoList []*types.Task) { + + // 获取目录中的文件信息 + d, _ := os.Open(e.logPath) + defer d.Close() + files, _ := d.ReadDir(0) + + // 填充切片 + for _, file := range files { + fileName := file.Name() + bytes, _ := os.ReadFile(e.logPath + "/" + fileName) + var info types.Task + _ = json.Unmarshal(bytes, &info) + fileInfoList = append(fileInfoList, &info) + } + + // 根据修改时间对切片进行排序 + + sort.Slice(fileInfoList, func(i, j int) bool { + + return fileInfoList[i].Ctime >= fileInfoList[j].Ctime + }) + return fileInfoList +} diff --git a/export_test.go b/export_test.go index 06b02a9..72dc689 100644 --- a/export_test.go +++ b/export_test.go @@ -40,7 +40,9 @@ func TestData(t *testing.T) { Order{OrderNum: "asdasd", OrderID: 15, CusNum: "asdzczxfaxc"}, } - out, err := NewExport(&Config{ + out := NewExport(WithJobName("a")) + + task_id, err := out.Run(&Config{ FileName: "a", Data: c, Ext: Xlsx, @@ -54,10 +56,16 @@ func TestData(t *testing.T) { if err != nil { panic(err) } - task_id, err := out.Run() - if err != nil { - panic(err) - } fmt.Println(task_id) select {} } + +func TestTaskInfo(t *testing.T) { + out, err := NewExport(WithJobName("a")).TaskInfo("1740733651965395783") + fmt.Println(out, err) +} + +func TestTaskHis(t *testing.T) { + out, err := NewExport(WithJobName("a")).TaskHis(1, 2) + fmt.Println(out, err) +} diff --git a/pkg/pkg.go b/pkg/pkg.go index bdbd9b9..f376261 100644 --- a/pkg/pkg.go +++ b/pkg/pkg.go @@ -9,6 +9,8 @@ import ( "time" ) +type () + func DefaultLogPath(jobName string) (string, error) { path, err := os.Getwd() path = fmt.Sprintf("%s/%s/%s", path, "log/export", jobName) diff --git a/types/types.go b/types/types.go index 118b374..4cf8caa 100644 --- a/types/types.go +++ b/types/types.go @@ -1,13 +1,31 @@ package types +import ( + "io/fs" + "time" +) + type ( Task struct { - TaskId string `json:"task_id"` - Url string `json:"url"` - Process int `json:"process"` - Ctime string `json:"ctime"` - Ftime string `json:"ftime"` - Status int8 `json:"status"` - FileAddr string `json:"file_addr"` + TaskId string `json:"task_id"` + Url string `json:"url"` + Process int `json:"process"` + Ctime string `json:"ctime"` + Ftime string `json:"ftime"` + Status int8 `json:"status"` + } + + ResPage struct { + Page int `json:"current_page"` + Limit int `json:"per_page"` + Total int `json:"total"` + LastPage int `json:"last_page"` + Data []*Task `json:"data"` + } + + FileInfoStatus struct { + fs.FileInfo + Status int + Time time.Time } )