作者 郑周

1. 获取zip文件 ->临时保存到本地 ->解压 ->解析xml ->创建模板

2. 返回key, 前端通过访问key验证数据处理结果
... ... @@ -2,14 +2,16 @@ package command
import (
"github.com/beego/beego/v2/core/validation"
"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/domain"
"unicode/utf8"
)
type CreateTemplateCommand struct {
CompanyId int64 `cname:"公司ID" json:"companyId"`
CreatorId int64 `cname:"创建人ID" json:"creatorId"`
Name string `cname:"模板名称" json:"name" valid:"Required"`
Describe string `cname:"模板描述" json:"describe"`
CompanyId int64 `cname:"公司ID" json:"companyId"`
CreatorId int64 `cname:"创建人ID" json:"creatorId"`
Name string `cname:"模板名称" json:"name" valid:"Required"`
Describe string `cname:"模板描述" json:"describe"`
NodeContents []*domain.NodeContent `cname:"环节-评估内容" json:"nodeContents"`
}
func (in *CreateTemplateCommand) Valid(validation *validation.Validation) {
... ...
... ... @@ -40,13 +40,21 @@ func (rs *EvaluationTemplateService) Create(in *command.CreateTemplateCommand) (
linkNodes := make([]*domain.LinkNode, 0)
sid, _ := utils.NewSnowflakeId()
linkNodes = append(linkNodes, &domain.LinkNode{
// 自评反馈
selfLinkNode := &domain.LinkNode{
Id: sid + 1,
Type: domain.LinkNodeSelfAssessment,
Name: "填写自评反馈",
NodeContents: make([]*domain.NodeContent, 0),
KpiCycle: domain.KpiCycleDay,
})
}
// 有环节自评评估内容,则直接使用
if len(in.NodeContents) > 0 {
selfLinkNode.NodeContents = in.NodeContents
}
linkNodes = append(linkNodes, selfLinkNode)
linkNodes = append(linkNodes, &domain.LinkNode{
Id: sid + 2,
Type: domain.LinkNodeAllInvite,
... ...
... ... @@ -17,6 +17,9 @@ var AdminJwtExpiresIn = int64(3600 * 24 * 7)
var AdminJWTSecretKey = "sg-storage"
// 上传临时Zip文件
var UPLOAD_ZIP_PATH = "./uploads/zip"
// Env 判断当前环境变量
var Env = "dev"
... ...
package xredis
import "fmt"
const UploadZipKey = "performance:zip:%s" // 上传ZIP文件
func CreateUploadZipKey(v string) string {
return fmt.Sprintf(UploadZipKey, v)
}
... ...
... ... @@ -2,8 +2,12 @@ package xredis
import (
"context"
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"time"
"github.com/go-redis/redis/v8"
"github.com/go-redsync/redsync/v4"
... ... @@ -35,3 +39,37 @@ func init() {
pool := goredis.NewPool(rdb)
rsync = redsync.New(pool)
}
func Set(key string, value interface{}, timeout time.Duration) error {
valueOf := reflect.ValueOf(value)
typeName := strings.ToLower(valueOf.Type().Name())
var newValue interface{}
if typeName == "string" || typeName == "int" || typeName == "int64" || typeName == "float64" {
newValue = value
} else {
mBytes, err := json.Marshal(value)
if err != nil {
return err
}
newValue = string(mBytes)
}
err := rdb.Set(rdb.Context(), key, newValue, timeout*time.Second).Err()
return err
}
func Get(key string) string {
value, err := rdb.Get(rdb.Context(), key).Result()
if err != nil {
return ""
}
return value
}
func GetBytes(key string) ([]byte, error) {
return rdb.Get(rdb.Context(), key).Bytes()
}
func Remove(key string) error {
return rdb.Del(rdb.Context(), key).Err()
}
... ...
package controllers
import (
"archive/zip"
"bufio"
"encoding/json"
"fmt"
service "gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/evaluation_template"
templateCommand "gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/evaluation_template/command"
"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/application/import/command"
"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/infrastructure/xredis"
"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/utils"
"io"
"mime/multipart"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/linmadan/egglib-go/core/application"
"github.com/linmadan/egglib-go/utils/tool_funs"
... ... @@ -183,3 +197,233 @@ func (controller *ImportController) parseTemplateNodeContent(data []*domain.Perf
return nil, nodeContents
}
func (controller *ImportController) ZipVerify() {
in := &command.VerifyKeyCommand{}
if err := controller.Unmarshal(in); err != nil {
controller.Response(nil, application.ThrowError(application.ARG_ERROR, err.Error()))
} else {
bytes, err := xredis.GetBytes(in.VerifyKey)
if err != nil {
controller.Response(nil, application.ThrowError(application.ARG_ERROR, err.Error()))
} else {
out := &command.OutResult{}
err := json.Unmarshal(bytes, out)
if err != nil {
controller.Response(nil, application.ThrowError(application.ARG_ERROR, err.Error()))
} else {
controller.Response(out, nil)
}
}
}
}
func (controller *ImportController) ZipImport() {
_, header, err := controller.GetFile("file")
if err != nil {
controller.Response(nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "上传错误:"+err.Error()))
return
}
file, err := header.Open()
if err != nil {
controller.Response(nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "文件错误:"+err.Error()))
return
}
// 写入本地
zipPath, day, id, err := controller.writeLocal(file)
if err != nil {
controller.Response(nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()))
return
}
out := command.OutResult{
Status: "uncompleted",
Success: make([]command.ErrorI, 0),
Failure: make([]command.ErrorI, 0),
}
key := xredis.CreateUploadZipKey(id)
_ = xredis.Set(key, out, 2*time.Hour)
controller.Response(map[string]string{"key": key}, nil)
go func() {
// 解压目标文件夹
dstDir := constant.UPLOAD_ZIP_PATH + "/" + day + "/" + id
fileNames, err := controller.Unzip(zipPath, dstDir)
if err != nil {
_ = xredis.Remove(key)
} else {
success := make([]command.ErrorI, 0)
failure := make([]command.ErrorI, 0)
for i := range fileNames {
fn := fileNames[i]
f, err := os.Open(path.Join(dstDir, fn))
if err != nil {
failure = append(failure, command.ErrorI{
FileName: fn,
Message: err.Error(),
})
continue
}
if err := controller.parserAndInsert(f); err != nil {
failure = append(failure, command.ErrorI{
FileName: fn,
Message: err.Error(),
})
continue
}
success = append(success, command.ErrorI{
FileName: fn,
Message: "",
})
}
out = command.OutResult{
Status: "completed",
Success: success,
Failure: failure,
}
_ = xredis.Set(key, out, 1*time.Hour)
}
}()
}
func (controller *ImportController) writeLocal(file multipart.File) (string, string, string, error) {
var err error
id, err := utils.NewSnowflakeId()
if err != nil {
return "", "", "", err
}
id2 := fmt.Sprintf("%v", id)
day := time.Now().Format("2006-01-02")
zipPath := constant.UPLOAD_ZIP_PATH + "/" + day + "/" + id2 + "/" + "temp"
var fd *os.File
dir := filepath.Dir(zipPath)
err = os.MkdirAll(dir, os.ModePerm)
if err != nil {
return "", "", "", err
}
fd, err = os.OpenFile(zipPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
return "", "", "", err
}
defer func(fd *os.File) {
if err = fd.Close(); err != nil {
}
}(fd)
wt := bufio.NewWriter(fd)
_, err = file.Seek(0, io.SeekStart)
if err != nil {
return "", "", "", err
}
_, err = io.Copy(wt, file)
if err != nil {
return "", "", "", err
}
err = wt.Flush()
if err != nil {
return "", "", "", err
}
return zipPath, day, id2, err
}
func (controller *ImportController) Unzip(zipPath, dstDir string) ([]string, error) {
// 文件名称
fileNames := make([]string, 0)
// open zip file
reader, err := zip.OpenReader(zipPath)
if err != nil {
return fileNames, err
}
defer reader.Close()
for _, file := range reader.File {
if err := controller.unzipFile(file, dstDir); err != nil {
return fileNames, err
} else {
fileNames = append(fileNames, file.Name)
}
}
return fileNames, nil
}
// 解析文件并插入数据
func (controller *ImportController) parserAndInsert(file *os.File) error {
reader, err := excelize.OpenReader(file)
if err != nil {
return application.ThrowError(application.INTERNAL_SERVER_ERROR, "上传错误:"+err.Error())
}
index := reader.GetActiveSheetIndex()
rows, err := reader.GetRows(reader.GetSheetName(index))
if err != nil {
return application.ThrowError(application.INTERNAL_SERVER_ERROR, "读取excel错误:"+err.Error())
}
dimensions, err := domain.LoadPerformanceDimensions(rows)
if err != nil {
return application.ThrowError(application.ARG_ERROR, err.Error())
}
if err, list := controller.parseTemplateNodeContent(dimensions); err != nil {
return application.ThrowError(application.ARG_ERROR, err.Error())
} else {
if len(list) == 0 {
return application.ThrowError(application.ARG_ERROR, "没有数据内容")
}
ruService := service.NewEvaluationTemplateService()
in := &templateCommand.CreateTemplateCommand{}
ua := middlewares.GetUser(controller.Ctx)
in.CompanyId = ua.CompanyId
in.CreatorId = ua.UserId
in.Name = file.Name()
in.Describe = ""
in.NodeContents = list
if _, err := ruService.Create(in); err != nil {
return application.ThrowError(application.ARG_ERROR, "数据创建错误")
}
}
return nil
}
func (controller *ImportController) unzipFile(file *zip.File, dstDir string) error {
// create the directory of file
filePath := path.Join(dstDir, file.Name)
if file.FileInfo().IsDir() {
if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
return err
}
return nil
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return err
}
// open the file
rc, err := file.Open()
if err != nil {
return err
}
defer rc.Close()
// create the file
w, err := os.Create(filePath)
if err != nil {
return err
}
defer w.Close()
// save the decompressed file content
_, err = io.Copy(w, rc)
return err
}
... ...
... ... @@ -11,6 +11,8 @@ func init() {
ns := web.NewNamespace("/v1/import",
web.NSBefore(filters.AllowCors(), middlewares.CheckAdminToken()),
web.NSRouter("/", &controllers.ImportController{}, "Post:Import"),
web.NSRouter("/zip", &controllers.ImportController{}, "Post:ZipImport"),
web.NSRouter("/zip-verify", &controllers.ImportController{}, "Post:ZipVerify"),
)
web.AddNamespace(ns)
}
... ...