瀏覽代碼

Merge branch 'bzq1/excel_rule_decimal_master' of eta_server/eta_api into master

鲍自强 6 月之前
父節點
當前提交
049798e40f

+ 418 - 32
controllers/data_manage/excel/excel_info.go

@@ -16,15 +16,16 @@ import (
 	"eta/eta_api/services/excel"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
-	"github.com/shopspring/decimal"
-	"github.com/yidane/formula"
 	"io"
 	"os"
 	"path/filepath"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/shopspring/decimal"
+	"github.com/yidane/formula"
 )
 
 // ExcelInfoController ETA表格管理
@@ -159,30 +160,31 @@ func (c *ExcelInfoController) Add() {
 	if req.Source == utils.TIME_TABLE {
 		jsonStrByte, err := json.Marshal(req.TableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,转json失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		var tableData request.TableDataReq
 		err = json.Unmarshal(jsonStrByte, &tableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,json转结构体失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 
 		tableDataConfig, err := excel2.GetTableDataConfig(tableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		edbInfoIdList = tableDataConfig.EdbInfoIdList
 
+		tableDataConfig.DecimalConfig = tableData.DecimalConfig
 		contentByte, err := json.Marshal(tableDataConfig)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取后,转json失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		content = string(contentByte)
@@ -675,21 +677,21 @@ func (c *ExcelInfoController) Detail() {
 	if excelDetail.Source == utils.TIME_TABLE {
 		jsonStrByte, err := json.Marshal(excelDetail.TableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,转json失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		var tableData request.TableDataReq
 		err = json.Unmarshal(jsonStrByte, &tableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,json转结构体失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList(tableData.EdbInfoIdList)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		excelDetail.ExcelSource = strings.Join(sourceNameList, ",")
@@ -936,28 +938,29 @@ func (c *ExcelInfoController) Edit() {
 	case utils.TIME_TABLE: // 自定义表格
 		jsonStrByte, err := json.Marshal(req.TableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,转json失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		var tableData request.TableDataReq
 		err = json.Unmarshal(jsonStrByte, &tableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,json转结构体失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		edbInfoIdList = tableData.EdbInfoIdList
 		tableDataConfig, err := excel2.GetTableDataConfig(tableData)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
+		tableDataConfig.DecimalConfig = tableData.DecimalConfig
 		contentByte, err := json.Marshal(tableDataConfig)
 		if err != nil {
-			br.Msg = "自定义表格数据获取失败"
-			br.ErrMsg = "自定义表格数据获取后,转json失败,Err:" + err.Error()
+			br.Msg = "时间序列表格数据获取失败"
+			br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
 			return
 		}
 		content = string(contentByte)
@@ -1643,7 +1646,10 @@ func (c *ExcelInfoController) GetExcelTableData() {
 	}
 
 	tableData = excel.HandleTableCell(tableData)
-
+	tableData, err = excel.HandleRuleToTableCell(excelInfo.ExcelInfoId, tableData)
+	if err != nil {
+		utils.FileLog.Info("表格管理规则处理失败,HandleRuleToTableCell err:", err.Error())
+	}
 	config := response.ExcelTableDetailConfigResp{
 		FontSize: 9,
 	}
@@ -1835,7 +1841,7 @@ func (c *ExcelInfoController) GetFirstEdbData() {
 		return
 	}
 
-	dataList, err := excel2.GetFirstEdbDataList(edbInfo, num, []string{})
+	dataList, err := excel2.GetFirstEdbDataList(edbInfo, num, []string{}, -1)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -1857,6 +1863,10 @@ func (c *ExcelInfoController) GetFirstEdbData() {
 	}
 	excelSource := strings.Join(sourceNameList, ",")
 	excelSourceEn := strings.Join(sourceNameEnList, ",")
+	if len(dataList) == 0 {
+		br.Msg = "指标数据异常,请检查"
+		return
+	}
 
 	br.Ret = 200
 	br.Success = true
@@ -1864,6 +1874,7 @@ func (c *ExcelInfoController) GetFirstEdbData() {
 	br.Data = response.TableDataItem{
 		EdbInfoId:     edbInfoId,
 		Data:          dataList,
+		Decimal:       -1,
 		ExcelSource:   excelSource,
 		ExcelSourceEn: excelSourceEn,
 	}
@@ -1914,7 +1925,7 @@ func (c *ExcelInfoController) GetOtherEdbData() {
 		br.ErrMsg = fmt.Sprint("获取指标信息失败,Err:", err.Error())
 		return
 	}
-	dataList, err := excel2.GetOtherEdbDataList(edbInfo, req.DateList)
+	dataList, err := excel2.GetOtherEdbDataListFollowDate(edbInfo, req.DateList, req.DateDecimal)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -1943,11 +1954,148 @@ func (c *ExcelInfoController) GetOtherEdbData() {
 	br.Data = response.TableDataItem{
 		EdbInfoId:     req.EdbInfoId,
 		Data:          dataList,
+		Decimal:       -1,
 		ExcelSource:   excelSource,
 		ExcelSourceEn: excelSourceEn,
 	}
 }
 
+// GetBatchEdbData
+// @Title 批量获取指定日期数据接口
+// @Description 批量获取未来日期数据接口
+// @Param	request	body request.GetBatchEdbDateDataReq true "type json string"
+// @router /excel_info/table/batch_edb_data_list [post]
+func (c *ExcelInfoController) GetBatchEdbData() {
+	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.GetBatchEdbDateDataReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if len(req.EdbInfoId) == 0 {
+		br.Msg = "请选择指标"
+		br.IsSendEmail = false
+		return
+	}
+	tableList := make([]*response.TableDataItem, 0)
+	var firstDataList []string
+	for i, v := range req.EdbInfoId {
+		if req.Num <= 0 {
+			br.Msg = "期数必须大于0"
+			br.IsSendEmail = false
+			return
+		}
+		edbInfo, err := data_manage.GetEdbInfoById(v)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = fmt.Sprint("获取指标信息失败,Err:", err.Error())
+			return
+		}
+		if len(req.DateList) == 0 {
+			req.Num = 12
+		}
+		if len(firstDataList) == 0 {
+			firstDataList = req.DateList
+		}
+		if len(firstDataList) != 0 && len(firstDataList) != req.Num {
+			req.Num = len(firstDataList)
+		}
+		if i == 0 {
+			dataList, err := excel2.GetFirstEdbDataList(edbInfo, req.Num, firstDataList, req.Decimal[i])
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
+				return
+			}
+
+			// 默认是倒序返回的数据,如果要正序的话,那么翻转下就好了
+			if req.SortType == "asc" {
+				for i, j := 0, len(dataList)-1; i < j; i, j = i+1, j-1 {
+					dataList[i], dataList[j] = dataList[j], dataList[i]
+				}
+			}
+			dataList = excel2.PadFirstEdbDataList(dataList, req.DateList, req.SortType, req.Decimal[i])
+
+			sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList([]int{v})
+			if err != nil {
+				br.Msg = "时间序列表格数据获取失败"
+				br.ErrMsg = "时间序列表格数据获取失败,Err:" + err.Error()
+				return
+			}
+			excelSource := strings.Join(sourceNameList, ",")
+			excelSourceEn := strings.Join(sourceNameEnList, ",")
+			if len(dataList) == 0 {
+				br.Msg = "指标数据异常,请检查"
+				return
+			}
+			tableList = append(tableList, &response.TableDataItem{
+				EdbInfoId:     v,
+				Data:          dataList,
+				Decimal:       req.Decimal[i],
+				ExcelSource:   excelSource,
+				ExcelSourceEn: excelSourceEn,
+			})
+			if len(firstDataList) == 0 {
+				tmpDataList := make([]string, 0)
+				for _, v := range dataList {
+					tmpDataList = append(tmpDataList, v.DataTime)
+				}
+				firstDataList = tmpDataList
+			}
+		} else {
+			dataList, err := excel2.GetOtherEdbDataList(edbInfo, firstDataList, req.Decimal[i])
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
+				return
+			}
+
+			// 默认是倒序返回的数据,如果要正序的话,那么翻转下就好了
+			if req.SortType == "asc" {
+				for i, j := 0, len(dataList)-1; i < j; i, j = i+1, j-1 {
+					dataList[i], dataList[j] = dataList[j], dataList[i]
+				}
+			}
+
+			sourceNameList, sourceNameEnList, err := excel2.GetEdbSourceByEdbInfoIdList([]int{v})
+			if err != nil {
+				br.Msg = "自定义表格数据获取失败"
+				br.ErrMsg = "自定义表格数据获取失败,Err:" + err.Error()
+				return
+			}
+			excelSource := strings.Join(sourceNameList, ",")
+			excelSourceEn := strings.Join(sourceNameEnList, ",")
+			tableList = append(tableList, &response.TableDataItem{
+				EdbInfoId:     v,
+				Decimal:       req.Decimal[i],
+				Data:          dataList,
+				ExcelSource:   excelSource,
+				ExcelSourceEn: excelSourceEn,
+			})
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = tableList
+}
+
 // GetFutureDateData
 // @Title 获取未来日期数据接口
 // @Description 获取未来日期数据接口
@@ -2091,7 +2239,7 @@ func (c *ExcelInfoController) GetFutureDateData() {
 		for i := lenDate - 1; i >= 0; i-- {
 			dateStrList = append(dateStrList, dateList[i].Format(utils.FormatDate))
 		}
-		for _, v := range req.EdbInfoIdList {
+		for j, v := range req.EdbInfoIdList {
 			tmpEdbInfo, ok := edbInfoMap[v]
 			if !ok {
 				br.Msg = "获取指标信息失败"
@@ -2099,7 +2247,7 @@ func (c *ExcelInfoController) GetFutureDateData() {
 				return
 			}
 
-			dataList, err := excel2.GetOtherEdbDataList(tmpEdbInfo, dateStrList)
+			dataList, err := excel2.GetOtherEdbDataList(tmpEdbInfo, dateStrList, req.Decimal[j])
 			if err != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -2107,6 +2255,7 @@ func (c *ExcelInfoController) GetFutureDateData() {
 			}
 			result = append(result, response.TableDataItem{
 				EdbInfoId: v,
+				Decimal:   req.Decimal[j],
 				Data:      dataList,
 			})
 		}
@@ -2182,7 +2331,7 @@ func (c *ExcelInfoController) GetHistoryDateData() {
 			br.ErrMsg = "获取指标信息失败,err:" + err.Error()
 			return
 		}
-		firstDataList, err := excel2.GetFirstHistoryEdbDataList(tmpEdbInfo, req.Num, req.EndDate)
+		firstDataList, err := excel2.GetFirstHistoryEdbDataList(tmpEdbInfo, req.Num, req.EndDate, req.Decimal[0])
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -2191,6 +2340,7 @@ func (c *ExcelInfoController) GetHistoryDateData() {
 
 		result = append(result, response.TableDataItem{
 			EdbInfoId: req.EdbInfoIdList[0],
+			Decimal:   req.Decimal[0],
 			Data:      firstDataList,
 		})
 
@@ -2211,7 +2361,7 @@ func (c *ExcelInfoController) GetHistoryDateData() {
 				return
 			}
 
-			dataList, err := excel2.GetOtherEdbDataList(tmpEdbInfo, dateStrList)
+			dataList, err := excel2.GetOtherEdbDataList(tmpEdbInfo, dateStrList, req.Decimal[k])
 			if err != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = fmt.Sprint("获取失败,Err:", err.Error())
@@ -2219,6 +2369,7 @@ func (c *ExcelInfoController) GetHistoryDateData() {
 			}
 			result = append(result, response.TableDataItem{
 				EdbInfoId: v,
+				Decimal:   req.Decimal[k],
 				Data:      dataList,
 			})
 		}
@@ -2966,3 +3117,238 @@ func (c *ExcelInfoController) GetEdbSource() {
 	br.Ret = 200
 	br.Success = true
 }
+
+// ExcelRule
+// @Title 添加表格规则
+// @Description 添加表格规则
+// @Param	request	body excel3.BatchRefreshExcelReq true "type json string"
+// @Success Ret=200 刷新成功
+// @router /excel_info/rule/add [post]
+func (c *ExcelInfoController) AddExcelRule() {
+	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.ExcelRuleMappingReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.LeftValue == "" {
+		br.Msg = "条件值不能为空"
+		return
+	}
+	if req.Scope == "" {
+		br.Msg = "应用选区不能为空"
+		return
+	}
+	if req.FontColor == "" {
+		br.Msg = "字体颜色不能为空"
+		return
+	}
+	if req.BackgroundColor == "" {
+		br.Msg = "背景颜色不能为空"
+		return
+	}
+	if req.RuleType == 3 && req.RightValue == "" {
+		br.Msg = "条件值不能为空"
+		return
+	}
+	err = excel2.AddExcelRule(req, c.Lang)
+	if err != nil {
+		br.Msg = "规则添加失败"
+		br.ErrMsg = "规则添加失败,Err:" + err.Error()
+		return
+	}
+	br.Msg = "添加成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// EditExcelRule
+// @Title 编辑表格规则
+// @Description 编辑表格规则
+// @Param	request	body request.ExcelRuleMappingReq true "type json string"
+// @Success Ret=200 刷新成功
+// @router /excel_info/rule/edit [post]
+func (c *ExcelInfoController) EditExcelRule() {
+	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.ExcelRuleMappingReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.LeftValue == "" {
+		br.Msg = "条件值不能为空"
+		return
+	}
+	if req.Scope == "" {
+		br.Msg = "应用选区不能为空"
+		return
+	}
+	if req.FontColor == "" {
+		br.Msg = "字体颜色不能为空"
+		return
+	}
+	if req.BackgroundColor == "" {
+		br.Msg = "背景颜色不能为空"
+		return
+	}
+	if req.RuleType == 3 && req.RightValue == "" {
+		br.Msg = "条件值不能为空"
+		return
+	}
+	if req.ExcelRuleMappingId <= 0 {
+		br.Msg = "非法的管理规则ID"
+		return
+	}
+	err = excel2.ModifyExcelRule(req, c.Lang)
+	if err != nil {
+		br.Msg = "规则编辑失败"
+		br.ErrMsg = "规则编辑失败,Err:" + err.Error()
+		return
+	}
+	br.Msg = "编辑成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// DeleteExcelRule
+// @Title 删除表格规则
+// @Description 删除表格规则
+// @Param	request	body request.ExcelRuleMappingReq true "type json string"
+// @Success Ret=200 刷新成功
+// @router /excel_info/rule/delete [post]
+func (c *ExcelInfoController) DeleteExcelRule() {
+	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.DeleteExcelRuleMappingReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ExcelRuleMappingId <= 0 {
+		br.Msg = "非法的管理规则ID"
+		return
+	}
+	err = excel3.DeleteExcelRuleMappingById(req.ExcelRuleMappingId)
+	if err != nil {
+		br.Msg = "规则删除失败"
+		br.ErrMsg = "规则删除失败,Err:" + err.Error()
+		return
+	}
+	br.Msg = "删除成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// GetExcelRuleList
+// @Title 表格规则列表
+// @Description 表格规则列表
+// @Param   ExcelInfoId   query   int  true       "id"
+// @Success Ret=200 获取成功
+// @router /excel_info/rule/list [get]
+func (c *ExcelInfoController) GetExcelRuleList() {
+	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
+	}
+	ExcelInfoId, _ := c.GetInt("ExcelInfoId")
+
+	if ExcelInfoId <= 0 {
+		br.Msg = "请选择表格"
+		return
+	}
+
+	items, err := excel2.GetExcelRuleList(ExcelInfoId)
+	if err != nil {
+		br.Msg = "管理规则编辑失败"
+		br.ErrMsg = "管理规则添加失败,Err:" + err.Error()
+		return
+	}
+	if items.List == nil {
+		items.List = []*excel3.ExcelInfoRuleMappingView{}
+	}
+
+	br.Data = items
+	br.Msg = "获取成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// GetExcelRuleDetail
+// @Title 表格规则详情
+// @Description 表格规则详情
+// @Param   ExcelInfoRuleMappingId   query   int  true       "id"
+// @Success Ret=200 获取成功
+// @router /excel_info/rule/detail [get]
+func (c *ExcelInfoController) GetExcelRuleDetail() {
+	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
+	}
+	excelInfoRuleMappingId, _ := c.GetInt("ExcelInfoRuleMappingId")
+
+	items, err := excel2.GetExcelRuleDetail(excelInfoRuleMappingId)
+	if err != nil {
+		br.Msg = "管理规则编辑失败"
+		br.ErrMsg = "管理规则添加失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = items
+	br.Msg = "获取成功"
+	br.Ret = 200
+	br.Success = true
+}

+ 82 - 0
models/data_manage/excel/excel_info_rule_mapping.go

@@ -0,0 +1,82 @@
+package excel
+
+import (
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type ExcelInfoRuleMapping struct {
+	ExcelInfoRuleMappingId int       `orm:"pk" description:"主键"`
+	ExcelInfoId            int       `description:"Excel信息ID"`
+	RuleType               int       `description:"规则类型"`
+	LeftValue              string    `description:"左值"`
+	LeftValueBack          string    `description:"左值后端存储"`
+	LeftValueType          int       `description:"左值类型"`
+	RightValue             string    `description:"右值"`
+	RightValueBack         string    `description:"右值后端存储"`
+	RightValueType         int       `description:"右值类型"`
+	FontColor              string    `description:"字体颜色"`
+	BackgroundColor        string    `description:"背景颜色"`
+	Remark                 string    `description:"预设颜色说明"`
+	RemarkEn               string    `description:"预设颜色英文说明"`
+	Scope                  string    `description:"作用范围"`
+	ScopeCoord             string    `description:"作用范围坐标"`
+	ScopeShow              string    `description:"作用范围坐标前端显示"`
+	CreateTime             time.Time `description:"创建时间"`
+}
+
+type ExcelInfoRuleMappingView struct {
+	ExcelInfoRuleMappingId int    `orm:"pk" description:"主键"`
+	ExcelInfoId            int    `description:"Excel信息ID"`
+	RuleType               int    `description:"规则类型"`
+	LeftValue              string `description:"左值"`
+	LeftValueBack          string `description:"左值后端存储" json:"-"`
+	LeftValueType          int    `description:"左值类型"`
+	RightValue             string `description:"右值"`
+	RightValueBack         string `description:"右值后端存储" json:"-"`
+	RightValueType         int    `description:"右值类型"`
+	FontColor              string `description:"字体颜色"`
+	BackgroundColor        string `description:"背景颜色"`
+	Remark                 string `description:"预设颜色说明"`
+	RemarkEn               string `description:"预设颜色英文说明"`
+	Scope                  string `description:"作用范围"`
+	ScopeCoord             string `description:"作用范围坐标"`
+	ScopeShow              string `description:"作用范围坐标前端显示"`
+	CreateTime             string `description:"创建时间"`
+}
+
+func (e *ExcelInfoRuleMapping) Insert() (insertId int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	insertId, err = o.Insert(e)
+	return
+}
+
+func (e *ExcelInfoRuleMapping) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(e, cols...)
+	return
+}
+
+// GetExcelRuleMappingByExcelInfoId 根据excelInfoId获取规则映射信息
+func GetExcelRuleMappingByExcelInfoId(id int) (items []*ExcelInfoRuleMappingView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM excel_info_rule_mapping WHERE excel_info_id = ? ORDER BY create_time ASC`
+	_, err = o.Raw(sql, id).QueryRows(&items)
+	return
+}
+
+// GetExcelRuleMappingById 根据主键Id获取规则映射信息
+func GetExcelRuleMappingById(id int) (item *ExcelInfoRuleMappingView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM excel_info_rule_mapping WHERE excel_info_rule_mapping_id = ?`
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func DeleteExcelRuleMappingById(id int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `DELETE FROM excel_info_rule_mapping WHERE excel_info_rule_mapping_id = ?`
+	_, err = o.Raw(sql, id).Exec()
+	return
+}

+ 111 - 1
models/data_manage/excel/request/excel_info.go

@@ -1,5 +1,7 @@
 package request
 
+import "encoding/json"
+
 // MoveExcelInfoReq 移动excel表格请求
 type MoveExcelInfoReq struct {
 	ExcelClassifyId int `description:"excel表格分类id"`
@@ -61,7 +63,16 @@ type CalculateReq struct {
 
 // GetOtherEdbDateDataReq 获取其他指标的指定日期的数据
 type GetOtherEdbDateDataReq struct {
-	EdbInfoId int      `description:"指标id"`
+	EdbInfoId   int            `description:"指标id"`
+	SortType    string         `description:"如何排序,是正序还是倒序,枚举值:asc 正序,desc 倒序,不传默认倒序"`
+	DateList    []string       `description:"日期列表,从小到大"`
+	DateDecimal map[string]int `description:"日期行的小数位数映射"`
+}
+
+type GetBatchEdbDateDataReq struct {
+	EdbInfoId []int    `description:"指标id"`
+	Num       int      `description:"默认期数"`
+	Decimal   []int    `description:"指标上的小数位数"`
 	SortType  string   `description:"如何排序,是正序还是倒序,枚举值:asc 正序,desc 倒序,不传默认倒序"`
 	DateList  []string `description:"日期列表,从小到大"`
 }
@@ -71,6 +82,7 @@ type GetFutureDateDataReq struct {
 	EdbInfoIdList []int  `description:"指标id列表,从左至右,从上到下的顺序"`
 	DateType      int    `description:"日期类型,1:期数,2:截止日期"`
 	Num           int    `description:"需要添加的期数"`
+	Decimal       []int  `description:"小数位数, 从左至右,从上到下的顺序"`
 	StartDate     string `description:"开始日期"`
 	EndDate       string `description:"结束日期"`
 }
@@ -79,6 +91,7 @@ type GetFutureDateDataReq struct {
 type GetHistoryDateDataReq struct {
 	EdbInfoIdList []int  `description:"指标id列表,从左至右,从上到下的顺序"`
 	Num           int    `description:"需要添加的期数"`
+	Decimal       []int  `description:"小数位数, 从左至右,从上到下的顺序"`
 	EndDate       string `description:"结束日期"`
 }
 
@@ -96,6 +109,12 @@ type TableDataReq struct {
 	Sort          int               `description:"日期排序,1:倒序,2:正序"`
 	Data          []EdbInfoData     `description:"数据列表"`
 	TextRowData   [][]ManualDataReq `description:"文本列表"`
+	DecimalConfig []DecimalConfig   `description:"小数位数配置"`
+}
+type DecimalConfig struct {
+	Row     string `description:"行上的索引, 目前仅保存指标的日期"`
+	Col     int    `description:"列上的索引, 目前仅保存edbInfoId"`
+	Decimal int    `description:"小数位数, 从左至右,从上到下的顺序"`
 }
 
 // EdbInfoData 自定义表格的数据
@@ -108,12 +127,54 @@ type EdbInfoData struct {
 	Frequency        string          `description:"频度"`
 	Unit             string          `description:"单位"`
 	UnitEn           string          `description:"英文单位"`
+	Decimal          int             `description:"小数位数"`
+	ClassifyId       int             `description:"所属分类" json:"-"`
+	IsJoinPermission int             `description:"是否加入权限管控,0:不加入;1:加入;默认:0" json:"-"`
+	HaveOperaAuth    bool            `description:"是否有数据权限,默认:false"`
+	Data             []ManualDataReq `description:"单元格数据列表"`
+}
+type EdbInfoDataTemp struct {
+	EdbInfoId        int             `description:"指标ID"`
+	Tag              string          `description:"标签"`
+	EdbName          string          `description:"指标名称"`
+	EdbNameEn        string          `description:"英文指标名称"`
+	EdbAliasName     string          `description:"指标别名"`
+	Frequency        string          `description:"频度"`
+	Unit             string          `description:"单位"`
+	UnitEn           string          `description:"英文单位"`
+	Decimal          *int            `description:"小数位数"`
 	ClassifyId       int             `description:"所属分类" json:"-"`
 	IsJoinPermission int             `description:"是否加入权限管控,0:不加入;1:加入;默认:0" json:"-"`
 	HaveOperaAuth    bool            `description:"是否有数据权限,默认:false"`
 	Data             []ManualDataReq `description:"单元格数据列表"`
 }
 
+func (e *EdbInfoData) UnmarshalJSON(data []byte) error {
+	var alias EdbInfoDataTemp
+
+	if err := json.Unmarshal(data, &alias); err != nil {
+		return err
+	}
+	if alias.Decimal != nil {
+		e.Decimal = *alias.Decimal
+	} else {
+		e.Decimal = -1
+	}
+	e.EdbInfoId = alias.EdbInfoId
+	e.Tag = alias.Tag
+	e.EdbName = alias.EdbName
+	e.EdbNameEn = alias.EdbNameEn
+	e.EdbAliasName = alias.EdbAliasName
+	e.Frequency = alias.Frequency
+	e.Unit = alias.Unit
+	e.UnitEn = alias.UnitEn
+	e.ClassifyId = alias.ClassifyId
+	e.IsJoinPermission = alias.IsJoinPermission
+	e.HaveOperaAuth = alias.HaveOperaAuth
+	e.Data = alias.Data
+	return nil
+}
+
 // ManualDataReq 自定义表格的单元格数据
 type ManualDataReq struct {
 	DataType            int               `description:"数据类型,1:普通的,2:插值法,3:手动输入,4:公式计算,5:预测值"`
@@ -121,9 +182,40 @@ type ManualDataReq struct {
 	DataTimeType        int               `description:"日期类型,1:实际日期;2:未来日期"`
 	ShowValue           string            `description:"展示值"`
 	Value               string            `description:"实际值(计算公式)"`
+	Decimal             int               `description:"小数位数"`
 	RelationEdbInfoList []RelationEdbInfo `description:"关联指标(计算公式中关联的指标,用于计算的时候去匹配)"`
 }
 
+type ManualDataTemp struct {
+	DataType            int               `description:"数据类型,1:普通的,2:插值法,3:手动输入,4:公式计算,5:预测值"`
+	DataTime            string            `description:"所属日期"`
+	DataTimeType        int               `description:"日期类型,1:实际日期;2:未来日期"`
+	ShowValue           string            `description:"展示值"`
+	Value               string            `description:"实际值(计算公式)"`
+	Decimal             *int              `description:"小数位数"`
+	RelationEdbInfoList []RelationEdbInfo `description:"关联指标(计算公式中关联的指标,用于计算的时候去匹配)"`
+}
+
+func (m *ManualDataReq) UnmarshalJSON(data []byte) error {
+	var alias ManualDataTemp
+
+	if err := json.Unmarshal(data, &alias); err != nil {
+		return err
+	}
+	if alias.Decimal != nil {
+		m.Decimal = *alias.Decimal
+	} else {
+		m.Decimal = -1
+	}
+	m.DataType = alias.DataType
+	m.DataTime = alias.DataTime
+	m.DataTimeType = alias.DataTimeType
+	m.ShowValue = alias.ShowValue
+	m.Value = alias.Value
+	m.RelationEdbInfoList = alias.RelationEdbInfoList
+	return nil
+}
+
 // RelationEdbInfo 自定义表格中单元格的关联指标
 type RelationEdbInfo struct {
 	Tag string `description:"指标标签"`
@@ -160,3 +252,21 @@ type ShareExcelInfoReq struct {
 	ViewUserIds []int `description:"查看权限用户IDs"`
 	EditUserIds []int `description:"编辑权限用户IDs"`
 }
+
+type ExcelRuleMappingReq struct {
+	ExcelRuleMappingId int    `description:"规则映射ID"`
+	ExcelInfoId        int    `description:"ETA表格ID"`
+	RuleType           int    `description:"规则类型:1-大于,2-小于,3-介于,4-等于,5-发生日期"`
+	LeftValue          string `description:"条件值"`
+	LeftValueType      int    `description:"条件值的类型,1:数值,2:坐标"`
+	RightValue         string `description:"条件值, 用于介于的条件"`
+	RightValueType     int    `description:"条件值的类型,1:数值,2:坐标"`
+	FontColor          string `description:"字体颜色"`
+	BackgroundColor    string `description:"背景颜色"`
+	Remark             string `description:"预设的单元格样式名称"`
+	Scope              string `description:"应用选区"`
+}
+
+type DeleteExcelRuleMappingReq struct {
+	ExcelRuleMappingId int `description:"规则映射ID"`
+}

+ 7 - 2
models/data_manage/excel/request/mixed_table.go

@@ -133,8 +133,13 @@ type MixDateCalculateTagReq struct {
 
 // MixCellShowStyle 混合表格 单元格样式展示计算
 type MixCellShowStyle struct {
-	Pn int    `description:"小数点位数增加或减少,正数表述增加,负数表示减少" json:"pn"`
-	Nt string `description:"变换类型:number 小数点位数改变,percent百分比," json:"nt"`
+	Pn              int         `description:"小数点位数增加或减少,正数表述增加,负数表示减少" json:"pn"`
+	Nt              string      `description:"变换类型:number 小数点位数改变,percent百分比," json:"nt"`
+	GlObj           interface{} `description:"公式对象:1:数值,2:百分比,3:文本" json:"glObj"`
+	Decimal         *int        `description:"小数点位数"`
+	Last            string      `description:"起始操作:nt|decimal"`
+	Color           string      `description:"颜色值,#RRG" json:"color"`
+	BackgroundColor string      `description:"背景颜色值,#RRG" json:"background-color"`
 }
 
 type DateDataBeforeAfterReq struct {

+ 7 - 1
models/data_manage/excel/response/excel_info.go

@@ -4,8 +4,9 @@ import (
 	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"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
 // AddExcelInfoResp 添加excel表格的返回
@@ -49,6 +50,7 @@ type TableCellResp struct {
 type TableDataItem struct {
 	EdbInfoId     int                     `description:"指标id"`
 	Data          []request.ManualDataReq `description:"数据列表"`
+	Decimal       int                     `description:"小数位数"`
 	ExcelSource   string                  `description:"表格来源str"`
 	ExcelSourceEn string                  `description:"表格来源(英文)"`
 }
@@ -118,3 +120,7 @@ type ShareExcelInfoDetail struct {
 	ViewUserIds []int `description:"查看权限用户IDs"`
 	EditUserIds []int `description:"编辑权限用户IDs"`
 }
+
+type ExcelRuleListResp struct {
+	List []*excel2.ExcelInfoRuleMappingView
+}

+ 10 - 9
models/db.go

@@ -506,15 +506,16 @@ func initChartFramework() {
 // 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 与 指标 的关系表
-		new(excel.ExcelWorker),     // 平衡表协作人表格
-		new(excel.ExcelChartEdb),   // 平衡表做图指标
-		new(excel.ExcelChartData),  // 平衡表作图数据
+		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 与 指标 的关系表
+		new(excel.ExcelWorker),          // 平衡表协作人表格
+		new(excel.ExcelChartEdb),        // 平衡表做图指标
+		new(excel.ExcelChartData),       // 平衡表作图数据
+		new(excel.ExcelInfoRuleMapping), //表格的管理规则
 	)
 }
 

+ 54 - 0
routers/commentsRouter.go

@@ -1276,6 +1276,60 @@ 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: "AddExcelRule",
+            Router: `/excel_info/rule/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: "DeleteExcelRule",
+            Router: `/excel_info/rule/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: "GetExcelRuleDetail",
+            Router: `/excel_info/rule/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: "EditExcelRule",
+            Router: `/excel_info/rule/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: "GetExcelRuleList",
+            Router: `/excel_info/rule/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: "GetBatchEdbData",
+            Router: `/excel_info/table/batch_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: "BatchRefresh",

+ 384 - 3
services/data/excel/excel_info.go

@@ -14,7 +14,10 @@ import (
 	"eta/eta_api/utils"
 	"fmt"
 	"sort"
+	"strings"
 	"time"
+
+	"github.com/xuri/excelize/v2"
 )
 
 // GetExcelDetailInfoByExcelInfoId 根据表格id获取表格详情
@@ -123,6 +126,7 @@ func formatExcelInfo2Detail(excelInfo *excel.ExcelInfo, sysUserId int, lang stri
 			err = errors.New("获取最新的表格数据失败,Err:" + tmpErr.Error())
 			return
 		}
+		result = SetExcelByDecimalConfig(result, tableDataConfig.DecimalConfig)
 
 		if len(result.EdbInfoIdList) > 0 {
 			classifyIdList := make([]int, 0)
@@ -182,6 +186,39 @@ func formatExcelInfo2Detail(excelInfo *excel.ExcelInfo, sysUserId int, lang stri
 	return
 }
 
+// SetExcelByDecimalConfig 设置表格的小数位
+func SetExcelByDecimalConfig(tableData request.TableDataReq, config []request.DecimalConfig) request.TableDataReq {
+	excelData := tableData.Data
+	edbInfoIndex := make(map[int]int)
+	dateIndex := make(map[string]int)
+	for i, v := range excelData {
+		edbInfoIndex[v.EdbInfoId] = i
+	}
+	for i, v := range excelData[0].Data {
+		dateIndex[v.DataTime] = i
+	}
+	for _, conf := range config {
+		if conf.Col > 0 {
+			if v, ok := edbInfoIndex[conf.Col]; ok {
+				excelData[v].Decimal = conf.Decimal
+				for i := 0; i < len(excelData[v].Data); i++ {
+					excelData[v].Data[i].Decimal = conf.Decimal
+				}
+			}
+		}
+		if conf.Row != "" {
+			if v, ok := dateIndex[conf.Row]; ok {
+				for i := 0; i < len(excelData); i++ {
+					excelData[i].Data[v].Decimal = conf.Decimal
+				}
+			}
+		}
+	}
+	tableData.Data = excelData
+	tableData.DecimalConfig = config
+	return tableData
+}
+
 // GetExcelInfoOpButton 获取ETA表格的操作权限
 func GetExcelInfoOpButton(sysUser *system.Admin, belongUserId, source int, haveOperaAuth bool) (button excel.ExcelInfoDetailButton) {
 	// 如果没有数据权限,那么直接返回
@@ -213,8 +250,9 @@ func GetExcelInfoOpButton(sysUser *system.Admin, belongUserId, source int, haveO
 }
 
 // GetFirstEdbDataList 获取第一列的数据
-func GetFirstEdbDataList(edbInfo *data_manage.EdbInfo, num int, manualDateList []string) (resultDataList []request.ManualDataReq, err error) {
+func GetFirstEdbDataList(edbInfo *data_manage.EdbInfo, num int, manualDateList []string, decimal int) (resultDataList []request.ManualDataReq, err error) {
 	var dataList []*data_manage.EdbDataList
+	resultDataList = make([]request.ManualDataReq, 0)
 	switch edbInfo.EdbInfoType {
 	case 0:
 		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, ``)
@@ -286,6 +324,7 @@ func GetFirstEdbDataList(edbInfo *data_manage.EdbInfo, num int, manualDateList [
 			DataTime:     dataList[lenData-i].DataTime,
 			ShowValue:    fmt.Sprint(dataList[lenData-i].Value),
 			Value:        fmt.Sprint(dataList[lenData-i].Value),
+			Decimal:      decimal,
 			DataTimeType: 1,
 		})
 	}
@@ -293,8 +332,160 @@ func GetFirstEdbDataList(edbInfo *data_manage.EdbInfo, num int, manualDateList [
 	return
 }
 
+// PadFirstEdbDataList 补齐第一列的数据
+func PadFirstEdbDataList(resultDataList []request.ManualDataReq, dateList []string, sortType string, decimal int) []request.ManualDataReq {
+	originDataNum := len(resultDataList)
+	requsetDateNum := len(dateList)
+	if originDataNum >= requsetDateNum {
+		return resultDataList
+	}
+	padNum := requsetDateNum - originDataNum
+	if sortType == "asc" {
+		for i := 0; i < padNum; i++ {
+			resultDataList = append(resultDataList, request.ManualDataReq{
+				DataType:     0,
+				DataTime:     dateList[originDataNum+i],
+				Decimal:      decimal,
+				ShowValue:    ``,
+				Value:        ``,
+				DataTimeType: 1,
+			})
+		}
+	} else {
+		var tmpDateList []request.ManualDataReq
+		for i := padNum - 1; i <= 0; i-- {
+			tmpDateList = append(tmpDateList, request.ManualDataReq{
+				DataType:     0,
+				DataTime:     dateList[originDataNum+i],
+				Decimal:      decimal,
+				ShowValue:    ``,
+				Value:        ``,
+				DataTimeType: 1,
+			})
+			resultDataList = append(tmpDateList, resultDataList...)
+		}
+
+	}
+	return resultDataList
+}
+
+// GetOtherEdbDataListFollowDate 获取其他列的数据,并设置日期的小数位数
+func GetOtherEdbDataListFollowDate(edbInfo *data_manage.EdbInfo, dateList []string, dateDecimal map[string]int) (resultDataList []request.ManualDataReq, err error) {
+	lenDate := len(dateList)
+	if lenDate <= 0 {
+		return
+	}
+	sortDateList := dateList
+	baseDateList := utils.StrArr{}
+	baseDateList = append(baseDateList, sortDateList...)
+	sort.Sort(baseDateList)
+	sortDateList = append([]string{}, baseDateList...)
+
+	endDateTime, err := time.ParseInLocation(utils.FormatDate, sortDateList[0], time.Local)
+	if err != nil {
+		return
+	}
+
+	firstDateTime, err := time.ParseInLocation(utils.FormatDate, sortDateList[lenDate-1], time.Local)
+	if err != nil {
+		return
+	}
+
+	var dataList []*data_manage.EdbDataList
+	switch edbInfo.EdbInfoType {
+	case 0:
+		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, ``)
+	case 1:
+		_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
+	default:
+		err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
+	}
+	if err != nil {
+		return
+	}
+
+	// 获取日期内的数据(包含开始日期前一个日期,以及 结束日期后一个日期,目的为了做空日期时的 插值法兼容)
+	baseDataList := make([]*data_manage.EdbDataList, 0)
+	var lastData *data_manage.EdbDataList
+	var isInsert bool
+	for _, data := range dataList {
+		tmpDate := data.DataTime
+		tmpDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		if tmpDateTime.Before(firstDateTime) {
+			lastData = data
+			continue
+		}
+
+		// 如果是第一次写入数据
+		if !isInsert && lastData != nil {
+			baseDataList = append(baseDataList, lastData)
+		}
+
+		if tmpDateTime.After(endDateTime) {
+			baseDataList = append(baseDataList, data)
+			break
+		}
+		baseDataList = append(baseDataList, data)
+		isInsert = true
+	}
+
+	// 实际数据的日期map
+	realValMap := make(map[string]string)
+	for _, v := range baseDataList {
+		realValMap[v.DataTime] = v.DataTime
+	}
+
+	// 插值法处理
+	handleDataMap := make(map[string]float64)
+	err = data.HandleDataByLinearRegression(baseDataList, handleDataMap)
+	if err != nil {
+		return
+	}
+
+	latestDateTime, _ := time.ParseInLocation(utils.FormatDate, edbInfo.LatestDate, time.Local)
+
+	// 对于不存在的数据做补充
+	for _, date := range sortDateList {
+		dataType := 1
+		if _, ok := realValMap[date]; !ok {
+			dataType = 2
+		} else {
+			dataTime, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
+			// 如果是预测指标,且当前值的日期,晚于实际日期,那么是预测值
+			if edbInfo.EdbInfoType == 1 && dataTime.After(latestDateTime) {
+				dataType = 5
+			}
+		}
+		var value, showValue string
+		if tmpVal, ok := handleDataMap[date]; ok {
+			value = fmt.Sprint(tmpVal)
+			showValue = value
+		} else {
+			dataType = 3
+		}
+		tmpData := request.ManualDataReq{
+			DataType:  dataType,
+			DataTime:  date,
+			ShowValue: showValue,
+			Value:     value,
+		}
+		if v, ok := dateDecimal[date]; ok {
+			tmpData.Decimal = v
+		} else {
+			tmpData.Decimal = -1
+		}
+		resultDataList = append(resultDataList, tmpData)
+	}
+
+	return
+}
+
 // GetOtherEdbDataList 获取其他列的数据
-func GetOtherEdbDataList(edbInfo *data_manage.EdbInfo, dateList []string) (resultDataList []request.ManualDataReq, err error) {
+func GetOtherEdbDataList(edbInfo *data_manage.EdbInfo, dateList []string, decimal int) (resultDataList []request.ManualDataReq, err error) {
 	lenDate := len(dateList)
 	if lenDate <= 0 {
 		return
@@ -394,6 +585,7 @@ func GetOtherEdbDataList(edbInfo *data_manage.EdbInfo, dateList []string) (resul
 		resultDataList = append(resultDataList, request.ManualDataReq{
 			DataType:  dataType,
 			DataTime:  date,
+			Decimal:   decimal,
 			ShowValue: showValue,
 			Value:     value,
 		})
@@ -403,7 +595,7 @@ func GetOtherEdbDataList(edbInfo *data_manage.EdbInfo, dateList []string) (resul
 }
 
 // GetFirstHistoryEdbDataList 获取指标的历史的数据
-func GetFirstHistoryEdbDataList(edbInfo *data_manage.EdbInfo, num int, endDate string) (resultDataList []request.ManualDataReq, err error) {
+func GetFirstHistoryEdbDataList(edbInfo *data_manage.EdbInfo, num int, endDate string, decimal int) (resultDataList []request.ManualDataReq, err error) {
 	endDateTime, err := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
 	if err != nil {
 		return
@@ -452,6 +644,7 @@ func GetFirstHistoryEdbDataList(edbInfo *data_manage.EdbInfo, num int, endDate s
 		resultDataList = append(resultDataList, request.ManualDataReq{
 			DataType:  dataType,
 			DataTime:  dataList[lenData-i].DataTime,
+			Decimal:   decimal,
 			ShowValue: fmt.Sprint(dataList[lenData-i].Value),
 			Value:     fmt.Sprint(dataList[lenData-i].Value),
 		})
@@ -614,3 +807,191 @@ func GetCustomAnalysisOpButton(sysUser *system.Admin, belongUserId int, permissi
 	}
 	return
 }
+
+func parseExcelScopeCoord(scopeList []string) (scopeCoord string, err error) {
+	if len(scopeList) == 2 {
+		x1, y1, er := excelize.CellNameToCoordinates(scopeList[0])
+		if er != nil {
+			return "", er
+		}
+		x2, y2, er := excelize.CellNameToCoordinates(scopeList[1])
+		if er != nil {
+			return "", er
+		}
+		scopeCoord = fmt.Sprintf("%d,%d,%d,%d", x1, y1, x2, y2)
+	}
+	if len(scopeList) == 1 {
+		x1, y1, er := excelize.CellNameToCoordinates(scopeList[0])
+		if er != nil {
+			return "", er
+		}
+		scopeCoord = fmt.Sprintf("%d,%d", x1, y1)
+	}
+	return
+}
+
+func ExcelRuleFormat(req *request.ExcelRuleMappingReq, lang string) (res *excel.ExcelInfoRuleMapping, err error) {
+	res = new(excel.ExcelInfoRuleMapping)
+	if req.RuleType == 5 {
+		switch req.LeftValue {
+		// 今天
+		case "today":
+			res.LeftValueBack = req.LeftValue
+		// 明天
+		case "tomorrow":
+			res.LeftValueBack = req.LeftValue
+		// 最近7天
+		case "last7days":
+			res.LeftValueBack = req.LeftValue
+		// 上周
+		case "lastweek":
+			res.LeftValueBack = req.LeftValue
+		// 本周
+		case "thisweek":
+			res.LeftValueBack = req.LeftValue
+		// 下周
+		case "nextweek":
+			res.LeftValueBack = req.LeftValue
+		// 上月
+		case "lastmonth":
+			res.LeftValueBack = req.LeftValue
+		// 本月
+		case "thismonth":
+			res.LeftValueBack = req.LeftValue
+		// 下月
+		case "nextmonth":
+			res.LeftValueBack = req.LeftValue
+		default:
+			err = errors.New("发生日期规则错误")
+			return
+		}
+	}
+	// 格式化条件值
+	switch req.LeftValueType {
+	// 坐标
+	case 2:
+		x, y, err := excelize.CellNameToCoordinates(req.LeftValue)
+		if err != nil {
+			return nil, err
+		}
+		res.LeftValue = req.LeftValue
+		res.LeftValueBack = fmt.Sprintf("%d,%d", x, y)
+	default:
+		res.LeftValue = req.LeftValue
+		res.LeftValueBack = req.LeftValue
+	}
+	switch req.RightValueType {
+	// 坐标
+	case 2:
+		x, y, err := excelize.CellNameToCoordinates(req.RightValue)
+		if err != nil {
+			return nil, err
+		}
+		res.RightValue = req.RightValue
+		res.RightValueBack = fmt.Sprintf("%d,%d", x, y)
+	default:
+		res.RightValue = req.RightValue
+		res.RightValueBack = req.RightValue
+	}
+	if res.LeftValueBack == "" {
+		res.LeftValueBack = req.LeftValue
+	}
+	if res.RightValueBack == "" {
+		res.RightValueBack = req.RightValue
+	}
+	res.RuleType = req.RuleType
+	res.ExcelInfoId = req.ExcelInfoId
+	res.ExcelInfoRuleMappingId = req.ExcelRuleMappingId
+	res.LeftValueType = req.LeftValueType
+	res.RightValueType = req.RightValueType
+	res.FontColor = req.FontColor
+	res.BackgroundColor = req.BackgroundColor
+	res.Remark = req.Remark
+	res.RemarkEn = req.Remark
+	res.ScopeShow = req.Scope
+	scopeList := strings.Split(req.Scope, ":")
+	res.ScopeCoord, err = parseExcelScopeCoord(scopeList)
+	return
+}
+
+func AddExcelRule(req *request.ExcelRuleMappingReq, lang string) (err error) {
+	excelRule, err := ExcelRuleFormat(req, lang)
+	if err != nil {
+		return
+	}
+	if excelRule.ExcelInfoRuleMappingId != 0 {
+		return errors.New("规则已存在")
+	}
+	excelRule.CreateTime = time.Now()
+	_, err = excelRule.Insert()
+	return
+}
+
+func ModifyExcelRule(req *request.ExcelRuleMappingReq, lang string) (err error) {
+	excelInfo, err := excel.GetExcelRuleMappingById(req.ExcelRuleMappingId)
+	if err != nil {
+		return
+	}
+	editExcelInfo, err := ExcelRuleFormat(req, lang)
+	if err != nil {
+		return
+	}
+	var updateCols []string
+	if excelInfo.LeftValue != editExcelInfo.LeftValue {
+		updateCols = append(updateCols, "LeftValue")
+		updateCols = append(updateCols, "LeftValueBack")
+	}
+	if excelInfo.LeftValueType != editExcelInfo.LeftValueType {
+		updateCols = append(updateCols, "LeftValueType")
+	}
+	if excelInfo.RightValue != editExcelInfo.RightValue {
+		updateCols = append(updateCols, "RightValue")
+		updateCols = append(updateCols, "RightValueBack")
+	}
+	if excelInfo.RightValueType != editExcelInfo.RightValueType {
+		updateCols = append(updateCols, "RightValueType")
+	}
+	if excelInfo.FontColor != editExcelInfo.FontColor {
+		updateCols = append(updateCols, "FontColor")
+	}
+	if excelInfo.BackgroundColor != editExcelInfo.BackgroundColor {
+		updateCols = append(updateCols, "BackgroundColor")
+	}
+	if excelInfo.Remark != editExcelInfo.Remark {
+		updateCols = append(updateCols, "Remark")
+	}
+	if excelInfo.RemarkEn != editExcelInfo.RemarkEn {
+		updateCols = append(updateCols, "RemarkEn")
+	}
+	if excelInfo.ScopeShow != editExcelInfo.ScopeShow {
+		updateCols = append(updateCols, "ScopeCoord")
+		updateCols = append(updateCols, "ScopeShow")
+	}
+	if len(updateCols) > 0 {
+		err = editExcelInfo.Update(updateCols)
+	}
+
+	return
+}
+
+// GetExcelRuleList 获取规则列表
+func GetExcelRuleList(excelInfoId int) (resp *response.ExcelRuleListResp, err error) {
+	resp = new(response.ExcelRuleListResp)
+	excelInfoList, err := excel.GetExcelRuleMappingByExcelInfoId(excelInfoId)
+	if err != nil {
+		return
+	}
+	resp.List = excelInfoList
+	return
+}
+
+// GetExcelRuleDetail 获取规则列表
+func GetExcelRuleDetail(excelInfoMappingId int) (resp *excel.ExcelInfoRuleMappingView, err error) {
+	resp = new(excel.ExcelInfoRuleMappingView)
+	excelInfoDetail, err := excel.GetExcelRuleMappingById(excelInfoMappingId)
+	if err != nil {
+		return
+	}
+	resp = excelInfoDetail
+	return
+}

+ 26 - 2
services/data/excel/mixed_table.go

@@ -8,12 +8,13 @@ import (
 	"eta/eta_api/services/data"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/shopspring/decimal"
-	"github.com/yidane/formula"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/shopspring/decimal"
+	"github.com/yidane/formula"
 )
 
 // BaseCalculate
@@ -1192,6 +1193,21 @@ func handleMixCellShowStyle(showStyleList []string, calculateCellMap map[string]
 			}
 			_, e := strconv.ParseFloat(val, 64) // 将字符串转换成float类型
 			if e != nil {                       // 如果没有错误发生则返回true,说明该字符串是一个合法的数字
+				var styleConf request.MixCellShowStyle
+				err = json.Unmarshal([]byte(cell.ShowStyle), &styleConf)
+				if err != nil {
+					err = fmt.Errorf("日期计算配置json解析失败失败: %s, Err:%s", config, err.Error())
+					return
+				}
+				// 前端传过来的json中有可能有glObj,需要去掉
+				if styleConf.GlObj != nil {
+					styleConf.GlObj = nil
+					tmpStyleConf, err := json.Marshal(styleConf)
+					if err == nil {
+						cell.ShowStyle = string(tmpStyleConf)
+					}
+				}
+				config[cellPosition.Column][cellPosition.Row] = cell
 				continue
 			}
 			var styleConf request.MixCellShowStyle
@@ -1206,6 +1222,14 @@ func handleMixCellShowStyle(showStyleList []string, calculateCellMap map[string]
 			} else {
 				cell.ShowFormatValue = cell.ShowValue
 			}
+			// 前端传过来的json中有可能有glObj,需要去掉
+			if styleConf.GlObj != nil {
+				styleConf.GlObj = nil
+				tmpStyleConf, err := json.Marshal(styleConf)
+				if err == nil {
+					cell.ShowStyle = string(tmpStyleConf)
+				}
+			}
 			config[cellPosition.Column][cellPosition.Row] = cell
 		}
 	}

+ 11 - 4
services/data/excel/time_table.go

@@ -7,12 +7,13 @@ import (
 	"eta/eta_api/services/data"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/shopspring/decimal"
-	"github.com/yidane/formula"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/shopspring/decimal"
+	"github.com/yidane/formula"
 )
 
 // TableDataConfig
@@ -26,6 +27,7 @@ type TableDataConfig struct {
 	ManualDate       []string                  `description:"手动配置的日期(未来的日期)"`
 	TableEdbInfoList []TableEdbInfo            `description:"表格内指标信息"`
 	TextRowData      [][]request.ManualDataReq `description:"文本列表"`
+	DecimalConfig    []request.DecimalConfig   `description:"小数位数配置"`
 }
 
 // TableEdbInfo
@@ -39,6 +41,7 @@ type TableEdbInfo struct {
 	Frequency    string `description:"频度"`
 	Unit         string `description:"单位"`
 	UnitEn       string `description:"英文单位"`
+	Decimal      int    `description:"小数位数"`
 }
 
 // ManualData
@@ -101,7 +104,7 @@ func GetDataByTableDataConfig(tableDataConfig TableDataConfig) (resultResp reque
 		err = errors.New("找不到A列指标")
 		return
 	}
-	baseFirstEdbInfoDataList, err := GetFirstEdbDataList(firstEdbInfo, tableDataConfig.Num, manualDateList)
+	baseFirstEdbInfoDataList, err := GetFirstEdbDataList(firstEdbInfo, tableDataConfig.Num, manualDateList, -1)
 	if err != nil {
 		return
 	}
@@ -166,7 +169,7 @@ func GetDataByTableDataConfig(tableDataConfig TableDataConfig) (resultResp reque
 			err = errors.New("找不到A列指标")
 			return
 		}
-		otherDataList, tmpErr := GetOtherEdbDataList(tmpEdbInfo, dateList)
+		otherDataList, tmpErr := GetOtherEdbDataList(tmpEdbInfo, dateList, -1)
 		if tmpErr != nil {
 			err = tmpErr
 			return
@@ -249,6 +252,7 @@ func GetDataByTableDataConfig(tableDataConfig TableDataConfig) (resultResp reque
 			EdbNameEn:    tableEdbInfo.EdbNameEn,
 			EdbAliasName: tableEdbInfo.EdbAliasName,
 			Frequency:    tableEdbInfo.Frequency,
+			Decimal:      tableEdbInfo.Decimal,
 			Unit:         tableEdbInfo.Unit,
 			UnitEn:       tableEdbInfo.UnitEn,
 			Data:         manualDataReqList,
@@ -277,6 +281,7 @@ func GetDataByTableDataConfig(tableDataConfig TableDataConfig) (resultResp reque
 				manualDataReqList = append(manualDataReqList, request.ManualDataReq{
 					DataType:            3,
 					DataTime:            tmpDateTimeStr,
+					Decimal:             tableEdbInfo.Decimal,
 					DataTimeType:        dataTimeType,
 					ShowValue:           "",
 					Value:               "",
@@ -290,6 +295,7 @@ func GetDataByTableDataConfig(tableDataConfig TableDataConfig) (resultResp reque
 				manualDataReqList = append(manualDataReqList, request.ManualDataReq{
 					DataType:            3,
 					DataTime:            tmpDateTimeStr,
+					Decimal:             tableEdbInfo.Decimal,
 					DataTimeType:        dataTimeType,
 					ShowValue:           "",
 					Value:               "",
@@ -374,6 +380,7 @@ func GetTableDataConfig(reqData request.TableDataReq) (tableDataConfig TableData
 			Frequency:    v.Frequency,
 			Unit:         v.Unit,
 			UnitEn:       v.UnitEn,
+			Decimal:      v.Decimal,
 		}
 		tableEdbInfoList = append(tableEdbInfoList, tmpTableEdbInfo)
 

+ 49 - 2
services/excel/lucky_sheet.go

@@ -6,13 +6,15 @@ import (
 	"eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/tealeg/xlsx"
-	"github.com/xuri/excelize/v2"
+	"math"
 	"os"
 	"reflect"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/tealeg/xlsx"
+	"github.com/xuri/excelize/v2"
 )
 
 type LuckySheetDataBak struct {
@@ -1743,8 +1745,53 @@ func GetTableDataByMixedTableData(config [][]request.MixedTableCellDataReq, hide
 					tmp.MergeCell.Column = cell.MerData.Mer.Col
 				}
 				if cell.ShowStyle != "" {
+					var styleConfig request.MixCellShowStyle
+					if err := json.Unmarshal([]byte(cell.ShowStyle), &styleConfig); err != nil {
+						utils.FileLog.Info("表格样式showStyle解析失败", err.Error())
+					}
 					showFormatValue := fmt.Sprintf("%v", cell.ShowFormatValue)
+					if styleConfig.BackgroundColor != "" {
+						tmp.Background = styleConfig.BackgroundColor
+					}
+					if styleConfig.Color != "" {
+						tmp.FontColor = styleConfig.Color
+					}
 					tmp.Monitor = showFormatValue
+					tmpShowValue, err := strconv.ParseFloat(cell.Value, 64)
+					if err == nil {
+						switch styleConfig.Last {
+						case "nt":
+							// 先进行数字的百分比计算,然后保留小数点位数
+							percent := tmpShowValue * 100
+							if styleConfig.Decimal == nil {
+								continue
+							}
+							factor := math.Pow(10, float64(*styleConfig.Decimal))
+							rounded := math.Round(percent*factor) / factor
+							tmp.Monitor = fmt.Sprintf("%g%%", rounded)
+						case "decimal":
+							// 先保留小数点位数,再进行百分比计算
+							if styleConfig.Decimal == nil {
+								continue
+							}
+							factor := math.Pow(10, float64(*styleConfig.Decimal))
+							rounded := math.Round(tmpShowValue*factor) / factor
+							if styleConfig.Nt == "percent" {
+								percent := rounded * 100
+								var precisionStr string
+								if *styleConfig.Decimal > 2 {
+									precision := *styleConfig.Decimal - 2
+									precisionStr = strconv.FormatFloat(rounded, 'f', precision, 64)
+								} else {
+									precisionStr = strconv.FormatFloat(math.Round(percent), 'f', -1, 64)
+								}
+								tmp.Monitor = fmt.Sprintf("%s%%", precisionStr)
+							} else {
+								tmp.Monitor = fmt.Sprintf("%g", rounded)
+							}
+						}
+					}
+
 				}
 				dataCol = append(dataCol, tmp)
 			}

+ 224 - 0
services/excel/lucky_sheet_table.go

@@ -1,8 +1,13 @@
 package excel
 
 import (
+	"eta/eta_api/models/data_manage/excel"
+	"eta/eta_api/utils"
 	"fmt"
 	"sort"
+	"strconv"
+	"strings"
+	"time"
 )
 
 // HandleTableCell 前端d毛需要我根据合并单元格处理掉多余的单元格
@@ -99,3 +104,222 @@ func handleCellVal(tmpTableColData LuckySheetDataValue) (valueStr string) {
 	}
 	return
 }
+
+// HandleRuleToTableCell 根据管理规则渲染单元格数据
+func HandleRuleToTableCell(excelInfoId int, oldTableData TableData) (newTableData TableData, err error) {
+	newTableData = oldTableData
+	excelRuleMappingList, err := excel.GetExcelRuleMappingByExcelInfoId(excelInfoId)
+	if err != nil {
+		return
+	}
+	if len(excelRuleMappingList) == 0 {
+		return
+	}
+	tableDataList := oldTableData.TableDataList
+	excelRuleMap := make(map[int]*excel.ExcelInfoRuleMappingView)
+	for _, v := range excelRuleMappingList {
+		excelRuleMap[v.ExcelInfoRuleMappingId] = v
+	}
+	ruleScopeMap := generateRuleScopeIndexMap(excelRuleMappingList)
+	for row, scopeValues := range ruleScopeMap {
+		for col, ruleId := range scopeValues {
+			if v, ok := excelRuleMap[ruleId]; ok {
+				if len(tableDataList) > row && len(tableDataList[row]) > col {
+					// 符合管理规则要求,则进行字体和背景颜色的渲染
+					if checkCellRule(v, tableDataList[row][col].Monitor, tableDataList) {
+						tableDataList[row][col].Background = v.BackgroundColor
+						tableDataList[row][col].FontColor = v.FontColor
+					}
+				} else {
+					continue
+				}
+			} else {
+				continue
+			}
+		}
+	}
+	return
+}
+
+func getCellValueByType(value string, valueType int, tableDataList [][]LuckySheetDataValue) (float64, bool) {
+	if valueType == 2 {
+		coords := strings.Split(value, ",")
+		var coordIntArr []int
+		for _, v := range coords {
+			t, _ := strconv.Atoi(v)
+			coordIntArr = append(coordIntArr, t)
+		}
+		if len(coordIntArr) == 2 {
+			x, y := coordIntArr[0]-1, coordIntArr[1]-1
+			conditionValue, err := strconv.ParseFloat(tableDataList[y][x].Monitor, 64)
+			if err != nil {
+				return 0, false
+			}
+			return conditionValue, true
+		}
+	} else {
+		conditionValue, err := strconv.ParseFloat(value, 64)
+		if err != nil {
+			return 0, false
+		}
+		return conditionValue, true
+	}
+	return 0, false
+}
+
+func checkCellRule(ruleInfo *excel.ExcelInfoRuleMappingView, value string, tableDataList [][]LuckySheetDataValue) bool {
+	var tableValue float64
+	var tableTime time.Time
+	var err error
+
+	if ruleInfo.RuleType == 5 {
+		tableTime, err = time.ParseInLocation(utils.FormatDate, value, time.Local)
+		if err != nil {
+			return false
+		}
+	} else {
+		tableValue, err = strconv.ParseFloat(value, 64)
+		if err != nil {
+			return false
+		}
+	}
+	switch ruleInfo.RuleType {
+	// 大于
+	case 1:
+		conditionValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
+		if !ok {
+			return false
+		}
+		if tableValue > conditionValue {
+			return true
+		}
+	// 小于
+	case 2:
+		conditionValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
+		if !ok {
+			return false
+		}
+		if tableValue < conditionValue {
+			return true
+		}
+	// 介于
+	case 3:
+		leftcondValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
+		if !ok {
+			return false
+		}
+		rightcondValue, ok := getCellValueByType(ruleInfo.RightValueBack, ruleInfo.RightValueType, tableDataList)
+		if !ok {
+			return false
+		}
+		if leftcondValue <= tableValue && tableValue <= rightcondValue {
+			return true
+		}
+	// 等于
+	case 4:
+		conditionValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
+		if !ok {
+			return false
+		}
+		if tableValue == conditionValue {
+			return true
+		}
+	// 发生日期
+	case 5:
+		// 发生日期
+		var dateStart, dataEnd time.Time
+		switch ruleInfo.LeftValueBack {
+		// 今天
+		case "today":
+			// 获得今天的零点零分零秒
+			dateStart = utils.Today()
+			if tableTime == dateStart {
+				return true
+			}
+		// 明天
+		case "tomorrow":
+			dateStart = utils.Tomorrow()
+			if tableTime == dateStart {
+				return true
+			}
+		// 最近7天
+		case "last7days":
+			dateStart, dataEnd = utils.Last7Days()
+			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
+				return true
+			}
+		// 上周
+		case "lastweek":
+			dateStart, dataEnd = utils.LastWeek()
+			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
+				return true
+			}
+		// 本周
+		case "thisweek":
+			dateStart, dataEnd = utils.ThisWeek()
+			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
+				return true
+			}
+		// 下周
+		case "nextweek":
+			dateStart, dataEnd = utils.NextWeek()
+			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
+				return true
+			}
+		// 上月
+		case "lastmonth":
+			dateStart, dataEnd = utils.LastMonth()
+			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
+				return true
+			}
+		// 本月
+		case "thismonth":
+			dateStart, dataEnd = utils.ThisMonth()
+			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
+				return true
+			}
+		// 下月
+		case "nextmonth":
+			dateStart, dataEnd = utils.NextMonth()
+			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
+				return true
+			}
+		default:
+			return false
+		}
+
+	}
+	return false
+}
+
+func generateRuleScopeIndexMap(items []*excel.ExcelInfoRuleMappingView) (ruleScopeMap map[int]map[int]int) {
+	ruleScopeMap = make(map[int]map[int]int)
+	for _, item := range items {
+		coords := strings.Split(item.ScopeCoord, ",")
+		var coordIntArr []int
+		for _, v := range coords {
+			t, _ := strconv.Atoi(v)
+			coordIntArr = append(coordIntArr, t)
+		}
+
+		if len(coords) == 4 {
+			xmin, ymin, xmax, ymax := coordIntArr[0]-1, coordIntArr[1]-1, coordIntArr[2]-1, coordIntArr[3]-1
+			for i := ymin; i <= ymax; i++ {
+				for j := xmin; j <= xmax; j++ {
+					if _, ok := ruleScopeMap[i]; !ok {
+						ruleScopeMap[i] = make(map[int]int)
+					}
+					ruleScopeMap[i][j] = item.ExcelInfoRuleMappingId
+				}
+			}
+		}
+		if len(coords) == 2 {
+			x, y := coordIntArr[0]-1, coordIntArr[1]-1
+			if _, ok := ruleScopeMap[y]; !ok {
+				ruleScopeMap[y] = make(map[int]int)
+			}
+			ruleScopeMap[y][x] = item.ExcelInfoRuleMappingId
+		}
+	}
+	return
+}

+ 2 - 1
static/ErrMsgConfig.json

@@ -57,5 +57,6 @@
   "当前指标已用作预测指标,不可删除": "The current metric is used as a forecasting indicator and cannot be deleted.",
   "当前指标已添加到跨品种分析,不可删除": "The current metric has been added to cross-commodity analysis and cannot be deleted.",
   "指标已删除,请刷新页面": "Metric deleted, please refresh the page.",
-  "删除失败": "Deletion failed."
+  "删除失败": "Deletion failed.",
+  "指标数据异常,请检查": "The metric data is abnormal, please check."
 }

+ 74 - 0
utils/time.go

@@ -0,0 +1,74 @@
+package utils
+
+import "time"
+
+// 获取今天的日期(零点零分零秒)
+func Today() time.Time {
+	now := time.Now()
+	return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
+}
+
+// 获取明天的日期(零点零分零秒)
+func Tomorrow() time.Time {
+	return Today().AddDate(0, 0, 1)
+}
+
+// 获取最近7天的日期范围
+func Last7Days() (time.Time, time.Time) {
+	today := Today()
+	return today.AddDate(0, 0, -6), today.Add(time.Hour * 23).Add(time.Minute * 59).Add(time.Second * 59)
+}
+
+// 获取上周的日期范围
+func LastWeek() (time.Time, time.Time) {
+	start := Today().AddDate(0, 0, -7)
+	end := start.AddDate(0, 0, 6).Add(time.Hour * 23).Add(time.Minute * 59).Add(time.Second * 59)
+	return start, end
+}
+
+// 获取本周的日期范围
+func ThisWeek() (time.Time, time.Time) {
+	start := Today().Round(0).Local().AddDate(0, 0, 0-int(time.Now().Weekday())+1) // 0是本周的第一天,+1是因为AddDate是相对于当前时间的
+	end := start.AddDate(0, 0, 6).Add(time.Hour * 23).Add(time.Minute * 59).Add(time.Second * 59)
+	return start, end
+}
+
+// 获取下周的日期范围
+func NextWeek() (time.Time, time.Time) {
+	_, thisEnd := ThisWeek()
+	start := thisEnd.AddDate(0, 0, 1)
+	end := start.AddDate(0, 0, 6).Add(time.Hour * 23).Add(time.Minute * 59).Add(time.Second * 59)
+	return start, end
+}
+
+// 获取上月的日期范围
+func LastMonth() (time.Time, time.Time) {
+	today := time.Now()
+	year, month, _ := today.Date()
+	start := time.Date(year, month-1, 1, 0, 0, 0, 0, today.Location())
+	end := time.Date(year, month, 0, 23, 59, 59, 999999999, today.Location())
+	return start, end
+}
+
+// 获取本月的日期范围
+func ThisMonth() (time.Time, time.Time) {
+	today := time.Now()
+	year, month, _ := today.Date()
+	start := time.Date(year, month, 1, 0, 0, 0, 0, today.Location())
+	end := time.Date(year, month+1, 0, 23, 59, 59, 999999999, today.Location())
+	return start, end
+}
+
+// 获取下月的日期范围
+func NextMonth() (time.Time, time.Time) {
+	now := time.Now()
+	year, month, _ := now.Date()
+	nextMonth := month + 1
+	if nextMonth > 12 {
+		nextMonth = 1
+		year++
+	}
+	startOfNextMonth := time.Date(year, nextMonth, 1, 0, 0, 0, 0, now.Location())
+	endOfNextMonth := startOfNextMonth.AddDate(0, 1, -1).Add(time.Hour*23 + time.Minute*59 + time.Second*59)
+	return startOfNextMonth, endOfNextMonth
+}