Pārlūkot izejas kodu

Merge branch 'eta/1.1.6'

# Conflicts:
#	models/data_manage/excel/request/excel_info.go
#	routers/commentsRouter.go
Roc 1 gadu atpakaļ
vecāks
revīzija
f5138514d9

+ 94 - 36
controllers/data_manage/edb_info.go

@@ -4065,6 +4065,10 @@ func (this *EdbInfoController) AllEdbInfoByEs() {
 	//指标来源
 	source, _ := this.GetInt("Source")
 
+	frequency := this.GetString("Frequency") //频度
+
+	isAddPredictEdb, _ := this.GetBool("IsAddPredictEdb") //是否查询添加预测指标
+
 	var edbInfoList []*data_manage.EdbInfoList
 	var err error
 
@@ -4092,6 +4096,46 @@ func (this *EdbInfoController) AllEdbInfoByEs() {
 
 		// 普通的搜索
 		total, edbInfoList, err = elastic.SearchEdbInfoData(utils.DATA_INDEX_NAME, keyWord, startSize, pageSize, filterSource, source, -1, ``, noPermissionEdbInfoIdList)
+	} else {
+		var condition string
+		var pars []interface{}
+		// 普通指标
+		condition += ` AND edb_info_type = ? `
+		pars = append(pars, 0)
+
+		// 无权限指标id
+		lenNoPermissionEdbInfoIdList := len(noPermissionEdbInfoIdList)
+		if lenNoPermissionEdbInfoIdList > 0 {
+			condition += ` AND edb_info_id  not in (` + utils.GetOrmInReplace(lenNoPermissionEdbInfoIdList) + `) `
+			pars = append(pars, noPermissionEdbInfoIdList)
+		}
+
+		switch filterSource {
+		case 2:
+			condition += ` AND frequency='月度' `
+		case 3:
+			condition += ` AND frequency <> '日度' `
+		case 4:
+			condition += ` AND edb_type = 1 `
+		case 5:
+			condition += ` AND source = 6 ` //来源(同比值)
+		case 6:
+			condition += ` AND frequency != ? `
+			pars = append(pars, "年度")
+		}
+
+		//频度
+		if frequency != "" {
+			condition += ` AND frequency = ? `
+			pars = append(pars, frequency)
+		}
+
+		// 查询只允许添加预测指标的搜索
+		if isAddPredictEdb {
+			condition += ` AND frequency in ("日度","周度","月度") `
+		}
+
+		total, edbInfoList, err = data_manage.GetEdbInfoFilterList(condition, pars, startSize, pageSize)
 	}
 	if err != nil {
 		edbInfoList = make([]*data_manage.EdbInfoList, 0)
@@ -4228,17 +4272,25 @@ func (this *EdbInfoController) GetEdbBeforeAndAfterDateData() {
 		br.IsSendEmail = false
 		return
 	}
-	if date == `` {
-		br.Msg = "请选择日期"
-		br.IsSendEmail = false
-		return
-	}
 	edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = fmt.Sprint("获取指标信息失败,Err:", err.Error())
 		return
 	}
+
+	// 当前日期
+	var currDate string
+	// 是否查找之后的数据
+	isFindAfter := true
+	if date == `` {
+		currDate = edbInfo.EndDate
+		isFindAfter = false
+		if num <= 0 {
+			num = 4 //默认获取前面的几期数据
+		}
+	}
+
 	dataList := make([]*data_manage.EdbDataList, 0)
 
 	startDate := date
@@ -4250,40 +4302,45 @@ func (this *EdbInfoController) GetEdbBeforeAndAfterDateData() {
 		dateType = "month"
 	}
 
-	// 后面的数据
-	afterList, err := data.GetEdbBeforeAndAfterDateData(edbInfo, startDate, "", 2, num)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = fmt.Sprint("获取后面的指数据失败,Err:", err.Error())
-		return
+	resp := data_manage.BeforeAndAfterDateDataResp{
+		List: dataList,
+		Date: "",
 	}
-
-	// 当前日期
-	var currDate string
-	lenBeforeList := len(afterList)
-	if lenBeforeList <= 0 {
-		br.Ret = 200
-		br.Success = true
-		br.Msg = "所选指标所选日期无值"
-		br.Data = dataList
-		return
-	} else {
-		var dateTimeStr string
-		switch dateType {
-		case "month":
-			dateTime, _ := time.ParseInLocation(utils.FormatDate, afterList[0].DataTime, time.Local)
-			dateTimeStr = dateTime.Format(utils.FormatYearMonthDate)
-		case "day":
-			dateTimeStr = afterList[0].DataTime
+	// 后面的数据
+	afterList := make([]*data_manage.EdbDataList, 0)
+	if isFindAfter {
+		afterList, err = data.GetEdbBeforeAndAfterDateData(edbInfo, startDate, "", 2, num)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprint("获取后面的指数据失败,Err:", err.Error())
+			return
 		}
-		currDate = afterList[0].DataTime
-		// 如果对应日期找不到,那么就直接返回吧
-		if dateTimeStr != date {
+
+		lenBeforeList := len(afterList)
+		if lenBeforeList <= 0 {
 			br.Ret = 200
 			br.Success = true
 			br.Msg = "所选指标所选日期无值"
-			br.Data = dataList
+			br.Data = resp
 			return
+		} else {
+			var dateTimeStr string
+			switch dateType {
+			case "month":
+				dateTime, _ := time.ParseInLocation(utils.FormatDate, afterList[0].DataTime, time.Local)
+				dateTimeStr = dateTime.Format(utils.FormatYearMonthDate)
+			case "day":
+				dateTimeStr = afterList[0].DataTime
+			}
+			currDate = afterList[0].DataTime
+			// 如果对应日期找不到,那么就直接返回吧
+			if dateTimeStr != date {
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "所选指标所选日期无值"
+				br.Data = resp
+				return
+			}
 		}
 	}
 
@@ -4310,9 +4367,10 @@ func (this *EdbInfoController) GetEdbBeforeAndAfterDateData() {
 		dataList[i], dataList[j] = dataList[j], dataList[i]
 	}
 
-	resp := data_manage.BeforeAndAfterDateDataResp{
-		List: dataList,
-		Date: currDate,
+	resp.List = dataList
+	// 前端不传入日期的时候,这个J皮不让返回这个字段,要不然他会颜色标记
+	if date != `` {
+		resp.Date = currDate
 	}
 
 	br.Ret = 200

+ 31 - 19
controllers/data_manage/excel/excel_info.go

@@ -60,7 +60,7 @@ func (c *ExcelInfoController) Add() {
 	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
 		deleteCache = false
 		br.Msg = "系统处理中,请稍后重试!"
-		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		br.ErrMsg = "系统处理中,请稍后重试!"
 		return
 	}
 	var req request.AddExcelInfoReq
@@ -181,9 +181,12 @@ func (c *ExcelInfoController) Add() {
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
-		if tmpErr != nil {
+		newResult, err, errMsg := excel2.GetMixedTableCellData(result)
+		if err != nil {
 			br.Msg = "获取失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
@@ -491,7 +494,7 @@ func (c *ExcelInfoController) Edit() {
 	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
 		deleteCache = false
 		br.Msg = "系统处理中,请稍后重试!"
-		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		br.ErrMsg = "系统处理中,请稍后重试!"
 		return
 	}
 	req.ExcelName = strings.Trim(req.ExcelName, " ")
@@ -581,7 +584,7 @@ func (c *ExcelInfoController) Edit() {
 	edbInfoIdList := make([]int, 0)
 	content := req.Content
 	switch excelInfo.Source {
-	case 2: // 自定义表格
+	case utils.TIME_TABLE: // 自定义表格
 		jsonStrByte, err := json.Marshal(req.TableData)
 		if err != nil {
 			br.Msg = "自定义表格数据获取失败"
@@ -609,7 +612,7 @@ func (c *ExcelInfoController) Edit() {
 			return
 		}
 		content = string(contentByte)
-	case 3: // 混合表格
+	case utils.MIXED_TABLE: // 混合表格
 		contentByte, err := json.Marshal(req.TableData)
 		if err != nil {
 			br.Msg = "混合表格数据获取失败"
@@ -625,9 +628,12 @@ func (c *ExcelInfoController) Edit() {
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
-		if tmpErr != nil {
+		newResult, err, errMsg := excel2.GetMixedTableCellData(result)
+		if err != nil {
 			br.Msg = "获取失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
@@ -1185,7 +1191,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 
 	var tableData excel.TableData
 	switch excelInfo.Source {
-	case 1:
+	case utils.EXCEL_DEFAULT:
 		luckySheetData, err := excel.GetLuckySheetData(excelInfo.Content)
 		if err != nil {
 			br.Msg = "获取失败"
@@ -1198,7 +1204,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
 			return
 		}
-	case 2:
+	case utils.TIME_TABLE:
 		var tableDataConfig excel2.TableDataConfig
 		err = json.Unmarshal([]byte(excelInfo.Content), &tableDataConfig)
 		if err != nil {
@@ -1218,7 +1224,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
 			return
 		}
-	case 3:
+	case utils.MIXED_TABLE:
 		var result request.MixedTableReq
 		err = json.Unmarshal([]byte(excelInfo.Content), &result)
 		if err != nil {
@@ -1226,9 +1232,12 @@ func (c *ExcelInfoController) GetExcelTableData() {
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
-		if tmpErr != nil {
+		newResult, err, errMsg := excel2.GetMixedTableCellData(result)
+		if err != nil {
 			br.Msg = "获取失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
@@ -1921,9 +1930,9 @@ func (c *ExcelInfoController) Download() {
 
 	var tableData excel.TableData
 	switch excelInfo.Source {
-	case 1:
+	case utils.EXCEL_DEFAULT:
 		br.Msg = "表格类型异常"
-	case 2: // 自定义表格
+	case utils.TIME_TABLE: // 自定义表格
 		var tableDataConfig excel2.TableDataConfig
 		err = json.Unmarshal([]byte(excelInfo.Content), &tableDataConfig)
 		if err != nil {
@@ -1943,7 +1952,7 @@ func (c *ExcelInfoController) Download() {
 			br.ErrMsg = "转换成table失败,Err:" + err.Error()
 			return
 		}
-	case 3: // 混合表格
+	case utils.MIXED_TABLE: // 混合表格
 		var result request.MixedTableReq
 		err = json.Unmarshal([]byte(excelInfo.Content), &result)
 		if err != nil {
@@ -1951,9 +1960,12 @@ func (c *ExcelInfoController) Download() {
 			br.ErrMsg = "表格json转结构体失败,Err:" + err.Error()
 			return
 		}
-		newResult, tmpErr := excel2.GetMixedTableCellData(result.Data)
-		if tmpErr != nil {
+		newResult, err, errMsg := excel2.GetMixedTableCellData(result)
+		if err != nil {
 			br.Msg = "获取失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
 			br.ErrMsg = "获取最新的数据失败,Err:" + err.Error()
 			return
 		}
@@ -2018,7 +2030,7 @@ func (c *ExcelInfoController) Copy() {
 	cacheKey := "CACHE_TABLE_INFO_EDIT_" + strconv.Itoa(req.ExcelInfoId)
 	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
 		br.Msg = "系统处理中,请稍后重试!"
-		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		br.ErrMsg = "系统处理中,请稍后重试!"
 		return
 	}
 	defer func() {

+ 237 - 0
controllers/data_manage/excel/mixed_table.go

@@ -0,0 +1,237 @@
+package excel
+
+import (
+	"encoding/json"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/excel/request"
+	"eta/eta_api/services/data"
+	excel2 "eta/eta_api/services/data/excel"
+	"strconv"
+)
+
+// GetSystemDate
+// @Title 获取系统日期(包含计算日期)
+// @Description 获取系统日期(包含计算日期)
+// @Param	request	body request.MixedTableCellDataReq true "type json string"
+// @router /excel_info/get_system_date [post]
+func (c *ExcelInfoController) GetSystemDate() {
+	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
+	}
+
+	var req request.MixedTableCellDataReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	date, err, errMsg := excel2.HandleDate(req.DataTimeType, req.Value)
+	if err != nil {
+		br.Msg = "获取系统日期失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "获取系统日期失败,Err:" + err.Error()
+		return
+	}
+
+	type resp struct {
+		Date string
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取系统日期成功"
+	br.Data = resp{
+		Date: date,
+	}
+}
+
+// CalculateData
+// @Title 公式计算(混合表格)
+// @Description 公式计算(混合表格)
+// @Param	request	body request.CalculateConf true "type json string"
+// @router /excel_info/mixed/calculate [post]
+func (c *ExcelInfoController) CalculateData() {
+	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
+	}
+
+	var req request.CalculateConf
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
+	if err != nil {
+		br.Msg = "获取指标信息失败!"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+
+	dataList := make([]*data_manage.EdbDataList, 0)
+	switch edbInfo.EdbInfoType {
+	case 0:
+		dataList, _ = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
+	case 1:
+		_, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
+	default:
+		br.Msg = "指标类型异常!"
+		br.ErrMsg = "指标类型异常,Err:" + strconv.Itoa(edbInfo.EdbInfoType)
+		return
+	}
+
+	//获取所有数据,计算所有数据
+	//获取部分数据,计算部分数据
+	// BaseCalculate 数据计算的结构体
+	type BaseCalculate struct {
+		DataList      []*data_manage.EdbDataList
+		Frequency     string `description:"需要转换的频度"`
+		Formula       interface{}
+		Calendar      string `description:"公历/农历"`
+		MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
+		MoveFrequency string `description:"移动频度"`
+		FromFrequency string `description:"来源的频度"`
+		Source        int    `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
+	}
+
+	req2 := &BaseCalculate{
+		DataList:      dataList,
+		Frequency:     req.Frequency,
+		Formula:       req.Formula,
+		Calendar:      req.Calendar,
+		MoveType:      req.MoveType,
+		MoveFrequency: req.MoveFrequency,
+		FromFrequency: edbInfo.Frequency,
+		Source:        req.Source,
+	}
+
+	// 调用指标库去更新
+	reqJson, tmpErr := json.Marshal(req2)
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	respItem, tmpErr := data.BaseCalculate(string(reqJson))
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	if respItem.Ret != 200 {
+		br.Msg = respItem.Msg
+		br.ErrMsg = respItem.ErrMsg
+		return
+	}
+
+	// 数据处理成需要返回的样式
+	num := 5
+	lenDate := len(respItem.Data.DateList)
+	if lenDate < 5 {
+		num = lenDate
+	}
+
+	var currDate string // 当前日期
+	dataListResp := make([]*data_manage.EdbDataList, 0)
+
+	if req.DataTime == `` {
+		for i := 1; i <= num; i++ {
+			date := respItem.Data.DateList[lenDate-i]
+			val, ok := respItem.Data.DataMap[date]
+			if !ok {
+				continue
+			}
+
+			dataListResp = append(dataListResp, &data_manage.EdbDataList{
+				Value:    val,
+				DataTime: date,
+			})
+		}
+	} else {
+		if val, ok := respItem.Data.DataMap[req.DataTime]; ok {
+			for i, tmpDate := range respItem.Data.DateList {
+				if tmpDate == req.DataTime {
+					if i+3 <= lenDate {
+						t1Date := respItem.Data.DateList[i+2]
+						if tmpVal, ok2 := respItem.Data.DataMap[t1Date]; ok2 {
+							// 当前日期
+							dataListResp = append(dataListResp, &data_manage.EdbDataList{
+								Value:    tmpVal,
+								DataTime: t1Date,
+							})
+						}
+					}
+
+					if i+2 <= lenDate {
+						t1Date := respItem.Data.DateList[i+1]
+						if tmpVal, ok2 := respItem.Data.DataMap[t1Date]; ok2 {
+							// 当前日期
+							dataListResp = append(dataListResp, &data_manage.EdbDataList{
+								Value:    tmpVal,
+								DataTime: t1Date,
+							})
+						}
+					}
+
+					// 当前日期
+					dataListResp = append(dataListResp, &data_manage.EdbDataList{
+						Value:    val,
+						DataTime: req.DataTime,
+					})
+					if i >= 1 {
+						t1Date := respItem.Data.DateList[i-1]
+						if tmpVal, ok2 := respItem.Data.DataMap[t1Date]; ok2 {
+							// 当前日期
+							dataListResp = append(dataListResp, &data_manage.EdbDataList{
+								Value:    tmpVal,
+								DataTime: t1Date,
+							})
+						}
+					}
+					if i >= 2 {
+						t1Date := respItem.Data.DateList[i-2]
+						if tmpVal, ok2 := respItem.Data.DataMap[t1Date]; ok2 {
+							// 当前日期
+							dataListResp = append(dataListResp, &data_manage.EdbDataList{
+								Value:    tmpVal,
+								DataTime: t1Date,
+							})
+						}
+					}
+				}
+			}
+		}
+	}
+	resp := data_manage.BeforeAndAfterDateDataResp{
+		List: dataListResp,
+		Date: currDate,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "计算成功"
+	br.Data = resp
+}

+ 1 - 3
go.mod

@@ -11,7 +11,7 @@ require (
 	github.com/alibabacloud-go/tea v1.1.20
 	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/aliyun/aliyun-oss-go-sdk v3.0.1+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
@@ -52,7 +52,6 @@ require (
 	github.com/aliyun/credentials-go v1.1.2 // indirect
 	github.com/andybalholm/cascadia v1.3.1 // indirect
 	github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02 // indirect
-	github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -95,7 +94,6 @@ require (
 	github.com/richardlehane/mscfb v1.0.4 // indirect
 	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/rs/xid v1.5.0 // indirect
-	github.com/satori/go.uuid v1.2.0 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/spf13/cast v1.5.0 // indirect

+ 2 - 6
go.sum

@@ -61,8 +61,8 @@ github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGn
 github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
 github.com/aliyun/alibaba-cloud-sdk-go v1.61.1656 h1:YTWW7mBjwviuRvqiEpqaAj0AyVPj9AoJmQGCb5lXYUc=
 github.com/aliyun/alibaba-cloud-sdk-go v1.61.1656/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
-github.com/aliyun/aliyun-oss-go-sdk v2.2.0+incompatible h1:ht2+VfbXtNLGhCsnTMc6/N26nSTBK6qdhktjYyjJQkk=
-github.com/aliyun/aliyun-oss-go-sdk v2.2.0+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
+github.com/aliyun/aliyun-oss-go-sdk v3.0.1+incompatible h1:so4m5rRA32Tc5GgKg/5gKUu0CRsYmVO3ThMP6T3CwLc=
+github.com/aliyun/aliyun-oss-go-sdk v3.0.1+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
 github.com/aliyun/credentials-go v1.1.2 h1:qU1vwGIBb3UJ8BwunHDRFtAhS6jnQLnde/yk0+Ih2GY=
 github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
 github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
@@ -74,8 +74,6 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
 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=
-github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
 github.com/beego/bee/v2 v2.0.4 h1:nEjPwxJ8D+cr54eWChJGoGRH7bJ7OQwbhx8rU0OQf7E=
 github.com/beego/bee/v2 v2.0.4/go.mod h1:wq0YrEmPcdNfDNpaUgiTkaW9zso7M8n0HCCShEBOzM0=
 github.com/beego/beego/v2 v2.0.7 h1:9KNnUM40tn3pbCOFfe6SJ1oOL0oTi/oBS/C/wCEdAXA=
@@ -373,8 +371,6 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
 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=

+ 2 - 28
models/data_manage/excel/request/excel_info.go

@@ -129,34 +129,8 @@ type CopyExcelInfoReq struct {
 	ExcelClassifyId int    `description:"分类id"`
 }
 
-// MixedTableReq 混合表格保存请求参数
-type MixedTableReq struct {
-	CellRelation string                    `description:"单元格关系"`
-	Data         [][]MixedTableCellDataReq `description:"混合表格单元格参数"`
-}
-
-// MixedTableCellDataReq 混合表格单元格参数
-type MixedTableCellDataReq struct {
-	Uid       string `description:"单元格唯一标识"`
-	DataType  int    `description:"数据类型,1:日期,2:指标,3:自定义文本,4:插值"`
-	DataTime  string `description:"所属日期"`
-	EdbInfoId int    `description:"指标id"`
-	ShowValue string `description:"展示值"`
-	Value     string `description:"实际值"`
-}
-
-// AddAndEditSandbox 添加/编辑沙盘的请求数据
-type AddAndEditSandbox struct {
-	ExcelInfoId          int    `description:"excel表格ID"`
-	Name               string `description:"沙盘名称"`
-	ChartPermissionId  int    `description:"品种权限id"`
-	Content            string `description:"沙盘内容"`
-	PicUrl             string `description:"沙盘图片地址"`
-	SvgData            string `description:"沙盘svg图片数据"`
-}
-
 // MarkEditExcel 标记编辑表格的请求数据
 type MarkEditExcel struct {
 	ExcelInfoId int `description:"表格id"`
-	Status    int `description:"标记状态,1:编辑中,2:编辑完成"`
-}
+	Status      int `description:"标记状态,1:编辑中,2:编辑完成"`
+}

+ 105 - 0
models/data_manage/excel/request/mixed_table.go

@@ -0,0 +1,105 @@
+package request
+
+// 单元格的数据类型
+const (
+	DateDT                   = iota + 1 //日期
+	EdbDT                               // 2 指标类型
+	CustomTextDT                        // 3 自定义文本
+	InsertDataDT                        // 4 插值(插入指标值,表格上,自动判断日期和指标的交集位置,插入值)
+	PopInsertDataDT                     // 5 弹框插值(在表格上选择日期,然后空白单元格选择弹框并选择指标,插入该指标与该日期的值)
+	FormulateCalculateDataDT            // 6 公式计算(A+B这种)
+	InsertEdbCalculateDataDT            // 7 插入指标系统计算公式生成的值
+)
+
+// 单元格的日期类型类型
+const (
+	CustomDateT = iota //手动输入日期
+	SystemDateT        // 系统日期
+	EdbDateDT          // 导入指标日期(指标库的最新日期)
+)
+
+// 单元格的日期类型类型
+const (
+	SystemCurrDateT      = iota + 1 //系统当前日期
+	SystemCalculateDateT            // 系统日期计算后的日期
+	SystemFrequencyDateT            // 导入系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
+)
+
+// MixedTableReq 混合表格保存请求参数
+type MixedTableReq struct {
+	CellRelation string                    `description:"单元格关系"`
+	Data         [][]MixedTableCellDataReq `description:"混合表格单元格参数"`
+}
+
+// MixedTableCellDataReq 混合表格单元格参数
+type MixedTableCellDataReq struct {
+	Uid          string `description:"单元格唯一标识"`
+	DataType     int    `description:"数据类型,1:日期,2:指标,3:自定义文本,4:插值"`
+	DataTime     string `description:"所属日期"`
+	DataTimeType int    `description:"日期类型:0:手动输入日期;1:导入系统日期;;3:导入指标日期(指标库的最新日期);"`
+	EdbInfoId    int    `description:"指标id"`
+	ShowValue    string `description:"展示值"`
+	Value        string `description:"实际值"`
+	Extra        string `description:"额外参数"`
+}
+
+// CellRelationConf
+// @Description: 单元格的关系配置结构体
+type CellRelationConf struct {
+	CellRelation
+	//Type         int          `json:"type" description:"数据类型,跟MixedTableCellDataReq的DataType保持一致"`
+	//Key          string       `json:"key" description:"单元格的唯一标识"`
+	RelationDate CellRelation `json:"relation_date"`
+	RelationEdb  CellRelation `json:"relation_edb"`
+}
+
+// CellRelation
+// @Description: 单元格的关系结构体
+type CellRelation struct {
+	Type int    `json:"type" description:"数据类型,跟MixedTableCellDataReq的DataType保持一致"`
+	Key  string `json:"key" description:"单元格的唯一标识"`
+}
+
+// SystemDateConf
+// @Description: 系统导入日期配置
+type SystemDateConf struct {
+	Source             int    `description:"类型,1:导入系统日期;2:导入系统日期计算后的日期;3:导入系统日期相关的指定频率"`
+	CalculateNum       int    `description:"计算频度的数量"`
+	CalculateFrequency string `description:"计算频度"`
+	Frequency          string `description:"指定频度"`
+	Day                string `description:"指定日期"`
+}
+
+// EdbDateConf
+// @Description: 导入指标日期配置
+type EdbDateConf struct {
+	EdbInfoId int `description:"指标id"`
+}
+
+// CalculateConf
+// @Description: 计算公式
+type CalculateConf struct {
+	EdbInfoId     int         `description:"指标id"`
+	DataTime      string      `description:"所属日期,这个日期有传递的话,那么就取上下两期+自己的数据;没有传就默认最近5期的数据"`
+	Frequency     string      `description:"需要转换的频度"`
+	Formula       interface{} `description:"计算公式,默认是string,实际上还需要转成其他样式"`
+	Calendar      string      `description:"公历/农历"`
+	MoveType      int         `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency string      `description:"移动频度"`
+	Source        int         `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
+}
+
+// BaseCalculateConf
+// @Description: 基础计算公式(A+B)
+type BaseCalculateConf struct {
+	Formula             string         `description:"计算公式,默认是string,实际上还需要转成其他样式"`
+	RelationEdbInfoList []RelationCell `description:"关联单元格(计算公式中关联的单元格,用于计算的时候去匹配)"`
+}
+
+// RelationCell
+// @Description: 关联单元格的信息
+type RelationCell struct {
+	Tag string `description:"指标标签"`
+	Row string `description:"第几行"`
+	Key string `json:"key" description:"单元格的唯一标识"`
+}

+ 18 - 0
routers/commentsRouter.go

@@ -376,6 +376,15 @@ func init() {
             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: "GetSystemDate",
+            Router: `/excel_info/get_system_date`,
+            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",
@@ -394,6 +403,15 @@ func init() {
             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: "CalculateData",
+            Router: `/excel_info/mixed/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: "Move",

+ 31 - 1
services/data/base_edb_lib.go

@@ -340,6 +340,36 @@ func PredictCalculateComputeCorrelation(edbInfoCalculateBatchSaveReqStr string)
 	return
 }
 
+// BaseCalculateResp 拟合残差计算相关性的值返回
+type BaseCalculateResp struct {
+	Ret         int
+	Msg         string
+	ErrMsg      string
+	ErrCode     string
+	Data        BaseCalculateDataResp
+	Success     bool `description:"true 执行成功,false 执行失败"`
+	IsSendEmail bool `json:"-" description:"true 发送邮件,false 不发送邮件"`
+	IsAddLog    bool `json:"-" description:"true 新增操作日志,false 不新增操作日志" `
+}
+
+// BaseCalculateDataResp
+// @Description: 基础计算的返回结果
+type BaseCalculateDataResp struct {
+	DataMap  map[string]float64
+	DateList []string
+}
+
+// BaseCalculate 基础计算
+func BaseCalculate(param string) (resp *BaseCalculateResp, err error) {
+	urlStr := "calculate/base"
+	_, resultByte, err := postAddEdbData(param, urlStr)
+	err = json.Unmarshal(resultByte, &resp)
+	if err != nil {
+		return
+	}
+	return
+}
+
 // postRefreshEdbData 刷新指标数据
 func postRefreshEdbData(param map[string]interface{}, urlStr string) (resp *models.BaseResponse, err error) {
 	postUrl := utils.EDB_LIB_URL + urlStr
@@ -393,6 +423,6 @@ func HttpPost(url, postData string, params ...string) ([]byte, error) {
 	}
 	defer resp.Body.Close()
 	b, err := ioutil.ReadAll(resp.Body)
-	fmt.Println("HttpPost:" + string(b))
+	utils.FileLog.Debug("HttpPost:" + string(b))
 	return b, err
 }

+ 7 - 93
services/data/excel/excel_info.go

@@ -53,7 +53,7 @@ func GetExcelDetailInfoByExcelInfoId(excelInfoId int) (excelDetail response.Exce
 	}
 
 	switch excelInfo.Source {
-	case 2: // 自定义表格
+	case utils.TIME_TABLE: // 自定义表格
 		var tableDataConfig TableDataConfig
 		err = json.Unmarshal([]byte(excelDetail.Content), &tableDataConfig)
 		if err != nil {
@@ -66,15 +66,19 @@ func GetExcelDetailInfoByExcelInfoId(excelInfoId int) (excelDetail response.Exce
 			return
 		}
 		excelDetail.TableData = result
-	case 3: // 混合表格
+	case utils.MIXED_TABLE: // 混合表格
 		var result request.MixedTableReq
 		err = json.Unmarshal([]byte(excelDetail.Content), &result)
 		if err != nil {
 			err = errors.New("表格json转结构体失败,Err:" + err.Error())
 			return
 		}
-		newData, tmpErr := GetMixedTableCellData(result.Data)
+		newData, tmpErr, tmpErrMsg := GetMixedTableCellData(result)
 		if tmpErr != nil {
+			errMsg = "获取失败"
+			if tmpErrMsg != `` {
+				errMsg = tmpErrMsg
+			}
 			err = errors.New("获取最新的数据失败,Err:" + tmpErr.Error())
 			return
 		}
@@ -1259,93 +1263,3 @@ func calculate(calculateFormula string, TagMap map[string]float64) (calVal, errM
 
 	return
 }
-
-// GetMixedTableCellData 获取混合表格数据
-func GetMixedTableCellData(config [][]request.MixedTableCellDataReq) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error) {
-	newMixedTableCellDataList = config
-
-	edbInfoIdList := make([]int, 0)
-	dataEdbInfoIdList := make([]int, 0)
-	for _, row := range config {
-		for _, cell := range row {
-			if cell.DataType == 2 {
-				edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
-			} else if utils.InArrayByInt([]int{4, 5}, cell.DataType) {
-				dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
-			}
-		}
-	}
-
-	edbInfoList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
-	if err != nil {
-		return
-	}
-
-	// 指标信息map
-	edbInfoMap := make(map[int]*data_manage.EdbInfo)
-	// 日度指标数据map
-	edbDataListMap := make(map[int]map[string]float64)
-	// 月度指标数据map
-	edbMonthDataListMap := make(map[int]map[string]float64)
-	for _, edbInfo := range edbInfoList {
-		edbInfoMap[edbInfo.EdbInfoId] = edbInfo
-
-		dataList := make([]*data_manage.EdbDataList, 0)
-		switch edbInfo.EdbInfoType {
-		case 0:
-			dataList, _ = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
-		case 1:
-			_, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
-		default:
-			err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
-		}
-
-		dateValMap := make(map[string]float64)
-		monthValMap := make(map[string]float64)
-		for _, data := range dataList {
-			// 日度数据
-			dateValMap[data.DataTime] = data.Value
-			// 月度数据(取该月份的第一个数据)
-			yearMonth := strings.Join(strings.Split(data.DataTime, "-")[0:2], "-")
-			if _, ok := monthValMap[yearMonth]; !ok {
-				monthValMap[yearMonth] = data.Value
-			}
-		}
-		edbDataListMap[edbInfo.EdbInfoId] = dateValMap
-		edbMonthDataListMap[edbInfo.EdbInfoId] = monthValMap
-	}
-
-	for k, row := range newMixedTableCellDataList {
-		for i, cell := range row {
-			if cell.DataType == 2 {
-				if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
-					cell.ShowValue = edbInfo.EdbName
-				}
-			} else if utils.InArrayByInt([]int{4, 5}, cell.DataType) {
-				tmpDateList := strings.Split(cell.DataTime, "-")
-				tmpDateValMap := make(map[string]float64)
-				if len(tmpDateList) == 2 {
-					//月度数据
-					if dateValMap, ok := edbMonthDataListMap[cell.EdbInfoId]; ok {
-						tmpDateValMap = dateValMap
-					}
-				} else {
-					// 日度数据
-					if dateValMap, ok := edbDataListMap[cell.EdbInfoId]; ok {
-						tmpDateValMap = dateValMap
-					}
-
-				}
-				if val, ok2 := tmpDateValMap[cell.DataTime]; ok2 {
-					//cell.ShowValue = fmt.Sprint(val)
-					cell.ShowValue = utils.FormatTableDataShowValue(val)
-				}
-			}
-
-			row[i] = cell
-		}
-		newMixedTableCellDataList[k] = row
-	}
-
-	return
-}

+ 769 - 0
services/data/excel/mixed_table.go

@@ -0,0 +1,769 @@
+package excel
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/excel/request"
+	"eta/eta_api/services/data"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
+	"github.com/yidane/formula"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// BaseCalculate
+// @Description: 指标数据计算请求
+type BaseCalculate struct {
+	DataList      []*data_manage.EdbDataList
+	Frequency     string `description:"需要转换的频度"`
+	Formula       interface{}
+	Calendar      string `description:"公历/农历"`
+	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency string `description:"移动频度"`
+	FromFrequency string `description:"来源的频度"`
+	Source        int    `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
+}
+
+// Cell
+// @Description: 单元格位置
+type Cell struct {
+	Column   int                           `description:"行"`
+	Row      int                           `description:"列"`
+	CellInfo request.MixedTableCellDataReq `description:"对应的单元格信息"`
+}
+
+// GetMixedTableCellData 获取混合表格数据
+func GetMixedTableCellData(mixedTableReq request.MixedTableReq) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error, errMsg string) {
+	cellRelationConf := mixedTableReq.CellRelation
+	config := mixedTableReq.Data
+
+	// 单元格关系配置x信息
+	cellRelationConfMap := make(map[string]request.CellRelationConf)
+	cellRelationConfList := make([]request.CellRelationConf, 0)
+	if cellRelationConf != `` {
+		err = json.Unmarshal([]byte(cellRelationConf), &cellRelationConfList)
+		if err != nil {
+			return
+		}
+
+		for _, v := range cellRelationConfList {
+			cellRelationConfMap[v.Key] = v
+		}
+	}
+
+	// 找出所有的关联指标id
+	config, edbInfoIdList, _, err, errMsg := handleConfig(config)
+	if err != nil {
+		return
+	}
+
+	// 查询所有关联的指标信息
+	edbInfoList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+	if err != nil {
+		return
+	}
+
+	// 指标信息map
+	edbInfoMap := make(map[int]*data_manage.EdbInfo)
+	// 日度指标数据map
+	edbDayDataListMap := make(map[int]map[string]float64)
+	// 月度指标数据map
+	edbMonthDataListMap := make(map[int]map[string]float64)
+	// 日度指标数据map
+	edbDataListMap := make(map[int][]*data_manage.EdbDataList)
+	for _, edbInfo := range edbInfoList {
+		edbInfoMap[edbInfo.EdbInfoId] = edbInfo
+
+		dataList := make([]*data_manage.EdbDataList, 0)
+		switch edbInfo.EdbInfoType {
+		case 0:
+			dataList, _ = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
+		case 1:
+			_, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
+		default:
+			err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
+		}
+
+		dateValMap := make(map[string]float64)
+		monthValMap := make(map[string]float64)
+		for _, tmpData := range dataList {
+			// 日度数据
+			dateValMap[tmpData.DataTime] = tmpData.Value
+			// 月度数据(取该月份的第一个数据)
+			yearMonth := strings.Join(strings.Split(tmpData.DataTime, "-")[0:2], "-")
+			if _, ok := monthValMap[yearMonth]; !ok {
+				monthValMap[yearMonth] = tmpData.Value
+			}
+		}
+		edbDayDataListMap[edbInfo.EdbInfoId] = dateValMap
+		edbMonthDataListMap[edbInfo.EdbInfoId] = monthValMap
+		edbDataListMap[edbInfo.EdbInfoId] = dataList
+	}
+
+	// 单元格实际绑定的信息map
+	cellDataRelationMap := make(map[string]request.MixedTableCellDataReq, 0)
+
+	// 处理指定指标的日期
+	for k, row := range config {
+		for i, cell := range row {
+			// 单元格是日期类型,且是日导入指标日期(指标库的最新日期)
+			if cell.DataType == request.DateDT && cell.DataTimeType == request.EdbDateDT {
+				if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
+					cell.ShowValue = edbInfo.EndDate
+					cell.DataTime = edbInfo.EndDate
+					config[k][i] = cell
+				}
+			}
+			row[i] = cell
+
+			cellDataRelationMap[cell.Uid] = cell
+		}
+		config[k] = row
+	}
+
+	// 指标计算的结果map
+	edbSourceDataMap := make(map[string]map[string]float64)
+
+	// 单元格对应的key与他的值(只处理数据类型)
+	cellKeyVal := make(map[string]float64)
+
+	// 基础计算单元格的位置信息
+	calculateCellMap := make(map[string]Cell)
+	calculateChainList := make([]string, 0)
+
+	// 处理单元格中的数据类型(除去基础计算,因为这个是依赖于其他)
+	for k, row := range config {
+		for i, cell := range row {
+			switch cell.DataType {
+			case request.EdbDT: // 指标类型
+				if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
+					cell.ShowValue = edbInfo.EdbName
+				}
+			case request.InsertDataDT, request.PopInsertDataDT: // 数据类型
+				if cell.DataTime == `` {
+					// 指标的最新日期
+					if dateValList, ok := edbDataListMap[cell.EdbInfoId]; ok {
+						tmpLenData := len(dateValList)
+						if tmpLenData > 0 {
+							cellKeyVal[cell.Uid] = dateValList[tmpLenData-1].Value
+							cell.ShowValue = utils.FormatTableDataShowValue(dateValList[tmpLenData-1].Value)
+						}
+					}
+				} else {
+					tmpDateList := strings.Split(cell.DataTime, "-")
+					tmpDateValMap := make(map[string]float64)
+					if len(tmpDateList) == 2 {
+						//月度数据
+						if dateValMap, ok := edbMonthDataListMap[cell.EdbInfoId]; ok {
+							tmpDateValMap = dateValMap
+						}
+					} else {
+						// 日度数据
+						if dateValMap, ok := edbDayDataListMap[cell.EdbInfoId]; ok {
+							tmpDateValMap = dateValMap
+						}
+
+					}
+					if val, ok2 := tmpDateValMap[cell.DataTime]; ok2 {
+						//cell.ShowValue = fmt.Sprint(val)
+						cellKeyVal[cell.Uid] = val
+						cell.ShowValue = utils.FormatTableDataShowValue(val)
+					}
+				}
+				calculateCellMap[cell.Uid] = Cell{
+					Column:   k,
+					Row:      i,
+					CellInfo: cell,
+				}
+			case request.CustomTextDT: //自定义文本
+				if cell.Value == `` {
+					continue
+				}
+				// 处理看下能否转成float,如果可以的话,说明这个也是可以参与计算的
+				tmpDeci, tmpErr := decimal.NewFromString(cell.Value)
+				if tmpErr == nil {
+					tmpVal, _ := tmpDeci.Float64()
+					cellKeyVal[cell.Uid] = tmpVal
+
+					calculateCellMap[cell.Uid] = Cell{
+						Column:   k,
+						Row:      i,
+						CellInfo: cell,
+					}
+				}
+
+			case request.FormulateCalculateDataDT: // 公式计算(A+B这种)
+				calculateCellMap[cell.Uid] = Cell{
+					Column:   k,
+					Row:      i,
+					CellInfo: cell,
+				}
+
+				calculateChainList = append(calculateChainList, cell.Uid)
+
+			case request.InsertEdbCalculateDataDT: // 插入指标系统计算公式生成的值
+				// 日期
+				var cellDateTime string
+				// 日期关系配置不存在,则默认最新数据
+				if relationConf, ok := cellRelationConfMap[cell.Uid]; ok {
+					if relationConf.RelationDate.Key == `` {
+						// 日期关系配置未绑定
+						continue
+					}
+					// 配置
+					relationCell, ok := cellDataRelationMap[relationConf.RelationDate.Key]
+					if !ok {
+						// 找不到对应日期的单元格
+						continue
+					}
+					cellDateTime = relationCell.DataTime
+				}
+
+				var tmpDataMap map[string]float64
+
+				key := utils.MD5(cell.Value)
+				tmpDataMap, ok := edbSourceDataMap[key]
+				if !ok {
+					// 对应的配置值
+					var tmpConfig request.CalculateConf
+					err = json.Unmarshal([]byte(cell.Value), &tmpConfig)
+					if err != nil {
+						return
+					}
+
+					tmpDataList, ok := edbDataListMap[tmpConfig.EdbInfoId]
+					if !ok {
+						continue
+					}
+					edbInfo, ok := edbInfoMap[tmpConfig.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					req2 := &BaseCalculate{
+						DataList:      tmpDataList,
+						Frequency:     tmpConfig.Frequency,
+						Formula:       tmpConfig.Formula,
+						Calendar:      tmpConfig.Calendar,
+						MoveType:      tmpConfig.MoveType,
+						MoveFrequency: tmpConfig.MoveFrequency,
+						FromFrequency: edbInfo.Frequency,
+						Source:        tmpConfig.Source,
+					}
+
+					// 调用指标库去更新
+					reqJson, tmpErr := json.Marshal(req2)
+					if tmpErr != nil {
+						utils.FileLog.Error(fmt.Sprintf("计算失败1,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
+						err = tmpErr
+						return
+					}
+					respItem, tmpErr := data.BaseCalculate(string(reqJson))
+					if tmpErr != nil {
+						utils.FileLog.Error(fmt.Sprintf("计算失败2,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
+						err = tmpErr
+						return
+					}
+					if respItem.Ret != 200 {
+						utils.FileLog.Error(fmt.Sprintf("计算失败3,配置信息;%s;原因:%s;错误原因:%s", cell.Value, respItem.Msg, respItem.ErrMsg))
+						continue
+					}
+
+					tmpDataMap = respItem.Data.DataMap
+					// 计算结果存一份,万一存在重复的计算方式,那么省的重新计算一下
+					edbSourceDataMap[key] = tmpDataMap
+
+					lenDataList := len(respItem.Data.DateList)
+					if cellDateTime == `` && lenDataList > 0 {
+						cellDateTime = respItem.Data.DateList[lenDataList-1]
+					}
+				}
+
+				val := tmpDataMap[cellDateTime]
+				cellKeyVal[cell.Uid] = val
+				cell.ShowValue = utils.FormatTableDataShowValue(val)
+			}
+
+			row[i] = cell
+		}
+		config[k] = row
+	}
+
+	// 公式链计算
+	if len(calculateChainList) > 0 {
+		for _, cellKey := range calculateChainList {
+			// 查找这个单元格的位置,直接map找了,而不是遍历整个单元格
+			cellPosition, ok := calculateCellMap[cellKey]
+			if !ok {
+				utils.FileLog.Error("找不到单元格位置:", cellKey)
+				continue
+			}
+
+			cell := config[cellPosition.Column][cellPosition.Row]
+			if cell.DataType != request.FormulateCalculateDataDT { // 判断公式计算(A+B这种)类型,不是的话也过滤了
+				continue
+			}
+
+			val, has, tmpErr, tmpErrMsg := getCalculateValueByCell(calculateCellMap, cellKey, cellKeyVal)
+			if tmpErr != nil {
+				errMsg = tmpErrMsg
+				err = tmpErr
+				return
+			}
+			if !has {
+				continue
+			}
+
+			cellKeyVal[cell.Uid] = val
+			cell.ShowValue = utils.FormatTableDataShowValue(val)
+			config[cellPosition.Column][cellPosition.Row] = cell
+
+		}
+	}
+
+	newMixedTableCellDataList = config
+
+	return
+}
+
+// getCalculateValue 获取公式计算的结果
+func getCalculateValueByCell(calculateCellMap map[string]Cell, key string, cellKeyValMap map[string]float64) (val float64, has bool, err error, errMsg string) {
+	// 单元格的标签名
+	val, ok := cellKeyValMap[key]
+	if ok {
+		has = true
+		return
+	}
+
+	// 查找单元格数据
+	cell, ok := calculateCellMap[key]
+	if !ok {
+		err = errors.New("查找单元格" + key + "的数据失败")
+		return
+	}
+
+	colData := cell.CellInfo
+
+	// 如果不是基础计算单元格,直接返回
+	if colData.DataType != request.FormulateCalculateDataDT {
+		return
+	}
+
+	// 如果是计算单元格
+
+	tagList := make([]utils.CellPosition, 0)
+	// 计算单元格relationCellList
+	var relationCellList []request.RelationCell
+	if colData.Extra == `` {
+		err = errors.New(colData.Uid + "没有绑定关系")
+		return
+	}
+	err = json.Unmarshal([]byte(colData.Extra), &relationCellList)
+	if err != nil {
+		return
+	}
+
+	for _, relation := range relationCellList {
+		//relationCellTagName := strings.ToUpper(relation.Tag) + relation.Row
+		tmpVal, _, tmpErr, tmpErrMsg := getCalculateValueByCell(calculateCellMap, relation.Key, cellKeyValMap)
+		if tmpErr != nil {
+			errMsg = tmpErrMsg
+			err = tmpErr
+			return
+		}
+		cellKeyValMap[relation.Key] = tmpVal
+
+		rowInt, tmpErr := strconv.Atoi(relation.Row)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		tagList = append(tagList, utils.CellPosition{
+			Tag:   relation.Tag,
+			Row:   rowInt,
+			Value: tmpVal,
+		})
+	}
+
+	// 计算
+	val, errMsg, err = calculateByCellList(strings.ToUpper(colData.Value), tagList)
+	if err != nil {
+		return
+	}
+	// 重新赋值
+	has = true
+	cellKeyValMap[key] = val
+
+	return
+}
+
+// handleConfig
+// @Description: 处理混合表格配置
+// @author: Roc
+// @datetime2023-10-27 13:24:53
+// @param configList [][]request.MixedTableCellDataReq
+// @return newConfig [][]request.MixedTableCellDataReq
+// @return edbInfoIdList []int
+// @return dataEdbInfoIdList []int
+// @return err error
+// @return errMsg string
+func handleConfig(configList [][]request.MixedTableCellDataReq) (newConfig [][]request.MixedTableCellDataReq, edbInfoIdList []int, dataEdbInfoIdList []int, err error, errMsg string) {
+	edbInfoIdList = make([]int, 0)
+	dataEdbInfoIdList = make([]int, 0)
+
+	for ck, rowList := range configList {
+		for rk, cell := range rowList {
+			switch cell.DataType {
+			case request.EdbDT: // 指标信息
+				edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
+			case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值
+				dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
+			case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值
+				var config request.CalculateConf
+				err = json.Unmarshal([]byte(cell.Value), &config)
+				if err != nil {
+					return
+				}
+				edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
+				dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
+
+			case request.DateDT: // 日期类型
+				if cell.DataTimeType == request.EdbDateDT {
+					var config request.EdbDateConf
+					err = json.Unmarshal([]byte(cell.Value), &config)
+					if err != nil {
+						return
+					}
+					edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
+				} else {
+					date, tmpErr, tmpErrMsg := handleDate(cell.DataTimeType, cell.Value)
+					if tmpErr != nil {
+						err = tmpErr
+						errMsg = tmpErrMsg
+						return
+					}
+					rowList[rk].DataTime = date
+					rowList[rk].ShowValue = date
+				}
+			}
+		}
+		configList[ck] = rowList
+	}
+
+	newConfig = configList
+
+	return
+}
+
+// HandleDate
+// @Description: 日期处理
+// @author: Roc
+// @datetime2023-10-27 09:37:02
+// @param dataTimeType int
+// @param val string
+// @return date string
+// @return err error
+// @return errMsg string
+func HandleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
+	return handleDate(dataTimeType, val)
+}
+
+// handleDate
+// @Description: 日期处理
+// @author: Roc
+// @datetime2023-10-27 09:36:49
+// @param dataTimeType int
+// @param val string
+// @return date string
+// @return err error
+// @return errMsg string
+func handleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
+	if val == `` {
+		errMsg = "错误的日期数据"
+		err = errors.New(errMsg)
+		return
+	}
+	switch dataTimeType {
+	case request.CustomDateT: //手动输入日期
+		date = val
+	case request.SystemDateT: // 系统日期
+		date, err, errMsg = handleSystemDateT(val)
+	case request.EdbDateDT: // 导入指标日期(指标库的最新日期)
+	default:
+		errMsg = "错误的日期类型"
+		err = errors.New(errMsg)
+		return
+	}
+
+	return
+}
+
+// handleSystemDateT
+// @Description: 处理导入系统日期
+// @author: Roc
+// @datetime2023-10-27 09:36:21
+// @param confStr string
+// @return date string
+// @return err error
+// @return errMsg string
+func handleSystemDateT(confStr string) (date string, err error, errMsg string) {
+	var config request.SystemDateConf
+	err = json.Unmarshal([]byte(confStr), &config)
+	if err != nil {
+		return
+	}
+	switch config.Source {
+	case request.SystemCurrDateT:
+		date = time.Now().Format(utils.FormatDate)
+	case request.SystemCalculateDateT:
+		date, err, errMsg = handleSystemCalculateDateT(config.CalculateNum, config.CalculateFrequency)
+	case request.SystemFrequencyDateT: // 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
+		date, err, errMsg = handleSystemAppointDateT(config.Day, config.Frequency)
+	default:
+		errMsg = "错误的日期日期导入方式"
+		err = errors.New(fmt.Sprint("错误的日期日期导入方式:", config.Source))
+		return
+	}
+
+	return
+}
+
+// handleSystemCalculateDateT
+// @Description: 处理系统日期计算后的日期
+// @author: Roc
+// @datetime2023-10-27 09:31:22
+// @param num int
+// @param frequency string
+// @return date string
+// @return err error
+// @return errMsg string
+func handleSystemCalculateDateT(num int, frequency string) (date string, err error, errMsg string) {
+	if err != nil {
+		return
+	}
+	currDate := time.Now()
+	switch frequency {
+	case "", "日":
+		date = currDate.AddDate(0, 0, num).Format(utils.FormatDate)
+	default:
+		errMsg = "错误的日期频度:" + frequency
+		err = errors.New(errMsg)
+		return
+	}
+
+	return
+}
+
+// handleSystemAppointDateT
+// @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
+// @author: Roc
+// @datetime2023-10-27 09:31:35
+// @param Frequency string
+// @param Day string
+// @return date string
+// @return err error
+// @return errMsg string
+func handleSystemAppointDateT(appointDay, frequency string) (date string, err error, errMsg string) {
+	currDate := time.Now()
+	switch frequency {
+	case "本周":
+		day := int(currDate.Weekday())
+		if day == 0 { // 周日
+			day = 7
+		}
+		num := 0
+		switch appointDay {
+		case "周一":
+			num = 1
+		case "周二":
+			num = 2
+		case "周三":
+			num = 3
+		case "周四":
+			num = 4
+		case "周五":
+			num = 5
+		case "周六":
+			num = 6
+		case "周日":
+			num = 7
+		}
+		day = num - day
+		date = currDate.AddDate(0, 0, day).Format(utils.FormatDate)
+	case "本旬":
+		day := currDate.Day()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if day <= 10 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
+			} else if day <= 20 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if day <= 10 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
+			} else if day <= 20 {
+				tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本月":
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
+		case "最后一天":
+			tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本季":
+		month := currDate.Month()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if month <= 3 {
+				tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 9 {
+				tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if month <= 3 {
+				tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
+			} else if month <= 9 {
+				tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本半年":
+		month := currDate.Month()
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
+			}
+		case "最后一天":
+			if month <= 6 {
+				tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
+			} else {
+				tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+			}
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	case "本年":
+		var tmpDate time.Time
+		switch appointDay {
+		case "第一天":
+			tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
+		case "最后一天":
+			tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
+		}
+		date = tmpDate.Format(utils.FormatDate)
+	default:
+		errMsg = "错误的日期频度:" + frequency
+		err = errors.New(errMsg)
+		return
+	}
+
+	return
+}
+
+// calculateByCellList
+// @Description: 根据单元格来进行公式计算
+// @author: Roc
+// @datetime2023-11-14 16:17:38
+// @param calculateFormula string
+// @param tagList []utils.CellPosition
+// @return calVal string
+// @return errMsg string
+// @return err error
+func calculateByCellList(calculateFormula string, tagList []utils.CellPosition) (calVal float64, errMsg string, err error) {
+	if calculateFormula == "" {
+		errMsg = "公式异常"
+		err = errors.New(errMsg)
+		return
+	}
+
+	calculateFormula = strings.TrimPrefix(calculateFormula, "=")
+	calculateFormula = strings.Replace(calculateFormula, "(", "(", -1)
+	calculateFormula = strings.Replace(calculateFormula, ")", ")", -1)
+	calculateFormula = strings.Replace(calculateFormula, ",", ",", -1)
+	calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
+	calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
+
+	rowList := make([]int, 0)
+	rowListMap := make(map[int][]utils.CellPosition)
+	for _, v := range tagList {
+		tmpRowList, ok := rowListMap[v.Row]
+		if !ok {
+			rowList = append(rowList, v.Row)
+			tmpRowList = make([]utils.CellPosition, 0)
+		}
+		tmpRowList = append(tmpRowList, v)
+		rowListMap[v.Row] = tmpRowList
+	}
+
+	sort.Ints(rowList)
+
+	list := make([]utils.CellPosition, 0)
+	for _, row := range rowList {
+		list = append(list, rowListMap[row]...)
+	}
+
+	formulaFormStr := utils.ReplaceFormulaByCellList(list, calculateFormula)
+	//计算公式异常,那么就移除该指标
+	if formulaFormStr == `` {
+		errMsg = "公式异常"
+		err = errors.New(errMsg)
+		return
+	}
+
+	expression := formula.NewExpression(formulaFormStr)
+	calResult, err := expression.Evaluate()
+	if err != nil {
+		errMsg = "计算失败"
+		err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
+		// 分母为0的报错
+		if strings.Contains(err.Error(), "divide by zero") {
+			errMsg = "分母不能为0"
+			err = errors.New("分母不能为空,计算公式:" + formulaFormStr)
+		}
+		return
+	}
+	// 如果计算结果是NAN,那么就提示报错
+	if calResult.IsNan() {
+		errMsg = "计算失败"
+		err = errors.New("计算失败:计算结果是:NAN;formulaStr:" + formulaFormStr)
+		return
+	}
+	calVal, err = calResult.Float64()
+	if err != nil {
+		return
+	}
+
+	// 转Decimal然后四舍五入
+	calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
+
+	return
+}

+ 1 - 2
services/data/future_good/base_future_good_lib.go

@@ -5,7 +5,6 @@ import (
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/utils"
-	"fmt"
 	"io/ioutil"
 	"net/http"
 	"strings"
@@ -86,6 +85,6 @@ func HttpPost(url, postData string, params ...string) ([]byte, error) {
 	resp, err := client.Do(req)
 	defer resp.Body.Close()
 	b, err := ioutil.ReadAll(resp.Body)
-	fmt.Println("HttpPost:" + string(b))
+	utils.FileLog.Debug("HttpPost:" + string(b))
 	return b, err
 }

+ 1 - 2
services/data/supply_analysis/base_supply_analysis_lib.go

@@ -4,7 +4,6 @@ import (
 	"encoding/json"
 	"eta/eta_api/models"
 	"eta/eta_api/utils"
-	"fmt"
 	"io/ioutil"
 	"net/http"
 	"strings"
@@ -92,6 +91,6 @@ func HttpPost(url, postData string, params ...string) ([]byte, error) {
 	resp, err := client.Do(req)
 	defer resp.Body.Close()
 	b, err := ioutil.ReadAll(resp.Body)
-	fmt.Println("HttpPost:" + string(b))
+	utils.FileLog.Debug("HttpPost:" + string(b))
 	return b, err
 }

+ 33 - 0
utils/calculate.go

@@ -188,6 +188,39 @@ func ReplaceFormula(valArr map[string]float64, formulaStr string) string {
 	return formulaStr
 }
 
+// CellPosition
+// @Description: 单元格位置
+type CellPosition struct {
+	Tag   string
+	Row   int
+	Value float64
+}
+
+// ReplaceFormulaByCellList
+// @Description: 根据单元格列表替换
+// @author: Roc
+// @datetime2023-11-14 16:16:12
+// @param cellList []CellPosition
+// @param formulaStr string
+// @return string
+func ReplaceFormulaByCellList(cellList []CellPosition, formulaStr string) string {
+	funMap := getFormulaMap()
+	for k, v := range funMap {
+		formulaStr = strings.Replace(formulaStr, k, v, -1)
+	}
+
+	replaceCount := 0
+	for _, cell := range cellList {
+		dvStr := fmt.Sprintf("%v", cell.Value)
+		formulaStr = strings.Replace(formulaStr, fmt.Sprint(cell.Tag, cell.Row), dvStr, -1)
+		replaceCount++
+	}
+	for k, v := range funMap {
+		formulaStr = strings.Replace(formulaStr, v, k, -1)
+	}
+	return formulaStr
+}
+
 func getFormulaMap() map[string]string {
 	funMap := make(map[string]string)
 	funMap["MAX"] = "[@@]"

+ 1 - 1
utils/config.go

@@ -249,7 +249,7 @@ func init() {
 	}
 	Rc, Re = cache.NewCache(REDIS_CACHE) //初始化缓存
 	if Re != nil {
-		fmt.Println(Re)
+		fmt.Println("redis链接异常:", Re)
 		panic(any(Re))
 	}