Browse Source

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

Roc 1 year ago
parent
commit
30dc2ff2b9
36 changed files with 4348 additions and 578 deletions
  1. 765 0
      controllers/data_manage/excel/custom_analysis.go
  2. 470 0
      controllers/data_manage/excel/custom_analysis_edb.go
  3. 74 67
      controllers/data_manage/excel/excel_classify.go
  4. 243 209
      controllers/data_manage/excel/excel_info.go
  5. 0 0
      etalogs/binlog/20231023.log
  6. 4 2
      go.mod
  7. 31 8
      go.sum
  8. 3 1
      models/data_manage/edb_info_calculate.go
  9. 13 7
      models/data_manage/excel/excel_classify.go
  10. 1 1
      models/data_manage/excel/excel_draft.go
  11. 95 0
      models/data_manage/excel/excel_edb_mapping.go
  12. 247 28
      models/data_manage/excel/excel_info.go
  13. 98 0
      models/data_manage/excel/excel_sheet.go
  14. 63 0
      models/data_manage/excel/excel_sheet_data.go
  15. 45 0
      models/data_manage/excel/request/excel.go
  16. 1 0
      models/data_manage/excel/request/excel_classify.go
  17. 1 0
      models/data_manage/excel/request/excel_info.go
  18. 4 2
      models/data_manage/excel/response/excel_classify.go
  19. 12 10
      models/data_manage/excel/response/excel_info.go
  20. 31 0
      models/data_manage/excel/response/sheet.go
  21. 16 3
      models/db.go
  22. 288 207
      routers/commentsRouter.go
  23. 8 2
      routers/router.go
  24. 10 0
      services/data/base_edb_lib.go
  25. 1 1
      services/data/chart_info_elastic.go
  26. 15 0
      services/data/edb_classify.go
  27. 5 0
      services/data/edb_info_calculate.go
  28. 426 0
      services/data/excel/custom_analysis.go
  29. 543 0
      services/data/excel/custom_analysis_edb.go
  30. 21 11
      services/data/excel/excel_info.go
  31. 268 0
      services/data/excel/excel_op.go
  32. 379 0
      services/excel/excel_to_lucky_sheet.go
  33. 58 19
      services/excel/lucky_sheet.go
  34. 49 0
      services/excel/lucky_sheet_excel.go
  35. 52 0
      services/excel/xml.go
  36. 8 0
      utils/constants.go

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

@@ -0,0 +1,765 @@
+package excel
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	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"
+	"fmt"
+	"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 := excelModel.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 = response.FindExcelInfo{
+		ExcelInfoId:     excelDetail.ExcelInfoId,
+		Source:          excelDetail.Source,
+		ExcelType:       excelDetail.ExcelType,
+		ExcelName:       excelDetail.ExcelName,
+		UniqueCode:      excelDetail.UniqueCode,
+		ExcelClassifyId: excelDetail.ExcelClassifyId,
+		SysUserId:       excelDetail.SysUserId,
+		SysUserRealName: excelDetail.SysUserRealName,
+		ExcelImage:      excelDetail.ExcelImage,
+		FileUrl:         excelDetail.FileUrl,
+		Sort:            excelDetail.Sort,
+		ModifyTime:      excelDetail.ModifyTime,
+		CreateTime:      excelDetail.CreateTime,
+		Button:          excel.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source),
+	}
+
+	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
+	}
+
+	// 获取是否存在该表格名称
+	{
+		var condition string
+		var pars []interface{}
+		condition += " AND source=? "
+		pars = append(pars, utils.CUSTOM_ANALYSIS_TABLE)
+
+		condition += " AND excel_name=? "
+		pars = append(pars, req.ExcelName)
+
+		count, err := excelModel.GetExcelInfoCountByCondition(condition, pars)
+		if err != nil {
+			br.Msg = "判断表格名称是否存在失败"
+			br.ErrMsg = "判断表格名称是否存在失败,Err:" + err.Error()
+			return
+		}
+		if count > 0 {
+			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
+
+	// 生成excel文件
+	go excel.UpdateExcelInfoFileUrl(excelInfo)
+
+	//新增操作日志
+	//{
+	//	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 := excelModel.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
+
+	// 生成excel文件
+	go excel.UpdateExcelInfoFileUrl(excelInfo)
+
+	//新增操作日志
+	//{
+	//	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 := excelModel.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 = response.FindExcelInfo{
+		ExcelInfoId:     excelDetail.ExcelInfoId,
+		Source:          excelDetail.Source,
+		ExcelType:       excelDetail.ExcelType,
+		ExcelName:       excelDetail.ExcelName,
+		UniqueCode:      excelDetail.UniqueCode,
+		ExcelClassifyId: excelDetail.ExcelClassifyId,
+		SysUserId:       excelDetail.SysUserId,
+		SysUserRealName: excelDetail.SysUserRealName,
+		ExcelImage:      excelDetail.ExcelImage,
+		FileUrl:         excelDetail.FileUrl,
+		Sort:            excelDetail.Sort,
+		ModifyTime:      excelDetail.ModifyTime,
+		CreateTime:      excelDetail.CreateTime,
+		Button:          excel.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source),
+	}
+	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 := excelModel.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.GetAllNoConfigSheetItemList(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
+}
+
+// FixTableData ETA1.0.2 自定义分析(生成指标数据修复)
+func FixTableData() {
+	// 获取一级分类
+	classifyList, err := excelModel.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 := &excelModel.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 = excelModel.AddExcelClassify(classify)
+		timeTableMap[v.ExcelClassifyId] = classify.ExcelClassifyId
+
+		// 混合表格
+		classify2 := &excelModel.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 = excelModel.AddExcelClassify(classify2)
+		mixTableMap[v.ExcelClassifyId] = classify2.ExcelClassifyId
+	}
+
+	// 修改时间序列表
+	{
+		// 获取时间序列表
+		timeTableExcelList, err := excelModel.GetNoContentExcelInfoAll(utils.TIME_TABLE, 0)
+		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
+			}
+			excelModel.UpdateExcelInfoClassifyId(classifyId, v.ExcelInfoId)
+		}
+	}
+
+	// 修改混合序列表
+	{
+		// 获取时间序列表
+		mixTableExcelList, err := excelModel.GetNoContentExcelInfoAll(utils.MIXED_TABLE, 0)
+		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
+			}
+			excelModel.UpdateExcelInfoClassifyId(classifyId, v.ExcelInfoId)
+		}
+	}
+
+	fmt.Println("完成数据修复")
+}
+
+// FixTableDataMapping ETA1.0.2 自定义分析(修复excel与指标的关系)
+func FixTableDataMapping() {
+
+	// 修改时间序列表
+	{
+		// 获取时间序列表
+		timeTableExcelList, err := excelModel.GetAllExcelInfoBySource(utils.TIME_TABLE)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			fmt.Println("获取时间序列表列表失败,Err:" + err.Error())
+			return
+		}
+
+		for _, v := range timeTableExcelList {
+
+			var tableData request.TableDataReq
+			err = json.Unmarshal([]byte(v.Content), &tableData)
+			if err != nil {
+				fmt.Println(v.ExcelInfoId, "json转结构体失败,Err:"+err.Error())
+				continue
+			}
+			if len(tableData.EdbInfoIdList) > 0 {
+				excelEdbMappingList := make([]*excelModel.ExcelEdbMapping, 0)
+				for _, edbInfoId := range tableData.EdbInfoIdList {
+					excelEdbMappingList = append(excelEdbMappingList, &excelModel.ExcelEdbMapping{
+						//ExcelEdbMappingId: 0,
+						ExcelInfoId: v.ExcelInfoId,
+						Source:      v.Source,
+						EdbInfoId:   edbInfoId,
+						CreateTime:  time.Now(),
+						ModifyTime:  time.Now(),
+					})
+				}
+				err = excelModel.AddExcelEdbMappingMulti(excelEdbMappingList)
+				if err != nil {
+					fmt.Println(v.ExcelInfoId, "自定义表格关系保存失败,Err:"+err.Error())
+					continue
+				}
+			}
+
+		}
+	}
+
+	//// 修改混合序列表
+	//{
+	//	// 获取时间序列表
+	//	mixTableExcelList, err := excelModel.GetAllExcelInfoBySource(utils.MIXED_TABLE)
+	//	if err != nil && err.Error() != utils.ErrNoRow() {
+	//		fmt.Println("获取时间序列表列表失败,Err:" + err.Error())
+	//		return
+	//	}
+	//
+	//	for _, excelInfo := range mixTableExcelList {
+	//		var result request.MixedTableReq
+	//		err = json.Unmarshal([]byte(excelInfo.Content), &result)
+	//		if err != nil {
+	//			fmt.Println(excelInfo.ExcelInfoId, "修改混合序列表,json转结构体失败,Err:"+err.Error())
+	//			continue
+	//		}
+	//		newResult, tmpErr := excel.GetMixedTableCellData(result.Data)
+	//		if tmpErr != nil {
+	//			fmt.Println(excelInfo.ExcelInfoId, "获取最新的数据失败,Err:"+err.Error())
+	//			continue
+	//		}
+	//		edbInfoIdList := make([]int, 0)
+	//		edbInfoIdMap := make(map[int]int)
+	//		for _, tmpV := range newResult {
+	//			for _, v := range tmpV {
+	//				if v.EdbInfoId > 0 {
+	//					if _, ok := edbInfoIdMap[v.EdbInfoId]; !ok {
+	//						edbInfoIdMap[v.EdbInfoId] = v.EdbInfoId
+	//						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+	//					}
+	//				}
+	//			}
+	//		}
+	//
+	//		if len(edbInfoIdList) > 0 {
+	//			excelEdbMappingList := make([]*excelModel.ExcelEdbMapping, 0)
+	//			for _, edbInfoId := range edbInfoIdList {
+	//				excelEdbMappingList = append(excelEdbMappingList, &excelModel.ExcelEdbMapping{
+	//					//ExcelEdbMappingId: 0,
+	//					ExcelInfoId: excelInfo.ExcelInfoId,
+	//					Source:      excelInfo.Source,
+	//					EdbInfoId:   edbInfoId,
+	//					CreateTime:  time.Now(),
+	//					ModifyTime:  time.Now(),
+	//				})
+	//			}
+	//			err = excelModel.AddExcelEdbMappingMulti(excelEdbMappingList)
+	//			if err != nil {
+	//				fmt.Println(excelInfo.ExcelInfoId, "混合表格关系保存失败,Err:"+err.Error())
+	//				continue
+	//			}
+	//		}
+	//
+	//	}
+	//
+	//}
+
+	fmt.Println("完成数据修复")
+}

+ 470 - 0
controllers/data_manage/excel/custom_analysis_edb.go

