Browse Source

Merge remote-tracking branch 'origin/eta/1.0.2' into debug

# Conflicts:
#	go.mod
#	go.sum
#	models/db.go
#	routers/router.go
Roc 1 year ago
parent
commit
15f7c1fdf1

+ 518 - 0
controllers/data_manage/excel/custom_analysis.go

@@ -0,0 +1,518 @@
+package excel
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	excelModel "eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/models/data_manage/excel/request"
+	"eta/eta_api/models/data_manage/excel/response"
+	"eta/eta_api/services/data/excel"
+	"eta/eta_api/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// CustomAnalysisController 自定义分析
+type CustomAnalysisController struct {
+	controllers.BaseAuthController
+}
+
+// ExcelByName
+// @Title 根据excel名称获取表格详情(基础信息+第一页初始化数据)
+// @Description 根据excel名称获取表格详情(基础信息+第一页初始化数据)
+// @Param   ExcelName   query   string  true       "搜索关键词"
+// @Success 200 {object} response.ExcelListResp
+// @router /excel_by_name [get]
+func (c *CustomAnalysisController) ExcelByName() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	excelName := c.GetString("ExcelName")
+	if excelName == `` {
+		br.Msg = "请选择表格"
+		br.ErrMsg = "ExcelName未传"
+		br.IsSendEmail = false
+		return
+	}
+
+	resp := response.FindExcelInfoResp{}
+
+	excelName = utils.TrimLRStr(excelName)
+	// 获取数据详情
+	excelDetail, err := data_manage.GetNoContentExcelInfoByName(excelName, utils.CUSTOM_ANALYSIS_TABLE)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = resp
+			return
+		}
+		br.Msg = "获取表格事变"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	resp.IsFind = true
+	resp.ExcelInfo = excelDetail
+	if excelDetail != nil {
+		sheetList, err := excelModel.GetAllSheetItemList(excelDetail.ExcelInfoId)
+		if err != nil {
+			br.Msg = "获取sheet失败"
+			br.ErrMsg = "获取sheet失败,err:" + err.Error()
+			return
+		}
+
+		resp.SheetList = sheetList
+	}
+
+	//resp := response.ExcelListResp{
+	//	Paging: page,
+	//	List:   list,
+	//}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// Add
+// @Title 新增表格接口
+// @Description 新增表格接口
+// @Param	request	body request.AddExcelInfoReq true "type json string"
+// @Success 200 {object} response.AddExcelInfoResp
+// @router /add [post]
+func (c *CustomAnalysisController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EXCEL_TABLE_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		return
+	}
+	var req request.AddExcelInfoReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.ExcelName = strings.Trim(req.ExcelName, " ")
+	if req.ExcelName == "" {
+		br.Msg = "请填写表格名称!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ExcelClassifyId <= 0 {
+		br.Msg = "分类参数错误!"
+		br.IsSendEmail = false
+		return
+	}
+
+	excelInfo, err, errMsg, isSendEmail := excel.AddCustomAnalysisTable(utils.TrimLRStr(req.ExcelName), req.Content, req.ExcelImage, req.ExcelClassifyId, sysUser)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 更新excel下载地址(默认的EXCEL需要更新,自定义表格不需要更新)
+	//if req.Source == 1 {
+	//	go UpdateExcelInfoFileUrl(excelInfo)
+	//}
+	//
+	resp := new(response.AddExcelInfoResp)
+	resp.ExcelInfoId = excelInfo.ExcelInfoId
+	resp.UniqueCode = excelInfo.UniqueCode
+
+	//新增操作日志
+	//{
+	//	excelLog := &data_manage.ExcelInfoLog{
+	//		//ExcelInfoLogId:  0,
+	//		ExcelInfoId:     excelInfo.ExcelInfoId,
+	//		ExcelName:       req.ExcelName,
+	//		ExcelClassifyId: req.ExcelClassifyId,
+	//		SysUserId:       sysUser.AdminId,
+	//		SysUserRealName: sysUser.RealName,
+	//		UniqueCode:      excelInfo.UniqueCode,
+	//		CreateTime:      time.Now(),
+	//		Content:         string(c.Ctx.Input.RequestBody),
+	//		Status:          "新增表格",
+	//		Method:          c.Ctx.Input.URI(),
+	//	}
+	//	go data_manage.AddExcelInfoLog(excelLog)
+	//}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = false //数据量太大了,不写入日志吧
+}
+
+// Save
+// @Title 保存表格接口
+// @Description 保存表格接口
+// @Param	request	body request.AddExcelInfoReq true "type json string"
+// @Success 200 {object} response.AddExcelInfoResp
+// @router /save [post]
+func (c *CustomAnalysisController) Save() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	deleteCache := true
+	cacheKey := "CACHE_EXCEL_TABLE_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		return
+	}
+	var req request.SaveExcelInfoReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.ExcelName = strings.Trim(req.ExcelName, " ")
+	if req.ExcelName == "" {
+		br.Msg = "请填写表格名称!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ExcelInfoId <= 0 {
+		br.Msg = "请选择excel!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ExcelClassifyId <= 0 {
+		br.Msg = "分类参数错误!"
+		br.IsSendEmail = false
+		return
+	}
+
+	excelInfo, err := data_manage.GetExcelInfoById(req.ExcelInfoId)
+	if err != nil {
+		br.Msg = "找不到该EXCEL!"
+		br.ErrMsg = "找不到该EXCEL!err:" + err.Error()
+		return
+	}
+
+	if excelInfo.Source != utils.CUSTOM_ANALYSIS_TABLE {
+		br.Msg = "EXCEL异常!"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg, isSendEmail := excel.SaveCustomAnalysisTable(excelInfo, utils.TrimLRStr(req.ExcelName), req.Content, req.ExcelImage, req.ExcelClassifyId, req.OpSheetList)
+	if err != nil {
+		br.Msg = "保存失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	// 更新excel下载地址(默认的EXCEL需要更新,自定义表格不需要更新)
+	//if req.Source == 1 {
+	//	go UpdateExcelInfoFileUrl(excelInfo)
+	//}
+	//
+	resp := new(response.AddExcelInfoResp)
+	resp.ExcelInfoId = excelInfo.ExcelInfoId
+	resp.UniqueCode = excelInfo.UniqueCode
+
+	//新增操作日志
+	//{
+	//	excelLog := &data_manage.ExcelInfoLog{
+	//		//ExcelInfoLogId:  0,
+	//		ExcelInfoId:     excelInfo.ExcelInfoId,
+	//		ExcelName:       req.ExcelName,
+	//		ExcelClassifyId: req.ExcelClassifyId,
+	//		SysUserId:       sysUser.AdminId,
+	//		SysUserRealName: sysUser.RealName,
+	//		UniqueCode:      excelInfo.UniqueCode,
+	//		CreateTime:      time.Now(),
+	//		Content:         string(c.Ctx.Input.RequestBody),
+	//		Status:          "新增表格",
+	//		Method:          c.Ctx.Input.URI(),
+	//	}
+	//	go data_manage.AddExcelInfoLog(excelLog)
+	//}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+	br.IsAddLog = false //数据量太大了,不写入日志吧
+}
+
+// BaseExcelDetail
+// @Title 根据excel名称获取表格详情(基础信息+第一页初始化数据)
+// @Description 根据excel名称获取表格详情(基础信息+第一页初始化数据)
+// @Param   UniqueCode   query   string  true       "excel唯一编码"
+// @Success 200 {object} response.ExcelListResp
+// @router /excel/base [get]
+func (c *CustomAnalysisController) BaseExcelDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	uniqueCode := c.GetString("UniqueCode")
+	if uniqueCode == `` {
+		br.Msg = "请选择表格"
+		br.ErrMsg = "UniqueCode未传"
+		br.IsSendEmail = false
+		return
+	}
+
+	resp := response.FindExcelInfoResp{}
+
+	// 获取数据详情
+	excelDetail, err := data_manage.GetNoContentExcelInfoByUniqueCode(uniqueCode)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = resp
+			return
+		}
+		br.Msg = "获取表格事变"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	resp.IsFind = true
+	resp.ExcelInfo = excelDetail
+	if excelDetail != nil {
+		sheetList, err := excelModel.GetAllSheetItemList(excelDetail.ExcelInfoId)
+		if err != nil {
+			br.Msg = "获取sheet失败"
+			br.ErrMsg = "获取sheet失败,err:" + err.Error()
+			return
+		}
+
+		if len(sheetList) > 0 {
+			sheetIdList := make([]int, 0)
+			for _, v := range sheetList {
+				sheetIdList = append(sheetIdList, v.ExcelSheetId)
+			}
+			// 获取所有sheet的第一页的数据
+			sheetDataList, err := excelModel.GetSheetDataListBySheetIdListAndPage(sheetIdList, 1)
+			if err != nil {
+				br.Msg = "获取sheet中的数据失败"
+				br.ErrMsg = "获取sheet中的数据失败,err:" + err.Error()
+				return
+			}
+
+			sheetDataMap := make(map[int]*excelModel.ExcelSheetData)
+			for _, v := range sheetDataList {
+				sheetDataMap[v.ExcelSheetId] = v
+			}
+
+			for k, v := range sheetList {
+				sheetData, ok := sheetDataMap[v.ExcelSheetId]
+				if !ok {
+					continue
+				}
+				v.Data = sheetData
+				sheetList[k] = v
+			}
+
+		}
+
+		// TODO 合并单元格信息、计算公式
+
+		resp.SheetList = sheetList
+	}
+
+	//resp := response.ExcelListResp{
+	//	Paging: page,
+	//	List:   list,
+	//}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// ExcelDataList
+// @Title 根据excel名称获取表格详情(基础信息+第一页初始化数据)
+// @Description 根据excel名称获取表格详情(基础信息+第一页初始化数据)
+// @Param   UniqueCode   query   string  true       "excel唯一编码"
+// @Param   Page   query   int  true       "页码"
+// @Success 200 {object} response.ExcelListResp
+// @router /excel/data [get]
+func (c *CustomAnalysisController) ExcelDataList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	uniqueCode := c.GetString("UniqueCode")
+	if uniqueCode == `` {
+		br.Msg = "请选择表格"
+		br.ErrMsg = "UniqueCode未传"
+		br.IsSendEmail = false
+		return
+	}
+
+	page, _ := c.GetInt("Page")
+	if page <= 0 {
+		br.Msg = "页码异常"
+		br.ErrMsg = "页码异常"
+		br.IsSendEmail = false
+		return
+	}
+
+	sheetList := make([]*excelModel.SheetItem, 0)
+	// 获取数据详情
+	excelDetail, err := data_manage.GetNoContentExcelInfoByUniqueCode(uniqueCode)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = sheetList
+			return
+		}
+		br.Msg = "获取表格事变"
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	if excelDetail.Source != utils.CUSTOM_ANALYSIS_TABLE {
+		br.Msg = "excel异常"
+		br.ErrMsg = "excel异常"
+		br.IsSendEmail = false
+		return
+	}
+
+	if excelDetail != nil {
+		sheetList, err = excelModel.GetAllSheetItemList(excelDetail.ExcelInfoId)
+		if err != nil {
+			br.Msg = "获取sheet失败"
+			br.ErrMsg = "获取sheet失败,err:" + err.Error()
+			return
+		}
+
+		if len(sheetList) > 0 {
+			sheetIdList := make([]int, 0)
+			for _, v := range sheetList {
+				sheetIdList = append(sheetIdList, v.ExcelSheetId)
+			}
+			// 获取所有sheet的第一页的数据
+			sheetDataList, err := excelModel.GetSheetDataListBySheetIdListAndPage(sheetIdList, page)
+			if err != nil {
+				br.Msg = "获取sheet中的数据失败"
+				br.ErrMsg = "获取sheet中的数据失败,err:" + err.Error()
+				return
+			}
+
+			sheetDataMap := make(map[int]*excelModel.ExcelSheetData)
+			for _, v := range sheetDataList {
+				sheetDataMap[v.ExcelSheetId] = v
+			}
+
+			for k, v := range sheetList {
+				sheetData, ok := sheetDataMap[v.ExcelSheetId]
+				if !ok {
+					continue
+				}
+				v.Data = sheetData
+				sheetList[k] = v
+			}
+
+		}
+
+		// TODO 合并单元格信息、计算公式
+
+	}
+
+	//resp := response.ExcelListResp{
+	//	Paging: page,
+	//	List:   list,
+	//}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = sheetList
+}

