fix: align admin behavior and Kratos integrations
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
func templateColumns(raw string) ([]string, map[string]string, error) {
|
||||
labels := map[string]string{}
|
||||
decoder := json.NewDecoder(strings.NewReader(raw))
|
||||
token, err := decoder.Token()
|
||||
if err != nil || token != json.Delim('{') {
|
||||
return nil, nil, err
|
||||
}
|
||||
keys := make([]string, 0)
|
||||
for decoder.More() {
|
||||
keyToken, tokenErr := decoder.Token()
|
||||
if tokenErr != nil {
|
||||
return nil, nil, tokenErr
|
||||
}
|
||||
key := keyToken.(string)
|
||||
var label string
|
||||
if tokenErr = decoder.Decode(&label); tokenErr != nil {
|
||||
return nil, nil, tokenErr
|
||||
}
|
||||
keys = append(keys, key)
|
||||
labels[key] = label
|
||||
}
|
||||
if _, err = decoder.Token(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return keys, labels, nil
|
||||
}
|
||||
func (s *ExportService) Export(ctx context.Context, tid string, params map[string]string) ([]byte, string, error) {
|
||||
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
rows, _, err := s.uc.QueryExport(ctx, template, params)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
keys, labels, err := templateColumns(template.TemplateInfo)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
file := excelize.NewFile()
|
||||
sheet := file.GetSheetName(0)
|
||||
for column, key := range keys {
|
||||
cell, _ := excelize.CoordinatesToCellName(column+1, 1)
|
||||
_ = file.SetCellValue(sheet, cell, labels[key])
|
||||
}
|
||||
for rowIndex, row := range rows {
|
||||
for column, key := range keys {
|
||||
cell, _ := excelize.CoordinatesToCellName(column+1, rowIndex+2)
|
||||
_ = file.SetCellValue(sheet, cell, row[key])
|
||||
}
|
||||
}
|
||||
buffer, err := file.WriteToBuffer()
|
||||
_ = file.Close()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return buffer.Bytes(), template.Name + ".xlsx", nil
|
||||
}
|
||||
func (s *ExportService) ExportBlankTemplate(ctx context.Context, tid string) ([]byte, string, error) {
|
||||
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
keys, labels, err := templateColumns(template.TemplateInfo)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
file := excelize.NewFile()
|
||||
sheet := file.GetSheetName(0)
|
||||
for column, key := range keys {
|
||||
cell, _ := excelize.CoordinatesToCellName(column+1, 1)
|
||||
_ = file.SetCellValue(sheet, cell, labels[key])
|
||||
}
|
||||
buffer, err := file.WriteToBuffer()
|
||||
_ = file.Close()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return buffer.Bytes(), template.Name + "_template.xlsx", nil
|
||||
}
|
||||
func (s *ExportService) Preview(ctx context.Context, tid string, params map[string]string) (string, error) {
|
||||
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s.uc.PreviewExport(ctx, template, params)
|
||||
}
|
||||
func (s *ExportService) Import(ctx context.Context, tid string, reader io.Reader) error {
|
||||
template, err := s.uc.FindExportTemplate(ctx, 0, tid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := excelize.OpenReader(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
sheets := file.GetSheetList()
|
||||
if len(sheets) == 0 {
|
||||
return errors.New("工作簿没有工作表")
|
||||
}
|
||||
rows, err := file.GetRows(sheets[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(rows) < 2 {
|
||||
return errors.New("Excel data is not enough.\nIt should contain title row and data")
|
||||
}
|
||||
keys, labels, err := templateColumns(template.TemplateInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reverse := map[string]string{}
|
||||
for _, key := range keys {
|
||||
reverse[labels[key]] = key
|
||||
}
|
||||
headers := rows[0]
|
||||
items := make([]map[string]any, 0, len(rows)-1)
|
||||
for _, row := range rows[1:] {
|
||||
item := map[string]any{}
|
||||
for column, value := range row {
|
||||
if column >= len(headers) {
|
||||
continue
|
||||
}
|
||||
key := reverse[headers[column]]
|
||||
if key != "" {
|
||||
item[key] = value
|
||||
}
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
if err = s.uc.ImportExportRows(ctx, template, items); err != nil {
|
||||
return fmt.Errorf("导入失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user