@@ -0,0 +1,470 @@
+package excel
+
+import (
+	"encoding/json"
+	"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/services/data"
+	"eta/eta_api/services/data/excel"
+	"eta/eta_api/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// EdbList
+// @Title 指标列表
+// @Description 指标列表
+// @Param   ExcelInfoId   query   int  true       "excel的id"
+// @Success 200 {object} []excel.ExcelEdbMappingItem
+// @router /edb/list [get]
+func (c *CustomAnalysisController) EdbList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	excelInfoId, _ := c.GetInt("ExcelInfoId")
+	if excelInfoId <= 0 {
+		br.Msg = "请选择excel"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取excel表详情
+	excelInfo, err := excelModel.GetExcelInfoById(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
+	}
+
+	list, err := excelModel.GetAllExcelEdbMappingItemByExcelInfoId(excelInfo.ExcelInfoId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	for k, v := range list {
+		var tmpCalculateFormula excelModel.CalculateFormula
+		err = json.Unmarshal([]byte(v.CalculateFormula), &tmpCalculateFormula)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "公式转换失败,Err:" + err.Error()
+			return
+		}
+		v.DateSequenceStr = tmpCalculateFormula.DateSequenceStr
+		v.DataSequenceStr = tmpCalculateFormula.DataSequenceStr
+		list[k] = v
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// AddEdb
+// @Title 新增指标接口
+// @Description 新增指标接口
+// @Param	request	body request.AddEdb true "type json string"
+// @Success 200 {object} data_manage.AddEdbInfoResp
+// @router /edb/add [post]
+func (c *CustomAnalysisController) AddEdb() {
+	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_EDB_" + 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.AddEdb
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.EdbName = strings.Trim(req.EdbName, " ")
+	if req.EdbName == "" {
+		br.Msg = "请填写指标名称!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ExcelInfoId <= 0 {
+		br.Msg = "请选择excel!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择指标分类!"
+		br.IsSendEmail = false
+		return
+	}
+
+	excelInfo, err := excelModel.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
+	}
+
+	//excel.GetCustomAnalysisExcelData(excelInfo)
+
+	dateList, dataList, err, errMsg := excel.HandleEdbSequenceVal(req.DateSequenceVal, req.DataSequenceVal)
+	if err != nil {
+		br.Msg = "时间序列或数据序列异常!"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "时间序列或数据序列处理异常!err:" + err.Error()
+		return
+	}
+
+	type CustomAnalysisData struct {
+		ExcelInfoId int `description:"excel的id"`
+		DateList    []string
+		DataList    []float64
+	}
+
+	type Formula struct {
+		DateSequenceStr string `description:"日期序列"`
+		DataSequenceStr string `description:"数据序列"`
+	}
+
+	formulaByte, err := json.Marshal(Formula{
+		DateSequenceStr: req.DateSequenceStr,
+		DataSequenceStr: req.DataSequenceStr,
+	})
+	if err != nil {
+		br.Msg = "时间序列或数据序列配置异常!"
+		br.ErrMsg = "json序列化时间序列或数据序列异常!err:" + err.Error()
+		return
+	}
+
+	req2 := &data_manage.EdbInfoCalculateBatchSaveReqByEdbLib{
+		AdminId:    sysUser.AdminId,
+		AdminName:  sysUser.RealName,
+		EdbName:    req.EdbName,
+		Frequency:  req.Frequency,
+		Unit:       req.Unit,
+		ClassifyId: req.ClassifyId,
+		Formula:    string(formulaByte), //公式
+		Source:     utils.DATA_SOURCE_CALCULATE_ZDYFX,
+		Data: CustomAnalysisData{
+			ExcelInfoId: req.ExcelInfoId,
+			DateList:    dateList,
+			DataList:    dataList,
+		},
+	}
+
+	// 调用指标库去更新
+	reqJson, err := json.Marshal(req2)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	respItem, err := data.BatchSaveEdbCalculateData(string(reqJson))
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	if respItem.Ret != 200 {
+		br.Msg = respItem.Msg
+		br.ErrMsg = respItem.ErrMsg
+		return
+	}
+
+	resp := respItem.Data
+
+	//添加es
+	data.AddOrEditEdbInfoToEs(resp.EdbInfoId)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+}
+
+// EditEdb
+// @Title 编辑指标接口
+// @Description 编辑指标接口
+// @Param	request	body request.EditEdb true "type json string"
+// @Success 200 {object} data_manage.AddEdbInfoResp
+// @router /edb/edit [post]
+func (c *CustomAnalysisController) EditEdb() {
+	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_EDB_" + 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.EditEdb
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	req.EdbName = strings.Trim(req.EdbName, " ")
+	if req.EdbName == "" {
+		br.Msg = "请填写指标名称!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ExcelInfoId <= 0 {
+		br.Msg = "请选择excel!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.EdbInfoId <= 0 {
+		br.Msg = "请选择指标!"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择指标分类!"
+		br.IsSendEmail = false
+		return
+	}
+
+	excelInfo, err := excelModel.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
+	}
+
+	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "指标已被删除,请刷新页面"
+			br.ErrMsg = "指标已被删除,请刷新页面:Err:" + err.Error()
+			return
+		}
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败:Err:" + err.Error()
+		return
+	}
+
+	//excel.GetCustomAnalysisExcelData(excelInfo)
+
+	dateList, dataList, err, errMsg := excel.HandleEdbSequenceVal(req.DateSequenceVal, req.DataSequenceVal)
+	if err != nil {
+		br.Msg = "时间序列或数据序列异常!"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "时间序列或数据序列处理异常!err:" + err.Error()
+		return
+	}
+
+	type CustomAnalysisData struct {
+		ExcelInfoId int `description:"excel的id"`
+		DateList    []string
+		DataList    []float64
+	}
+
+	type Formula struct {
+		DateSequenceStr string `description:"日期序列"`
+		DataSequenceStr string `description:"数据序列"`
+	}
+
+	formulaByte, err := json.Marshal(Formula{
+		DateSequenceStr: req.DateSequenceStr,
+		DataSequenceStr: req.DataSequenceStr,
+	})
+	if err != nil {
+		br.Msg = "时间序列或数据序列配置异常!"
+		br.ErrMsg = "json序列化时间序列或数据序列异常!err:" + err.Error()
+		return
+	}
+
+	// 构造请求
+	req2 := &data_manage.EdbInfoCalculateBatchEditReqByEdbLib{
+		EdbInfoId:  req.EdbInfoId,
+		EdbName:    req.EdbName,
+		Frequency:  req.Frequency,
+		Unit:       req.Unit,
+		ClassifyId: req.ClassifyId,
+		Formula:    string(formulaByte), //公式
+		Source:     utils.DATA_SOURCE_CALCULATE_ZDYFX,
+		Data: CustomAnalysisData{
+			ExcelInfoId: req.ExcelInfoId,
+			DateList:    dateList,
+			DataList:    dataList,
+		},
+	}
+
+	// 调用指标库去更新
+	reqJson, err := json.Marshal(req2)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	respItem, err := data.BatchEditEdbCalculateData(string(reqJson))
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+	if respItem.Ret != 200 {
+		br.Msg = respItem.Msg
+		br.ErrMsg = respItem.ErrMsg
+		return
+	}
+
+	resp := respItem.Data
+
+	//添加es
+	data.AddOrEditEdbInfoToEs(resp.EdbInfoId)
+
+	// 修改关联的预测指标基础信息
+	go data.ModifyPredictEdbBaseInfoBySourceEdb(edbInfo)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+}
+
+// EdbRefresh
+// @Title 指标列表
+// @Description 指标列表
+// @Param   ExcelInfoId   query   int  true       "excel的id"
+// @Success 200 {object} []excel.ExcelEdbMappingItem
+// @router /edb/refresh [get]
+func (c *CustomAnalysisController) EdbRefresh() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	excelInfoId, _ := c.GetInt("ExcelInfoId")
+	if excelInfoId <= 0 {
+		br.Msg = "请选择excel"
+		br.IsSendEmail = false
+		return
+	}
+	cacheKey := "CACHE_EXCEL_EDB_REFRESH_" + strconv.Itoa(c.SysUser.AdminId)
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + c.SysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		return
+	}
+	defer func() {
+		_ = utils.Rc.Delete(cacheKey)
+	}()
+
+	// 获取excel表详情
+	excelInfo, err := excelModel.GetExcelInfoById(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.Refresh(excelInfo)
+	if err != nil {
+		br.Msg = "刷新失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "刷新失败,Err:" + err.Error()
+		br.IsSendEmail = isSendEmail
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "刷新成功"
+}
+
+//func init() {
+//	excelInfo, err := excelModel.GetExcelInfoById(160)
+//	if err != nil {
+//		fmt.Println("查找excel失败:", err)
+//		return
+//	}
+//	_, err, _ = excel.GenerateExcelCustomAnalysisExcel(excelInfo)
+//	if err != nil {
+//		fmt.Println("生成excel失败:", err)
+//		return
+//	}
+//}

+ 74 - 67
controllers/data_manage/excel_classify.go → controllers/data_manage/excel/excel_classify.go

@@ -1,12 +1,13 @@
-package data_manage
+package excel
 
 import (
 	"encoding/json"
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
-	"eta/eta_api/models/data_manage"
-	"eta/eta_api/models/data_manage/request"
-	"eta/eta_api/models/data_manage/response"
+	"eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/models/data_manage/excel/request"
+	response2 "eta/eta_api/models/data_manage/excel/response"
+	excel2 "eta/eta_api/services/data/excel"
 	"eta/eta_api/utils"
 	"strconv"
 	"time"
@@ -20,6 +21,8 @@ type ExcelClassifyController struct {
 // List
 // @Title excel表格分类列表
 // @Description excel表格分类列表接口
+// @Param   Source   query   int  true       "格来源,1:excel插件的表格,2:自定义表格,3:混合表格,默认:1"
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
 // @Success 200 {object} response.ExcelClassifyListResp
 // @router /excel_classify/list [get]
 func (this *ExcelClassifyController) List() {
@@ -29,23 +32,34 @@ func (this *ExcelClassifyController) List() {
 		this.ServeJSON()
 	}()
 
+	source, _ := this.GetInt("Source")
+	if source <= 0 {
+		source = utils.EXCEL_DEFAULT
+	}
+	//只看我的
+	isShowMe, _ := this.GetBool("IsShowMe")
+	showUserId := 0
+	if isShowMe {
+		showUserId = this.SysUser.AdminId
+	}
+
 	// 获取一级分类
-	rootList, err := data_manage.GetExcelClassifyByParentId(0)
+	rootList, err := excel.GetExcelClassifyByParentId(0, source)
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	// 获取所有excel表格分类
-	allExcelInfo, err := data_manage.GetNoContentExcelInfoAll()
+	// 根据来源获取所有excel表格(无内容)
+	allExcelInfo, err := excel.GetNoContentExcelInfoAll(source, showUserId)
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
 		return
 	}
 
-	ExcelInfoMap := make(map[int][]*data_manage.ExcelClassifyItems)
+	ExcelInfoMap := make(map[int][]*excel.ExcelClassifyItems)
 	for _, v := range allExcelInfo {
 		ExcelInfoMap[v.ExcelClassifyId] = append(ExcelInfoMap[v.ExcelClassifyId], v)
 	}
@@ -59,18 +73,18 @@ func (this *ExcelClassifyController) List() {
 	//		v.Children = items
 	//	}
 	//}
-	nodeAll := make([]*data_manage.ExcelClassifyItems, 0)
+	nodeAll := make([]*excel.ExcelClassifyItems, 0)
 	for _, v := range rootList {
-		var items []*data_manage.ExcelClassifyItems
+		var items []*excel.ExcelClassifyItems
 		if tmpItem, ok := ExcelInfoMap[v.ExcelClassifyId]; ok {
 			items = tmpItem
 		} else {
-			items = make([]*data_manage.ExcelClassifyItems, 0)
+			items = make([]*excel.ExcelClassifyItems, 0)
 		}
 		v.Children = items
 		nodeAll = append(nodeAll, v)
 	}
-	resp := response.ExcelClassifyListResp{
+	resp := response2.ExcelClassifyListResp{
 		AllNodes: nodeAll,
 	}
 	br.Ret = 200
@@ -82,6 +96,7 @@ func (this *ExcelClassifyController) List() {
 // ExcelClassifyItems
 // @Title 获取所有excel表格分类接口-不包含表格
 // @Description 获取所有excel表格分类接口-不包含表格
+// @Param   Source   query   int  true       "格来源,1:excel插件的表格,2:自定义表格,3:混合表格,默认:1"
 // @Success 200 {object} response.ExcelClassifyListResp
 // @router /excel_classify/items [get]
 func (this *ExcelClassifyController) ExcelClassifyItems() {
@@ -90,13 +105,18 @@ func (this *ExcelClassifyController) ExcelClassifyItems() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	rootList, err := data_manage.GetExcelClassifyByParentId(0)
+
+	source, _ := this.GetInt("Source")
+	if source <= 0 {
+		source = utils.EXCEL_DEFAULT
+	}
+	rootList, err := excel.GetExcelClassifyByParentId(0, source)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
-	resp := response.ExcelClassifyListResp{
+	resp := response2.ExcelClassifyListResp{
 		AllNodes: rootList,
 	}
 	br.Ret = 200
@@ -135,8 +155,13 @@ func (this *ExcelClassifyController) AddExcelClassify() {
 		return
 	}
 
+	source := req.Source
+	if source <= 0 {
+		source = utils.EXCEL_DEFAULT
+	}
+
 	// 获取同级分类下存在同名分类的数量
-	count, err := data_manage.GetExcelClassifyCount(req.ExcelClassifyName, req.ParentId)
+	count, err := excel.GetExcelClassifyCount(req.ExcelClassifyName, req.ParentId, source)
 	if err != nil {
 		br.Msg = "判断名称是否已存在失败"
 		br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
@@ -148,14 +173,15 @@ func (this *ExcelClassifyController) AddExcelClassify() {
 		return
 	}
 	//获取该层级下最大的排序数
-	maxSort, err := data_manage.GetExcelClassifyMaxSort(req.ParentId)
+	maxSort, err := excel.GetExcelClassifyMaxSort(req.ParentId)
 
 	// 入库
 	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
-	classify := &data_manage.ExcelClassify{
+	classify := &excel.ExcelClassify{
 		//ExcelClassifyId:   0,
 		ExcelClassifyName: req.ExcelClassifyName,
 		ParentId:          req.ParentId,
+		Source:            source,
 		SysUserId:         this.SysUser.AdminId,
 		SysUserRealName:   this.SysUser.RealName,
 		Level:             req.Level + 1,
@@ -164,7 +190,7 @@ func (this *ExcelClassifyController) AddExcelClassify() {
 		CreateTime:        time.Now(),
 		ModifyTime:        time.Now(),
 	}
-	_, err = data_manage.AddExcelClassify(classify)
+	_, err = excel.AddExcelClassify(classify)
 	if err != nil {
 		br.Msg = "保存分类失败"
 		br.ErrMsg = "保存分类失败,Err:" + err.Error()
@@ -206,7 +232,7 @@ func (this *ExcelClassifyController) EditExcelClassify() {
 		return
 	}
 
-	item, err := data_manage.GetExcelClassifyById(req.ExcelClassifyId)
+	item, err := excel.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
 		br.Msg = "保存失败"
 		br.Msg = "获取分类信息失败,Err:" + err.Error()
@@ -222,7 +248,7 @@ func (this *ExcelClassifyController) EditExcelClassify() {
 	}
 
 	// 获取同级分类下存在同名分类的数量
-	count, err := data_manage.GetExcelClassifyCount(req.ExcelClassifyName, item.ParentId)
+	count, err := excel.GetExcelClassifyCount(req.ExcelClassifyName, item.ParentId, item.Source)
 	if err != nil {
 		br.Msg = "判断名称是否已存在失败"
 		br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
@@ -278,7 +304,7 @@ func (this *ExcelClassifyController) DeleteExcelClassifyCheck() {
 	var tipsMsg string
 
 	// 校验是否存在该分类
-	ExcelClassifyInfo, err := data_manage.GetExcelClassifyById(req.ExcelClassifyId)
+	ExcelClassifyInfo, err := excel.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
 		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "该分类不存在"
@@ -298,7 +324,7 @@ func (this *ExcelClassifyController) DeleteExcelClassifyCheck() {
 	//删除分类
 	if req.ExcelClassifyId > 0 && req.ExcelInfoId == 0 {
 		//判断表格分类下,是否含有表格
-		count, err := data_manage.GetExcelInfoCountByClassifyId(req.ExcelClassifyId)
+		count, err := excel.GetExcelInfoCountByClassifyId(req.ExcelClassifyId)
 		if err != nil {
 			br.Msg = "删除失败"
 			br.ErrMsg = "分类下是否含有指标失败,Err:" + err.Error()
@@ -328,7 +354,7 @@ func (this *ExcelClassifyController) DeleteExcelClassifyCheck() {
 		tipsMsg = "可删除,进行删除操作"
 	}
 
-	resp := response.ExcelClassifyDeleteCheckResp{
+	resp := response2.ExcelClassifyDeleteCheckResp{
 		DeleteStatus: deleteStatus,
 		TipsMsg:      tipsMsg,
 	}
@@ -376,7 +402,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 	//删除分类
 	if req.ExcelClassifyId > 0 && req.ExcelInfoId == 0 {
 		//判断是否含有指标
-		count, err := data_manage.GetExcelInfoCountByClassifyId(req.ExcelClassifyId)
+		count, err := excel.GetExcelInfoCountByClassifyId(req.ExcelClassifyId)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "删除失败"
 			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
@@ -389,7 +415,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 			return
 		}
 
-		classifyItem, err := data_manage.GetExcelClassifyById(req.ExcelClassifyId)
+		classifyItem, err := excel.GetExcelClassifyById(req.ExcelClassifyId)
 		if err != nil {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取分类失败,Err:" + err.Error()
@@ -408,10 +434,10 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 		}
 	}
 
-	resp := response.AddExcelInfoResp{}
+	resp := response2.AddExcelInfoResp{}
 	//删除表格
 	if req.ExcelInfoId > 0 {
-		excelInfo, err := data_manage.GetExcelInfoById(req.ExcelInfoId)
+		excelInfo, err := excel.GetExcelInfoById(req.ExcelInfoId)
 		if err != nil {
 			if err.Error() == utils.ErrNoRow() {
 				br.Msg = "表格已删除,请刷新页面"
@@ -428,18 +454,22 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 			br.IsSendEmail = false
 			return
 		}
-		//删除表格及关联指标
-		excelInfo.IsDelete = 1
-		err = excelInfo.Update([]string{"IsDelete"})
+
+		// 删除excel
+		err, errMsg, isSendEmail := excel2.Delete(excelInfo, sysUser)
 		if err != nil {
 			br.Msg = "删除失败"
-			br.ErrMsg = "删除失败,Err:" + err.Error()
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = "删除失败,Err:" + err.Error()
+			br.IsSendEmail = isSendEmail
 			return
 		}
 
 		// 返回下一个表格的信息
 		{
-			var nextItem *data_manage.ExcelInfo
+			var nextItem *excel.ExcelInfo
 			var condition string
 			var pars []interface{}
 			condition += " AND excel_classify_id=? "
@@ -447,7 +477,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 
 			condition += " AND (sort>? OR (sort=? AND excel_info_id<?) ) "
 			pars = append(pars, excelInfo.Sort, excelInfo.Sort, excelInfo.ExcelInfoId)
-			nextItem, err = data_manage.GetNextExcelInfoByCondition(condition, pars)
+			nextItem, err = excel.GetNextExcelInfoByCondition(condition, pars)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
@@ -456,37 +486,14 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 
 			// 如果没找到,那么查找下一个分类的第一个表格
 			if nextItem == nil {
-				currClassifyInfo, err := data_manage.GetExcelClassifyById(excelInfo.ExcelClassifyId)
+				currClassifyInfo, err := excel.GetExcelClassifyById(excelInfo.ExcelClassifyId)
 				if err != nil && err.Error() != utils.ErrNoRow() {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取当前表格分类信息失败,Err:" + err.Error()
 					return
 				}
 
-				//var condition string
-				//var pars []interface{}
-				//condition += " AND level=3 "
-				//pars = append(pars, chartInfo.ExcelClassifyId)
-
-				//condition += " AND (sort>? OR (sort=? and excel_classify_id >?) ) "
-				//pars = append(pars, currClassifyInfo.Sort, currClassifyInfo.Sort, currClassifyInfo.ExcelClassifyId)
-				//
-				//classifyItem, err := data_manage.GetNextExcelClassifyByCondition(condition, pars)
-				//if err != nil && err.Error() != utils.ErrNoRow() {
-				//	br.Msg = "删除失败"
-				//	br.ErrMsg = "获取下一级表格分类信息失败,Err:" + err.Error()
-				//	return
-				//}
-				//if classifyItem != nil {
-				//	nextItem, err = data_manage.GetNextExcelInfo(excelInfo.ExcelClassifyId)
-				//	if err != nil && err.Error() != utils.ErrNoRow() {
-				//		br.Msg = "删除失败"
-				//		br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
-				//		return
-				//	}
-				//}
-
-				nextItem, err = data_manage.GetNextExcelInfo(excelInfo.ExcelClassifyId, currClassifyInfo.Sort)
+				nextItem, err = excel.GetNextExcelInfo(excelInfo.ExcelClassifyId, currClassifyInfo.Sort, currClassifyInfo.Source)
 				if err != nil && err.Error() != utils.ErrNoRow() {
 					br.Msg = "删除失败"
 					br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
@@ -496,7 +503,7 @@ func (this *ExcelClassifyController) DeleteExcelClassify() {
 
 			// 如果找到下一个表格了,那么就返回
 			if nextItem != nil {
-				resp = response.AddExcelInfoResp{
+				resp = response2.AddExcelInfoResp{
 					ExcelInfoId: nextItem.ExcelInfoId,
 					UniqueCode:  nextItem.UniqueCode,
 				}
@@ -561,7 +568,7 @@ func (this *ExcelClassifyController) ExcelClassifyMove() {
 		return
 	}
 	//判断分类是否存在
-	ExcelClassifyInfo, err := data_manage.GetExcelClassifyById(req.ClassifyId)
+	ExcelClassifyInfo, err := excel.GetExcelClassifyById(req.ClassifyId)
 	if err != nil {
 		br.Msg = "移动失败"
 		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
@@ -571,7 +578,7 @@ func (this *ExcelClassifyController) ExcelClassifyMove() {
 
 	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
 	if ExcelClassifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 {
-		parentExcelClassifyInfo, err := data_manage.GetExcelClassifyById(req.ParentClassifyId)
+		parentExcelClassifyInfo, err := excel.GetExcelClassifyById(req.ParentClassifyId)
 		if err != nil {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取上级分类信息失败,Err:" + err.Error()
@@ -586,7 +593,7 @@ func (this *ExcelClassifyController) ExcelClassifyMove() {
 	//如果有传入 上一个兄弟节点分类id
 	if req.PrevClassifyId > 0 {
 		//上一个兄弟节点
-		prevClassify, err := data_manage.GetExcelClassifyById(req.PrevClassifyId)
+		prevClassify, err := excel.GetExcelClassifyById(req.PrevClassifyId)
 		if err != nil {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
@@ -596,7 +603,7 @@ func (this *ExcelClassifyController) ExcelClassifyMove() {
 		//如果是移动在两个兄弟节点之间
 		if req.NextClassifyId > 0 {
 			//下一个兄弟节点
-			nextClassify, err := data_manage.GetExcelClassifyById(req.NextClassifyId)
+			nextClassify, err := excel.GetExcelClassifyById(req.NextClassifyId)
 			if err != nil {
 				br.Msg = "移动失败"
 				br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
@@ -606,13 +613,13 @@ func (this *ExcelClassifyController) ExcelClassifyMove() {
 			if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == ExcelClassifyInfo.Sort {
 				//变更兄弟节点的排序
 				updateSortStr := `sort + 2`
-				_ = data_manage.UpdateExcelClassifySortByParentId(prevClassify.ParentId, prevClassify.ExcelClassifyId, prevClassify.Sort, updateSortStr)
+				_ = excel.UpdateExcelClassifySortByParentId(prevClassify.ParentId, prevClassify.ExcelClassifyId, prevClassify.Sort, updateSortStr)
 			} else {
 				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
 				if nextClassify.Sort-prevClassify.Sort == 1 {
 					//变更兄弟节点的排序
 					updateSortStr := `sort + 1`
-					_ = data_manage.UpdateExcelClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
+					_ = excel.UpdateExcelClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
 				}
 			}
 		}
@@ -622,7 +629,7 @@ func (this *ExcelClassifyController) ExcelClassifyMove() {
 		updateCol = append(updateCol, "Sort", "ModifyTime")
 
 	} else {
-		firstClassify, err := data_manage.GetFirstExcelClassifyByParentId(ExcelClassifyInfo.ParentId)
+		firstClassify, err := excel.GetFirstExcelClassifyByParentId(ExcelClassifyInfo.ParentId)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
@@ -632,7 +639,7 @@ func (this *ExcelClassifyController) ExcelClassifyMove() {
 		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
 		if firstClassify != nil && firstClassify.Sort == 0 {
 			updateSortStr := ` sort + 1 `
-			_ = data_manage.UpdateExcelClassifySortByParentId(firstClassify.ParentId, firstClassify.ExcelClassifyId-1, 0, updateSortStr)
+			_ = excel.UpdateExcelClassifySortByParentId(firstClassify.ParentId, firstClassify.ExcelClassifyId-1, 0, updateSortStr)
 		}
 
 		ExcelClassifyInfo.Sort = 0 //那就是排在第一位

+ 243 - 209
controllers/data_manage/excel_info.go → controllers/data_manage/excel/excel_info.go

@@ -1,21 +1,24 @@
-package data_manage
+package excel
 
 import (
+	"archive/zip"
 	"encoding/json"
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
-	"eta/eta_api/models/data_manage/request"
-	"eta/eta_api/models/data_manage/response"
-	"eta/eta_api/services"
-	"eta/eta_api/services/alarm_msg"
+	excel3 "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"
+	excel2 "eta/eta_api/services/data/excel"
 	"eta/eta_api/services/excel"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"github.com/yidane/formula"
+	"io"
 	"os"
+	"path/filepath"
 	"strconv"
 	"strings"
 	"time"
@@ -79,7 +82,7 @@ func (c *ExcelInfoController) Add() {
 		return
 	}
 
-	excelClassify, err := data_manage.GetExcelClassifyById(req.ExcelClassifyId)
+	excelClassify, err := excel3.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
 		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "分类不存在"
@@ -107,7 +110,7 @@ func (c *ExcelInfoController) Add() {
 	pars = append(pars, req.ExcelName)
 
 	// 获取分类下是否存在该表格名称
-	count, err := data_manage.GetExcelInfoCountByCondition(condition, pars)
+	count, err := excel3.GetExcelInfoCountByCondition(condition, pars)
 	if err != nil {
 		br.Msg = "判断表格名称是否存在失败"
 		br.ErrMsg = "判断表格名称是否存在失败,Err:" + err.Error()
@@ -124,6 +127,9 @@ func (c *ExcelInfoController) Add() {
 		req.Source = 1
 	}
 	content := req.Content
+
+	// 引用的指标id
+	edbInfoIdList := make([]int, 0)
 	// 自定义表格
 	if req.Source == 2 {
 		jsonStrByte, err := json.Marshal(req.TableData)
@@ -140,12 +146,14 @@ func (c *ExcelInfoController) Add() {
 			return
 		}
 
-		tableDataConfig, err := data.GetTableDataConfig(tableData)
+		tableDataConfig, err := excel2.GetTableDataConfig(tableData)
 		if err != nil {
 			br.Msg = "自定义表格数据获取失败"
 			br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
 			return
 		}
+		edbInfoIdList = tableDataConfig.EdbInfoIdList
+
 		contentByte, err := json.Marshal(tableDataConfig)
 		if err != nil {
 			br.Msg = "自定义表格数据获取失败"
@@ -164,10 +172,35 @@ func (c *ExcelInfoController) Add() {
 			return
 		}
 		content = string(contentByte)
+
+		var result request.MixedTableReq
+		err = json.Unmarshal(contentByte, &result)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
+			return
+		}
+		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
+		if tmpErr != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
+			return
+		}
+		edbInfoIdMap := make(map[int]int)
+		for _, tmpV := range newResult {
+			for _, v := range tmpV {
+				if v.EdbInfoId > 0 {
+					if _, ok := edbInfoIdMap[v.EdbInfoId]; !ok {
+						edbInfoIdMap[v.EdbInfoId] = v.EdbInfoId
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+				}
+			}
+		}
 	}
 
 	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
-	excelInfo := &data_manage.ExcelInfo{
+	excelInfo := &excel3.ExcelInfo{
 		//ExcelInfoId:     0,
 		ExcelName:       req.ExcelName,
 		Source:          req.Source,
@@ -184,7 +217,20 @@ func (c *ExcelInfoController) Add() {
 		CreateTime:      time.Now(),
 	}
 
-	err = data_manage.AddExcelInfo(excelInfo)
+	excelEdbMappingList := make([]*excel3.ExcelEdbMapping, 0)
+	if len(edbInfoIdList) > 0 {
+		for _, edbInfoId := range edbInfoIdList {
+			excelEdbMappingList = append(excelEdbMappingList, &excel3.ExcelEdbMapping{
+				//ExcelEdbMappingId: 0,
+				//ExcelInfoId:       0,
+				Source:     excelInfo.Source,
+				EdbInfoId:  edbInfoId,
+				CreateTime: time.Now(),
+				ModifyTime: time.Now(),
+			})
+		}
+	}
+	err = excel3.AddExcelInfo(excelInfo, excelEdbMappingList)
 	if err != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = "保存失败,Err:" + err.Error()
@@ -193,7 +239,7 @@ func (c *ExcelInfoController) Add() {
 
 	// 更新excel下载地址(默认的EXCEL需要更新,自定义表格不需要更新)
 	if req.Source == 1 {
-		go UpdateExcelInfoFileUrl(excelInfo)
+		go excel2.UpdateExcelInfoFileUrl(excelInfo)
 	}
 
 	resp := new(response.AddExcelInfoResp)
@@ -233,6 +279,8 @@ func (c *ExcelInfoController) Add() {
 // @Param   ExcelClassifyId   query   int  true       "分类id"
 // @Param   Keyword   query   string  true       "搜索关键词"
 // @Param   AdminId   query   int  false       "创建人id"
+// @Param   Source   query   int  true       "格来源,1:excel插件的表格,2:自定义表格,3:混合表格,默认:1"
+// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
 // @Success 200 {object} response.ExcelListResp
 // @router /excel_info/list [get]
 func (c *ExcelInfoController) List() {
@@ -255,6 +303,7 @@ func (c *ExcelInfoController) List() {
 	currentIndex, _ := c.GetInt("CurrentIndex")
 	keyword := c.GetString("Keyword")
 	adminId, _ := c.GetInt("AdminId")
+	source, _ := c.GetInt("Source")
 
 	var total int
 	page := paging.GetPaging(currentIndex, pageSize, total)
@@ -271,9 +320,18 @@ func (c *ExcelInfoController) List() {
 	var condition string
 	var pars []interface{}
 
+	// 如果没有传的话,那就是代表前三种表格
+	if source <= 0 {
+		condition += " AND source in (?,?,?) "
+		pars = append(pars, utils.EXCEL_DEFAULT, utils.TIME_TABLE, utils.MIXED_TABLE)
+	} else {
+		condition += " AND source = ? "
+		pars = append(pars, source)
+	}
+
 	// 筛选分类
 	if excelClassifyId > 0 {
-		_, err := data_manage.GetExcelClassifyById(excelClassifyId)
+		_, err := excel3.GetExcelClassifyById(excelClassifyId)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取表格信息失败"
 			br.ErrMsg = "获取信息失败,GetExcelClassify,Err:" + err.Error()
@@ -290,8 +348,14 @@ func (c *ExcelInfoController) List() {
 		condition += " AND sys_user_id = ? "
 		pars = append(pars, adminId)
 	}
+	//只看我的
+	isShowMe, _ := c.GetBool("IsShowMe")
+	if isShowMe {
+		condition += " AND sys_user_id = ? "
+		pars = append(pars, sysUser.AdminId)
+	}
 	//获取表格信息
-	list, err := data_manage.GetNoContentExcelListByCondition(condition, pars, startSize, pageSize)
+	list, err := excel3.GetNoContentExcelListByCondition(condition, pars, startSize, pageSize)
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		br.Success = true
 		br.Msg = "获取表格信息失败"
@@ -300,10 +364,10 @@ func (c *ExcelInfoController) List() {
 	}
 
 	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
-		list = make([]*data_manage.MyExcelInfoList, 0)
+		list = make([]*excel3.MyExcelInfoList, 0)
 	}
 	// 总数据量
-	dataCount, err := data_manage.GetExcelListCountByCondition(condition, pars)
+	dataCount, err := excel3.GetExcelListCountByCondition(condition, pars)
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		br.Msg = "获取表格列表信息失败"
 		br.ErrMsg = "获取表格列表数据总数失败,Err:" + err.Error()
@@ -350,7 +414,7 @@ func (c *ExcelInfoController) Detail() {
 	}
 
 	// 获取数据详情
-	excelDetail, errMsg, err := data.GetExcelDetailInfoByExcelInfoId(excelInfoId)
+	excelDetail, errMsg, err := excel2.GetExcelDetailInfoByExcelInfoId(excelInfoId)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = err.Error()
@@ -358,7 +422,7 @@ func (c *ExcelInfoController) Detail() {
 	}
 
 	// excel表格按钮权限
-	excelDetail.Button = data.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source)
+	excelDetail.Button = excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source)
 
 	br.Ret = 200
 	br.Success = true
@@ -424,7 +488,7 @@ func (c *ExcelInfoController) Edit() {
 		return
 	}
 
-	excelClassify, err := data_manage.GetExcelClassifyById(req.ExcelClassifyId)
+	excelClassify, err := excel3.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
 		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "分类不存在"
@@ -456,7 +520,7 @@ func (c *ExcelInfoController) Edit() {
 	pars = append(pars, req.ExcelName)
 
 	// 获取分类下是否存在该表格名称
-	count, err := data_manage.GetExcelInfoCountByCondition(condition, pars)
+	count, err := excel3.GetExcelInfoCountByCondition(condition, pars)
 	if err != nil {
 		br.Msg = "ETA判断表格名称是否存在失败"
 		br.ErrMsg = "判断ETA表格名称是否存在失败,Err:" + err.Error()
@@ -468,7 +532,7 @@ func (c *ExcelInfoController) Edit() {
 		return
 	}
 
-	excelInfo, err := data_manage.GetExcelInfoById(req.ExcelInfoId)
+	excelInfo, err := excel3.GetExcelInfoById(req.ExcelInfoId)
 	if err != nil {
 		br.Msg = "获取ETA表格失败"
 		br.ErrMsg = "获取ETA表格失败,Err:" + err.Error()
@@ -477,7 +541,7 @@ func (c *ExcelInfoController) Edit() {
 
 	// 操作权限校验
 	{
-		button := data.GetExcelInfoOpButton(sysUser, excelInfo.SysUserId, excelInfo.Source)
+		button := excel2.GetExcelInfoOpButton(sysUser, excelInfo.SysUserId, excelInfo.Source)
 		if !button.OpButton {
 			br.Msg = "无操作权限"
 			br.Msg = "无操作权限"
@@ -486,6 +550,8 @@ func (c *ExcelInfoController) Edit() {
 		}
 	}
 
+	// 引用的指标id
+	edbInfoIdList := make([]int, 0)
 	content := req.Content
 	switch excelInfo.Source {
 	case 2: // 自定义表格
@@ -502,7 +568,8 @@ func (c *ExcelInfoController) Edit() {
 			br.ErrMsg = "自定义表格数据获取失败,json转结构体失败,Err:" + err.Error()
 			return
 		}
-		tableDataConfig, err := data.GetTableDataConfig(tableData)
+		edbInfoIdList = tableData.EdbInfoIdList
+		tableDataConfig, err := excel2.GetTableDataConfig(tableData)
 		if err != nil {
 			br.Msg = "自定义表格数据获取失败"
 			br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
@@ -523,6 +590,31 @@ func (c *ExcelInfoController) Edit() {
 			return
 		}
 		content = string(contentByte)
+
+		var result request.MixedTableReq
+		err = json.Unmarshal(contentByte, &result)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
+			return
+		}
+		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
+		if tmpErr != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
+			return
+		}
+		edbInfoIdMap := make(map[int]int)
+		for _, tmpV := range newResult {
+			for _, v := range tmpV {
+				if v.EdbInfoId > 0 {
+					if _, ok := edbInfoIdMap[v.EdbInfoId]; !ok {
+						edbInfoIdMap[v.EdbInfoId] = v.EdbInfoId
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+				}
+			}
+		}
 	}
 
 	excelInfo.ModifyTime = time.Now()
@@ -534,7 +626,21 @@ func (c *ExcelInfoController) Edit() {
 
 	updateExcelInfoParams := []string{"ModifyTime", "ExcelName", "ExcelType", "ExcelClassifyId", "ExcelImage", "Content"}
 
-	err = data_manage.EditExcelInfo(excelInfo, updateExcelInfoParams)
+	excelEdbMappingList := make([]*excel3.ExcelEdbMapping, 0)
+	if len(edbInfoIdList) > 0 {
+		for _, edbInfoId := range edbInfoIdList {
+			excelEdbMappingList = append(excelEdbMappingList, &excel3.ExcelEdbMapping{
+				//ExcelEdbMappingId: 0,
+				ExcelInfoId: excelInfo.ExcelInfoId,
+				Source:      excelInfo.Source,
+				EdbInfoId:   edbInfoId,
+				CreateTime:  time.Now(),
+				ModifyTime:  time.Now(),
+			})
+		}
+	}
+
+	err = excel3.EditExcelInfo(excelInfo, updateExcelInfoParams, excelEdbMappingList)
 	if err != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = "保存失败,Err:" + err.Error()
@@ -543,12 +649,12 @@ func (c *ExcelInfoController) Edit() {
 
 	// 更新excel下载地址(默认的EXCEL需要更新,自定义表格不需要更新)
 	if excelInfo.Source == 1 {
-		go UpdateExcelInfoFileUrl(excelInfo)
+		go excel2.UpdateExcelInfoFileUrl(excelInfo)
 	}
 
 	// 加入草稿
 	{
-		excelDraftInfo := &data_manage.ExcelDraft{
+		excelDraftInfo := &excel3.ExcelDraft{
 			//ExcelDraftId: 0,
 			ExcelId:    req.ExcelInfoId,
 			Name:       req.ExcelName,
@@ -558,7 +664,7 @@ func (c *ExcelInfoController) Edit() {
 			CreateTime: time.Now(),
 		}
 
-		err = data_manage.AddExcelDraft(excelDraftInfo)
+		err = excel3.AddExcelDraft(excelDraftInfo)
 	}
 
 	resp := response.AddExcelInfoResp{
@@ -619,7 +725,7 @@ func (c *ExcelInfoController) Move() {
 	}
 
 	//判断分类是否存在
-	_, err = data_manage.GetExcelClassifyById(req.ExcelClassifyId)
+	_, err = excel3.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
 		br.Msg = "移动失败"
 		br.ErrMsg = "获取分类信息失败" + err.Error()
@@ -633,7 +739,7 @@ func (c *ExcelInfoController) Move() {
 	}
 
 	// 获取表格信息
-	excelInfo, err := data_manage.GetExcelInfoById(req.ExcelInfoId)
+	excelInfo, err := excel3.GetExcelInfoById(req.ExcelInfoId)
 	if err != nil {
 		br.Msg = "移动失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
@@ -643,7 +749,7 @@ func (c *ExcelInfoController) Move() {
 	//如果改变了分类,那么移动该表格数据
 	if excelInfo.ExcelClassifyId != req.ExcelClassifyId {
 		//查询需要修改的分类下是否存在同一个表格名称
-		tmpExcelInfo, tmpErr := data_manage.GetExcelInfoByClassifyIdAndName(req.ExcelClassifyId, excelInfo.ExcelName)
+		tmpExcelInfo, tmpErr := excel3.GetExcelInfoByClassifyIdAndName(req.ExcelClassifyId, excelInfo.ExcelName)
 		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
 			br.Msg = "移动失败"
 			br.ErrMsg = "移动失败,Err:" + tmpErr.Error()
@@ -670,7 +776,7 @@ func (c *ExcelInfoController) Move() {
 	updateCol := make([]string, 0)
 	//如果有传入 上一个兄弟节点分类id
 	if req.PrevExcelInfoId > 0 {
-		prevExcelInfo, err := data_manage.GetExcelInfoById(req.PrevExcelInfoId)
+		prevExcelInfo, err := excel3.GetExcelInfoById(req.PrevExcelInfoId)
 		if err != nil {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
@@ -680,7 +786,7 @@ func (c *ExcelInfoController) Move() {
 		//如果是移动在两个兄弟节点之间
 		if req.NextExcelInfoId > 0 {
 			//下一个兄弟节点
-			nextExcelInfo, err := data_manage.GetExcelInfoById(req.NextExcelInfoId)
+			nextExcelInfo, err := excel3.GetExcelInfoById(req.NextExcelInfoId)
 			if err != nil {
 				br.Msg = "移动失败"
 				br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
@@ -690,13 +796,13 @@ func (c *ExcelInfoController) Move() {
 			if prevExcelInfo.Sort == nextExcelInfo.Sort || prevExcelInfo.Sort == excelInfo.Sort {
 				//变更兄弟节点的排序
 				updateSortStr := `sort + 2`
-				_ = data_manage.UpdateExcelInfoSortByClassifyId(prevExcelInfo.ExcelClassifyId, prevExcelInfo.Sort, prevExcelInfo.ExcelInfoId, updateSortStr)
+				_ = excel3.UpdateExcelInfoSortByClassifyId(prevExcelInfo.ExcelClassifyId, prevExcelInfo.Sort, prevExcelInfo.ExcelInfoId, updateSortStr)
 			} else {
 				//如果下一个兄弟的排序权重正好是上个兄弟节点下一层,那么需要再加一层了
 				if nextExcelInfo.Sort-prevExcelInfo.Sort == 1 {
 					//变更兄弟节点的排序
 					updateSortStr := `sort + 1`
-					_ = data_manage.UpdateExcelInfoSortByClassifyId(prevExcelInfo.ExcelClassifyId, prevExcelInfo.Sort, prevExcelInfo.ExcelInfoId, updateSortStr)
+					_ = excel3.UpdateExcelInfoSortByClassifyId(prevExcelInfo.ExcelClassifyId, prevExcelInfo.Sort, prevExcelInfo.ExcelInfoId, updateSortStr)
 				}
 			}
 		}
@@ -707,7 +813,7 @@ func (c *ExcelInfoController) Move() {
 		updateCol = append(updateCol, "Sort", "ModifyTime")
 
 	} else {
-		firstClassify, err := data_manage.GetFirstExcelInfoByClassifyId(req.ExcelClassifyId)
+		firstClassify, err := excel3.GetFirstExcelInfoByClassifyId(req.ExcelClassifyId)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "移动失败"
 			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
@@ -717,7 +823,7 @@ func (c *ExcelInfoController) Move() {
 		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
 		if firstClassify != nil && firstClassify.Sort == 0 {
 			updateSortStr := ` sort + 1 `
-			_ = data_manage.UpdateExcelInfoSortByClassifyId(firstClassify.ExcelClassifyId, 0, firstClassify.ExcelInfoId-1, updateSortStr)
+			_ = excel3.UpdateExcelInfoSortByClassifyId(firstClassify.ExcelClassifyId, 0, firstClassify.ExcelInfoId-1, updateSortStr)
 		}
 
 		// 变更表格在当前分类下的排序
@@ -803,36 +909,28 @@ func (c *ExcelInfoController) Delete() {
 	}
 
 	// 获取表格信息
-	excelInfo, err := data_manage.GetExcelInfoById(req.ExcelInfoId)
+	excelInfo, err := excel3.GetExcelInfoById(req.ExcelInfoId)
 	if err != nil {
 		br.Msg = "删除失败"
 		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
 		return
 	}
 
-	// 操作权限校验
-	{
-		button := data.GetExcelInfoOpButton(sysUser, excelInfo.SysUserId, excelInfo.Source)
-		if !button.DeleteButton {
-			br.Msg = "无操作权限"
-			br.Msg = "无操作权限"
-			br.IsSendEmail = false
-			return
-		}
-	}
-
-	//更新
-	excelInfo.IsDelete = 1
-	err = excelInfo.Update([]string{"IsDelete"})
+	// 删除excel
+	err, errMsg, isSendEmail := excel2.Delete(excelInfo, sysUser)
 	if err != nil {
 		br.Msg = "删除失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
 		br.ErrMsg = "删除失败,Err:" + err.Error()
+		br.IsSendEmail = isSendEmail
 		return
 	}
 
 	// 返回下一个表格的信息
 	{
-		var nextItem *data_manage.ExcelInfo
+		var nextItem *excel3.ExcelInfo
 		var condition string
 		var pars []interface{}
 		condition += " AND excel_classify_id=? "
@@ -840,7 +938,7 @@ func (c *ExcelInfoController) Delete() {
 
 		condition += " AND sort>=? "
 		pars = append(pars, excelInfo.Sort)
-		nextItem, err = data_manage.GetNextExcelInfoByCondition(condition, pars)
+		nextItem, err = excel3.GetNextExcelInfoByCondition(condition, pars)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "删除失败"
 			br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
@@ -849,7 +947,7 @@ func (c *ExcelInfoController) Delete() {
 
 		// 如果没找到,那么查找下一个分类的第一个表格
 		if nextItem == nil {
-			currClassifyInfo, err := data_manage.GetExcelClassifyById(excelInfo.ExcelClassifyId)
+			currClassifyInfo, err := excel3.GetExcelClassifyById(excelInfo.ExcelClassifyId)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取当前表格分类信息失败,Err:" + err.Error()
@@ -878,7 +976,7 @@ func (c *ExcelInfoController) Delete() {
 			//	}
 			//}
 
-			nextItem, err = data_manage.GetNextExcelInfo(excelInfo.ExcelClassifyId, currClassifyInfo.Sort)
+			nextItem, err = excel3.GetNextExcelInfo(excelInfo.ExcelClassifyId, currClassifyInfo.Sort, currClassifyInfo.Source)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "删除失败"
 				br.ErrMsg = "获取下一级表格信息失败,Err:" + err.Error()
@@ -947,7 +1045,7 @@ func (c *ExcelInfoController) AddDraft() {
 		return
 	}
 
-	excelClassify, err := data_manage.GetExcelClassifyById(req.ExcelClassifyId)
+	excelClassify, err := excel3.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
 		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "分类不存在"
@@ -975,14 +1073,14 @@ func (c *ExcelInfoController) AddDraft() {
 	pars = append(pars, req.ExcelName)
 
 	// 获取分类下是否存在该表格名称
-	_, err = data_manage.GetExcelInfoById(req.ExcelInfoId)
+	_, err = excel3.GetExcelInfoById(req.ExcelInfoId)
 	if err != nil {
 		br.Msg = "判断表格名称是否存在失败"
 		br.ErrMsg = "判断表格名称是否存在失败,Err:" + err.Error()
 		return
 	}
 
-	excelDraftInfo := &data_manage.ExcelDraft{
+	excelDraftInfo := &excel3.ExcelDraft{
 		//ExcelDraftId: 0,
 		ExcelId:    req.ExcelInfoId,
 		Name:       req.ExcelName,
@@ -992,7 +1090,7 @@ func (c *ExcelInfoController) AddDraft() {
 		CreateTime: time.Now(),
 	}
 
-	err = data_manage.AddExcelDraft(excelDraftInfo)
+	err = excel3.AddExcelDraft(excelDraftInfo)
 	if err != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = "保存失败,Err:" + err.Error()
@@ -1033,7 +1131,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 		return
 	}
 	//获取eta表格信息
-	excelInfo, err := data_manage.GetExcelInfoByUniqueCode(uniqueCode)
+	excelInfo, err := excel3.GetExcelInfoByUniqueCode(uniqueCode)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取ETA表格信息失败,Err:" + err.Error()
@@ -1061,14 +1159,14 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			return
 		}
 	case 2:
-		var tableDataConfig data.TableDataConfig
+		var tableDataConfig excel2.TableDataConfig
 		err = json.Unmarshal([]byte(excelInfo.Content), &tableDataConfig)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		result, err := data.GetDataByTableDataConfig(tableDataConfig)
+		result, err := excel2.GetDataByTableDataConfig(tableDataConfig)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取最新的表格数据失败,Err:" + err.Error()
@@ -1088,7 +1186,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		newResult, tmpErr := data.GetMixedTableCellData(result.Data)
+		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
 		if tmpErr != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
@@ -1117,47 +1215,6 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	br.Data = resp
 }
 
-// UpdateExcelInfoFileUrl 更新excel表格的下载地址
-func UpdateExcelInfoFileUrl(excelInfo *data_manage.ExcelInfo) {
-	var err error
-	defer func() {
-		if err != nil {
-			go alarm_msg.SendAlarmMsg(fmt.Sprintf("更新excel表格的下载地址失败,表格id:%d;表格名称:%s; ERR:%s", excelInfo.ExcelInfoId, excelInfo.ExcelName, err), 3)
-		}
-	}()
-	fileName := excelInfo.ExcelName + "_" + excelInfo.UniqueCode + ".xlsx"
-	luckySheetData, err := excel.GetLuckySheetData(excelInfo.Content)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	//_, err = luckySheetData.GetTableDataByLuckySheetDataStr()
-	downloadFilePath, err := luckySheetData.ToExcel()
-	defer func() {
-		_ = os.Remove(downloadFilePath)
-	}()
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-
-	resourceUrl := ``
-	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadImgToMinIo(fileName, downloadFilePath)
-		if err != nil {
-			return
-		}
-	} else {
-		resourceUrl, err = services.UploadAliyunV2(fileName, downloadFilePath)
-		if err != nil {
-			return
-		}
-	}
-	excelInfo.FileUrl = resourceUrl
-	err = excelInfo.Update([]string{"FileUrl"})
-}
-
 //func init() {
 //
 //	excelInfo, err := data_manage.GetExcelInfoById(52)
@@ -1317,7 +1374,7 @@ func (c *ExcelInfoController) GetFirstEdbData() {
 		return
 	}
 
-	dataList, err := data.GetFirstEdbDataList(edbInfo, num, []string{})
+	dataList, err := excel2.GetFirstEdbDataList(edbInfo, num, []string{})
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -1385,7 +1442,7 @@ func (c *ExcelInfoController) GetOtherEdbData() {
 		br.ErrMsg = fmt.Sprint("获取指标信息失败,Err:", err.Error())
 		return
 	}
-	dataList, err := data.GetOtherEdbDataList(edbInfo, req.DateList)
+	dataList, err := excel2.GetOtherEdbDataList(edbInfo, req.DateList)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -1559,7 +1616,7 @@ func (c *ExcelInfoController) GetFutureDateData() {
 				return
 			}
 
-			dataList, err := data.GetOtherEdbDataList(tmpEdbInfo, dateStrList)
+			dataList, err := excel2.GetOtherEdbDataList(tmpEdbInfo, dateStrList)
 			if err != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -1642,7 +1699,7 @@ func (c *ExcelInfoController) GetHistoryDateData() {
 			br.ErrMsg = "获取指标信息失败,err:" + err.Error()
 			return
 		}
-		firstDataList, err := data.GetFirstHistoryEdbDataList(tmpEdbInfo, req.Num, req.EndDate)
+		firstDataList, err := excel2.GetFirstHistoryEdbDataList(tmpEdbInfo, req.Num, req.EndDate)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -1671,7 +1728,7 @@ func (c *ExcelInfoController) GetHistoryDateData() {
 				return
 			}
 
-			dataList, err := data.GetOtherEdbDataList(tmpEdbInfo, dateStrList)
+			dataList, err := excel2.GetOtherEdbDataList(tmpEdbInfo, dateStrList)
 			if err != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -1719,7 +1776,7 @@ func (c *ExcelInfoController) Refresh() {
 	}
 
 	// 获取数据详情
-	excelDetail, errMsg, err := data.GetExcelDetailInfoByExcelInfoId(excelInfoId)
+	excelDetail, errMsg, err := excel2.GetExcelDetailInfoByExcelInfoId(excelInfoId)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = err.Error()
@@ -1728,7 +1785,7 @@ func (c *ExcelInfoController) Refresh() {
 
 	// 操作权限校验
 	{
-		button := data.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source)
+		button := excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source)
 		if !button.RefreshButton {
 			br.Msg = "无操作权限"
 			br.Msg = "无操作权限"
@@ -1797,13 +1854,13 @@ func (c *ExcelInfoController) Download() {
 		br.IsSendEmail = false
 		return
 	}
-	var excelInfo *data_manage.ExcelInfo
+	var excelInfo *excel3.ExcelInfo
 	var err error
 	//获取eta表格信息
 	if excelInfoId > 0 {
-		excelInfo, err = data_manage.GetExcelInfoById(excelInfoId)
+		excelInfo, err = excel3.GetExcelInfoById(excelInfoId)
 	} else {
-		excelInfo, err = data_manage.GetExcelInfoByUniqueCode(uniqueCode)
+		excelInfo, err = excel3.GetExcelInfoByUniqueCode(uniqueCode)
 	}
 	if err != nil {
 		br.Msg = "获取失败"
@@ -1827,14 +1884,14 @@ func (c *ExcelInfoController) Download() {
 	case 1:
 		br.Msg = "表格类型异常"
 	case 2: // 自定义表格
-		var tableDataConfig data.TableDataConfig
+		var tableDataConfig excel2.TableDataConfig
 		err = json.Unmarshal([]byte(excelInfo.Content), &tableDataConfig)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		result, err := data.GetDataByTableDataConfig(tableDataConfig)
+		result, err := excel2.GetDataByTableDataConfig(tableDataConfig)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取最新的表格数据失败,Err:" + err.Error()
@@ -1854,7 +1911,7 @@ func (c *ExcelInfoController) Download() {
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		newResult, tmpErr := data.GetMixedTableCellData(result.Data)
+		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
 		if tmpErr != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
@@ -1906,7 +1963,6 @@ func (c *ExcelInfoController) Copy() {
 		return
 	}
 
-	deleteCache := true
 	var req request.CopyExcelInfoReq
 	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
 	if err != nil {
@@ -1920,17 +1976,15 @@ func (c *ExcelInfoController) Copy() {
 	}
 
 	cacheKey := "CACHE_TABLE_INFO_EDIT_" + strconv.Itoa(req.ExcelInfoId)
-	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
 	}
+	defer func() {
+		_ = utils.Rc.Delete(cacheKey)
+	}()
+
 	req.ExcelName = strings.Trim(req.ExcelName, " ")
 	if req.ExcelName == "" {
 		br.Msg = "请填写表格名称!"
@@ -1944,97 +1998,17 @@ func (c *ExcelInfoController) Copy() {
 		return
 	}
 
-	excelClassify, err := data_manage.GetExcelClassifyById(req.ExcelClassifyId)
-	if err != nil {
-		if err.Error() == utils.ErrNoRow() {
-			br.Msg = "分类不存在"
-			br.ErrMsg = "分类不存在"
-			br.IsSendEmail = false
-			return
-		}
-		br.Msg = "获取分类信息失败"
-		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
-		return
-	}
-	if excelClassify == nil {
-		br.Msg = "分类不存在"
-		br.ErrMsg = "分类不存在"
-		br.IsSendEmail = false
-		return
-	}
-
-	// 获取原ETA表格信息
-	oldExcelInfo, err := data_manage.GetExcelInfoById(req.ExcelInfoId)
+	excelInfo, err, errMsg, isSendEmail := excel2.Copy(req.ExcelInfoId, req.ExcelClassifyId, req.ExcelName, sysUser)
 	if err != nil {
-		br.Msg = "获取ETA表格失败"
-		br.ErrMsg = "获取ETA表格失败,Err:" + err.Error()
-		return
-	}
-
-	// 操作权限校验
-	{
-		button := data.GetExcelInfoOpButton(sysUser, oldExcelInfo.SysUserId, oldExcelInfo.Source)
-		if !button.CopyButton {
-			br.Msg = "无操作权限"
-			br.Msg = "无操作权限"
-			br.IsSendEmail = false
-			return
-		}
-	}
-
-	// 检验分类下是否存在该表格名称
-	{
-		var condition string
-		var pars []interface{}
-		condition += " AND excel_classify_id=? "
-		pars = append(pars, req.ExcelClassifyId)
-
-		condition += " AND excel_name=? "
-		pars = append(pars, req.ExcelName)
-
-		count, err := data_manage.GetExcelInfoCountByCondition(condition, pars)
-		if err != nil {
-			br.Msg = "判断表格名称是否存在失败"
-			br.ErrMsg = "判断表格名称是否存在失败,Err:" + err.Error()
-			return
+		br.Msg = "复制失败"
+		if errMsg != `` {
+			br.Msg = errMsg
 		}
-		if count > 0 {
-			br.Msg = "表格名称已存在,请重新填写表格名称"
-			br.IsSendEmail = false
-			return
-		}
-	}
-
-	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
-	excelInfo := &data_manage.ExcelInfo{
-		//ExcelInfoId:     0,
-		ExcelName:       req.ExcelName,
-		Source:          oldExcelInfo.Source,
-		ExcelType:       oldExcelInfo.ExcelType,
-		UniqueCode:      utils.MD5(utils.EXCEL_DATA_PREFIX + "_" + timestamp),
-		ExcelClassifyId: req.ExcelClassifyId,
-		SysUserId:       sysUser.AdminId,
-		SysUserRealName: sysUser.RealName,
-		Content:         oldExcelInfo.Content,
-		ExcelImage:      oldExcelInfo.ExcelImage,
-		Sort:            0,
-		IsDelete:        0,
-		ModifyTime:      time.Now(),
-		CreateTime:      time.Now(),
-	}
-
-	err = data_manage.AddExcelInfo(excelInfo)
-	if err != nil {
-		br.Msg = "保存失败"
-		br.ErrMsg = "保存失败,Err:" + err.Error()
+		br.ErrMsg = "复制失败,Err:" + err.Error()
+		br.IsSendEmail = isSendEmail
 		return
 	}
 
-	// 更新excel下载地址(默认的EXCEL需要更新,自定义表格不需要更新)
-	if excelInfo.Source == 1 {
-		go UpdateExcelInfoFileUrl(excelInfo)
-	}
-
 	resp := new(response.AddExcelInfoResp)
 	resp.ExcelInfoId = excelInfo.ExcelInfoId
 	resp.UniqueCode = excelInfo.UniqueCode
@@ -2109,3 +2083,63 @@ func (c *ExcelInfoController) Copy() {
 //	//byteStr, _ := json.Marshal(result)
 //	//utils.FileLog.Info(string(byteStr))
 //}
+
+//func init() {
+//	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
+}

+ 0 - 0
etalogs/binlog/20231023.log


+ 4 - 2
go.mod

@@ -12,8 +12,10 @@ require (
 	github.com/alibabacloud-go/tea-utils/v2 v2.0.1
 	github.com/aliyun/alibaba-cloud-sdk-go v1.61.1656
 	github.com/aliyun/aliyun-oss-go-sdk v2.2.0+incompatible
+	github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
 	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
@@ -31,7 +33,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
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1
@@ -106,7 +108,7 @@ require (
 	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.12.0 // indirect
-	golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
+	golang.org/x/image v0.5.0 // indirect
 	golang.org/x/net v0.14.0 // indirect
 	golang.org/x/sys v0.11.0 // indirect
 	golang.org/x/text v0.12.0 // indirect

+ 31 - 8
go.sum

@@ -70,6 +70,8 @@ github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEq
 github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02 h1:o2oaBQGTzO+xNh12e7xWkphNe7H2DTiWv1ml9a2P9PQ=
 github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
 github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
+github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
 github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
 github.com/aws/aws-sdk-go v1.42.23/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs=
 github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
@@ -80,6 +82,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=
@@ -271,6 +275,7 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
 github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
 github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@@ -364,11 +369,13 @@ github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7
 github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
 github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
+github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
 github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
 github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
@@ -430,8 +437,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=
@@ -440,6 +447,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=
@@ -452,20 +460,23 @@ 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.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
 golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
 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=
@@ -482,12 +493,15 @@ 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.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/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
 golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -500,6 +514,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=
@@ -523,20 +539,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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
 golang.org/x/sys v0.11.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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -554,6 +576,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=
@@ -618,7 +642,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=

+ 3 - 1
models/data_manage/edb_info_calculate.go

@@ -199,9 +199,10 @@ type EdbInfoCalculateBatchSaveReqByEdbLib struct {
 	MoveType         int              `description:"移动方式:1:领先(默认),2:滞后"`
 	MoveFrequency    string           `description:"移动频度:天/周/月/季/年"`
 	Calendar         string           `description:"公历/农历"`
+	Data             interface{}      `description:"数据列"`
 }
 
-// EdbInfoCalculateBatchEditReq 编辑计算指标的请求参数
+// EdbInfoCalculateBatchEditReqByEdbLib 编辑计算指标的请求参数
 type EdbInfoCalculateBatchEditReqByEdbLib struct {
 	EdbName       string `description:"指标名称"`
 	Frequency     string `description:"频度"`
@@ -215,6 +216,7 @@ type EdbInfoCalculateBatchEditReqByEdbLib struct {
 	MoveFrequency string `description:"移动频度:天/周/月/季/年"`
 	Calendar      string `description:"公历/农历"`
 	EdbInfoIdArr  []EdbInfoFromTag
+	Data          interface{} `description:"数据列"`
 }
 
 func GetEdbInfoCalculateMap(edbInfoId, source int) (list []*EdbInfo, err error) {

+ 13 - 7
models/data_manage/excel_classify.go → models/data_manage/excel/excel_classify.go

@@ -1,4 +1,4 @@
-package data_manage
+package excel
 
 import (
 	"fmt"
@@ -9,6 +9,7 @@ import (
 // ExcelClassify excel表格分类
 type ExcelClassify struct {
 	ExcelClassifyId   int       `orm:"column(excel_classify_id);pk"`
+	Source            int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
 	ExcelClassifyName string    `description:"分类名称"`
 	ParentId          int       `description:"父级id"`
 	SysUserId         int       `description:"创建人id"`
@@ -25,14 +26,19 @@ 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
 }
 
 // GetExcelClassifyCount 获取同级分类下存在同名分类的数量
-func GetExcelClassifyCount(ExcelClassifyName string, parentId int) (count int, err error) {
+func GetExcelClassifyCount(ExcelClassifyName string, parentId, source int) (count int, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := `SELECT COUNT(1) AS count FROM excel_classify WHERE parent_id=? AND excel_classify_name=? AND is_delete=0 `
-	err = o.Raw(sql, parentId, ExcelClassifyName).QueryRow(&count)
+	sql := `SELECT COUNT(1) AS count FROM excel_classify WHERE parent_id=? AND source = ? AND excel_classify_name=? AND is_delete=0 `
+	err = o.Raw(sql, parentId, source, ExcelClassifyName).QueryRow(&count)
 	return
 }
 
@@ -43,10 +49,10 @@ func GetExcelClassifyById(classifyId int) (item *ExcelClassify, err error) {
 	return
 }
 
-func GetExcelClassifyByParentId(parentId int) (items []*ExcelClassifyItems, err error) {
+func GetExcelClassifyByParentId(parentId, source int) (items []*ExcelClassifyItems, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM excel_classify WHERE parent_id=? AND is_delete=0 order by sort asc,excel_classify_id asc`
-	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	sql := ` SELECT * FROM excel_classify WHERE parent_id=? AND source = ? AND is_delete=0 order by sort asc,excel_classify_id asc`
+	_, err = o.Raw(sql, parentId, source).QueryRows(&items)
 	return
 }
 

+ 1 - 1
models/data_manage/excel_draft.go → models/data_manage/excel/excel_draft.go

@@ -1,4 +1,4 @@
-package data_manage
+package excel
 
 import (
 	"github.com/beego/beego/v2/client/orm"

+ 95 - 0
models/data_manage/excel/excel_edb_mapping.go

@@ -0,0 +1,95 @@
+package excel
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ExcelEdbMapping excel与指标的关系表
+type ExcelEdbMapping struct {
+	ExcelEdbMappingId int       `orm:"column(excel_edb_mapping_id);pk"`
+	ExcelInfoId       int       `description:"excel的id"`
+	Source            int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
+	EdbInfoId         int       `description:"计算指标id"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+}
+
+// AddExcelEdbMappingMulti 批量添加excel与指标的关系
+func AddExcelEdbMappingMulti(items []*ExcelEdbMapping) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+// Add 添加excel与指标的关系
+func (e *ExcelEdbMapping) Add() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Insert(e)
+	return
+}
+
+// GetExcelEdbMappingByEdbInfoId 根据指标id获取配置关系
+func GetExcelEdbMappingByEdbInfoId(edbInfoId int) (item *ExcelEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM excel_edb_mapping WHERE 1=1 AND edb_info_id = ? `
+
+	err = o.Raw(sql, edbInfoId).QueryRow(&item)
+	return
+}
+
+// GetExcelEdbMappingByExcelInfoId 根据excel的id获取配置关系
+func GetExcelEdbMappingByExcelInfoId(excelInfoId int) (items []*ExcelEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM excel_edb_mapping WHERE 1=1 AND excel_info_id = ? `
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&items)
+
+	return
+}
+
+type ExcelEdbMappingItem struct {
+	EdbInfoId        int    `description:"指标id"`
+	UniqueCode       string `description:"唯一编码"`
+	EdbName          string `description:"指标名称"`
+	ClassifyId       int    `description:"分类id"`
+	Frequency        string `description:"频度"`
+	Unit             string `description:"单位"`
+	CalculateFormula string `json:"-"`
+	DateSequenceStr  string `description:"日期序列公式"`
+	DataSequenceStr  string `description:"数据序列公式"`
+}
+
+// CalculateFormula 计算公式
+type CalculateFormula struct {
+	DateSequenceStr string `json:"DateSequenceStr"`
+	DataSequenceStr string `json:"DataSequenceStr"`
+}
+
+// GetAllExcelEdbMappingItemByExcelInfoId 根据品种id获取所有的指标结果集
+func GetAllExcelEdbMappingItemByExcelInfoId(excelInfoId int) (items []*ExcelEdbMappingItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT a.edb_info_id,a.unique_code,a.edb_name,a.classify_id,a.frequency,a.unit,calculate_formula FROM edb_info AS a 
+         JOIN excel_edb_mapping AS b ON a.edb_info_id=b.edb_info_id 
+         WHERE b.excel_info_id = ? ORDER BY b.excel_edb_mapping_id ASC `
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&items)
+	return
+}
+
+// GetNoCustomAnalysisExcelEdbMappingCount 根据指标id获取非自定义分析的关联关系
+func GetNoCustomAnalysisExcelEdbMappingCount(edbInfoId int) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count FROM excel_edb_mapping a 
+                          join excel_info b on a.excel_info_id=b.excel_info_id
+                          WHERE edb_info_id=? AND a.source != 4 AND b.is_delete = 0`
+	err = o.Raw(sql, edbInfoId).QueryRow(&count)
+	return
+}
+
+// GetAllExcelEdbMappingByExcelInfoId 根据品种id获取所有的指标
+func GetAllExcelEdbMappingByExcelInfoId(excelInfoId int) (items []*ExcelEdbMapping, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT b.* FROM  excel_edb_mapping a
+         WHERE a.excel_info_id = ? ORDER BY a.excel_edb_mapping_id ASC `
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&items)
+	return
+}

+ 247 - 28
models/data_manage/excel_info.go → models/data_manage/excel/excel_info.go

@@ -1,4 +1,4 @@
-package data_manage
+package excel
 
 import (
 	"fmt"
@@ -9,7 +9,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:"表格唯一编码"`
@@ -49,22 +49,72 @@ type MyExcelInfoList struct {
 }
 
 // AddExcelInfo 新增表格
-func AddExcelInfo(excelInfo *ExcelInfo) (err error) {
-	o := orm.NewOrmUsingDB("data")
+func AddExcelInfo(excelInfo *ExcelInfo, excelEdbMappingList []*ExcelEdbMapping) (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)
+
+	// excel与指标的关联关系
+	dataNum := len(excelEdbMappingList)
+	if dataNum > 0 {
+		for k, v := range excelEdbMappingList {
+			v.ExcelInfoId = excelInfo.ExcelInfoId
+			excelEdbMappingList[k] = v
+		}
+		_, err = o.InsertMulti(dataNum, excelEdbMappingList)
+	}
+
 	return
 }
 
 // EditExcelInfo 编辑表格
-func EditExcelInfo(excelInfo *ExcelInfo, updateExcelInfoParams []string) (err error) {
-	o := orm.NewOrmUsingDB("data")
+func EditExcelInfo(excelInfo *ExcelInfo, updateExcelInfoParams []string, excelEdbMappingList []*ExcelEdbMapping) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
 	// ETA表格信息变更
 	_, err = o.Update(excelInfo, updateExcelInfoParams...)
+	if err != nil {
+		return
+	}
+
+	// 删除关系表
+	sql := `DELETE FROM excel_edb_mapping WHERE excel_info_id=? `
+	_, err = o.Raw(sql, excelInfo.ExcelInfoId).Exec()
+
+	// excel与指标的关联关系
+	dataNum := len(excelEdbMappingList)
+	if dataNum > 0 {
+		for k, v := range excelEdbMappingList {
+			v.ExcelInfoId = excelInfo.ExcelInfoId
+			excelEdbMappingList[k] = v
+		}
+		_, err = o.InsertMulti(dataNum, excelEdbMappingList)
+	}
+
 	return
 }
 
@@ -79,12 +129,28 @@ func GetExcelInfoAll() (items []*ExcelClassifyItems, err error) {
 }
 
 // GetNoContentExcelInfoAll 获取不含content的表格列表 用于分类展示
-func GetNoContentExcelInfoAll() (items []*ExcelClassifyItems, err error) {
+func GetNoContentExcelInfoAll(source, userId 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 = ?  `
+
+	pars := []interface{}{source}
+
+	if userId > 0 {
+		sql += ` AND sys_user_id = ? `
+		pars = append(pars, userId)
+	}
+	sql += `  ORDER BY sort asc,create_time desc `
+	_, err = o.Raw(sql, pars...).QueryRows(&items)
+	return
+}
+
+// GetAllExcelInfoBySource 根据来源获取包含content的表格列表
+func GetAllExcelInfoBySource(source int) (items []*ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info where is_delete=0  AND source = ?  ORDER BY sort asc,create_time desc `
+	_, err = o.Raw(sql, source).QueryRows(&items)
 	return
 }
 
@@ -136,14 +202,15 @@ func GetNextExcelInfoByCondition(condition string, pars []interface{}) (item *Ex
 }
 
 // GetNextExcelInfo 根据分类id获取下一个excel表格
-func GetNextExcelInfo(classifyId, classifySort int) (item *ExcelInfo, err error) {
+func GetNextExcelInfo(classifyId, classifySort, source int) (item *ExcelInfo, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT b.* FROM excel_classify AS a
 			INNER JOIN excel_info AS b ON a.excel_classify_id=b.excel_classify_id
 			WHERE (a.sort>? OR (a.sort=? and a.excel_classify_id>?) ) AND a.is_delete=0 AND b.is_delete=0
+			AND a.source = ? AND b.source = ? 
 			ORDER BY a.sort ASC,b.sort asc,b.create_time desc
 			LIMIT 1 `
-	err = o.Raw(sql, classifySort, classifySort, classifyId).QueryRow(&item)
+	err = o.Raw(sql, classifySort, classifySort, classifyId, source, source).QueryRow(&item)
 	return
 }
 
@@ -180,10 +247,11 @@ func GetFirstExcelInfoByClassifyId(classifyId int) (item *ExcelInfo, err error)
 // UpdateExcelInfoSortByClassifyId 根据表格id更新排序
 func UpdateExcelInfoSortByClassifyId(classifyId, nowSort, prevExcelInfoId int, updateSort string) (err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` update excel_info set sort = ` + updateSort + ` WHERE excel_classify_id=? and sort > ? AND is_delete=0 `
+	sql := ` update excel_info set sort = ` + updateSort + ` WHERE excel_classify_id=? AND is_delete=0 AND ( sort > ? `
 	if prevExcelInfoId > 0 {
-		sql += ` or (excel_info_id > ` + fmt.Sprint(prevExcelInfoId) + ` and sort = ` + fmt.Sprint(nowSort) + `)`
+		sql += ` or (excel_info_id < ` + fmt.Sprint(prevExcelInfoId) + ` and sort = ` + fmt.Sprint(nowSort) + `)`
 	}
+	sql += `)`
 	_, err = o.Raw(sql, classifyId, nowSort).Exec()
 	return
 }
@@ -252,24 +320,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
 }
@@ -281,3 +335,168 @@ 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
+}
+
+// AddExcelInfoAndSheet 新增excel
+func AddExcelInfoAndSheet(excelInfo *ExcelInfo, sheetParamsList []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 := &ExcelSheet{
+			ExcelSheetId: 0,
+			ExcelInfoId:  excelInfo.ExcelInfoId,
+			SheetName:    sheetInfo.SheetName,
+			PageNum:      dataNum,
+			Index:        sheetInfo.Index,
+			Sort:         sheetInfo.Sort,
+			Config:       sheetInfo.Config,
+			CalcChain:    sheetInfo.CalcChain,
+			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
+}
+
+// SaveExcelInfoAndSheet 编辑保存
+func SaveExcelInfoAndSheet(excelInfo *ExcelInfo, updateExcelInfoParam []string, sheetParamsList []AddExcelSheetParams) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 表格信息入库
+	_, err = o.Update(excelInfo, updateExcelInfoParam...)
+	if err != nil {
+		return
+	}
+
+	// 先删除历史的sheet信息
+	sql := `DELETE FROM excel_sheet WHERE excel_info_id = ?`
+	_, err = o.Raw(sql, excelInfo.ExcelInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 再删除历史sheet中的cell data信息
+	sql = `DELETE FROM excel_sheet_data WHERE excel_info_id = ?`
+	_, err = o.Raw(sql, excelInfo.ExcelInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// sheet信息入库
+	for _, sheetInfo := range sheetParamsList {
+		dataNum := len(sheetInfo.DataList)
+
+		//sheet信息入库
+		excelSheetInfo := &ExcelSheet{
+			ExcelSheetId: 0,
+			ExcelInfoId:  excelInfo.ExcelInfoId,
+			SheetName:    sheetInfo.SheetName,
+			PageNum:      dataNum,
+			Index:        sheetInfo.Index,
+			Sort:         sheetInfo.Sort,
+			Config:       sheetInfo.Config,
+			CalcChain:    sheetInfo.CalcChain,
+			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
+}

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

@@ -0,0 +1,98 @@
+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:"总页码数"`
+	Index        string    `description:"excel数据中的index"`
+	Sort         int       `description:"排序"`
+	Config       string    `description:"配置信息"`
+	CalcChain    string    `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" json:"-"`
+	ExcelInfoId  int             `description:"excel的id"  json:"-"`
+	SheetName    string          `description:"sheet名称"`
+	PageNum      int             `description:"数据总页码数"`
+	Index        string          `description:"excel数据中的index"`
+	Sort         int             `description:"排序"`
+	Config       string          `description:"sheet配置"`
+	CalcChain    string          `description:"计算公式"`
+	ModifyTime   time.Time       `description:"最近修改日期" json:"-"`
+	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
+}
+
+// GetAllNoConfigSheetItemList 根据excel_id获取所有的sheet详情
+func GetAllNoConfigSheetItemList(excelInfoId int) (item []*SheetItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT excel_sheet_id,excel_info_id,sheet_name,sort,page_num,create_time
+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名称"`
+	Index        string            `description:"excel数据中的index"`
+	Sort         int               `description:"排序"`
+	Config       string            `description:"配置信息"`
+	CalcChain    string            `description:"计算公式"`
+	DataList     []*ExcelSheetData `description:"excel的数据"`
+}

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

@@ -0,0 +1,63 @@
+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) (items []*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(&items)
+
+	return
+}
+
+// GetAllSheetDataListByExcelInfoId 根据表格id获取所有的sheet的所有数据详情
+func GetAllSheetDataListByExcelInfoId(excelInfoId int) (items []*ExcelSheetData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *
+FROM excel_sheet_data WHERE 1=1 AND excel_info_id = ? ORDER BY sort ASC `
+	_, err = o.Raw(sql, excelInfoId).QueryRows(&items)
+
+	return
+}

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

@@ -0,0 +1,45 @@
+package request
+
+// 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"`
+}
+
+type AddEdb struct {
+	ExcelInfoId     int      `description:"表格ID"`
+	DateSequenceStr string   `description:"日期序列"`
+	DateSequenceVal []string `description:"日期序列的值列表"`
+	DataSequenceStr string   `description:"数据序列"`
+	DataSequenceVal []string `description:"数据序列的值列表"`
+	EdbName         string   `description:"指标名称"`
+	ClassifyId      int      `description:"分类id"`
+	Frequency       string   `description:"频率"`
+	Unit            string   `description:"单位"`
+}
+
+type EditEdb struct {
+	ExcelInfoId     int      `description:"表格ID"`
+	EdbInfoId       int      `description:"指标ID"`
+	DateSequenceStr string   `description:"日期序列"`
+	DateSequenceVal []string `description:"日期序列的值列表"`
+	DataSequenceStr string   `description:"数据序列"`
+	DataSequenceVal []string `description:"数据序列的值列表"`
+	EdbName         string   `description:"指标名称"`
+	ClassifyId      int      `description:"分类id"`
+	Frequency       string   `description:"频率"`
+	Unit            string   `description:"单位"`
+}

+ 1 - 0
models/data_manage/request/excel_classify.go → models/data_manage/excel/request/excel_classify.go

@@ -5,6 +5,7 @@ type AddExcelClassifyReq struct {
 	ExcelClassifyName string `description:"分类名称"`
 	ParentId          int    `description:"父级id,第一级传0" json:"-"`
 	Level             int    `description:"层级,第一级传0,其余传上一级的层级" json:"-"`
+	Source            int    `description:"1:excel插件的表格,2:自定义表格,3:混合表格,默认:1"`
 }
 
 // EditExcelClassifyReq 修改excel分类请求

+ 1 - 0
models/data_manage/request/excel_info.go → models/data_manage/excel/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"`

+ 4 - 2
models/data_manage/response/excel_classify.go → models/data_manage/excel/response/excel_classify.go

@@ -1,9 +1,11 @@
 package response
 
-import "eta/eta_api/models/data_manage"
+import (
+	"eta/eta_api/models/data_manage/excel"
+)
 
 type ExcelClassifyListResp struct {
-	AllNodes []*data_manage.ExcelClassifyItems
+	AllNodes []*excel.ExcelClassifyItems
 }
 
 type ExcelClassifyDeleteCheckResp struct {

+ 12 - 10
models/data_manage/response/excel_info.go → models/data_manage/excel/response/excel_info.go

@@ -1,8 +1,8 @@
 package response
 
 import (
-	"eta/eta_api/models/data_manage"
-	"eta/eta_api/models/data_manage/request"
+	excel2 "eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/services/excel"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"time"
@@ -17,7 +17,7 @@ type AddExcelInfoResp struct {
 // ExcelListResp 表格列表返回数据
 type ExcelListResp struct {
 	Paging *paging.PagingItem
-	List   []*data_manage.MyExcelInfoList
+	List   []*excel2.MyExcelInfoList
 }
 
 // ExcelTableDetailResp  excel表格详情
@@ -43,8 +43,8 @@ type TableDataItem struct {
 
 // TableDetailResp  excel表格详情
 type TableDetailResp struct {
-	ExcelInfo data_manage.ExcelInfo `description:"表格基础信息"`
-	TableData request.TableDataReq  `description:"表格内容"`
+	ExcelInfo excel2.ExcelInfo     `description:"表格基础信息"`
+	TableData request.TableDataReq `description:"表格内容"`
 }
 
 // ExcelInfoDetail excel表格详情(前端使用)
@@ -70,9 +70,11 @@ type ExcelInfoDetail struct {
 
 // ExcelInfoDetailButton 操作按钮
 type ExcelInfoDetailButton struct {
-	RefreshButton  bool `description:"是否可编辑"`
-	CopyButton     bool `description:"是否可另存为"`
-	DownloadButton bool `description:"是否可下载"`
-	OpButton       bool `description:"是否可编辑"`
-	DeleteButton   bool `description:"是否可删除"`
+	RefreshButton    bool `description:"是否可刷新"`
+	CopyButton       bool `description:"是否可另存为"`
+	DownloadButton   bool `description:"是否可下载"`
+	OpButton         bool `description:"是否可编辑"`
+	DeleteButton     bool `description:"是否可删除"`
+	OpEdbButton      bool `description:"是否可生成指标"`
+	RefreshEdbButton bool `description:"是否可刷新指标"`
 }

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

@@ -0,0 +1,31 @@
+package response
+
+import (
+	"eta/eta_api/models/data_manage/excel"
+	"time"
+)
+
+// FindExcelInfoResp 根据名称获取excel的信息
+type FindExcelInfoResp struct {
+	IsFind    bool               `description:"是否存在同名文件"`
+	ExcelInfo FindExcelInfo      `description:"表格详情"`
+	SheetList []*excel.SheetItem `description:"sheet列表"`
+}
+
+// FindExcelInfo excel的数据详情
+type FindExcelInfo struct {
+	ExcelInfoId     int                   `orm:"column(excel_info_id);pk"`
+	Source          int                   `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	ExcelType       int                   `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName       string                `description:"表格名称"`
+	UniqueCode      string                `description:"表格唯一编码"`
+	ExcelClassifyId int                   `description:"表格分类id"`
+	SysUserId       int                   `description:"操作人id"`
+	SysUserRealName string                `description:"操作人真实姓名"`
+	ExcelImage      string                `description:"表格图片"`
+	FileUrl         string                `description:"表格下载地址"`
+	Sort            int                   `description:"排序字段,数字越小越排前面"`
+	ModifyTime      time.Time             `description:"最近修改日期"`
+	CreateTime      time.Time             `description:"创建日期"`
+	Button          ExcelInfoDetailButton `description:"操作权限"`
+}

+ 16 - 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"
@@ -140,6 +141,9 @@ func init() {
 	if utils.BusinessCode == utils.BusinessCodeSandbox {
 		initEtaTrial()
 	}
+
+	// 初始化EXCEL的表
+	initExcel()
 }
 
 // initSystem 系统表 数据表
@@ -260,9 +264,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),    //钢联化工
@@ -414,3 +415,15 @@ func initEtaTrial() {
 		new(eta_trial.QuestionnaireFillRecord), // 问卷填写记录表
 	)
 }
+
+// initExcel 初始化EXCEL
+func initExcel() {
+	orm.RegisterModel(
+		new(excel.ExcelClassify),   //ETA excel表格分类
+		new(excel.ExcelInfo),       //ETA excel表格
+		new(excel.ExcelDraft),      //ETA excel表格草稿
+		new(excel.ExcelSheet),      //ETA excel sheet
+		new(excel.ExcelSheetData),  //ETA excel sheet data
+		new(excel.ExcelEdbMapping), //ETA excel 与 指标 的关系表
+	)
+}

+ 288 - 207
routers/commentsRouter.go

@@ -178,6 +178,294 @@ 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: "AddEdb",
+            Router: `/edb/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: "EditEdb",
+            Router: `/edb/edit`,
+            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: "EdbList",
+            Router: `/edb/list`,
+            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: "EdbRefresh",
+            Router: `/edb/refresh`,
+            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: "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/excel:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"],
+        beego.ControllerComments{
+            Method: "AddExcelClassify",
+            Router: `/excel_classify/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"],
+        beego.ControllerComments{
+            Method: "DeleteExcelClassify",
+            Router: `/excel_classify/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"],
+        beego.ControllerComments{
+            Method: "DeleteExcelClassifyCheck",
+            Router: `/excel_classify/delete/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"],
+        beego.ControllerComments{
+            Method: "EditExcelClassify",
+            Router: `/excel_classify/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"],
+        beego.ControllerComments{
+            Method: "ExcelClassifyItems",
+            Router: `/excel_classify/items`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/excel_classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelClassifyController"],
+        beego.ControllerComments{
+            Method: "ExcelClassifyMove",
+            Router: `/excel_classify/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/excel_info/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Copy",
+            Router: `/excel_info/copy`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Delete",
+            Router: `/excel_info/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/excel_info/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "AddDraft",
+            Router: `/excel_info/draft/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/excel_info/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/excel_info/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/excel_info/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Calculate",
+            Router: `/excel_info/table/calculate`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Download",
+            Router: `/excel_info/table/download`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetFirstEdbData",
+            Router: `/excel_info/table/first_edb_data_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetFutureDateData",
+            Router: `/excel_info/table/future_date_list`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetHistoryDateData",
+            Router: `/excel_info/table/history_date_list`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetOtherEdbData",
+            Router: `/excel_info/table/other_edb_data_list`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "Refresh",
+            Router: `/excel_info/table/refresh`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetExcelTableData",
+            Router: `/excel_info/table_data`,
+            AllowHTTPMethods: []string{"get"},
+            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",
@@ -2716,213 +3004,6 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"],
-        beego.ControllerComments{
-            Method: "AddExcelClassify",
-            Router: `/excel_classify/add`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"],
-        beego.ControllerComments{
-            Method: "DeleteExcelClassify",
-            Router: `/excel_classify/delete`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"],
-        beego.ControllerComments{
-            Method: "DeleteExcelClassifyCheck",
-            Router: `/excel_classify/delete/check`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"],
-        beego.ControllerComments{
-            Method: "EditExcelClassify",
-            Router: `/excel_classify/edit`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"],
-        beego.ControllerComments{
-            Method: "ExcelClassifyItems",
-            Router: `/excel_classify/items`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"],
-        beego.ControllerComments{
-            Method: "List",
-            Router: `/excel_classify/list`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelClassifyController"],
-        beego.ControllerComments{
-            Method: "ExcelClassifyMove",
-            Router: `/excel_classify/move`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Add",
-            Router: `/excel_info/add`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Copy",
-            Router: `/excel_info/copy`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Delete",
-            Router: `/excel_info/delete`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Detail",
-            Router: `/excel_info/detail`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "AddDraft",
-            Router: `/excel_info/draft/add`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Edit",
-            Router: `/excel_info/edit`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "List",
-            Router: `/excel_info/list`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Move",
-            Router: `/excel_info/move`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Calculate",
-            Router: `/excel_info/table/calculate`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Download",
-            Router: `/excel_info/table/download`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "GetFirstEdbData",
-            Router: `/excel_info/table/first_edb_data_list`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "GetFutureDateData",
-            Router: `/excel_info/table/future_date_list`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "GetHistoryDateData",
-            Router: `/excel_info/table/history_date_list`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "GetOtherEdbData",
-            Router: `/excel_info/table/other_edb_data_list`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "Refresh",
-            Router: `/excel_info/table/refresh`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ExcelInfoController"],
-        beego.ControllerComments{
-            Method: "GetExcelTableData",
-            Router: `/excel_info/table_data`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualController"],
         beego.ControllerComments{
             Method: "ClassifyList",

+ 8 - 2
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"
@@ -149,8 +150,8 @@ func init() {
 				&data_manage.ChartInfoController{},
 				&data_manage.ManualController{},
 				&data_manage.BaseFromChangesVisitorsCovidController{},
-				&data_manage.ExcelClassifyController{},
-				&data_manage.ExcelInfoController{},
+				&excel.ExcelClassifyController{},
+				&excel.ExcelInfoController{},
 				&data_manage.PredictEdbClassifyController{},
 				&data_manage.PredictEdbInfoController{},
 				&data_manage.BaseFromNationalStatisticsController{},
@@ -266,6 +267,11 @@ func init() {
 				&trade_analysis.TradeAnalysisController{},
 			),
 		),
+		web.NSNamespace("/custom_analysis",
+			web.NSInclude(
+				&excel.CustomAnalysisController{},
+			),
+		),
 		web.NSNamespace("/out_link",
 			web.NSInclude(
 				&controllers.OutLinkController{},

+ 10 - 0
services/data/base_edb_lib.go

@@ -287,6 +287,16 @@ func SaveAdjustEdbInfo(param string) (resp *models.BaseResponse, err error) {
 	return
 }
 
+// ResetCustomAnalysisData 重置自定义表格的数据
+func ResetCustomAnalysisData(reqStr string) (resp *AddPredictEdbDataResponse, err error) {
+	_, resultByte, err := postAddEdbData(reqStr, "calculate/custom_analysis/reset")
+	err = json.Unmarshal(resultByte, &resp)
+	if err != nil {
+		return
+	}
+	return
+}
+
 // CalculateComputeCorrelationResp 拟合残差计算相关性的值返回
 type CalculateComputeCorrelationResp struct {
 	Ret         int

+ 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"
 )

+ 15 - 0
services/data/edb_classify.go

@@ -4,6 +4,7 @@ import (
 	"errors"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/excel"
 	"eta/eta_api/models/system"
 	"eta/eta_api/utils"
 	"fmt"
@@ -566,6 +567,20 @@ func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, reque
 			}
 		}
 
+		// 判断指标是否用作表格引用
+		{
+			calculateCount, tmpErr := excel.GetNoCustomAnalysisExcelEdbMappingCount(edbInfoId)
+			if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+				errMsg = "删除失败"
+				err = errors.New("当前指标已添加到表格,GetNoCustomAnalysisExcelEdbMappingCount Err:" + tmpErr.Error())
+				return
+			}
+			if calculateCount > 0 {
+				errMsg = "当前指标已添加到表格,不可删除"
+				return
+			}
+		}
+
 		//真实删除
 		tmpErr = data_manage.DeleteEdbInfoAndData(edbInfo.EdbInfoId, edbInfo.Source)
 		if tmpErr != nil {

+ 5 - 0
services/data/edb_info_calculate.go

@@ -685,6 +685,11 @@ func handleDataByLinearRegression(edbInfoDataList []*data_manage.EdbDataList, ha
 	return
 }
 
+// HandleDataByLinearRegression 插值法补充数据(线性方程式)
+func HandleDataByLinearRegression(edbInfoDataList []*data_manage.EdbDataList, handleDataMap map[string]float64) (err error) {
+	return handleDataByLinearRegression(edbInfoDataList, handleDataMap)
+}
+
 // CallCalculateComputeCorrelation 调用计算拟合残差的相关系数
 func CallCalculateComputeCorrelation(data *data_manage.EdbInfoCalculateBatchSaveReqByEdbLib) (val string, err error, errMsg string) {
 	errMsg = "计算失败"

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

@@ -0,0 +1,426 @@
+package excel
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/models/data_manage/excel/request"
+	"eta/eta_api/models/system"
+	"eta/eta_api/utils"
+	"strconv"
+	"time"
+)
+
+var cellSplitNum = 10000 // 基础分割单元格数
+
+// AddCustomAnalysisTable 添加自定义分析表格
+func AddCustomAnalysisTable(excelName, content, excelImage string, excelClassifyId int, sysUser *system.Admin) (excelInfo *excel.ExcelInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	contentByte := []byte(content)
+
+	var luckySheetList []LuckySheet
+
+	err = json.Unmarshal(contentByte, &luckySheetList)
+	if err != nil {
+		return
+	}
+
+	// sheet内容为空
+	if len(luckySheetList) <= 0 {
+		errMsg = "sheet内容为空"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	excelClassify, err := excel.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 := excel.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 = &excel.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)
+
+	// sheet处理
+	sheetNameMap := make(map[string]string)
+	for k, sheetInfo := range luckySheetList {
+		sheetName := utils.TrimLRStr(sheetInfo.Name)
+		_, ok := sheetNameMap[sheetName]
+		if ok {
+			errMsg = "excel表中存在同名sheet"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+
+		sheetConf, tmpErr := json.Marshal(sheetInfo.Config)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 计算公式
+		sheetCalcChain, tmpErr := json.Marshal(sheetInfo.CalcChain)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		addSheetItem := excel.AddExcelSheetParams{
+			ExcelSheetId: 0,
+			ExcelInfoId:  0,
+			SheetName:    sheetName,
+			Index:        sheetInfo.Index,
+			Sort:         k,
+			Config:       string(sheetConf),
+			CalcChain:    string(sheetCalcChain),
+		}
+
+		lenCellData := len(sheetInfo.CellData)
+
+		splitLen := lenCellData / cellSplitNum
+		residue := lenCellData % cellSplitNum
+		if residue > 0 {
+			splitLen += 1
+		}
+
+		sheetDataList := make([]*excel.ExcelSheetData, 0)
+		for i := 0; i < splitLen; i++ {
+
+			startRow := i * cellSplitNum
+			endRow := (i + 1) * cellSplitNum
+			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 + 1,
+				Data:         string(tmpDataByte),
+				ModifyTime:   time.Now(),
+				CreateTime:   time.Now(),
+			})
+		}
+		addSheetItem.DataList = sheetDataList
+
+		addSheetList = append(addSheetList, addSheetItem)
+	}
+
+	err = excel.AddExcelInfoAndSheet(excelInfo, addSheetList)
+
+	return
+}
+
+// SaveCustomAnalysisTable 编辑自定义分析表格
+func SaveCustomAnalysisTable(excelInfo *excel.ExcelInfo, excelName, content, excelImage string, excelClassifyId int, sheetOpList []request.SheetOp) (err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	contentByte := []byte(content)
+
+	var luckySheetList []LuckySheet
+
+	err = json.Unmarshal(contentByte, &luckySheetList)
+	if err != nil {
+		return
+	}
+
+	// sheet内容为空
+	if len(luckySheetList) <= 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 := excel.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 := excel.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
+	// 如果分类不传入的话,那么分类不变更
+	if excelClassifyId <= 0 {
+		excelInfo.ExcelClassifyId = excelClassifyId
+	}
+	// 如果缩略图不传入的话,那么缩略图不变更
+	if excelImage != `` {
+		excelInfo.ExcelImage = excelImage
+	}
+	excelInfo.ModifyTime = time.Now()
+	updateExcelInfoParam := []string{"ExcelName", "ExcelClassifyId", "ExcelImage", "ModifyTime"}
+
+	addSheetList := make([]excel.AddExcelSheetParams, 0)
+
+	// sheet处理
+	sheetNameMap := make(map[string]string)
+	for k, sheetInfo := range luckySheetList {
+		sheetName := utils.TrimLRStr(sheetInfo.Name)
+		_, ok := sheetNameMap[sheetName]
+		if ok {
+			errMsg = "excel表中存在同名sheet"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+
+		sheetConf, tmpErr := json.Marshal(sheetInfo.Config)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 计算公式
+		sheetCalcChain, tmpErr := json.Marshal(sheetInfo.CalcChain)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		addSheetItem := excel.AddExcelSheetParams{
+			ExcelSheetId: 0,
+			ExcelInfoId:  excelInfo.ExcelInfoId,
+			SheetName:    sheetName,
+			Index:        sheetInfo.Index,
+			Sort:         k,
+			Config:       string(sheetConf),
+			CalcChain:    string(sheetCalcChain),
+		}
+
+		lenCellData := len(sheetInfo.CellData)
+
+		splitLen := lenCellData / cellSplitNum
+		residue := lenCellData % cellSplitNum
+		if residue > 0 {
+			splitLen += 1
+		}
+
+		sheetDataList := make([]*excel.ExcelSheetData, 0)
+		for i := 0; i < splitLen; i++ {
+
+			startRow := i * cellSplitNum
+			endRow := (i + 1) * cellSplitNum
+			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:  excelInfo.ExcelInfoId,
+				ExcelSheetId: 0,
+				Sort:         i + 1,
+				Data:         string(tmpDataByte),
+				ModifyTime:   time.Now(),
+				CreateTime:   time.Now(),
+			})
+		}
+		addSheetItem.DataList = sheetDataList
+
+		addSheetList = append(addSheetList, addSheetItem)
+	}
+
+	err = excel.SaveExcelInfoAndSheet(excelInfo, updateExcelInfoParam, addSheetList)
+
+	return
+}
+
+type LuckySheet 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"`
+	Config           interface{}
+	Index            string               `json:"index"`
+	Order            int                  `json:"order"`
+	ZoomRatio        int                  `json:"zoomRatio"`
+	ShowGridLines    string               `json:"showGridLines"`
+	DefaultColWidth  int                  `json:"defaultColWidth"`
+	DefaultRowHeight int                  `json:"defaultRowHeight"`
+	CellData         []LuckySheetCellData `json:"celldata"`
+	CalcChain        []interface{}        `json:"calcChain"`
+	//DataVerification struct {
+	//} `json:"dataVerification"`
+	//Hyperlink struct {
+	//} `json:"hyperlink"`
+	//Hide int `json:"hide"`
+}
+
+// LuckySheetCellData 单元格数据
+type LuckySheetCellData struct {
+	R int         `json:"r"`
+	C int         `json:"c"`
+	V interface{} `json:"v,omitempty"`
+}

+ 543 - 0
services/data/excel/custom_analysis_edb.go

@@ -0,0 +1,543 @@
+package excel
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/services/data"
+	excelServices "eta/eta_api/services/excel"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/araddon/dateparse"
+	"github.com/shopspring/decimal"
+	"github.com/xuri/excelize/v2"
+	"strings"
+)
+
+// GetCustomAnalysisExcelData 获取自定义分析的表格data数据
+func GetCustomAnalysisExcelData(excelInfo *excel.ExcelInfo) (luckySheet excelServices.LuckySheet, err error, errMsg string) {
+	// 查找当前excel的sheet列表
+	sheetList, err := excel.GetAllSheetList(excelInfo.ExcelInfoId)
+	if err != nil {
+		errMsg = "保存失败"
+		err = errors.New("查找当前excel的sheet列表失败,Err:" + err.Error())
+		return
+	}
+	currSheetMap := make(map[string]string)
+	for _, sheet := range sheetList {
+		currSheetMap[sheet.SheetName] = sheet.SheetName
+	}
+
+	sheetCellDataMapList := make(map[int][]excelServices.LuckySheetCellData)
+
+	// 通过excel的id获取各个sheet的单元格数据map
+	{
+		dataList, tmpErr := excel.GetAllSheetDataListByExcelInfoId(excelInfo.ExcelInfoId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		for _, cellData := range dataList {
+			sheetDataList, ok := sheetCellDataMapList[cellData.ExcelSheetId]
+			if !ok {
+				sheetDataList = make([]excelServices.LuckySheetCellData, 0)
+			}
+
+			tmpSheetDataList := make([]excelServices.LuckySheetCellData, 0)
+			err = json.Unmarshal([]byte(cellData.Data), &tmpSheetDataList)
+			if err != nil {
+				return
+			}
+			sheetCellDataMapList[cellData.ExcelSheetId] = append(sheetDataList, tmpSheetDataList...)
+		}
+	}
+
+	// 转成luckySheet的数据格式
+	luckySheet = excelServices.LuckySheet{
+		SheetList: make([]excelServices.LuckySheetData, 0),
+	}
+
+	for _, sheet := range sheetList {
+		var luckySheetDataConfig excelServices.LuckySheetDataConfig
+		err = json.Unmarshal([]byte(sheet.Config), &luckySheetDataConfig)
+		if err != nil {
+			return
+		}
+		tmpLuckySheetDataInfo := excelServices.LuckySheetData{
+			Name:     sheet.SheetName,
+			Index:    sheet.Sort,
+			CellData: sheetCellDataMapList[sheet.ExcelSheetId],
+			Config:   luckySheetDataConfig,
+		}
+		luckySheet.SheetList = append(luckySheet.SheetList, tmpLuckySheetDataInfo)
+	}
+
+	return
+}
+
+// GenerateExcelCustomAnalysisExcel 根据自定义分析的表格data数据生成excel
+func GenerateExcelCustomAnalysisExcel(excelInfo *excel.ExcelInfo) (downloadFilePath string, err error, errMsg string) {
+	luckySheet, err, errMsg := GetCustomAnalysisExcelData(excelInfo)
+	if err != nil {
+		return
+	}
+
+	downloadFilePath, err = luckySheet.ToExcel()
+
+	return
+}
+
+// HandleEdbSequenceVal 处理日期集和数据集(获取可用的日期、数据集)
+func HandleEdbSequenceVal(dateSequenceVal, dataSequenceVal []string) (newDateList []string, newDataList []float64, err error, errMsg string) {
+	newDateList = make([]string, 0)
+	newDataList = make([]float64, 0)
+
+	// 数据集
+	type dataStruct struct {
+		Value float64
+		Ok    bool
+	}
+	dataList := make([]dataStruct, 0)
+	{
+		var startData bool
+		for _, v := range dataSequenceVal {
+			// 如果没有数据集,那么就过滤
+			if v == `` {
+				// 如果开始插入数据了,那么就需要插入不存在值
+				if startData {
+					dataList = append(dataList, dataStruct{
+						Value: 0,
+						Ok:    false,
+					})
+				}
+				continue
+			}
+
+			v = strings.Replace(v, ",", "", -1)
+			v = strings.Replace(v, ",", "", -1)
+			tmpValDec, tmpErr := decimal.NewFromString(v)
+			if tmpErr != nil {
+				if startData {
+					dataList = append(dataList, dataStruct{
+						Value: 0,
+						Ok:    false,
+					})
+				}
+				continue
+			}
+			startData = true
+
+			tmpVal, _ := tmpValDec.Float64()
+			dataList = append(dataList, dataStruct{
+				Value: tmpVal,
+				Ok:    true,
+			})
+		}
+	}
+
+	// 日期集
+	dateList := make([]string, 0)
+	{
+		var startData bool
+		for _, v := range dateSequenceVal {
+			// 如果没有数据集,那么就过滤
+			if v == `` {
+				// 如果开始插入数据了,那么就需要插入不存在值
+				if startData {
+					dateList = append(dateList, "")
+				}
+				continue
+			}
+
+			t1, tmpErr := dateparse.ParseAny(v)
+			if tmpErr != nil {
+				if startData {
+					dateList = append(dateList, "")
+				}
+				continue
+			}
+			startData = true
+
+			dateList = append(dateList, t1.Format(utils.FormatDate))
+		}
+	}
+
+	lenData := len(dataList)
+	lenDate := len(dateList)
+
+	// 最小个数
+	num := lenDate
+	if num > lenData {
+		num = lenData
+	}
+
+	for i := 0; i < num; i++ {
+		date := dateList[i]
+		data := dataList[i]
+
+		// 日期为空、数据为空
+		if !data.Ok || date == `` {
+			continue
+		}
+
+		newDateList = append(newDateList, date)
+		newDataList = append(newDataList, data.Value)
+	}
+
+	return
+}
+
+// Refresh  刷新表格关联的指标信息
+func Refresh(excelInfo *excel.ExcelInfo) (err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	list, err := excel.GetAllExcelEdbMappingItemByExcelInfoId(excelInfo.ExcelInfoId)
+	if err != nil {
+		errMsg = "获取失败"
+		return
+	}
+
+	// 没有关联指标,那么就退出吧
+	if len(list) <= 0 {
+		return
+	}
+
+	for k, v := range list {
+		var tmpCalculateFormula excel.CalculateFormula
+		err = json.Unmarshal([]byte(v.CalculateFormula), &tmpCalculateFormula)
+		if err != nil {
+			errMsg = "获取失败"
+			err = errors.New("公式转换失败,Err:" + err.Error())
+			return
+		}
+		v.DateSequenceStr = tmpCalculateFormula.DateSequenceStr
+		v.DataSequenceStr = tmpCalculateFormula.DataSequenceStr
+		list[k] = v
+	}
+
+	luckySheet, err, errMsg := GetCustomAnalysisExcelData(excelInfo)
+	if err != nil {
+		return
+	}
+
+	// 获取excel表格数据
+	xlsxFile, err := luckySheet.GetExcelData()
+	if err != nil {
+		return
+	}
+
+	//fmt.Println(xlsxFile)
+
+	// ResetCustomAnalysisData 数据重置的结构体
+	type ResetCustomAnalysisData struct {
+		EdbInfoId int
+		DateList  []string
+		DataList  []float64
+	}
+
+	for _, v := range list {
+		dateList := make([]string, 0)
+		dataList := make([]string, 0)
+
+		// 日期序列
+		{
+			sheetName, startColumnName, endColumnName, startNum, endNum, isAll, isRow, isColumn, tmpErr := GetSheetStr(v.DateSequenceStr)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+
+			// 查找sheet页
+			sheetInfo, ok := xlsxFile.Sheet[sheetName]
+			if !ok {
+				errMsg = "找不到" + sheetName
+				err = errors.New(errMsg)
+				return
+			}
+
+			// 选择行的数据
+			if isRow {
+				// 开始列名、结束列
+				var startColumn, endColumn int
+				if isAll {
+					// 结束列(其实也就是整列的个数)
+					endColumn = len(sheetInfo.Cols) - 1
+				} else {
+					//startNum = startNum - 1
+					//endNum = endNum - 1
+
+					tmpStartColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+					if tmpErr != nil {
+						errMsg = "列名异常:" + startColumnName
+						err = errors.New(errMsg)
+						return
+					}
+
+					tmpEndColumn, tmpErr := excelize.ColumnNameToNumber(endColumnName)
+					if tmpErr != nil {
+						errMsg = "列名异常:" + endColumnName
+						err = errors.New(errMsg)
+						return
+					}
+					startColumn = tmpStartColumn - 1
+					endColumn = tmpEndColumn - 1
+				}
+
+				for currColumn := startColumn; currColumn <= endColumn; currColumn++ {
+					currCell := sheetInfo.Cell(startNum, currColumn)
+					if currCell == nil {
+						errMsg = fmt.Sprintf("第%d列,第%d行数据异常", startColumn, startNum)
+						err = errors.New(errMsg)
+						return
+					}
+					dateList = append(dateList, currCell.Value)
+				}
+
+			} else if isColumn { // 选择列的数据
+				if isAll {
+					// 结束行(其实也就是整个sheet有多少行)
+					endNum = len(sheetInfo.Rows) - 1
+				} else {
+					startNum = startNum - 1
+					endNum = endNum - 1
+				}
+
+				startColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+				if tmpErr != nil {
+					errMsg = "列名异常:" + startColumnName
+					err = errors.New(errMsg)
+					return
+				}
+				startColumn = startColumn - 1
+
+				for currRow := startNum; currRow <= endNum; currRow++ {
+					currCell := sheetInfo.Cell(currRow, startColumn)
+					if currCell == nil {
+						errMsg = fmt.Sprintf("第%d列,第%d行数据异常", startColumn, startNum)
+						err = errors.New(errMsg)
+						return
+					}
+					dateList = append(dateList, currCell.Value)
+				}
+			}
+
+		}
+
+		// 数据序列
+		{
+			sheetName, startColumnName, endColumnName, startNum, endNum, isAll, isRow, isColumn, tmpErr := GetSheetStr(v.DataSequenceStr)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+
+			// 查找sheet页
+			sheetInfo, ok := xlsxFile.Sheet[sheetName]
+			if !ok {
+				errMsg = "找不到" + sheetName
+				err = errors.New(errMsg)
+				return
+			}
+
+			// 选择行的数据
+			if isRow {
+				// 开始列名、结束列
+				var startColumn, endColumn int
+				if isAll {
+					// 结束列(其实也就是整列的个数)
+					endColumn = len(sheetInfo.Cols) - 1
+				} else {
+					//startNum = startNum - 1
+					//endNum = endNum - 1
+
+					tmpStartColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+					if tmpErr != nil {
+						errMsg = "列名异常:" + startColumnName
+						err = errors.New(errMsg)
+						return
+					}
+
+					tmpEndColumn, tmpErr := excelize.ColumnNameToNumber(endColumnName)
+					if tmpErr != nil {
+						errMsg = "列名异常:" + endColumnName
+						err = errors.New(errMsg)
+						return
+					}
+					startColumn = tmpStartColumn - 1
+					endColumn = tmpEndColumn - 1
+				}
+
+				for currColumn := startColumn; currColumn <= endColumn; currColumn++ {
+					currCell := sheetInfo.Cell(startNum, currColumn)
+					if currCell == nil {
+						errMsg = fmt.Sprintf("第%d列,第%d行数据异常", startColumn, startNum)
+						err = errors.New(errMsg)
+						return
+					}
+					dataList = append(dataList, currCell.Value)
+				}
+
+			} else if isColumn { // 选择列的数据
+				if isAll {
+					// 结束行(其实也就是整个sheet有多少行)
+					endNum = len(sheetInfo.Rows) - 1
+				} else {
+					startNum = startNum - 1
+					endNum = endNum - 1
+				}
+
+				startColumn, tmpErr := excelize.ColumnNameToNumber(startColumnName)
+				if tmpErr != nil {
+					errMsg = "列名异常:" + startColumnName
+					err = errors.New(errMsg)
+					return
+				}
+				startColumn = startColumn - 1
+
+				for currRow := startNum; currRow <= endNum; currRow++ {
+					currCell := sheetInfo.Cell(currRow, startColumn)
+					if currCell == nil {
+						errMsg = fmt.Sprintf("第%d列,第%d行数据异常", startColumn, startNum)
+						err = errors.New(errMsg)
+						return
+					}
+					dataList = append(dataList, currCell.Value)
+				}
+			}
+
+		}
+
+		//fmt.Println("日期序列结束")
+
+		// 将excel中的日期、数据系列处理
+		relDateList, relDataList, tmpErr, tmpErrMsg := HandleEdbSequenceVal(dateList, dataList)
+		if tmpErr != nil {
+			err = tmpErr
+			errMsg = tmpErrMsg
+			return
+		}
+		req2 := &ResetCustomAnalysisData{
+			EdbInfoId: v.EdbInfoId,
+			DateList:  relDateList,
+			DataList:  relDataList,
+		}
+
+		// 调用指标库去更新
+		reqJson, tmpErr := json.Marshal(req2)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		respItem, tmpErr := data.ResetCustomAnalysisData(string(reqJson))
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		if respItem.Ret != 200 {
+			errMsg = respItem.Msg
+			err = errors.New(respItem.ErrMsg)
+			return
+		}
+		//sheetInfo.Cell()
+	}
+
+	//xlsxFile.Sheet[]
+
+	return
+}
+
+// GetSheetStr
+// @return sheetName string 用户选择的sheet名称
+// @return startColumnName string 用户选择的开始列名称
+// @return endColumnName string 用户选择的结束列名称
+// @return startNum int 用户选择的开始列单元格位置
+// @return endNum int 用户选择的结束列单元格位置
+// @return isAll bool 是否选择整行/列数据
+// @return isRow bool 是否选择行数据
+// @return isColumn bool 是否选择列数据
+func GetSheetStr(sequenceStr string) (sheetName, startColumnName, endColumnName string, startNum, endNum int, isAll, isRow, isColumn bool, err error) {
+	// 找出sheetName
+	tmpList := strings.Split(sequenceStr, "!")
+	if len(tmpList) != 2 {
+		err = errors.New("错误的公式,查找sheet异常:" + sequenceStr)
+		return
+	}
+
+	sheetName = tmpList[0]
+
+	// 分离开始/结束单元格
+	tmpList = strings.Split(tmpList[1], ":")
+	if len(tmpList) != 2 {
+		err = errors.New("错误的公式,查找开始/结束单元格异常:" + sequenceStr)
+		return
+	}
+
+	startList := strings.Split(tmpList[0], "$")
+	endList := strings.Split(tmpList[1], "$")
+
+	lenList := len(startList)
+	if lenList != len(endList) {
+		err = errors.New("错误的公式,开始与结束单元格异常:" + sequenceStr)
+		return
+	}
+
+	if lenList != 3 && lenList != 2 {
+		err = errors.New("错误的公式:" + sequenceStr)
+		return
+	}
+
+	startColumnName = startList[1]
+	endColumnName = endList[1]
+
+	// 长度为2的话,那说明是整行或整列
+	if lenList == 2 {
+		isAll = true
+
+		startDeci, tmpErr1 := decimal.NewFromString(startList[1])
+		endDeci, tmpErr2 := decimal.NewFromString(endList[1])
+
+		if tmpErr1 == nil && tmpErr2 == nil {
+			isRow = true // 正常转换的话,那么就是整行
+			startNum = int(startDeci.IntPart())
+			endNum = int(endDeci.IntPart())
+			startColumnName = ``
+			endColumnName = ``
+
+			return
+		}
+
+		if tmpErr1 == nil || tmpErr2 == nil {
+			err = errors.New("错误的公式2:" + sequenceStr)
+			return
+		}
+
+		// 如果不能转成数字,那么就是整列
+		isColumn = true
+
+		return
+	}
+
+	// 确定行
+	startDeci, tmpErr1 := decimal.NewFromString(startList[2])
+	endDeci, tmpErr2 := decimal.NewFromString(endList[2])
+	if tmpErr1 != nil && tmpErr1 != tmpErr2 {
+		err = errors.New("错误的公式3:" + sequenceStr)
+		return
+	}
+
+	startNum = int(startDeci.IntPart())
+	endNum = int(endDeci.IntPart())
+
+	if startColumnName != endColumnName && startNum != endNum {
+		err = errors.New("选区不允许跨行或者跨列")
+	}
+
+	if startColumnName == endColumnName {
+		isColumn = true // 列数据
+	} else {
+		isRow = true // 行数据
+	}
+
+	return
+}

+ 21 - 11
services/data/excel_info.go → services/data/excel/excel_info.go

@@ -1,12 +1,14 @@
-package data
+package excel
 
 import (
 	"encoding/json"
 	"errors"
 	"eta/eta_api/models/data_manage"
-	"eta/eta_api/models/data_manage/request"
-	"eta/eta_api/models/data_manage/response"
+	"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/models/system"
+	"eta/eta_api/services/data"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/shopspring/decimal"
@@ -21,7 +23,7 @@ import (
 func GetExcelDetailInfoByExcelInfoId(excelInfoId int) (excelDetail response.ExcelInfoDetail, errMsg string, err error) {
 	errMsg = `获取失败`
 	//获取eta表格信息
-	excelInfo, err := data_manage.GetExcelInfoById(excelInfoId)
+	excelInfo, err := excel.GetExcelInfoById(excelInfoId)
 	if err != nil {
 		err = errors.New("获取ETA表格信息失败,Err:" + err.Error())
 		if err.Error() == utils.ErrNoRow() {
@@ -90,7 +92,7 @@ func GetExcelInfoOpButton(sysUser *system.Admin, belongUserId, source int) (butt
 	button.CopyButton = true
 	button.DownloadButton = true
 
-	if source == 1 {
+	if source == utils.EXCEL_DEFAULT {
 		button.OpButton = true
 	}
 
@@ -101,6 +103,14 @@ func GetExcelInfoOpButton(sysUser *system.Admin, belongUserId, source int) (butt
 		button.DeleteButton = true
 	}
 
+	// 自定义分析
+	if source == utils.CUSTOM_ANALYSIS_TABLE {
+		if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN || sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN || sysUser.AdminId == belongUserId {
+			button.OpEdbButton = true      // 生成、查看指标按钮
+			button.RefreshEdbButton = true // 刷新指标按钮
+		}
+	}
+
 	return
 }
 
@@ -111,7 +121,7 @@ func GetFirstEdbDataList(edbInfo *data_manage.EdbInfo, num int, manualDateList [
 	case 0:
 		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
 	case 1:
-		_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
+		_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
 	default:
 		err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
 	}
@@ -212,7 +222,7 @@ func GetOtherEdbDataList(edbInfo *data_manage.EdbInfo, dateList []string) (resul
 	case 0:
 		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
 	case 1:
-		_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
+		_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
 	default:
 		err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
 	}
@@ -257,7 +267,7 @@ func GetOtherEdbDataList(edbInfo *data_manage.EdbInfo, dateList []string) (resul
 
 	// 插值法处理
 	handleDataMap := make(map[string]float64)
-	err = handleDataByLinearRegression(baseDataList, handleDataMap)
+	err = data.HandleDataByLinearRegression(baseDataList, handleDataMap)
 	if err != nil {
 		return
 	}
@@ -306,7 +316,7 @@ func GetFirstHistoryEdbDataList(edbInfo *data_manage.EdbInfo, num int, endDate s
 	case 0:
 		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, endDate)
 	case 1:
-		_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, endDate, true)
+		_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, endDate, true)
 	default:
 		err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
 	}
@@ -489,7 +499,7 @@ func GetTableDataConfig(reqData request.TableDataReq) (tableDataConfig TableData
 		case 0:
 			firstDataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
 		case 1:
-			_, firstDataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
+			_, firstDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
 		default:
 			err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
 		}
@@ -1287,7 +1297,7 @@ func GetMixedTableCellData(config [][]request.MixedTableCellDataReq) (newMixedTa
 		case 0:
 			dataList, _ = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
 		case 1:
-			_, dataList, _, _, _, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
+			_, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
 		default:
 			err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
 		}

+ 268 - 0
services/data/excel/excel_op.go

@@ -0,0 +1,268 @@
+package excel
+
+import (
+	"errors"
+	excelModel "eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services"
+	"eta/eta_api/services/alarm_msg"
+	excel "eta/eta_api/services/excel"
+	"eta/eta_api/utils"
+	"fmt"
+	"os"
+	"strconv"
+	"time"
+)
+
+// Delete excel删除
+func Delete(excelInfo *excelModel.ExcelInfo, sysUser *system.Admin) (err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	// 操作权限校验
+	{
+		button := GetExcelInfoOpButton(sysUser, excelInfo.SysUserId, excelInfo.Source)
+		if !button.DeleteButton {
+			errMsg = "无操作权限"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+
+	// 自定义分析,需要做这个指标关联的校验
+	if excelInfo.Source == utils.CUSTOM_ANALYSIS_TABLE {
+		list, tmpErr := excelModel.GetExcelEdbMappingByExcelInfoId(excelInfo.ExcelInfoId)
+		if tmpErr != nil {
+			errMsg = `获取关联的指标信息失败`
+			err = tmpErr
+			return
+		}
+
+		if len(list) > 0 {
+			errMsg = "已关联指标,不可删除!"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+
+	// 标记删除
+	excelInfo.IsDelete = 1
+	excelInfo.ModifyTime = time.Now()
+	err = excelInfo.Update([]string{"IsDelete", "ModifyTime"})
+
+	return
+}
+
+// Copy 复制excel
+func Copy(oldExcelInfoId, excelClassifyId int, excelName string, sysUser *system.Admin) (excelInfo *excelModel.ExcelInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+
+	excelName = utils.TrimLRStr(excelName)
+
+	excelClassify, err := excelModel.GetExcelClassifyById(excelClassifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "分类不存在"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取分类信息失败"
+		return
+	}
+	if excelClassify == nil {
+		errMsg = "分类不存在"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	// 获取原ETA表格信息
+	oldExcelInfo, err := excelModel.GetExcelInfoById(oldExcelInfoId)
+	if err != nil {
+		errMsg = "获取ETA表格失败"
+		return
+	}
+
+	// 操作权限校验
+	{
+		button := GetExcelInfoOpButton(sysUser, oldExcelInfo.SysUserId, oldExcelInfo.Source)
+		if !button.CopyButton {
+			errMsg = "无操作权限"
+			err = errors.New(errMsg)
+			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 := excelModel.GetExcelInfoCountByCondition(condition, pars)
+		if tmpErr != nil {
+			errMsg = "判断表格名称是否存在失败"
+			err = tmpErr
+			return
+		}
+		if count > 0 {
+			errMsg = "表格名称已存在,请重新填写表格名称"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+	}
+
+	// 表格信息
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	excelInfo = &excelModel.ExcelInfo{
+		//ExcelInfoId:     0,
+		ExcelName:       excelName,
+		Source:          oldExcelInfo.Source,
+		ExcelType:       oldExcelInfo.ExcelType,
+		UniqueCode:      utils.MD5(utils.EXCEL_DATA_PREFIX + "_" + timestamp),
+		ExcelClassifyId: excelClassifyId,
+		SysUserId:       sysUser.AdminId,
+		SysUserRealName: sysUser.RealName,
+		Content:         oldExcelInfo.Content,
+		ExcelImage:      oldExcelInfo.ExcelImage,
+		FileUrl:         oldExcelInfo.FileUrl,
+		Sort:            0,
+		IsDelete:        0,
+		ModifyTime:      time.Now(),
+		CreateTime:      time.Now(),
+	}
+
+	// 如果不是自定义分析,那么直接加主表就好了
+	if excelInfo.Source != utils.CUSTOM_ANALYSIS_TABLE {
+
+		// 获取excel与指标的关系表
+		list, tmpErr := excelModel.GetAllExcelEdbMappingByExcelInfoId(excelInfo.ExcelInfoId)
+		if tmpErr != nil {
+			errMsg = "获取失败"
+			err = tmpErr
+			return
+		}
+		for k, v := range list {
+			v.ExcelEdbMappingId = 0
+			v.ExcelInfoId = 0
+			list[k] = v
+		}
+
+		err = excelModel.AddExcelInfo(excelInfo, list)
+		if err != nil {
+			errMsg = "保存失败"
+		}
+
+		return
+	}
+
+	// 自定义分析,需要有额外信息
+	addSheetList := make([]excelModel.AddExcelSheetParams, 0)
+
+	// 获取所有的sheet页
+	oldSheetItemList, err := excelModel.GetAllSheetList(oldExcelInfo.ExcelInfoId)
+	if err != nil {
+		errMsg = `获取sheet页失败`
+		return
+	}
+
+	// 获取所有的sheet页的sheet数据
+	sheetCellDataMapList := make(map[int][]*excelModel.ExcelSheetData)
+	{
+		dataList, tmpErr := excelModel.GetAllSheetDataListByExcelInfoId(oldExcelInfo.ExcelInfoId)
+		if tmpErr != nil {
+			errMsg = `获取sheet页的单元格数据失败`
+			err = tmpErr
+			return
+		}
+
+		for _, cellData := range dataList {
+			sheetDataList, ok := sheetCellDataMapList[cellData.ExcelSheetId]
+			if !ok {
+				sheetDataList = make([]*excelModel.ExcelSheetData, 0)
+			}
+			sheetCellDataMapList[cellData.ExcelSheetId] = append(sheetDataList, cellData)
+		}
+	}
+
+	// sheet处理
+	for _, sheetInfo := range oldSheetItemList {
+		addSheetItem := excelModel.AddExcelSheetParams{
+			ExcelSheetId: 0,
+			ExcelInfoId:  0,
+			SheetName:    sheetInfo.SheetName,
+			Sort:         sheetInfo.Sort,
+			Config:       sheetInfo.Config,
+			CalcChain:    sheetInfo.CalcChain,
+		}
+
+		sheetDataList, ok := sheetCellDataMapList[sheetInfo.ExcelSheetId]
+		if ok {
+			for i, sheetData := range sheetDataList {
+				sheetData.ExcelDataId = 0
+				sheetData.ExcelSheetId = 0
+				sheetData.ExcelInfoId = 0
+				sheetDataList[i] = sheetData
+			}
+		}
+
+		addSheetItem.DataList = sheetDataList
+
+		addSheetList = append(addSheetList, addSheetItem)
+	}
+
+	// 添加表格
+	err = excelModel.AddExcelInfoAndSheet(excelInfo, addSheetList)
+
+	return
+}
+
+// UpdateExcelInfoFileUrl 更新excel表格的下载地址
+func UpdateExcelInfoFileUrl(excelInfo *excelModel.ExcelInfo) {
+	var err error
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg(fmt.Sprintf("更新excel表格的下载地址失败,表格id:%d;表格名称:%s; ERR:%s", excelInfo.ExcelInfoId, excelInfo.ExcelName, err), 3)
+		}
+	}()
+	fileName := excelInfo.ExcelName + "_" + excelInfo.UniqueCode + ".xlsx"
+
+	var downloadFilePath string // excel文件下载地址
+
+	switch excelInfo.Source {
+	case utils.EXCEL_DEFAULT: // 自定义表格
+		luckySheetData, err := excel.GetLuckySheetData(excelInfo.Content)
+		if err != nil {
+			fmt.Println("err:", err)
+			return
+		}
+		//_, err = luckySheetData.GetTableDataByLuckySheetDataStr()
+		downloadFilePath, err = luckySheetData.ToExcel()
+	case utils.CUSTOM_ANALYSIS_TABLE: // 自定义分析表格
+		downloadFilePath, err, _ = GenerateExcelCustomAnalysisExcel(excelInfo)
+	}
+
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	defer func() {
+		_ = os.Remove(downloadFilePath)
+	}()
+
+	//上传到阿里云
+	resourceUrl, err := services.UploadAliyunV2(fileName, downloadFilePath)
+	if err != nil {
+		return
+	}
+	excelInfo.FileUrl = resourceUrl
+	err = excelInfo.Update([]string{"FileUrl"})
+}

+ 379 - 0
services/excel/excel_to_lucky_sheet.go

@@ -0,0 +1,379 @@
+package excel
+
+import (
+	"encoding/json"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
+	"github.com/xuri/excelize/v2"
+	"sync"
+	"time"
+)
+
+// ConvToLuckySheet 普通的excel转luckySheet数据
+func ConvToLuckySheet(filePath string) (err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+		}
+	}()
+	f, err := excelize.OpenFile(filePath)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	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 {
+			err = tmpErr
+			return
+		}
+		sheetDataList = append(sheetDataList, sheetData)
+	}
+
+	byteS, err := json.Marshal(sheetDataList)
+	if err != nil {
+		return
+	}
+	utils.FileLog.Info(string(byteS))
+
+	return
+}
+
+// SimpleLuckySheetData sheet表格数据
+type SimpleLuckySheetData struct {
+	Name  string `json:"name" description:"工作表名称"`
+	Index int    `json:"index" description:"工作表索引"`
+	//Row      int                        `json:"row" description:"行数"`
+	//Column   int                        `json:"column" description:"列数"`
+	CellData  []SimpleLuckySheetCellData `json:"celldata" description:"单元格数据"`
+	Config    SimpleLuckySheetDataConfig `json:"config" description:""`
+	CalcChain []CalcChain                `json:"calcChain" description:"公式链"`
+	//Status            int64   `json:"status" description:"激活状态"`
+}
+
+type CalcChain struct {
+	Col   int64         `json:"c"`     //列数
+	Row   int64         `json:"r"`     //行数
+	Index int           `json:"index"` //工作表id
+	Func  []interface{} `json:"func"`  //公式信息,包含公式计算结果和公式字符串
+	Color string        `json:"color"` //"w":采用深度优先算法 "b":普通计算
+	//Parent  interface{}   `json:"parent"`
+	//Chidren struct {
+	//} `json:"chidren"`
+	Times int `json:"times"`
+}
+
+// SimpleLuckySheetDataConfig sheet表单的配置
+type SimpleLuckySheetDataConfig struct {
+	BorderInfo []LuckySheetDataConfigBorderInfo `json:"borderInfo" description:"边框"`
+	Colhidden  map[string]int64                 `json:"colhidden" description:"隐藏列,示例值:\"colhidden\":{\"30\":0,\"31\":0}"`
+	//CustomHeight struct {
+	//	Zero int64 `json:"0"`
+	//} `json:"customHeight" description:""`
+	//CustomWidth struct {
+	//	Two int64 `json:"2" description:""`
+	//} `json:"customWidth" description:""`
+	Merge map[string]LuckySheetDataConfigMerge `json:"merge" description:"合并单元格"`
+	//Rowlen map[string]float64                   `json:"rowlen" description:"每个单元格的行高"`
+	Columnlen map[string]float64 `json:"columnlen" description:"每个单元格的列宽"`
+}
+
+// SimpleLuckySheetCellData 单个单元格数据
+type SimpleLuckySheetCellData struct {
+	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:"显示值"`
+	//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:"公式"`
+	//MergeCell LuckySheetDataConfigMerge `json:"mc" description:"合并单元格信息"`
+}
+
+func getLuckySheetData(f *excelize.File, sheetIndex int, sheetName string) (sheetData SimpleLuckySheetData, err error) {
+	cellData := make([]SimpleLuckySheetCellData, 0)         // excel数据
+	mergeData := make(map[string]LuckySheetDataConfigMerge) //合并单元格数据
+	calcChainList := make([]CalcChain, 0)                   //公式链信息
+
+	sheetData = SimpleLuckySheetData{
+		Name:  sheetName,
+		Index: sheetIndex,
+		//Row:      0,
+		//Column:   0,
+		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
+
+	wg := sync.WaitGroup{}
+	wg.Add(1)
+	// 协程处理合并单元格
+	go func() {
+		defer func() {
+			wg.Done()
+		}()
+		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
+				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)
+
+	// 每次分割就是5000条
+	splitNum := 500
+	splitLen := lenRow / splitNum
+	residue := lenRow % splitNum
+	if residue > 0 {
+		splitLen += 1
+	}
+
+	for i := 0; i < splitLen; i++ {
+		wg.Add(1)
+
+		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,
+					}
+					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
+
+	sheetData.CellData = cellData
+	sheetData.CalcChain = calcChainList
+	//sheetData.Column = maxColumnIndex + 1
+
+	return
+}
+
+// emuToPx 计量单位emu转px
+func emuToPx(num float64) float64 {
+	return num * 15
+}

+ 58 - 19
services/excel/lucky_sheet.go

@@ -3,7 +3,7 @@ package excel
 import (
 	"encoding/json"
 	"errors"
-	"eta/eta_api/models/data_manage/request"
+	"eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/tealeg/xlsx"
@@ -107,17 +107,22 @@ type LuckySheetDataBak struct {
 
 // LuckySheetData sheet表格数据
 type LuckySheetData struct {
+	Name     string               `json:"name" description:"工作表名称"`
+	Index    int                  `json:"index" description:"工作表索引"`
+	Row      int                  `json:"row" description:"行数"`
+	Column   int                  `json:"column" description:"列数"`
 	CellData []LuckySheetCellData `json:"celldata" description:"单元格数据"`
 	ChWidth  int64                `json:"ch_width" description:"工作表区域的宽度"`
 	Config   LuckySheetDataConfig `json:"config" description:""`
 	//Index             int                  `json:"index" description:"工作表索引"`
-	RhHeight          float64 `json:"rh_height" description:"工作表区域的高度"`
-	ScrollLeft        float64 `json:"scrollLeft" description:"左右滚动条位置"`
-	ScrollTop         float64 `json:"scrollTop" description:"上下滚动条位置"`
-	Status            int64   `json:"status" description:"激活状态"`
-	VisibleDataColumn []int64 `json:"visibledatacolumn" description:"所有列的位置信息,递增的列位置数据,初始化无需设置"`
-	VisibleDataRow    []int64 `json:"visibledatarow" description:"所有行的位置信息,递增的行位置数据,初始化无需设置"`
-	ZoomRatio         float64 `json:"zoomRatio" description:"sheet缩放比例"`
+	RhHeight          float64       `json:"rh_height" description:"工作表区域的高度"`
+	ScrollLeft        float64       `json:"scrollLeft" description:"左右滚动条位置"`
+	ScrollTop         float64       `json:"scrollTop" description:"上下滚动条位置"`
+	CalcChain         []interface{} `json:"calcChain" description:"公式链"`
+	Status            int64         `json:"status" description:"激活状态"`
+	VisibleDataColumn []int64       `json:"visibledatacolumn" description:"所有列的位置信息,递增的列位置数据,初始化无需设置"`
+	VisibleDataRow    []int64       `json:"visibledatarow" description:"所有行的位置信息,递增的行位置数据,初始化无需设置"`
+	ZoomRatio         float64       `json:"zoomRatio" description:"sheet缩放比例"`
 }
 
 // LuckySheetDataConfig sheet表单的配置
@@ -331,6 +336,27 @@ func (tableData TableData) ToExcel() (downloadFilePath string, err error) {
 	if err != nil {
 		return
 	}
+
+	// 将单个sheet的数据写入到excel
+	err = tableData.WriteExcelSheetData(xlsxFile, "sheet1")
+	if err != nil {
+		return
+	}
+
+	//return
+	err = xlsxFile.Save(downloadFilePath)
+	if err != nil {
+		return
+	}
+	//randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
+	//downloadFileName := "即将到期客户数据_" + randStr + ".xlsx"
+	//this.Ctx.Output.Download(downLoadnFilePath, downloadFileName)
+
+	return
+}
+
+// WriteExcelSheetData 通过 TableData生成excel表格数据
+func (tableData TableData) WriteExcelSheetData(xlsxFile *xlsx.File, sheetName string) (err error) {
 	style := xlsx.NewStyle()
 	alignment := xlsx.Alignment{
 		Horizontal: "center",
@@ -341,7 +367,7 @@ func (tableData TableData) ToExcel() (downloadFilePath string, err error) {
 	style.Alignment = alignment
 	style.ApplyAlignment = true
 
-	sheet, err := xlsxFile.AddSheet("sheet1")
+	sheet, err := xlsxFile.AddSheet(sheetName)
 	if err != nil {
 		return
 	}
@@ -419,7 +445,24 @@ func (tableData TableData) ToExcel() (downloadFilePath string, err error) {
 					}
 				}
 			}
-			tmpRow.SetString(valueStr)
+			//tmpRow.SetString(valueStr)
+			switch cellInfo.CellType.Fa {
+			case "General":
+				if cellInfo.CellType.S != nil {
+					tmpRow.SetString(valueStr)
+				} else {
+					tmpRow.SetValue(cellInfo.Value)
+				}
+			case "@":
+				tmpRow.SetString(valueStr)
+			default:
+				tmpRow.SetString(valueStr)
+			}
+			if cellInfo.Function != `` {
+				//xlsxFile.
+				//xlsxFile.SetCellFormula
+				tmpRow.SetFormula(cellInfo.Function)
+			}
 			//if cellInfo.Function != `` {
 			//	tmpRow.SetFormula(cellInfo.Function)
 			//}
@@ -433,14 +476,7 @@ func (tableData TableData) ToExcel() (downloadFilePath string, err error) {
 			}
 		}
 	}
-	//return
-	err = xlsxFile.Save(downloadFilePath)
-	if err != nil {
-		return
-	}
-	//randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
-	//downloadFileName := "即将到期客户数据_" + randStr + ".xlsx"
-	//this.Ctx.Output.Download(downLoadnFilePath, downloadFileName)
+
 	return
 }
 
@@ -1175,7 +1211,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 {

+ 49 - 0
services/excel/lucky_sheet_excel.go

@@ -0,0 +1,49 @@
+package excel
+
+import "github.com/tealeg/xlsx"
+
+type LuckySheet struct {
+	SheetList []LuckySheetData `description:"sheet数据"`
+}
+
+// GetExcelData 通过 luckySheetData获取excel表格数据
+func (item *LuckySheet) GetExcelData() (xlsxFile *xlsx.File, err error) {
+	xlsxFile = xlsx.NewFile()
+	if err != nil {
+		return
+	}
+
+	for _, sheet := range item.SheetList {
+		tableData, tmpErr := sheet.GetTableDataByLuckySheetDataStr()
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		err = tableData.WriteExcelSheetData(xlsxFile, sheet.Name)
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// ToExcel 通过 luckySheetData生成excel表格文件
+func (item *LuckySheet) ToExcel() (downloadFilePath string, err error) {
+	// 获取生成的excel路径
+	downloadFilePath, err = getDownloadPath()
+	if err != nil {
+		return
+	}
+
+	// 获取excel表格数据
+	xlsxFile, err := item.GetExcelData()
+	if err != nil {
+		return
+	}
+
+	// 文件保存
+	err = xlsxFile.Save(downloadFilePath)
+
+	return
+}

+ 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
+}

+ 8 - 0
utils/constants.go

@@ -280,6 +280,14 @@ const (
 	CHART_MULTIPLE_GRAPH_LINE_FEATURE_FREQUENCY          = 10 // 统计特征-频率分布图表
 )
 
+// ETA表格
+const (
+	EXCEL_DEFAULT         = 1 // 自定义excel
+	TIME_TABLE            = 2 // 时间序列表格
+	MIXED_TABLE           = 3 // 混合表格
+	CUSTOM_ANALYSIS_TABLE = 4 // 自定义分析表格
+)
+
 // 图表样式类型
 const (
 	CHART_TYPE_CURVE           = 1  //曲线图