+ 2 - 2
controllers/data_manage/excel_classify.go

@@ -43,8 +43,8 @@ func (this *ExcelClassifyController) List() {
 		return
 	}
 
-	// 获取所有excel表格分类
-	allExcelInfo, err := data_manage.GetNoContentExcelInfoAll()
+	// 根据来源获取所有excel表格(无内容)
+	allExcelInfo, err := data_manage.GetNoContentExcelInfoAll(source)
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()

+ 144 - 1
controllers/data_manage/excel_info.go

@@ -1,6 +1,7 @@
 package data_manage
 
 import (
+	"archive/zip"
 	"encoding/json"
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
@@ -15,7 +16,9 @@ import (
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"github.com/yidane/formula"
+	"io"
 	"os"
+	"path/filepath"
 	"strconv"
 	"strings"
 	"time"
@@ -2107,6 +2110,146 @@ func (c *ExcelInfoController) Copy() {
 //}
 
 //func init() {
-//	filePath := `static/tmpFile/化工23.05.24.xlsx`
+//	startNow := time.Now()
+//	fmt.Println(startNow.Format(utils.FormatDateTime))
+//	startTime := startNow.Unix()
+//	//filePath := `static/tmpFile/test/化工23.05.24.xlsx`
+//	filePath := `static/tmpFile/1. TAROUND_202308010201-500.xlsx`
+//	//filePath := `static/tmpFile/化工23.05.24.xml`
+//	//filePath := `static/tmpFile/化工23.05.24/xl/workbook.xml`
+//	//filePath := `static/tmpFile/1. TAROUND_202308010201.xlsx`
+//
+//	//filePath := `static/tmpFile/1. TAROUND_202308010201-2.xlsx`
+//
+//	//filePath := `static/tmpFile/5. Outage_Values_Daily.xlsx`
+//	//filePath := `static/tmpFile/1. TAROUND_202308010201 - 副本.xlsx`
 //	excel.ConvToLuckySheet(filePath)
+//	cz := time.Now().Unix() - startTime
+//	fmt.Printf("处理完需要的时间:%d秒;约耗时:%d分%d秒", cz, cz/60, cz%60)
+//	fmt.Println()
+//
+//	//sheetName := `日度`
+//	//sheetName := `月度`
+//	//fmt.Println(excel.GetDefaultSheetIndex(filePath, sheetName))
+//
+//	//decompressZip(filePath)
 //}
+
+// src: 需要解压的zip文件
+func decompressZip(src string) error {
+	archive, err := zip.OpenReader(src)
+	if err != nil {
+		return err
+	}
+	dir := filepath.Dir(src) + "/zip"
+	defer archive.Close()
+	for _, f := range archive.File {
+		filePath := filepath.Join(dir, f.Name)
+		if f.FileInfo().IsDir() {
+			os.MkdirAll(filePath, os.ModePerm)
+			continue
+		}
+		if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
+			return fmt.Errorf("failed to make directory (%v)", err)
+		}
+		dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
+		if err != nil {
+			return fmt.Errorf("failed to create file (%v)", err)
+		}
+		fileInArchive, err := f.Open()
+		if err != nil {
+			return fmt.Errorf("failed to open file in zip (%v)", err)
+		}
+		if _, err := io.Copy(dstFile, fileInArchive); err != nil {
+			return fmt.Errorf("failed to copy file in zip (%v)", err)
+		}
+		dstFile.Close()
+		fileInArchive.Close()
+	}
+	return nil
+}
+
+// FixTableData ETA1.0.2 自定义分析(生成指标数据修复)
+func FixTableData() {
+	// 获取一级分类
+	classifyList, err := data_manage.GetExcelClassifyByParentId(0, utils.EXCEL_DEFAULT)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		fmt.Println("数据修复失败,Err:" + err.Error())
+		return
+	}
+	timeTableMap := make(map[int]int)
+	mixTableMap := make(map[int]int)
+	for _, v := range classifyList {
+		// 时间序列表格
+		classify := &data_manage.ExcelClassify{
+			//ExcelClassifyId:   0,
+			ExcelClassifyName: v.ExcelClassifyName,
+			ParentId:          v.ParentId,
+			Source:            utils.TIME_TABLE,
+			SysUserId:         v.SysUserId,
+			SysUserRealName:   v.SysUserRealName,
+			Level:             v.Level,
+			UniqueCode:        utils.MD5(fmt.Sprint(v.UniqueCode, "_", utils.TIME_TABLE)),
+			Sort:              v.Sort,
+			CreateTime:        time.Now(),
+			ModifyTime:        time.Now(),
+		}
+		_, err = data_manage.AddExcelClassify(classify)
+		timeTableMap[v.ExcelClassifyId] = classify.ExcelClassifyId
+
+		// 混合表格
+		classify2 := &data_manage.ExcelClassify{
+			//ExcelClassifyId:   0,
+			ExcelClassifyName: v.ExcelClassifyName,
+			ParentId:          v.ParentId,
+			Source:            utils.MIXED_TABLE,
+			SysUserId:         v.SysUserId,
+			SysUserRealName:   v.SysUserRealName,
+			Level:             v.Level,
+			UniqueCode:        utils.MD5(fmt.Sprint(v.UniqueCode, "_", utils.MIXED_TABLE)),
+			Sort:              v.Sort,
+			CreateTime:        time.Now(),
+			ModifyTime:        time.Now(),
+		}
+		_, err = data_manage.AddExcelClassify(classify2)
+		mixTableMap[v.ExcelClassifyId] = classify2.ExcelClassifyId
+	}
+
+	// 修改时间序列表
+	{
+		// 获取时间序列表
+		timeTableExcelList, err := data_manage.GetNoContentExcelInfoAll(utils.TIME_TABLE)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			fmt.Println("获取时间序列表列表失败,Err:" + err.Error())
+			return
+		}
+
+		for _, v := range timeTableExcelList {
+			classifyId, ok := timeTableMap[v.ExcelClassifyId]
+			if !ok {
+				continue
+			}
+			data_manage.UpdateExcelInfoClassifyId(classifyId, v.ExcelInfoId)
+		}
+	}
+
+	// 修改混合序列表
+	{
+		// 获取时间序列表
+		mixTableExcelList, err := data_manage.GetNoContentExcelInfoAll(utils.MIXED_TABLE)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			fmt.Println("获取时间序列表列表失败,Err:" + err.Error())
+			return
+		}
+
+		for _, v := range mixTableExcelList {
+			classifyId, ok := mixTableMap[v.ExcelClassifyId]
+			if !ok {
+				continue
+			}
+			data_manage.UpdateExcelInfoClassifyId(classifyId, v.ExcelInfoId)
+		}
+	}
+
+	fmt.Println("完成数据修复")
+}

