app_table_file.go 6.9 KB
package service

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/beego/beego/v2/client/httplib"
	"github.com/linmadan/egglib-go/core/application"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/command"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/query"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/apilib"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
	"os"
	"strings"
	"time"
)

func (fileService *FileService) CreateAppTableFile(ctx *domain.Context, cmd *command.CreateAppTableFileCommand) (*command.CreateFileCommand, error) {
	response := &command.CreateFileCommand{}
	var (
		titles   = make([]string, 0)
		dataList = make([][]string, 0)
	)
	for _, filed := range cmd.Fields {
		titles = append(titles, filed.Name)
	}
	for i := range cmd.Data {
		row := make([]string, 0)
		for _, filed := range titles {
			if v, ok := cmd.Data[i][filed]; ok {
				row = append(row, v)
			} else {
				row = append(row, "")
			}
		}
		dataList = append(dataList, row)
	}
	fileUpload, err := saveFile(cmd.Name, titles, dataList, nil)
	if err != nil {
		return nil, factory.FastError(err)
	}
	response.Name = cmd.Name
	if !strings.HasSuffix(response.Name, domain.XLSX) {
		response.Name = response.Name + domain.XLSX
	}
	response.Url = fileUpload.Url
	response.FileSize = int(fileUpload.FileSize)
	response.FileFrom = domain.FileFromDigitalAppClient
	return response, nil
}

func saveFile(name string, title []string, dataList [][]string, toInterfaces func([]string) []interface{}) (FileUpload, error) {
	var (
		response = FileUpload{}
		err      error
	)
	var writerTo = excel.NewXLXSWriterTo(title, dataList)
	if toInterfaces != nil {
		writerTo.ToInterfaces = toInterfaces
	}
	filename := fmt.Sprintf("%v_%v.xlsx", name, time.Now().Format("060102150405"))
	path := fmt.Sprintf("public/%v", filename)
	if err = writerTo.Save(path); err != nil {
		return response, factory.FastError(err)
	}
	api := apilib.NewApiAuthLib(constant.OPEN_API_HOST)
	uploadResponse, err := api.Upload(apilib.RequestUpload{
		UploadFileMap: map[string]string{"file": path},
	})
	if err != nil {
		return response, err
	}
	if stat, err := os.Stat(path); err == nil {
		response.FileSize = stat.Size()
	}
	response.Url = domain.ConvertInternalFileUrlToPublic(uploadResponse.Path)
	response.FileName = name
	response.Ext = domain.XLSX

	return response, nil
}

type FileUpload struct {
	Url      string `json:"url"`
	Ext      string `json:"ext"`
	FileName string `json:"fileName"`
	FileSize int64  `json:"fileSize"`
}

func (fileService *FileService) DeleteAppTableFile(ctx *domain.Context, cmd *command.DeleteAppTableFileCommand) (interface{}, error) {
	//if err := cmd.ValidateCommand(); err != nil {
	//	return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	//}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
	file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
	if err == domain.ErrorNotFound {
		return nil, factory.FastError(errors.New("文件不存在"))
	}
	if err != nil {
		return nil, factory.FastError(err)
	}
	if _, err := fileRepository.Remove(file); err != nil {
		return nil, factory.FastError(err)
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd *command.AppTableFileAppendDataCommand) (interface{}, error) {
	//if err := cmd.ValidateCommand(); err != nil {
	//	return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	//}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
	file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
	if err == domain.ErrorNotFound {
		return nil, factory.FastError(errors.New("文件不存在"))
	}
	if err != nil {
		return nil, factory.FastError(err)
	}

	// 下载文件
	f, err := httplib.Get(domain.ConvertFileUrlToInternal(file.FileInfo.Url)).Bytes()
	if err != nil {
		return nil, factory.FastError(err)
	}
	reader := bytes.NewReader(f)
	var importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext)
	data, err := importer.OpenExcelFromIoReader(reader)
	if err != nil {
		return nil, factory.FastError(err)
	}
	titles := importer.Reader().Header().Columns
	for _, f := range cmd.Fields {
		found := false
		for _, column := range titles {
			if column == f.Name {
				found = true
				break
			}
		}
		if !found {
			titles = append(titles, f.Name)
		}
	}
	// 填充旧数据
	// 追加文件
	for i := range data {
		if len(data[i]) < len(titles) {
			for j := 0; j < (len(titles) - len(data[i])); j++ {
				data[i] = append(data[i], "")
			}
		}
	}
	for i := range cmd.Data {
		row := make([]string, 0)
		for _, filed := range titles {
			if v, ok := cmd.Data[i][filed]; ok {
				row = append(row, v)
			} else {
				row = append(row, "")
			}
		}
		data = append(data, row)
	}

	// 上传文件
	fileUpload, err := saveFile(cmd.Name, titles, data, nil)
	if err != nil {
		return nil, factory.FastError(err)
	}

	// 更新文件
	file.FileInfo.Url = fileUpload.Url
	file.FileInfo.FileSize = int(fileUpload.FileSize)
	file.FileInfo.RowCount = len(data)
	_, err = fileRepository.Save(file)
	if err != nil {
		return nil, factory.FastError(err)
	}

	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return struct{}{}, nil
}

func (fileService *FileService) AppTableFileList(ctx *domain.Context, cmd *query.ListAppTableFileCommand) (interface{}, error) {
	return fileService.GetAppFile(ctx, cmd.AppKey, cmd.Name)
}