+ 7 - 6
go.mod

@@ -14,6 +14,7 @@ require (
 	github.com/aliyun/aliyun-oss-go-sdk v2.2.0+incompatible
 	github.com/beego/bee/v2 v2.0.4
 	github.com/beego/beego/v2 v2.0.7
+	github.com/beevik/etree v1.2.0
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-sql-driver/mysql v1.7.0
 	github.com/go-xorm/xorm v0.7.9
@@ -29,7 +30,7 @@ require (
 	github.com/tealeg/xlsx v1.0.5
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.541
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses v1.0.541
-	github.com/xuri/excelize/v2 v2.6.1
+	github.com/xuri/excelize/v2 v2.7.1
 	github.com/yidane/formula v0.0.0-20210902154546-0782e1736717
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 )
@@ -96,11 +97,11 @@ require (
 	github.com/tjfoc/gmsm v1.3.2 // indirect
 	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
 	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
-	golang.org/x/crypto v0.5.0 // indirect
-	golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
-	golang.org/x/net v0.5.0 // indirect
-	golang.org/x/sys v0.4.0 // indirect
-	golang.org/x/text v0.6.0 // indirect
+	golang.org/x/crypto v0.8.0 // indirect
+	golang.org/x/image v0.5.0 // indirect
+	golang.org/x/net v0.9.0 // indirect
+	golang.org/x/sys v0.7.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
 	golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
 	google.golang.org/protobuf v1.28.1 // indirect
 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect

+ 31 - 16
go.sum

@@ -80,6 +80,8 @@ github.com/beego/beego/v2 v2.0.7 h1:9KNnUM40tn3pbCOFfe6SJ1oOL0oTi/oBS/C/wCEdAXA=
 github.com/beego/beego/v2 v2.0.7/go.mod h1:f0uOEkmJWgAuDTlTxUdgJzwG3PDSIf3UWF3NpMohbFE=
 github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
 github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
+github.com/beevik/etree v1.2.0 h1:l7WETslUG/T+xOPs47dtd6jov2Ii/8/OjCldk5fYfQw=
+github.com/beevik/etree v1.2.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -413,8 +415,8 @@ github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnD
 github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
 github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
-github.com/xuri/excelize/v2 v2.6.1 h1:ICBdtw803rmhLN3zfvyEGH3cwSmZv+kde7LhTDT659k=
-github.com/xuri/excelize/v2 v2.6.1/go.mod h1:tL+0m6DNwSXj/sILHbQTYsLi9IF4TW59H2EF3Yrx1AU=
+github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdVI=
+github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZOmcF4nTpY=
 github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
 github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/yidane/formula v0.0.0-20210902154546-0782e1736717 h1:9CTJJpdISGxMAELfVlprj5kZEsJEaNAWiobv8ZAd72U=
@@ -423,6 +425,7 @@ github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369/go.mod
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
 github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
 github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
@@ -435,20 +438,22 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
-golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
+golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
+golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE=
-golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
+golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
+golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -465,14 +470,16 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
-golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -483,6 +490,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -506,21 +515,26 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
-golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
-golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
@@ -536,6 +550,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -598,7 +614,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 79 - 0
models/data_manage/excel/excel_sheet.go

@@ -0,0 +1,79 @@
+package excel
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ExcelSheet excel表格详情表
+type ExcelSheet struct {
+	ExcelSheetId int       `orm:"column(excel_sheet_id);pk"`
+	ExcelInfoId  int       `description:"excel的id"`
+	SheetName    string    `description:"sheet名称"`
+	PageNum      int       `description:"总页码数"`
+	Sort         int       `description:"排序"`
+	ModifyTime   time.Time `description:"最近修改日期"`
+	CreateTime   time.Time `description:"创建日期"`
+}
+
+// Update 更新 excel表格的sheet基础信息
+func (excelSheet *ExcelSheet) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(excelSheet, cols...)
+
+	return
+}
+
+// AddExcelSheet 新增excel表格的sheet基础信息
+func AddExcelSheet(excelInfo *ExcelSheet) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	// 表格信息入库
+	lastId, err := o.Insert(excelInfo)
+	if err != nil {
+		return
+	}
+	excelInfo.ExcelInfoId = int(lastId)
+
+	return
+}
+
+// GetAllSheetList 根据excel_id获取所有的sheet
+func GetAllSheetList(excelInfoId int) (item []*ExcelSheet, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+FROM excel_sheet WHERE 1=1 AND excel_info_id = ? `
+	sql += " ORDER BY sort asc "
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&item)
+	return
+}
+
+// SheetItem excel表格详情表
+type SheetItem struct {
+	ExcelSheetId int             `orm:"column(excel_sheet_id);pk"`
+	ExcelInfoId  int             `description:"excel的id"`
+	SheetName    string          `description:"sheet名称"`
+	PageNum      int             `description:"数据总页码数"`
+	Sort         int             `description:"排序"`
+	ModifyTime   time.Time       `description:"最近修改日期"`
+	CreateTime   time.Time       `description:"创建日期"`
+	Data         *ExcelSheetData `description:"excel的数据"`
+}
+
+// GetAllSheetItemList 根据excel_id获取所有的sheet详情
+func GetAllSheetItemList(excelInfoId int) (item []*SheetItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+FROM excel_sheet WHERE 1=1 AND excel_info_id = ? `
+	sql += " ORDER BY sort asc "
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&item)
+	return
+}
+
+// AddExcelSheetParams excel表格详情表
+type AddExcelSheetParams struct {
+	ExcelSheetId int               `orm:"column(excel_sheet_id);pk"`
+	ExcelInfoId  int               `description:"excel的id"`
+	SheetName    string            `description:"sheet名称"`
+	Sort         int               `description:"排序"`
+	DataList     []*ExcelSheetData `description:"excel的数据"`
+}

+ 53 - 0
models/data_manage/excel/excel_sheet_data.go

@@ -0,0 +1,53 @@
+package excel
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ExcelSheetData excel表格详情表
+type ExcelSheetData struct {
+	ExcelDataId  int       `orm:"column(excel_data_id);pk"`
+	ExcelInfoId  int       `description:"数据归属的excel_info的id"`
+	ExcelSheetId int       `description:"数据归属sheet"`
+	Sort         int       `description:"数据排序"`
+	Data         string    `description:"数据,分页存储"`
+	ModifyTime   time.Time `description:"最近修改日期"`
+	CreateTime   time.Time `description:"创建日期"`
+}
+
+// Update 更新 excel表格的sheet基础信息
+func (ExcelSheetData *ExcelSheetData) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(ExcelSheetData, cols...)
+
+	return
+}
+
+// AddExcelSheetData 新增excel表格的sheet基础信息
+func AddExcelSheetData(excelInfo *ExcelSheetData) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	// 表格信息入库
+	lastId, err := o.Insert(excelInfo)
+	if err != nil {
+		return
+	}
+	excelInfo.ExcelInfoId = int(lastId)
+
+	return
+}
+
+// GetSheetDataListBySheetIdListAndPage 根据sheet_id列表和页码获取所有的sheet数据详情
+func GetSheetDataListBySheetIdListAndPage(excelSheetIdList []int, page int) (item []*ExcelSheetData, err error) {
+	num := len(excelSheetIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+FROM excel_sheet_data WHERE 1=1 AND excel_sheet_id in (` + utils.GetOrmInReplace(num) + `) AND sort = ? `
+	_, err = o.Raw(sql, excelSheetIdList, page).QueryRows(&item)
+
+	return
+}

+ 31 - 0
models/data_manage/excel/request/excel.go

@@ -0,0 +1,31 @@
+package request
+
+// AddExcelInfoReq 新增表格请求
+type AddExcelInfoReq struct {
+	ExcelInfoId     int         `description:"表格ID"`
+	ExcelName       string      `description:"表格名称"`
+	Source          int         `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	ExcelType       int         `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelImage      string      `description:"表格截图"`
+	ExcelClassifyId int         `description:"分类id"`
+	Content         string      `description:"Excel表格内容"`
+	TableData       interface{} `description:"自定义表格的数据内容"`
+}
+
+// SaveExcelInfoReq 编辑表格请求
+type SaveExcelInfoReq struct {
+	ExcelInfoId     int         `description:"表格ID"`
+	ExcelName       string      `description:"表格名称"`
+	Source          int         `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	ExcelType       int         `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelImage      string      `description:"表格截图"`
+	ExcelClassifyId int         `description:"分类id"`
+	Content         string      `description:"Excel表格内容"`
+	TableData       interface{} `description:"自定义表格的数据内容"`
+	OpSheetList     []SheetOp   `description:"sheet操作"`
+}
+type SheetOp struct {
+	SheetIndex int    `description:"对应的sheet下标"`
+	SheetName  string `description:"对应的sheet名称"`
+	OpType     string `description:"操作类型,新增:add;替换:replace,追加:append"`
+}

+ 19 - 0
models/data_manage/excel/response/sheet.go

@@ -0,0 +1,19 @@
+package response
+
+import (
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/excel"
+)
+
+// FindExcelInfoResp 根据名称获取excel的信息
+type FindExcelInfoResp struct {
+	IsFind    bool                         `description:"是否存在同名文件"`
+	ExcelInfo *data_manage.MyExcelInfoList `description:"图表详情"`
+	SheetList []*excel.SheetItem           `description:"sheet列表"`
+}
+
+// AddExcelInfoResp 添加excel表格的返回
+type AddExcelInfoResp struct {
+	ExcelInfoId int    `description:"表格id"`
+	UniqueCode  string `description:"表格唯一编码"`
+}

+ 6 - 1
models/data_manage/excel_classify.go

@@ -9,7 +9,7 @@ import (
 // ExcelClassify excel表格分类
 type ExcelClassify struct {
 	ExcelClassifyId   int       `orm:"column(excel_classify_id);pk"`
-	Source            int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,默认:1"`
+	Source            int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
 	ExcelClassifyName string    `description:"分类名称"`
 	ParentId          int       `description:"父级id"`
 	SysUserId         int       `description:"创建人id"`
@@ -26,6 +26,11 @@ type ExcelClassify struct {
 func AddExcelClassify(item *ExcelClassify) (lastId int64, err error) {
 	o := orm.NewOrmUsingDB("data")
 	lastId, err = o.Insert(item)
+	if err != nil {
+		return
+	}
+	item.ExcelClassifyId = int(lastId)
+
 	return
 }
 

+ 92 - 19
models/data_manage/excel_info.go

@@ -1,6 +1,7 @@
 package data_manage
 
 import (
+	"eta/eta_api/models/data_manage/excel"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"time"
@@ -9,7 +10,7 @@ import (
 // ExcelInfo excel表格详情表
 type ExcelInfo struct {
 	ExcelInfoId     int       `orm:"column(excel_info_id);pk"`
-	Source          int       `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	Source          int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
 	ExcelType       int       `description:"表格类型,1:指标列,2:日期列,默认:1"`
 	ExcelName       string    `description:"表格名称"`
 	UniqueCode      string    `description:"表格唯一编码"`
@@ -79,12 +80,12 @@ func GetExcelInfoAll() (items []*ExcelClassifyItems, err error) {
 }
 
 // GetNoContentExcelInfoAll 获取不含content的表格列表 用于分类展示
-func GetNoContentExcelInfoAll() (items []*ExcelClassifyItems, err error) {
+func GetNoContentExcelInfoAll(source int) (items []*ExcelClassifyItems, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT excel_info_id,excel_classify_id,excel_name AS excel_classify_name,
              unique_code,sys_user_id,sys_user_real_name
-            FROM excel_info where is_delete=0 ORDER BY sort asc,create_time desc `
-	_, err = o.Raw(sql).QueryRows(&items)
+            FROM excel_info where is_delete=0  AND source = ?  ORDER BY sort asc,create_time desc `
+	_, err = o.Raw(sql, source).QueryRows(&items)
 	return
 }
 
@@ -253,24 +254,10 @@ func GetExcelListCountByCondition(condition string, pars []interface{}) (count i
 	return
 }
 
-// GetMyExcelListByAdminId 根据操作人id获取表格列表
-func GetMyExcelListByAdminId(adminId int) (item []*MyChartView, err error) {
-	o := orm.NewOrmUsingDB("data")
-	//sql := ` SELECT * FROM my_chart WHERE 1=1 AND admin_id=? `
-
-	sql := ` SELECT a.*,GROUP_CONCAT(c.my_chart_classify_id SEPARATOR ',') AS my_chart_classify_id FROM my_chart AS a
-			LEFT JOIN  my_chart_classify_mapping AS b ON a.my_chart_id=b.my_chart_id AND a.admin_id=b.admin_id
-			LEFT JOIN my_chart_classify AS c ON b.my_chart_classify_id=c.my_chart_classify_id AND b.admin_id=c.admin_id
-			WHERE 1=1 AND a.admin_id=? AND a.source=2
-			GROUP BY a.chart_info_id `
-	_, err = o.Raw(sql, adminId).QueryRows(&item)
-	return
-}
-
 // GetExcelViewInfoByExcelInfoId 根据excelInfoId 获取ETA表格详情
 func GetExcelViewInfoByExcelInfoId(excelInfoId int) (item *MyExcelInfoList, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM excel_info WHERE excel_info_id = ? AND is_delete=0 `
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time FROM excel_info WHERE excel_info_id = ? AND is_delete=0 `
 	err = o.Raw(sql, excelInfoId).QueryRow(&item)
 	return
 }
@@ -282,3 +269,89 @@ func GetExcelInfoCountByClassifyId(classifyId int) (total int64, err error) {
 	err = o.Raw(sql, classifyId).QueryRow(&total)
 	return
 }
+
+// UpdateExcelInfoClassifyId 更改表格分类
+func UpdateExcelInfoClassifyId(classifyId, excelInfoId int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` update excel_info set excel_classify_id = ? WHERE excel_info_id=? `
+	_, err = o.Raw(sql, classifyId, excelInfoId).Exec()
+
+	return
+}
+
+// GetNoContentExcelInfoByName 根据名称 获取eta表格详情
+func GetNoContentExcelInfoByName(excelName string, source int) (item *MyExcelInfoList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time 
+ FROM excel_info WHERE excel_name = ? AND source = ? AND is_delete=0 `
+	err = o.Raw(sql, excelName, source).QueryRow(&item)
+
+	return
+}
+
+// GetNoContentExcelInfoByUniqueCode 根据unique_code来获取excel表格详情
+func GetNoContentExcelInfoByUniqueCode(uniqueCode string) (item *MyExcelInfoList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time 
+ FROM excel_info WHERE unique_code=? AND is_delete=0 `
+	err = o.Raw(sql, uniqueCode).QueryRow(&item)
+	return
+}
+
+func AddExcelInfoAndSheet(excelInfo *ExcelInfo, sheetParamsList []excel.AddExcelSheetParams) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 表格信息入库
+	lastId, err := o.Insert(excelInfo)
+	if err != nil {
+		return
+	}
+	excelInfo.ExcelInfoId = int(lastId)
+
+	// sheet信息入库
+	for _, sheetInfo := range sheetParamsList {
+		dataNum := len(sheetInfo.DataList)
+
+		//sheet信息入库
+		excelSheetInfo := &excel.ExcelSheet{
+			ExcelSheetId: 0,
+			ExcelInfoId:  excelInfo.ExcelInfoId,
+			SheetName:    sheetInfo.SheetName,
+			PageNum:      dataNum,
+			Sort:         sheetInfo.Sort,
+			ModifyTime:   time.Now(),
+			CreateTime:   time.Now(),
+		}
+		sheetId, tmpErr := o.Insert(excelSheetInfo)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		excelSheetInfo.ExcelSheetId = int(sheetId)
+
+		// data信息入库
+		if dataNum > 0 {
+			for k, _ := range sheetInfo.DataList {
+				sheetInfo.DataList[k].ExcelSheetId = excelSheetInfo.ExcelSheetId
+				sheetInfo.DataList[k].ExcelInfoId = excelSheetInfo.ExcelInfoId
+			}
+			_, tmpErr = o.InsertMulti(dataNum, sheetInfo.DataList)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+		}
+	}
+
+	return
+}

+ 1 - 0
models/data_manage/request/excel_info.go

@@ -15,6 +15,7 @@ type DeleteExcelInfoReq struct {
 
 // AddExcelInfoReq 新增表格请求
 type AddExcelInfoReq struct {
+	ExcelInfoId     int         `description:"表格ID"`
 	ExcelName       string      `description:"表格名称"`
 	Source          int         `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
 	ExcelType       int         `description:"表格类型,1:指标列,2:日期列,默认:1"`

+ 15 - 3
models/db.go

@@ -3,6 +3,7 @@ package models
 import (
 	"eta/eta_api/models/company"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/excel"
 	future_good2 "eta/eta_api/models/data_manage/future_good"
 	"eta/eta_api/models/data_manage/supply_analysis"
 	"eta/eta_api/models/eta_trial"
@@ -141,6 +142,9 @@ func init() {
 	if utils.BusinessCode == utils.BusinessCodeSandbox {
 		initEtaTrial()
 	}
+
+	// 初始化EXCEL的表
+	initExcel()
 }
 
 // initSystem 系统表 数据表
@@ -261,9 +265,6 @@ func initEdbData() {
 		new(data_manage.EdbInfoCalculateMapping),
 		new(data_manage.EdbDataCalculateZjpj),            //直接拼接
 		new(data_manage.EdbDataCalculateLjztbpj),         //累计同比值拼接
-		new(data_manage.ExcelClassify),                   //ETA excel表格分类
-		new(data_manage.ExcelInfo),                       //ETA excel表格
-		new(data_manage.ExcelDraft),                      //ETA excel表格草稿
 		new(data_manage.PredictEdbConf),                  //预测指标配置
 		new(data_manage.BaseFromMysteelChemicalClassify), //预测指标配置
 		new(data_manage.BaseFromMysteelChemicalIndex),    //钢联化工
@@ -416,3 +417,14 @@ func initEtaTrial() {
 		new(eta_trial.QuestionnaireFillRecord), // 问卷填写记录表
 	)
 }
+
+// initExcel 初始化EXCEL
+func initExcel() {
+	orm.RegisterModel(
+		new(data_manage.ExcelClassify), //ETA excel表格分类
+		new(data_manage.ExcelInfo),     //ETA excel表格
+		new(data_manage.ExcelDraft),    //ETA excel表格草稿
+		new(excel.ExcelSheet),          //ETA excel sheet
+		new(excel.ExcelSheetData),      //ETA excel sheet data
+	)
+}

+ 45 - 0
routers/commentsRouter.go

@@ -178,6 +178,51 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"],
+        beego.ControllerComments{
+            Method: "BaseExcelDetail",
+            Router: `/excel/base`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"],
+        beego.ControllerComments{
+            Method: "ExcelDataList",
+            Router: `/excel/data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"],
+        beego.ControllerComments{
+            Method: "ExcelByName",
+            Router: `/excel_by_name`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"],
+        beego.ControllerComments{
+            Method: "Save",
+            Router: `/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/future_good:FutureGoodChartClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/future_good:FutureGoodChartClassifyController"],
         beego.ControllerComments{
             Method: "AddChartClassify",

+ 6 - 0
routers/router.go

@@ -11,6 +11,7 @@ import (
 	"eta/eta_api/controllers"
 	"eta/eta_api/controllers/data_manage"
 	"eta/eta_api/controllers/data_manage/correlation"
+	"eta/eta_api/controllers/data_manage/excel"
 	future_good2 "eta/eta_api/controllers/data_manage/future_good"
 	"eta/eta_api/controllers/data_manage/line_equation"
 	"eta/eta_api/controllers/data_manage/line_feature"
@@ -282,6 +283,11 @@ func init() {
 				&eta_trial.EtaTrialController{},
 			),
 		),
+		web.NSNamespace("/custom_analysis",
+			web.NSInclude(
+				&excel.CustomAnalysisController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 1 - 1
services/data/chart_info_elastic.go

@@ -1,10 +1,10 @@
 package data
 
 import (
-	"fmt"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/services/elastic"
 	"eta/eta_api/utils"
+	"fmt"
 	"strconv"
 	"strings"
 )

+ 396 - 0
services/data/excel/custom_analysis.go

@@ -0,0 +1,396 @@
+package excel
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/models/data_manage/excel/request"
+	"eta/eta_api/models/system"
+	"eta/eta_api/utils"
+	"fmt"
+	"strconv"
+	"time"
+)
+
+// AddCustomAnalysisTable 添加自定义分析表格
+func AddCustomAnalysisTable(excelName, content, excelImage string, excelClassifyId int, sysUser *system.Admin) (excelInfo *data_manage.ExcelInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	contentByte := []byte(content)
+
+	var luckySheet LuckySheet
+
+	err = json.Unmarshal(contentByte, &luckySheet)
+	if err != nil {
+		return
+	}
+
+	// sheet内容为空
+	if len(luckySheet.Sheets) <= 0 {
+		errMsg = "sheet内容为空"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	excelClassify, err := data_manage.GetExcelClassifyById(excelClassifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "分类不存在"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取分类信息失败"
+		err = errors.New("获取分类信息失败,Err:" + err.Error())
+		return
+	}
+	if excelClassify == nil {
+		errMsg = "分类不存在"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	if excelClassify.Source != utils.CUSTOM_ANALYSIS_TABLE {
+		errMsg = "当前分类不是自定义分析分类"
+		err = errors.New("当前分类不是自定义分析分类")
+		isSendEmail = false
+		return
+	}
+
+	// 校验是否同名文件
+	{
+		var condition string
+		var pars []interface{}
+		condition += " AND excel_classify_id=? "
+		pars = append(pars, excelClassifyId)
+
+		condition += " AND excel_name=? "
+		pars = append(pars, excelName)
+
+		// 获取分类下是否存在该表格名称
+		count, tmpErr := data_manage.GetExcelInfoCountByCondition(condition, pars)
+		if tmpErr != nil {
+			errMsg = "判断表格名称是否存在失败"
+			err = errors.New("判断表格名称是否存在失败,Err:" + tmpErr.Error())
+			return
+		}
+		if count > 0 {
+			errMsg = "表格名称已存在,请重新填写表格名称"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	// 表格
+	excelInfo = &data_manage.ExcelInfo{
+		//ExcelInfoId:     0,
+		ExcelName: excelName,
+		Source:    utils.CUSTOM_ANALYSIS_TABLE,
+		//ExcelType:       req.ExcelType,
+		UniqueCode:      utils.MD5(utils.EXCEL_DATA_PREFIX + "_" + timestamp),
+		ExcelClassifyId: excelClassifyId,
+		SysUserId:       sysUser.AdminId,
+		SysUserRealName: sysUser.RealName,
+		Content:         ``,
+		ExcelImage:      excelImage,
+		Sort:            0,
+		IsDelete:        0,
+		ModifyTime:      time.Now(),
+		CreateTime:      time.Now(),
+	}
+
+	addSheetList := make([]excel.AddExcelSheetParams, 0)
+	splitNum := 2000 // 基础分割单元格数
+
+	// sheet处理
+	sheetNameMap := make(map[string]string)
+	for k, sheetInfo := range luckySheet.Sheets {
+		sheetName := utils.TrimLRStr(sheetInfo.Name)
+		_, ok := sheetNameMap[sheetName]
+		if ok {
+			errMsg = "excel表中存在同名sheet"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		addSheetItem := excel.AddExcelSheetParams{
+			ExcelSheetId: 0,
+			ExcelInfoId:  0,
+			SheetName:    sheetName,
+			Sort:         k,
+		}
+
+		lenCellData := len(sheetInfo.Celldata)
+
+		splitLen := lenCellData / splitNum
+		residue := lenCellData % splitNum
+		if residue > 0 {
+			splitLen += 1
+		}
+
+		sheetDataList := make([]*excel.ExcelSheetData, 0)
+		for i := 0; i < splitLen; i++ {
+
+			startRow := i * splitNum
+			endRow := (i + 1) * splitNum
+			if i == splitLen-1 && residue > 0 {
+				endRow = lenCellData
+			}
+
+			tmpData := sheetInfo.Celldata[startRow:endRow]
+			tmpDataByte, tmpErr := json.Marshal(tmpData)
+			if tmpErr != nil {
+				errMsg = "保存失败"
+				err = errors.New("保存失败:" + tmpErr.Error())
+				return
+			}
+			sheetDataList = append(sheetDataList, &excel.ExcelSheetData{
+				ExcelDataId:  0,
+				ExcelInfoId:  0,
+				ExcelSheetId: 0,
+				Sort:         i,
+				Data:         string(tmpDataByte),
+				ModifyTime:   time.Now(),
+				CreateTime:   time.Now(),
+			})
+		}
+		addSheetItem.DataList = sheetDataList
+
+		addSheetList = append(addSheetList, addSheetItem)
+	}
+
+	err = data_manage.AddExcelInfoAndSheet(excelInfo, addSheetList)
+
+	return
+}
+
+func SaveCustomAnalysisTable(excelInfo *data_manage.ExcelInfo, excelName, content, excelImage string, excelClassifyId int, sheetOpList []request.SheetOp) (err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	contentByte := []byte(content)
+
+	var luckySheet LuckySheet
+
+	err = json.Unmarshal(contentByte, &luckySheet)
+	if err != nil {
+		return
+	}
+
+	// sheet内容为空
+	if len(luckySheet.Sheets) <= 0 {
+		errMsg = "sheet内容为空"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	// sheet内容为空
+	if len(sheetOpList) <= 0 {
+		errMsg = "sheet操作为空"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	excelClassify, err := data_manage.GetExcelClassifyById(excelClassifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "分类不存在"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取分类信息失败"
+		err = errors.New("获取分类信息失败,Err:" + err.Error())
+		return
+	}
+	if excelClassify == nil {
+		errMsg = "分类不存在"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	if excelClassify.Source != utils.CUSTOM_ANALYSIS_TABLE {
+		errMsg = "当前分类不是自定义分析分类"
+		err = errors.New("当前分类不是自定义分析分类")
+		isSendEmail = false
+		return
+	}
+
+	// 校验是否同名文件
+	{
+		var condition string
+		var pars []interface{}
+		condition += " AND excel_classify_id=?  AND excel_info_id !=?  "
+		pars = append(pars, excelClassifyId, excelInfo.ExcelInfoId)
+
+		condition += " AND excel_name=? "
+		pars = append(pars, excelName)
+
+		// 获取分类下是否存在该表格名称
+		count, tmpErr := data_manage.GetExcelInfoCountByCondition(condition, pars)
+		if tmpErr != nil {
+			errMsg = "判断表格名称是否存在失败"
+			err = errors.New("判断表格名称是否存在失败,Err:" + tmpErr.Error())
+			return
+		}
+		if count > 0 {
+			errMsg = "表格名称已存在,请重新填写表格名称"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+
+	// 查找当前excel的sheet列表
+	currSheetList, err := excel.GetAllSheetList(excelInfo.ExcelInfoId)
+	if err != nil {
+		errMsg = "保存失败"
+		err = errors.New("查找当前excel的sheet列表失败,Err:" + err.Error())
+		return
+	}
+	currSheetMap := make(map[string]string)
+	for _, currSheet := range currSheetList {
+		currSheetMap[currSheet.SheetName] = currSheet.SheetName
+	}
+
+	for k, sheetOp := range sheetOpList {
+		sheetName := utils.TrimLRStr(sheetOp.SheetName)
+		switch sheetOp.OpType {
+		case "add":
+			// 新增
+			_, ok := currSheetMap[sheetName]
+			if ok {
+				errMsg = "存在同名sheet:" + sheetName
+				err = errors.New(errMsg)
+				isSendEmail = false
+				return
+			}
+		case "replace":
+			// 替换
+		case "append":
+			// 追加
+		default:
+			errMsg = fmt.Sprint("第", k+1, "个sheet,错误的操作类型")
+			err = errors.New(errMsg + "op:" + sheetOp.OpType)
+			isSendEmail = false
+			return
+		}
+	}
+
+	// 表格
+	excelInfo.ExcelName = excelName
+	excelInfo.ExcelClassifyId = excelClassifyId
+	excelInfo.ModifyTime = time.Now()
+
+	addSheetList := make([]excel.AddExcelSheetParams, 0)
+	splitNum := 2000 // 基础分割单元格数
+
+	// sheet处理
+	sheetNameMap := make(map[string]string)
+	for k, sheetInfo := range luckySheet.Sheets {
+		sheetName := utils.TrimLRStr(sheetInfo.Name)
+		_, ok := sheetNameMap[sheetName]
+		if ok {
+			errMsg = "excel表中存在同名sheet"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		addSheetItem := excel.AddExcelSheetParams{
+			ExcelSheetId: 0,
+			ExcelInfoId:  0,
+			SheetName:    sheetName,
+			Sort:         k,
+		}
+
+		lenCellData := len(sheetInfo.Celldata)
+
+		splitLen := lenCellData / splitNum
+		residue := lenCellData % splitNum
+		if residue > 0 {
+			splitLen += 1
+		}
+
+		sheetDataList := make([]*excel.ExcelSheetData, 0)
+		for i := 0; i < splitLen; i++ {
+
+			startRow := i * splitNum
+			endRow := (i + 1) * splitNum
+			if i == splitLen-1 && residue > 0 {
+				endRow = lenCellData
+			}
+
+			tmpData := sheetInfo.Celldata[startRow:endRow]
+			tmpDataByte, tmpErr := json.Marshal(tmpData)
+			if tmpErr != nil {
+				errMsg = "保存失败"
+				err = errors.New("保存失败:" + tmpErr.Error())
+				return
+			}
+			sheetDataList = append(sheetDataList, &excel.ExcelSheetData{
+				ExcelDataId:  0,
+				ExcelInfoId:  0,
+				ExcelSheetId: 0,
+				Sort:         i,
+				Data:         string(tmpDataByte),
+				ModifyTime:   time.Now(),
+				CreateTime:   time.Now(),
+			})
+		}
+		addSheetItem.DataList = sheetDataList
+
+		addSheetList = append(addSheetList, addSheetItem)
+	}
+
+	err = data_manage.AddExcelInfoAndSheet(excelInfo, addSheetList)
+
+	return
+}
+
+type LuckySheet struct {
+	Info struct {
+		Name           string    `json:"name"`
+		Creator        string    `json:"creator"`
+		Lastmodifiedby string    `json:"lastmodifiedby"`
+		CreatedTime    time.Time `json:"createdTime"`
+		ModifiedTime   time.Time `json:"modifiedTime"`
+		Company        string    `json:"company"`
+		Appversion     string    `json:"appversion"`
+	} `json:"info"`
+	Sheets []struct {
+		Name string `json:"name"`
+		//Config struct {
+		//	Columnlen struct {
+		//		Num15 int `json:"15"`
+		//		Num16 int `json:"16"`
+		//		Num20 int `json:"20"`
+		//		Num34 int `json:"34"`
+		//		Num35 int `json:"35"`
+		//	} `json:"columnlen"`
+		//} `json:"config"`
+		Index            string `json:"index"`
+		Order            string `json:"order"`
+		ZoomRatio        int    `json:"zoomRatio"`
+		ShowGridLines    string `json:"showGridLines"`
+		DefaultColWidth  int    `json:"defaultColWidth"`
+		DefaultRowHeight int    `json:"defaultRowHeight"`
+		Celldata         []struct {
+			R int         `json:"r"`
+			C int         `json:"c"`
+			V interface{} `json:"v,omitempty"`
+		} `json:"celldata"`
+		CalcChain []interface{} `json:"calcChain"`
+		//DataVerification struct {
+		//} `json:"dataVerification"`
+		//Hyperlink struct {
+		//} `json:"hyperlink"`
+		//Hide int `json:"hide"`
+	} `json:"sheets"`
+}

+ 229 - 97
services/excel/excel_to_lucky_sheet.go

@@ -6,6 +6,8 @@ import (
 	"fmt"
 	"github.com/shopspring/decimal"
 	"github.com/xuri/excelize/v2"
+	"sync"
+	"time"
 )
 
 // ConvToLuckySheet 普通的excel转luckySheet数据
@@ -23,6 +25,8 @@ func ConvToLuckySheet(filePath string) (err error) {
 	sheetDataList := make([]SimpleLuckySheetData, 0)
 	// 获取所有sheet
 	sheetList := f.GetSheetList()
+	fmt.Println("读取完成后", time.Now().Format(utils.FormatDateTime))
+
 	for sheetIndex, sheetName := range sheetList {
 		sheetData, tmpErr := getLuckySheetData(f, sheetIndex, sheetName)
 		if tmpErr != nil {
@@ -31,11 +35,13 @@ func ConvToLuckySheet(filePath string) (err error) {
 		}
 		sheetDataList = append(sheetDataList, sheetData)
 	}
+
 	byteS, err := json.Marshal(sheetDataList)
 	if err != nil {
 		return
 	}
 	utils.FileLog.Info(string(byteS))
+
 	return
 }
 
@@ -80,19 +86,20 @@ type SimpleLuckySheetDataConfig struct {
 
 // SimpleLuckySheetCellData 单个单元格数据
 type SimpleLuckySheetCellData struct {
-	Col   int64                     `json:"c" description:"列"`
-	Row   int64                     `json:"r" description:"行"`
-	Value SimpleLuckySheetDataValue `json:"v" description:"单元格内值的数据"`
+	Col int64 `json:"c" description:"列"`
+	Row int64 `json:"r" description:"行"`
+	//Value SimpleLuckySheetDataValue `json:"v" description:"单元格内值的数据"`
+	Value interface{} `json:"v" description:"单元格内值的数据"`
 }
 
 // SimpleLuckySheetDataValue 单元格内值的数据
 type SimpleLuckySheetDataValue struct {
 	CellType LuckySheetDataCellType `json:"ct" description:"单元格值格式:文本、时间等	"`
 	Value    interface{}            `json:"v" description:"原始值"`
-	Monitor  string                 `json:"m" description:"显示值"`
+	//Monitor  string                 `json:"m" description:"显示值"`
 	//Fontsize       int                    `description:"字体大小,14"`
-	TextBeak int         `description:"文本换行,	0 截断、1溢出、2 自动换行"`
-	Tb       interface{} `json:"tb" description:"文本换行,	0 截断、1溢出、2 自动换行"`
+	//TextBeak int         `description:"文本换行,	0 截断、1溢出、2 自动换行"`
+	//Tb       interface{} `json:"tb" description:"文本换行,	0 截断、1溢出、2 自动换行"`
 	//Ps        LuckySheetDataCellComment `json:"ps" description:"批注"`
 	Function string `json:"f" description:"公式"`
 	//MergeCell LuckySheetDataConfigMerge `json:"mc" description:"合并单元格信息"`
@@ -111,126 +118,251 @@ func getLuckySheetData(f *excelize.File, sheetIndex int, sheetName string) (shee
 		CellData: cellData,
 		Config:   SimpleLuckySheetDataConfig{},
 	}
+	fmt.Println("开始读取sheet数据:", time.Now().Format(utils.FormatDateTime))
 	rows, tmpErr := f.GetRows(sheetName)
 	if tmpErr != nil {
 		err = tmpErr
 		return
 	}
+	fmt.Println("读取完sheet数据:", time.Now().Format(utils.FormatDateTime))
+	lenRow := len(rows)
+	fmt.Println("总共:", lenRow, "条数据")
+	if lenRow <= 0 {
+		return
+	}
+
 	//sheetData.Row = len(rows)
 	//sheetData.Column = len(Column)
 
 	// 最大单元格数
 	maxColumnIndex := 0
-	mergeCellList, err := f.GetMergeCells(sheetName)
-	if err != nil {
-		return
-	}
 
-	for _, v := range mergeCellList {
-		// 左上角单元格位置
-		cStartIndex, rStartIndex, tmpErr := excelize.CellNameToCoordinates(v.GetStartAxis())
-		if tmpErr != nil {
-			err = tmpErr
-			return
-		}
-		// 右下角单元格位置
-		cEndIndex, rEndIndex, tmpErr := excelize.CellNameToCoordinates(v.GetEndAxis())
-		if tmpErr != nil {
-			err = tmpErr
+	wg := sync.WaitGroup{}
+	wg.Add(1)
+	// 协程处理合并单元格
+	go func() {
+		defer func() {
+			wg.Done()
+		}()
+		mergeCellList, err := f.GetMergeCells(sheetName)
+		if err != nil {
 			return
 		}
-		//fmt.Println(v.GetEndAxis())
-		tmpLuckySheetDataConfigMerge := LuckySheetDataConfigMerge{
-			Row:    rStartIndex - 1,
-			Column: cStartIndex - 1,
-			Rs:     rEndIndex - rStartIndex + 1,
-			Cs:     cEndIndex - cStartIndex + 1,
-		}
-		mergeData[fmt.Sprint(rStartIndex-1, "_", cStartIndex-1)] = tmpLuckySheetDataConfigMerge
-	}
-	sheetData.Config.Merge = mergeData
-
-	colWidthMap := make(map[string]float64)
-	for rIndex, row := range rows {
-		for cIndex, colCell := range row {
-			if rIndex == 0 {
-				//colName, tmpErr := excelize.ColumnNumberToName(cIndex + 1)
-				//if tmpErr != nil {
-				//	err = tmpErr
-				//	return
-				//}
-				//colWidth, tmpErr := f.GetColWidth(sheetName, colName)
-				//if tmpErr != nil {
-				//	err = tmpErr
-				//	return
-				//}
-				//colWidthMap[fmt.Sprint(cIndex)] = emuToPx(colWidth)
-			}
-			if maxColumnIndex < cIndex {
-				maxColumnIndex = cIndex
-			}
-			cellName, tmpErr := excelize.CoordinatesToCellName(cIndex+1, rIndex+1)
+		for _, v := range mergeCellList {
+			// 左上角单元格位置
+			cStartIndex, rStartIndex, tmpErr := excelize.CellNameToCoordinates(v.GetStartAxis())
 			if tmpErr != nil {
 				err = tmpErr
 				return
 			}
-			cellType, tmpErr := f.GetCellType(sheetName, cellName)
+			// 右下角单元格位置
+			cEndIndex, rEndIndex, tmpErr := excelize.CellNameToCoordinates(v.GetEndAxis())
 			if tmpErr != nil {
 				err = tmpErr
 				return
 			}
-			cellFormula, tmpErr := f.GetCellFormula(sheetName, cellName)
-			if tmpErr != nil {
-				err = tmpErr
-				return
+			//fmt.Println(v.GetEndAxis())
+			tmpLuckySheetDataConfigMerge := LuckySheetDataConfigMerge{
+				Row:    rStartIndex - 1,
+				Column: cStartIndex - 1,
+				Rs:     rEndIndex - rStartIndex + 1,
+				Cs:     cEndIndex - cStartIndex + 1,
 			}
+			mergeData[fmt.Sprint(rStartIndex-1, "_", cStartIndex-1)] = tmpLuckySheetDataConfigMerge
+		}
+		sheetData.Config.Merge = mergeData
+	}()
 
-			fmt.Println(cellName, ": ", "类型:", cellType, ",公式:", cellFormula, ",值", colCell, "\t")
+	colWidthMap := make(map[string]float64)
 
-			var colCellIntfac interface{}
-			cellTypeT := "g"
-			//colCell = utils.Tof
-			tmpDec, tmpErr := decimal.NewFromString(colCell)
-			if tmpErr != nil {
-				colCellIntfac = colCell
-			} else {
-				colCellIntfac, _ = tmpDec.Float64()
-				cellTypeT = "n"
-			}
+	// 每次分割就是5000条
+	splitNum := 500
+	splitLen := lenRow / splitNum
+	residue := lenRow % splitNum
+	if residue > 0 {
+		splitLen += 1
+	}
 
-			if cellFormula != `` {
-				cellFormula = `=` + cellFormula
-
-				calcChainList = append(calcChainList, CalcChain{
-					Col:   int64(cIndex),
-					Row:   int64(rIndex),
-					Index: sheetIndex,
-					Func:  []interface{}{true, colCell, cellFormula},
-					Color: "w",
-					Times: 0,
-				})
-			}
+	for i := 0; i < splitLen; i++ {
+		wg.Add(1)
 
-			cellData = append(cellData, SimpleLuckySheetCellData{
-				Col: int64(cIndex),
-				Row: int64(rIndex),
-				Value: SimpleLuckySheetDataValue{
-					CellType: LuckySheetDataCellType{
+		startRow := i * splitNum
+		endRow := (i + 1) * splitNum
+		if i == splitLen-1 && residue > 0 {
+			endRow = lenRow
+		}
+
+		go func(currStartRow, currEndRow int) {
+			defer func() {
+				wg.Done()
+			}()
+
+			for rIndex := currStartRow; rIndex < currEndRow; rIndex++ {
+				row := rows[rIndex]
+				for cIndex, colCell := range row {
+					if rIndex == 0 {
+						//colName, tmpErr := excelize.ColumnNumberToName(cIndex + 1)
+						//if tmpErr != nil {
+						//	err = tmpErr
+						//	return
+						//}
+						//colWidth, tmpErr := f.GetColWidth(sheetName, colName)
+						//if tmpErr != nil {
+						//	err = tmpErr
+						//	return
+						//}
+						//colWidthMap[fmt.Sprint(cIndex)] = emuToPx(colWidth)
+					}
+					if maxColumnIndex < cIndex {
+						maxColumnIndex = cIndex
+					}
+					cellName, tmpErr := excelize.CoordinatesToCellName(cIndex+1, rIndex+1)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					//cellType, tmpErr := f.GetCellType(sheetName, cellName)
+					//if tmpErr != nil {
+					//	err = tmpErr
+					//	return
+					//}
+					cellFormula, tmpErr := f.GetCellFormula(sheetName, cellName)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+
+					//fmt.Println(cellName, ": ", "类型:", cellType, ",公式:", cellFormula, ",值", colCell, "\t")
+
+					var colCellIntfac interface{}
+					cellTypeT := "g"
+					//colCell = utils.Tof
+					tmpDec, tmpErr := decimal.NewFromString(colCell)
+					if tmpErr != nil {
+						colCellIntfac = colCell
+					} else {
+						colCellIntfac, _ = tmpDec.Float64()
+						cellTypeT = "n"
+					}
+
+					if cellFormula != `` {
+						cellFormula = `=` + cellFormula
+
+						calcChainList = append(calcChainList, CalcChain{
+							Col:   int64(cIndex),
+							Row:   int64(rIndex),
+							Index: sheetIndex,
+							Func:  []interface{}{true, colCell, cellFormula},
+							Color: "w",
+							Times: 0,
+						})
+					}
+					//CellType LuckySheetDataCellType `json:"ct" description:"单元格值格式:文本、时间等	"`
+					//Value    interface{}            `json:"v" description:"原始值"`
+					////Monitor  string                 `json:"m" description:"显示值"`
+					////Fontsize       int                    `description:"字体大小,14"`
+					////TextBeak int         `description:"文本换行,	0 截断、1溢出、2 自动换行"`
+					////Tb       interface{} `json:"tb" description:"文本换行,	0 截断、1溢出、2 自动换行"`
+					////Ps        LuckySheetDataCellComment `json:"ps" description:"批注"`
+					//Function string `json:"f" description:"公式"`
+
+					valueMap := make(map[string]interface{})
+					valueMap["ct"] = LuckySheetDataCellType{
 						Fa: "General",
 						T:  cellTypeT,
-						//S:  nil,
-					},
-					Value:   colCellIntfac,
-					Monitor: colCell,
-					//Background:     "",
-					//FontFamily:     0,
-					//FontColor:      "",
-					Function: cellFormula,
-					//MergeCell: LuckySheetDataConfigMerge{},
-				},
-			})
-		}
+					}
+					valueMap["v"] = colCellIntfac
+					if cellFormula != `` {
+						valueMap["f"] = cellFormula
+					}
+					cellData = append(cellData, SimpleLuckySheetCellData{
+						Col:   int64(cIndex),
+						Row:   int64(rIndex),
+						Value: valueMap,
+					})
+				}
+			}
+		}(startRow, endRow)
 	}
+	wg.Wait()
+
+	fmt.Println("解析完sheet数据:", time.Now().Format(utils.FormatDateTime))
+	//for rIndex, row := range rows {
+	//	for cIndex, colCell := range row {
+	//		if rIndex == 0 {
+	//			//colName, tmpErr := excelize.ColumnNumberToName(cIndex + 1)
+	//			//if tmpErr != nil {
+	//			//	err = tmpErr
+	//			//	return
+	//			//}
+	//			//colWidth, tmpErr := f.GetColWidth(sheetName, colName)
+	//			//if tmpErr != nil {
+	//			//	err = tmpErr
+	//			//	return
+	//			//}
+	//			//colWidthMap[fmt.Sprint(cIndex)] = emuToPx(colWidth)
+	//		}
+	//		if maxColumnIndex < cIndex {
+	//			maxColumnIndex = cIndex
+	//		}
+	//		cellName, tmpErr := excelize.CoordinatesToCellName(cIndex+1, rIndex+1)
+	//		if tmpErr != nil {
+	//			err = tmpErr
+	//			return
+	//		}
+	//		//cellType, tmpErr := f.GetCellType(sheetName, cellName)
+	//		//if tmpErr != nil {
+	//		//	err = tmpErr
+	//		//	return
+	//		//}
+	//		cellFormula, tmpErr := f.GetCellFormula(sheetName, cellName)
+	//		if tmpErr != nil {
+	//			err = tmpErr
+	//			return
+	//		}
+	//
+	//		//fmt.Println(cellName, ": ", "类型:", cellType, ",公式:", cellFormula, ",值", colCell, "\t")
+	//
+	//		var colCellIntfac interface{}
+	//		cellTypeT := "g"
+	//		//colCell = utils.Tof
+	//		tmpDec, tmpErr := decimal.NewFromString(colCell)
+	//		if tmpErr != nil {
+	//			colCellIntfac = colCell
+	//		} else {
+	//			colCellIntfac, _ = tmpDec.Float64()
+	//			cellTypeT = "n"
+	//		}
+	//
+	//		if cellFormula != `` {
+	//			cellFormula = `=` + cellFormula
+	//
+	//			calcChainList = append(calcChainList, CalcChain{
+	//				Col:   int64(cIndex),
+	//				Row:   int64(rIndex),
+	//				Index: sheetIndex,
+	//				Func:  []interface{}{true, colCell, cellFormula},
+	//				Color: "w",
+	//				Times: 0,
+	//			})
+	//		}
+	//
+	//		cellData = append(cellData, SimpleLuckySheetCellData{
+	//			Col: int64(cIndex),
+	//			Row: int64(rIndex),
+	//			Value: SimpleLuckySheetDataValue{
+	//				CellType: LuckySheetDataCellType{
+	//					Fa: "General",
+	//					T:  cellTypeT,
+	//				},
+	//				Value:    colCellIntfac,
+	//				Monitor:  colCell,
+	//				Function: cellFormula,
+	//				//MergeCell: LuckySheetDataConfigMerge{},
+	//			},
+	//		})
+	//	}
+	//}
 
 	sheetData.Config.Columnlen = colWidthMap
 

+ 4 - 1
services/excel/lucky_sheet.go

@@ -1176,7 +1176,10 @@ func (item *LuckySheetData) ToExcel2() (downloadFilePath string, err error) {
 	f := excelize.NewFile()
 	// Create a new sheet.
 	sheetName := `Sheet1`
-	sheetIndex := f.NewSheet(sheetName)
+	sheetIndex, err := f.NewSheet(sheetName)
+	if err != nil {
+		return
+	}
 
 	//设置列宽度
 	for k, v := range tableData.RowWidthList {

+ 52 - 0
services/excel/xml.go

@@ -0,0 +1,52 @@
+package excel
+
+import (
+	"errors"
+	"github.com/beevik/etree"
+)
+
+// GetDefaultSheetIndex 获取数据源工作表索引
+func GetDefaultSheetIndex(workbookPath string, defaultSheetName string) (defaultSheetIndex int, err error) {
+	doc := etree.NewDocument()
+	if err = doc.ReadFromFile(workbookPath); err != nil {
+		return
+	}
+	flag := false
+	workbook := doc.SelectElement("workbook")
+	sheets := workbook.SelectElement("sheets")
+	for index, sheet := range sheets.SelectElements("sheet") {
+		for _, attr := range sheet.Attr {
+			if attr.Key == "name" && attr.Value == defaultSheetName {
+				defaultSheetIndex = index
+				flag = true
+			}
+		}
+	}
+	if flag == false {
+		err = errors.New(defaultSheetName + "工作表未找到")
+	}
+	return
+}
+
+// GetDefaultSheetIndex 获取数据源工作表索引
+func GetDefaultSheetData(sheetPath string, defaultSheetName string) (defaultSheetIndex int, err error) {
+	doc := etree.NewDocument()
+	if err = doc.ReadFromFile(sheetPath); err != nil {
+		return
+	}
+	flag := false
+	workbook := doc.SelectElement("worksheet")
+	sheets := workbook.SelectElement("sheets")
+	for index, sheet := range sheets.SelectElements("sheet") {
+		for _, attr := range sheet.Attr {
+			if attr.Key == "name" && attr.Value == defaultSheetName {
+				defaultSheetIndex = index
+				flag = true
+			}
+		}
+	}
+	if flag == false {
+		err = errors.New(defaultSheetName + "工作表未找到")
+	}
+	return
+}

+ 4 - 3
utils/constants.go

@@ -276,9 +276,10 @@ const (
 
 // ETA表格
 const (
-	EXCEL_DEFAULT = 1 // 自定义excel
-	TIME_TABLE    = 2 // 时间序列表格
-	MIXED_TABLE   = 3 // 混合表格
+	EXCEL_DEFAULT         = 1 // 自定义excel
+	TIME_TABLE            = 2 // 时间序列表格
+	MIXED_TABLE           = 3 // 混合表格
+	CUSTOM_ANALYSIS_TABLE = 4 // 自定义分析表格
 )
 
 // 图表样式类型