Browse Source

Merge branch 'eta/2.0.0' of http://8.136.199.33:3000/eta_server/eta_api into bzq1/execl-edit

zqbao 7 months ago
parent
commit
3f96d4858f

+ 1 - 1
controllers/data_manage/data_manage_permission/data_move.go

@@ -271,7 +271,7 @@ func (c *DataMangePermissionController) MoveEdbChartUser() {
 		return
 	}
 
-	err, errMsg := data_manage_permission.MoveEdbChart(req.Source, req.SubSource, req.UserId, req.NewUserId, req.IsSelectAll, req.DataIdList, req.NoDataIdList, req.Keyword, req.ClassifyId, sysUser.AdminId)
+	err, errMsg := data_manage_permission.MoveEdbChart(req.Source, req.SubSource, req.UserId, req.NewUserId, req.IsSelectAll, req.DataIdList, req.NoDataIdList, req.Keyword, req.ClassifyId, sysUser.AdminId, sysUser.RealName)
 	if err != nil {
 		//br.Success = true
 		br.Msg = "移动失败"

+ 1519 - 0
controllers/data_manage/manual_edb.go

@@ -0,0 +1,1519 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/system"
+	"eta/eta_api/services/data"
+	etaTrialService "eta/eta_api/services/eta_trial"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/shopspring/decimal"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// ManualEdbController 手工指标服务(鉴权)
+type ManualEdbController struct {
+	controllers.BaseAuthController
+}
+
+// EdbDetail
+// @Title 指标列表
+// @Description 指标列表
+// @Param   TradeCode   query   string  true       "指标编码"
+// @Success 200 {object} models.TargetDetailResp
+// @router /target/edb/detail [get]
+func (c *ManualEdbController) EdbDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	// 指标编码
+	tradeCode := c.GetString("TradeCode")
+	if tradeCode == `` {
+		br.Msg = "请输入指标编码"
+		br.IsSendEmail = false
+		return
+	}
+
+	manualEdbInfo, err := models.GetTargetByTradeCode(tradeCode)
+	if err != nil {
+		br.Msg = "获取指标失败"
+		br.ErrMsg = "获取指标失败,err:" + err.Error()
+		return
+	}
+
+	// 如果不是超管账号,那么得校验下当前用户是否有该指标的权限
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		//获取账户所拥有权限的分类id集合
+		count, err := models.GetCountManualUserClassify(sysUser.AdminId, manualEdbInfo.ClassifyId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.ErrMsg = "获取分类数据失败,err:" + err.Error()
+			return
+		}
+
+		if count <= 0 {
+			br.Msg = "无权访问"
+			br.ErrMsg = "无权访问"
+			br.IsSendEmail = false
+			return
+		}
+	}
+
+	classifyList := make([]*models.EdbdataClassify, 0)
+	{
+		classify, err := models.GetManualClassifyByClassifyId(manualEdbInfo.ClassifyId)
+		if err != nil {
+			br.Msg = "获取分类信息失败"
+			br.ErrMsg = "获取分类信息失败,err:" + err.Error()
+			return
+		}
+		parentClassify, err := models.GetManualClassifyByClassifyId(classify.ParentId)
+		if err != nil {
+			br.Msg = "获取分类信息失败"
+			br.ErrMsg = "获取父级分类信息失败,err:" + err.Error()
+			return
+		}
+		classifyList = []*models.EdbdataClassify{
+			parentClassify, classify,
+		}
+	}
+
+	// 明细数据
+	{
+		dataList, err := models.GetEdbDataListByCode(manualEdbInfo.TradeCode)
+		if err != nil {
+			br.Msg = "获取明细数据失败"
+			br.ErrMsg = "获取明细数据失败,err:" + err.Error()
+			return
+		}
+
+		manualEdbInfo.DataList = dataList
+	}
+
+	resp := models.TargetDetailResp{
+		Detail:       manualEdbInfo,
+		ClassifyList: classifyList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	//br.Data = resp
+	br.Data = resp
+}
+
+// ClassifyEdbList
+// @Title 分类指标列表
+// @Description 指标列表
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Success 200 {object} models.TargetDetailResp
+// @router /target/classify/edb/list [get]
+func (c *ManualEdbController) ClassifyEdbList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.Ret = 408
+		return
+	}
+	resp := new(models.EdbdataClassifyResp)
+
+	classifyId, _ := c.GetInt("ClassifyId") //分类
+	if classifyId <= 0 {
+		br.Msg = "请传入分类"
+		br.ErrMsg = "请传入分类"
+		br.IsSendEmail = false
+	}
+
+	var condition string
+	var pars []interface{}
+
+	// 如果不是超管账号,那么得校验下当前用户是否有该指标的权限
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		//获取账户所拥有权限的分类id集合
+		count, err := models.GetCountManualUserClassify(sysUser.AdminId, classifyId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.ErrMsg = "获取分类数据失败,err:" + err.Error()
+			return
+		}
+
+		if count <= 0 {
+			br.Msg = "无权访问"
+			br.ErrMsg = "无权访问"
+			br.IsSendEmail = false
+			return
+		}
+	}
+
+	list := make([]*models.EdbdataClassifyList, 0)
+
+	condition += ` AND a.classify_id = ? `
+	pars = append(pars, classifyId)
+
+	tmpList, err := models.GetEdbInfoList(condition, pars, 0, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	for _, v := range tmpList {
+		list = append(list, &models.EdbdataClassifyList{
+			ClassifyId:   0,
+			ClassifyName: v.SecName,
+			ParentId:     v.ClassifyId,
+			Child:        nil,
+			TradeCode:    v.TradeCode,
+			UniqueCode:   utils.MD5(v.TradeCode),
+		})
+	}
+
+	resp.List = list
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// EdbSearch
+// @Title 指标搜索
+// @Description 指标搜索
+// @Param   Keyword   query   string  false       "关键字搜索"
+// @Success 200 {object} models.TargetItemListResp
+// @router /target/edb/search [get]
+func (c *ManualEdbController) EdbSearch() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	//关键字
+	keyword := c.GetString("Keyword")
+
+	var condition string
+	var pars []interface{}
+
+	//userId := sysUser.AdminId
+	//超管账号可以查看分类下的所有频度数据
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		classifyIdList, err := data.GetUserManualClassifyIdList(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.Msg = "获取拥有的分类数据失败,Err:" + err.Error()
+			return
+		}
+		num := len(classifyIdList)
+		if num > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+			pars = append(pars, classifyIdList)
+		}
+
+	}
+
+	if keyword != "" {
+		condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
+		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	}
+
+	total, err := models.GetCountEdbInfoList(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	list, err := models.GetEdbInfoList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	for _, v := range list {
+		v.UniqueCode = utils.MD5(v.TradeCode)
+	}
+
+	resp := models.EdbListResp{
+		List:   list,
+		Paging: paging.GetPaging(currentIndex, pageSize, total),
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// EdbList
+// @Title 获取研究员指标
+// @Description 获取研究员指标
+// @Param   Frequency   query   string  false       "频度;枚举值:日度、周度、月度、季度、半年度、年度"
+// @Param   Keyword   query   string  false       "关键字搜索"
+// @Param   TradeCode   query   string  false       "指标唯一编码"
+// @Param   ClassifyId   query   int  false       "分类id"
+// @Param   UserId   query   int  false       "用户id"
+// @Success 200 {object} models.TargetItemListResp
+// @router /target/edb/list [get]
+func (c *ManualEdbController) EdbList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	// 频度
+	frequency := c.GetString("Frequency")
+	//关键字
+	keyword := c.GetString("Keyword")
+	//关键字
+	classifyId, _ := c.GetInt("ClassifyId", 0)
+	//用户ID
+	userId, _ := c.GetInt("UserId", 0)
+
+	var condition string
+	var pars []interface{}
+
+	//超管账号可以查看分类下的所有频度数据
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		classifyIdList, err := data.GetUserManualClassifyIdList(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.Msg = "获取拥有的分类数据失败,Err:" + err.Error()
+			return
+		}
+		num := len(classifyIdList)
+		if num > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+			pars = append(pars, classifyIdList)
+		}
+
+	}
+
+	// 关键词
+	if keyword != "" {
+		condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
+		pars = utils.GetLikeKeywordPars(pars, keyword, 2)
+	}
+	if frequency != "" {
+		condition += ` AND a.frequency = ?`
+		pars = append(pars, frequency)
+	}
+
+	// 所属分类
+	if classifyId > 0 {
+		// 获取有用权限的分类
+		classifyList, err := models.GetEdbdataClassify(int64(userId))
+		if err != nil {
+			return
+		}
+
+		var isParent bool
+		classifyIdList := make([]int, 0)
+		for _, v := range classifyList {
+			if v.ClassifyId == classifyId {
+				isParent = true
+				classifyIdList = append(classifyIdList, v.ClassifyId)
+				if v.Child != nil && len(v.Child) > 0 {
+					for _, vv := range v.Child {
+						classifyIdList = append(classifyIdList, vv.ClassifyId)
+					}
+				}
+				break
+			}
+		}
+
+		num := len(classifyIdList)
+		if num > 0 && isParent {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+			pars = append(pars, classifyIdList)
+		} else {
+			condition += ` AND a.classify_id = ? `
+			pars = append(pars, classifyId)
+		}
+	}
+
+	// 所属用户
+	if userId > 0 {
+		condition += ` AND a.user_id = ? `
+		pars = append(pars, userId)
+	}
+
+	total, err := models.GetCountEdbInfoList(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	list, err := models.GetEdbInfoList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	resp := models.EdbListResp{
+		List:   list,
+		Paging: paging.GetPaging(currentIndex, pageSize, total),
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// EditExcelData
+// @Title 根据excel的样式去编辑指标
+// @Description 根据excel的样式去编辑指标
+// @Param  request	body models.ManualEdbExcelStyleEditReq true "type json string"
+// @Success 200
+// @router /target/edb/excel_style/edit [post]
+func (c *ManualEdbController) EditExcelData() {
+	br := new(models.BaseResponse).Init()
+	var err error
+	errs := make([]string, 0)
+	defer func() {
+		if len(errs) > 0 {
+			utils.FileLog.Info("编辑EXCEL数据 新增或修改数据失败,Err:" + strings.Join(errs, "\n"))
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	var req data_manage.ManualEdbExcelStyleEditReq
+	err = json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.TradeCode == `` {
+		br.Msg = "指标编码异常!"
+		br.ErrMsg = "指标编码异常!"
+		return
+	}
+	if req.Unit == `` {
+		br.Msg = "单位填写异常!"
+		br.ErrMsg = "单位填写异常!"
+		return
+	}
+	if req.Frequency == `` {
+		br.Msg = "频度填写异常!"
+		br.ErrMsg = "频度填写异常!"
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "品种填写异常!"
+		br.ErrMsg = "品种填写异常!"
+		return
+	}
+
+	// 获取指标信息
+	manualEdbInfo, err := models.GetEdbinfoByTradeCode(req.TradeCode)
+	if err != nil {
+		br.Msg = `找不到该指标`
+		br.Msg = `找不到该指标,ERR:` + err.Error()
+		return
+	}
+
+	// 如果不是超管账号,那么得校验下当前用户是否有该指标的权限
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		//获取账户所拥有权限的分类id集合
+		count, err := models.GetCountManualUserClassify(sysUser.AdminId, manualEdbInfo.ClassifyId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.ErrMsg = "获取分类数据失败,err:" + err.Error()
+			return
+		}
+
+		if count <= 0 {
+			br.Msg = "无权访问"
+			br.ErrMsg = "无权访问"
+			br.IsSendEmail = false
+			return
+		}
+	}
+
+	dateValueMap := make(map[string]string)
+	//取到所有数据
+	for _, dateValue := range req.Data {
+		dateValueMap[dateValue.Date] = strconv.FormatFloat(dateValue.Value, 'f', -1, 64)
+	}
+
+	//操作指标,新增指标及数据等
+	{
+		var isUpdateEdb, isUpdateData bool
+
+		secName := strings.TrimSpace(req.EdbName)
+		frequency := strings.TrimSpace(req.Frequency)
+		unit := strings.TrimSpace(req.Unit)
+
+		// 指标基础信息变更
+		{
+			updateCols := make([]string, 0)
+
+			if manualEdbInfo.SecName != secName {
+				// 校验是否存在相同指标名称
+				var condition string
+				var pars []interface{}
+				condition += " AND SEC_NAME=? AND left(TRADE_CODE,1)='W' AND REMARK='手动' AND TRADE_CODE != ? "
+				pars = append(pars, secName, req.TradeCode)
+				count, err := models.GetManualEdbCountByCondition(condition, pars)
+				if err != nil {
+					br.Msg = `指标保存失败`
+					br.ErrMsg = `获取同名指标信息异常,ERR:` + err.Error()
+					return
+				}
+				if count > 0 {
+					br.Msg = `已存在同名指标`
+					br.ErrMsg = `已存在同名指标`
+					br.IsSendEmail = false
+					return
+				}
+
+				updateCols = append(updateCols, "SecName")
+				manualEdbInfo.SecName = secName
+			}
+
+			if manualEdbInfo.ClassifyId != req.ClassifyId {
+				updateCols = append(updateCols, "ClassifyId")
+				manualEdbInfo.ClassifyId = req.ClassifyId
+			}
+
+			if manualEdbInfo.Frequency != frequency {
+				updateCols = append(updateCols, "Frequency")
+				manualEdbInfo.Frequency = frequency
+			}
+
+			if manualEdbInfo.Unit != unit {
+				updateCols = append(updateCols, "Unit")
+				manualEdbInfo.Unit = unit
+			}
+
+			if len(updateCols) > 0 {
+				isUpdateEdb = true
+				manualEdbInfo.ModifyTime = time.Now().Format(utils.FormatDateTime)
+				updateCols = append(updateCols, "ModifyTime")
+				err = manualEdbInfo.Update(updateCols)
+				if err != nil {
+					br.Msg = `指标保存失败`
+					br.ErrMsg = `指标保存失败,ERR:` + err.Error()
+					return
+				}
+			}
+		}
+
+		// 当前已经存在的指标明细数据
+		targetDataList, tmpErr := models.GetTargetsDataList(manualEdbInfo.TradeCode)
+		if tmpErr != nil {
+			err = tmpErr
+		}
+		existDataMap := make(map[string]string)
+		deleteDataMap := make(map[string]string)
+		for _, tmpData := range targetDataList {
+			existDataMap[tmpData.Dt] = tmpData.Close
+			deleteDataMap[tmpData.Dt] = tmpData.Dt
+		}
+
+		addDataList := make([]*models.Edbdata, 0)
+
+		for createDate, closeVal := range dateValueMap {
+			if createDate == "" || closeVal == "" {
+				continue
+			}
+			//判断数据是否已经存在
+			tmpVal, ok3 := existDataMap[createDate]
+			// 不存在,那么后面进行插入
+			if !ok3 {
+				addDataList = append(addDataList, &models.Edbdata{
+					TradeCode:  manualEdbInfo.TradeCode,
+					Dt:         createDate,
+					Close:      closeVal,
+					ModifyTime: time.Now(),
+				})
+				continue
+			}
+
+			delete(deleteDataMap, createDate)
+
+			// 库里面的数据
+			tmpValDecimal, tmpErr := decimal.NewFromString(tmpVal)
+			if tmpErr != nil {
+				fmt.Println("tmpVal Parse err:", tmpErr.Error())
+				err = tmpErr
+				continue
+			}
+			// 用户填写的数据
+			closeValDecimal, tmpErr := decimal.NewFromString(closeVal)
+			if tmpErr != nil {
+				fmt.Println("closeVal Parse err:", tmpErr.Error())
+				err = tmpErr
+				continue
+			}
+			if !tmpValDecimal.Equal(closeValDecimal) {
+				isUpdateData = true
+				fmt.Println("更新数值")
+				err = models.ModifyTargetsDataByImport(manualEdbInfo.TradeCode, createDate, closeVal)
+				if err != nil {
+					fmt.Println("ModifyTargetsDataByImport err:", err.Error())
+					errs = append(errs, err.Error())
+					//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 修改数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
+				}
+			}
+		}
+
+		// 新增指标
+		if len(addDataList) > 0 {
+			isUpdateData = true
+			err = models.OnlyMultiAddEdbdata(addDataList)
+			if err != nil {
+				fmt.Println("MultiAddEdbdata err:", err.Error())
+				errs = append(errs, err.Error())
+			}
+		}
+
+		// 删除不需要的日期数据
+		num := len(deleteDataMap)
+		if num > 0 {
+			isUpdateData = true
+			deleteDateList := make([]string, 0)
+			for date := range deleteDataMap {
+				deleteDateList = append(deleteDateList, date)
+			}
+
+			err = models.DelEdbdataByCodeAndDateList(manualEdbInfo.TradeCode, deleteDateList)
+			if err != nil {
+				fmt.Println("DelEdbdataByCodeAndDateList err:", err.Error())
+				errs = append(errs, err.Error())
+			}
+		}
+
+		// 添加记录
+		if isUpdateEdb {
+			record := &models.EdbinfoOpRecord{
+				TradeCode:  manualEdbInfo.TradeCode,
+				Remark:     "编辑指标",
+				UserId:     sysUser.AdminId,
+				UserName:   sysUser.RealName,
+				CreateTime: time.Now(),
+			}
+			go func() {
+				_ = record.Create()
+			}()
+		}
+
+		// 更新数据
+		if isUpdateData {
+			record := &models.EdbinfoOpRecord{
+				TradeCode:  manualEdbInfo.TradeCode,
+				Remark:     "更新数据",
+				UserId:     sysUser.AdminId,
+				UserName:   sysUser.RealName,
+				CreateTime: time.Now(),
+			}
+			go func() {
+				data.ModifyManualEdbMaxMinDate(manualEdbInfo.TradeCode)
+				_ = record.Create()
+			}()
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+}
+
+// BatchEdbList
+// @Title 获取研究员指标
+// @Description 获取研究员指标
+// @Param	request	body models.BatchAddEdbReq true "type json string"
+// @Success 200 {object} models.TargetItemListResp
+// @router /target/edb/batch/list [post]
+func (c *ManualEdbController) BatchEdbList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	var req models.BatchManualEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+
+	pageSize := req.PageSize
+	currentIndex := req.CurrentIndex
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	req.Keyword = strings.TrimSpace(req.Keyword)
+
+	var condition string
+	var pars []interface{}
+
+	// 是否加到指标库
+	condition += ` AND a.is_join_edb = ? `
+	pars = append(pars, 0)
+
+	//超管账号可以查看分类下的所有频度数据
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		classifyIdList, err := data.GetUserManualClassifyIdList(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.Msg = "获取拥有的分类数据失败,Err:" + err.Error()
+			return
+		}
+		num := len(classifyIdList)
+		if num > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+			pars = append(pars, classifyIdList)
+		}
+
+	}
+
+	// 关键词
+	if req.Keyword != "" {
+		condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
+		pars = utils.GetLikeKeywordPars(pars, req.Keyword, 2)
+	}
+
+	// 所属分类
+	lenFrequency := len(req.FrequencyList)
+	if lenFrequency > 0 {
+		condition += ` AND a.frequency in (` + utils.GetOrmInReplace(lenFrequency) + `) `
+		pars = append(pars, req.FrequencyList)
+	}
+
+	// 所属分类
+	lenClassify := len(req.ClassifyIdList)
+	if lenClassify > 0 {
+		condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(lenClassify) + `) `
+		pars = append(pars, req.ClassifyIdList)
+	}
+
+	// 所属用户
+	lenUser := len(req.UserIdList)
+	if lenUser > 0 {
+		condition += ` AND a.user_id in (` + utils.GetOrmInReplace(lenUser) + `) `
+		pars = append(pars, req.UserIdList)
+	}
+
+	total, err := models.GetCountEdbInfoList(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	list, err := models.GetEdbInfoList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	resp := models.EdbListResp{
+		List:   list,
+		Paging: paging.GetPaging(currentIndex, pageSize, total),
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+	br.IsAddLog = false
+}
+
+// BatchAddEdbCheck
+// @Title 新增校验
+// @Description 新增校验
+// @Param	request	body data_manage.BatchManualEdbReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /target/edb/batch/add/check [post]
+func (c *ManualEdbController) BatchAddEdbCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 最大批量添加的数量
+	codeMax := 30
+
+	var req models.BatchManualEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+
+	req.Keyword = strings.TrimSpace(req.Keyword)
+
+	var condition string
+	var pars []interface{}
+
+	//
+	condition += ` AND a.is_join_edb = 0 `
+
+	//超管账号可以查看分类下的所有频度数据
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		classifyIdList, err := data.GetUserManualClassifyIdList(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.Msg = "获取拥有的分类数据失败,Err:" + err.Error()
+			return
+		}
+		num := len(classifyIdList)
+		if num > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+			pars = append(pars, classifyIdList)
+		}
+
+	}
+
+	if req.ListAll {
+		// 关键词
+		if req.Keyword != "" {
+			condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
+			pars = utils.GetLikeKeywordPars(pars, req.Keyword, 2)
+		}
+
+		// 所属分类
+		lenFrequency := len(req.FrequencyList)
+		if lenFrequency > 0 {
+			condition += ` AND a.frequency in (` + utils.GetOrmInReplace(lenFrequency) + `) `
+			pars = append(pars, req.FrequencyList)
+		}
+
+		// 所属分类
+		lenClassify := len(req.ClassifyIdList)
+		if lenClassify > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(lenClassify) + `) `
+			pars = append(pars, req.ClassifyIdList)
+		}
+
+		// 所属用户
+		lenUser := len(req.UserIdList)
+		if lenUser > 0 {
+			condition += ` AND a.user_id in (` + utils.GetOrmInReplace(lenUser) + `) `
+			pars = append(pars, req.UserIdList)
+		}
+
+		lenTradeList := len(req.TradeCodeList)
+		// 指标
+		if lenTradeList > 0 {
+			condition += ` AND a.TRADE_CODE not in (` + utils.GetOrmInReplace(lenTradeList) + `) `
+			pars = append(pars, req.TradeCodeList)
+		}
+	} else {
+		lenTradeList := len(req.TradeCodeList)
+		if lenTradeList <= 0 {
+			br.Msg = "请选择指标"
+			br.ErrMsg = "请选择指标"
+			return
+		}
+		// 指标
+		if lenTradeList > 0 {
+			condition += ` AND a.TRADE_CODE in (` + utils.GetOrmInReplace(lenTradeList) + `) `
+			pars = append(pars, req.TradeCodeList)
+		}
+	}
+
+	list, err := models.GetEdbInfoList(condition, pars, 0, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	if len(list) > codeMax {
+		br.Msg = fmt.Sprintf("最多只能选择%d个指标", codeMax)
+		return
+	}
+
+	br.Data = list
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// NameCheck
+// @Title 重名校验
+// @Description 批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /target/edb/batch/add/name_check [post]
+func (c *ManualEdbController) NameCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		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 []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+
+	type NameCheckResult struct {
+		EdbCode string
+		EdbName string
+		Exist   bool
+	}
+	indexNames := make([]string, 0)
+	resp := make([]*NameCheckResult, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		resp = append(resp, &NameCheckResult{
+			EdbCode: v.EdbCode,
+			EdbName: v.EdbName,
+		})
+	}
+
+	// 重名校验
+	edbList, e := data_manage.GetEdbInfoByNameArr(indexNames, utils.EDB_INFO_TYPE)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取重名指标失败, Err: " + e.Error()
+		return
+	}
+	nameExists := make(map[string]bool)
+	for _, v := range edbList {
+		nameExists[v.EdbName] = true
+	}
+	if len(nameExists) > 0 {
+		for _, v := range resp {
+			v.Exist = nameExists[v.EdbName]
+		}
+	}
+
+	br.Data = resp
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// BatchAdd2Edb
+// @Title 批量新增到指标库
+// @Description 批量新增到指标库
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /target/edb/batch/add [post]
+func (c *ManualEdbController) BatchAdd2Edb() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 最大批量添加的数量
+	codeMax := 30
+
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_MANUAL_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		return
+	}
+	var req []*data_manage.AddEdbInfoReq
+	if e := json.Unmarshal(c.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if len(req) == 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+	if len(req) > codeMax {
+		br.Msg = "批量添加指标数量不得超过30个"
+		return
+	}
+	indexNames := make([]string, 0)
+	for _, v := range req {
+		v.EdbCode = strings.TrimSpace(v.EdbCode)
+		if v.EdbCode == "" {
+			br.Msg = "指标ID不可为空"
+			return
+		}
+		v.EdbName = strings.TrimSpace(v.EdbName)
+		if v.EdbName == "" {
+			br.Msg = "请输入指标名称"
+			return
+		}
+		indexNames = append(indexNames, v.EdbName)
+		v.Frequency = strings.TrimSpace(v.Frequency)
+		if v.Frequency == "" {
+			br.Msg = "请选择频度"
+			return
+		}
+		v.Unit = strings.TrimSpace(v.Unit)
+		if v.Unit == "" {
+			br.Msg = "请输入单位"
+			return
+		}
+		if v.ClassifyId <= 0 {
+			br.Msg = "请选择分类"
+			return
+		}
+	}
+
+	// 限定同一时间最多批量新增30个指标
+	for _, v := range req {
+		var r data.ManualIndexSource2EdbReq
+		r.EdbCode = v.EdbCode
+		r.EdbName = v.EdbName
+		r.Frequency = v.Frequency
+		r.Unit = v.Unit
+		r.ClassifyId = v.ClassifyId
+		r.AdminId = sysUser.AdminId
+		r.AdminRealName = sysUser.RealName
+
+		edbInfo, e, errMsg, skip := data.ManualIndexSource2Edb(r, c.Lang)
+		if e != nil {
+			br.Msg = "操作失败"
+			if errMsg != "" {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = e.Error()
+			return
+		}
+		if skip {
+			continue
+		}
+
+		// 试用平台更新用户累计新增指标数
+		if utils.BusinessCode == utils.BusinessCodeSandbox {
+			go func() {
+				adminItem, e := system.GetSysAdminById(sysUser.AdminId)
+				if e != nil {
+					tips := fmt.Sprintf("试用平台更新用户累计新增指标数-获取用户失败, Err: " + e.Error())
+					utils.FileLog.Info(tips)
+					return
+				}
+				if adminItem.DepartmentName != "ETA试用客户" {
+					return
+				}
+				var ur etaTrialService.EtaTrialUserReq
+				ur.Mobile = adminItem.Mobile
+				_, _ = etaTrialService.UpdateUserIndexNum(ur)
+			}()
+		}
+
+		// 新增操作日志
+		{
+			edbLog := new(data_manage.EdbInfoLog)
+			edbLog.EdbInfoId = edbInfo.EdbInfoId
+			edbLog.SourceName = edbInfo.SourceName
+			edbLog.Source = edbInfo.Source
+			edbLog.EdbCode = edbInfo.EdbCode
+			edbLog.EdbName = edbInfo.EdbName
+			edbLog.ClassifyId = edbInfo.ClassifyId
+			edbLog.SysUserId = sysUser.AdminId
+			edbLog.SysUserRealName = sysUser.RealName
+			edbLog.CreateTime = time.Now()
+			edbLog.Content = string(c.Ctx.Input.RequestBody)
+			edbLog.Status = "新增指标"
+			edbLog.Method = c.Ctx.Input.URI()
+			go data_manage.AddEdbInfoLog(edbLog)
+		}
+	}
+
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// BatchDelEdbCheck
+// @Title 新增校验
+// @Description 新增校验
+// @Param	request	body data_manage.BatchManualEdbReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /target/edb/batch/del/check [post]
+func (c *ManualEdbController) BatchDelEdbCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		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 models.BatchManualEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+
+	req.Keyword = strings.TrimSpace(req.Keyword)
+
+	var condition string
+	var pars []interface{}
+
+	// 就是为了找出已经加入指标库的指标
+	condition += ` AND a.is_join_edb = ? `
+	pars = append(pars, 1)
+
+	//超管账号可以查看分类下的所有频度数据
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		classifyIdList, err := data.GetUserManualClassifyIdList(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.Msg = "获取拥有的分类数据失败,Err:" + err.Error()
+			return
+		}
+		num := len(classifyIdList)
+		if num > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+			pars = append(pars, classifyIdList)
+		}
+
+	}
+
+	if req.ListAll {
+		// 关键词
+		if req.Keyword != "" {
+			condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
+			pars = utils.GetLikeKeywordPars(pars, req.Keyword, 2)
+		}
+
+		// 所属分类
+		lenFrequency := len(req.FrequencyList)
+		if lenFrequency > 0 {
+			condition += ` AND a.frequency in (` + utils.GetOrmInReplace(lenFrequency) + `) `
+			pars = append(pars, req.FrequencyList)
+		}
+
+		// 所属分类
+		lenClassify := len(req.ClassifyIdList)
+		if lenClassify > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(lenClassify) + `) `
+			pars = append(pars, req.ClassifyIdList)
+		}
+
+		// 所属用户
+		lenUser := len(req.UserIdList)
+		if lenUser > 0 {
+			condition += ` AND a.user_id in (` + utils.GetOrmInReplace(lenUser) + `) `
+			pars = append(pars, req.UserIdList)
+		}
+
+		lenTradeList := len(req.TradeCodeList)
+		// 指标
+		if lenTradeList > 0 {
+			condition += ` AND a.TRADE_CODE not in (` + utils.GetOrmInReplace(lenTradeList) + `) `
+			pars = append(pars, req.TradeCodeList)
+		}
+	} else {
+		lenTradeList := len(req.TradeCodeList)
+		if lenTradeList <= 0 {
+			br.Msg = "请选择指标"
+			br.ErrMsg = "请选择指标"
+			return
+		}
+		// 指标
+		if lenTradeList > 0 {
+			condition += ` AND a.TRADE_CODE in (` + utils.GetOrmInReplace(lenTradeList) + `) `
+			pars = append(pars, req.TradeCodeList)
+		}
+	}
+
+	list, err := models.GetEdbInfoList(condition, pars, 0, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	br.Data = list
+	br.Msg = "校验成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// BatchDel
+// @Title 批量删除
+// @Description 批量新增
+// @Param	request	body data_manage.AddEdbInfoReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /target/edb/batch/del [post]
+func (c *ManualEdbController) BatchDel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	deleteCache := true
+	cacheKey := "CACHE_EDB_INFO_BATCH_ADD_MANUAL_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			_ = utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(c.Ctx.Input.RequestBody)
+		return
+	}
+	var req models.BatchManualEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+
+	req.Keyword = strings.TrimSpace(req.Keyword)
+
+	var condition string
+	var pars []interface{}
+
+	// 就是为了找出已经加入指标库的指标
+	condition += ` AND a.is_join_edb = ? `
+	pars = append(pars, 0)
+
+	//超管账号可以查看分类下的所有频度数据
+	if sysUser.RoleTypeCode != utils.ROLE_TYPE_CODE_ADMIN {
+		classifyIdList, err := data.GetUserManualClassifyIdList(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取分类数据失败"
+			br.Msg = "获取拥有的分类数据失败,Err:" + err.Error()
+			return
+		}
+		num := len(classifyIdList)
+		if num > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(num) + `) `
+			pars = append(pars, classifyIdList)
+		}
+	}
+
+	if req.ListAll {
+		// 关键词
+		if req.Keyword != "" {
+			condition += ` AND (a.SEC_NAME like ?  or a.TRADE_CODE like ? )`
+			pars = utils.GetLikeKeywordPars(pars, req.Keyword, 2)
+		}
+
+		// 所属分类
+		lenFrequency := len(req.FrequencyList)
+		if lenFrequency > 0 {
+			condition += ` AND a.frequency in (` + utils.GetOrmInReplace(lenFrequency) + `) `
+			pars = append(pars, req.FrequencyList)
+		}
+
+		// 所属分类
+		lenClassify := len(req.ClassifyIdList)
+		if lenClassify > 0 {
+			condition += ` AND a.classify_id in (` + utils.GetOrmInReplace(lenClassify) + `) `
+			pars = append(pars, req.ClassifyIdList)
+		}
+
+		// 所属用户
+		lenUser := len(req.UserIdList)
+		if lenUser > 0 {
+			condition += ` AND a.user_id in (` + utils.GetOrmInReplace(lenUser) + `) `
+			pars = append(pars, req.UserIdList)
+		}
+
+		lenTradeList := len(req.TradeCodeList)
+		// 指标
+		if lenTradeList > 0 {
+			condition += ` AND a.TRADE_CODE not in (` + utils.GetOrmInReplace(lenTradeList) + `) `
+			pars = append(pars, req.TradeCodeList)
+		}
+	} else {
+		lenTradeList := len(req.TradeCodeList)
+		if lenTradeList <= 0 {
+			br.Msg = "请选择指标"
+			br.ErrMsg = "请选择指标"
+			return
+		}
+		// 指标
+		if lenTradeList > 0 {
+			condition += ` AND a.TRADE_CODE in (` + utils.GetOrmInReplace(lenTradeList) + `) `
+			pars = append(pars, req.TradeCodeList)
+		}
+	}
+
+	list, err := models.GetEdbInfoList(condition, pars, 0, 0)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+
+	// TODO 二次校验指标是否已经加到指标库
+	{
+		codeList := make([]string, 0)
+		// 限定同一时间最多批量新增30个指标
+		for _, v := range list {
+			codeList = append(codeList, v.TradeCode)
+		}
+		err = models.DelManualIndexByCodeList(codeList)
+		if err != nil {
+			br.Msg = "删除失败"
+			br.ErrMsg = "删除失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	br.Msg = "删除成功"
+	br.Ret = 200
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// ImportData
+// @Title 导入数据
+// @Description 导入数据
+// @Param   EntryFile   query   file  true       "文件"
+// @Success 200 Ret=200 录入成功
+// @router /import/data [post]
+func (c *ManualEdbController) ImportData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+	file, _, err := c.GetFile("EntryFile")
+	if err != nil {
+		br.Msg = "获取文件失败"
+		br.ErrMsg = "获取文件失败,Err:" + err.Error()
+		return
+	}
+	path := "./static/数据导入_" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	defer file.Close()
+	err = c.SaveToFile("EntryFile", path)
+	if err != nil {
+		br.Msg = "文件保存失败"
+		br.ErrMsg = "文件保存失败,Err:" + err.Error()
+		return
+	}
+	if utils.RunMode == "debug" {
+		defer os.Remove(path)
+	}
+
+	successCount, failCount, err, errMsg := data.ImportManualData(path, sysUser)
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	resp := models.EdbdataImportResp{
+		SuccessCount: successCount,
+		FailCount:    failCount,
+	}
+	if failCount > 0 {
+		if successCount == 0 {
+			resp.Status = -1
+			resp.Msg = "导入失败"
+		} else {
+			resp.Status = 1
+			resp.Msg = "存在部分导入失败"
+		}
+	} else {
+		resp.Status = 0
+	}
+	br.Msg = "导入成功"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+}
+
+// RecordList
+// @Title 获取指标操作记录列表
+// @Description 获取指标操作记录列表
+// @Param   TradeCode   query   string  false       "指标编码"
+// @Success 200 {object} models.EdbinfoOpRecordListResp
+// @router /target/edb/op/record/list [get]
+func (c *ManualEdbController) RecordList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	// 频度
+	tradeCode := c.GetString("TradeCode")
+	if tradeCode == `` {
+		br.Msg = `请选择指标`
+		br.ErrMsg = `请选择指标`
+		br.IsSendEmail = false
+		return
+	}
+
+	total, list, err := models.GetEdbinfoOpRecordPageList(tradeCode, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	resp := models.EdbinfoOpRecordListResp{
+		List:   list,
+		Paging: paging.GetPaging(currentIndex, pageSize, total),
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 493 - 478
controllers/target.go

@@ -184,6 +184,20 @@ func (this *TargetController) DataAdd() {
 		br.ErrMsg = "新增失败,Err:" + err.Error()
 		return
 	}
+
+	// 添加操作记录
+	go func() {
+		record := &models.EdbinfoOpRecord{
+			TradeCode:  edbdata.TradeCode,
+			Remark:     "更新数据",
+			UserId:     this.SysUser.AdminId,
+			UserName:   this.SysUser.RealName,
+			CreateTime: time.Now(),
+		}
+		data.ModifyManualEdbMaxMinDate(edbdata.TradeCode)
+		_ = record.Create()
+	}()
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "新增成功"
@@ -444,7 +458,7 @@ func (this *TargetController) TargetList() {
 		return
 	}
 	total := 0
-	list := make([]*models.Edbinfo, 0)
+	list := make([]*models.EdbinfoItem, 0)
 
 	//有分类数据权限才查询
 	if len(classifyIdStrList) > 0 {
@@ -483,14 +497,14 @@ func (this *TargetController) TargetList() {
 			br.ErrMsg = "获取失败,Err:" + err.Error()
 			return
 		}
-		tmpList, err := models.GetEdbinfoList(condition, pars, startSize, pageSize, mobile, sysUser.RoleType)
+		tmpList, err := models.GetEdbinfoItemList(condition, pars, startSize, pageSize, mobile, sysUser.RoleType)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取失败,Err:" + err.Error()
 			return
 		}
 		if len(tmpList) <= 0 {
-			list = make([]*models.Edbinfo, 0)
+			list = make([]*models.EdbinfoItem, 0)
 		} else {
 			list = tmpList
 		}
@@ -577,7 +591,8 @@ func (this *TargetController) TargetAdd() {
 		br.Msg = "指标名称已存在"
 		return
 	}
-	err = models.AddEdbinfo(maxTradeCode, req.SecName, req.Unit, "手动", req.Frequency, req.NoticeTime, req.ClassifyId, sysUser.AdminId)
+
+	err = models.AddEdbinfo(maxTradeCode, req.SecName, req.Unit, "手动", req.Frequency, req.NoticeTime, req.ClassifyId, sysUser.AdminId, sysUser.RealName)
 	if err != nil {
 		br.Msg = "新增失败"
 		br.ErrMsg = "新增失败,Err:" + err.Error()
@@ -750,10 +765,12 @@ func (this *TargetController) ClassifyList() {
 			edbInfoGroupCountMap[edbInfoGroupCount.ClassifyId] = edbInfoGroupCount.Count
 		}
 		for _, classifyList := range list {
+			classifyList.UniqueCode = utils.MD5(fmt.Sprint(classifyList.ClassifyId))
 			if classifyList.Child != nil {
 				for _, classify := range classifyList.Child {
 					if total, ok := edbInfoGroupCountMap[classify.ClassifyId]; ok {
 						classify.EdbInfoTotal = total
+						classify.UniqueCode = utils.MD5(fmt.Sprint(classify.ClassifyId))
 					}
 				}
 			}
@@ -771,6 +788,7 @@ func (this *TargetController) ClassifyList() {
 // @Title 下载模板
 // @Description 下载模板
 // @Success 200 {object} models.EdbdataClassifyResp
+// @Param   Source   query   int  false       "来源:1:模板1;2:模板2"
 // @router /template [get]
 func (this *TargetCommonController) TemplateDownload() {
 	br := new(models.BaseResponse).Init()
@@ -778,8 +796,15 @@ func (this *TargetCommonController) TemplateDownload() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
+	source, _ := this.GetInt("Source")
+	switch source {
+	case 2:
+		this.Ctx.Output.Download("./static/template/导入模板2.xlsx", "数据导入模板2.xlsx")
+	default:
+		this.Ctx.Output.Download("./static/template/导入模板1.xlsx", "数据导入模板1.xlsx")
+	}
 
-	this.Ctx.Output.Download("./static/数据导入模板.xlsx", "数据导入模板.xlsx")
+	//this.Ctx.Output.Download("./static/数据导入模板.xlsx", "数据导入模板.xlsx")
 
 	br.Ret = 200
 	br.Success = true
@@ -805,460 +830,6 @@ func (this *TargetCommonController) TemplateDownloadEn() {
 	br.Msg = "下载成功"
 }
 
-// ImportData
-// @Title 导入数据
-// @Description 导入数据
-// @Param   EntryFile   query   file  true       "文件"
-// @Success 200 Ret=200 录入成功
-// @router /import/data [post]
-func (this *TargetController) ImportData() {
-	br := new(models.BaseResponse).Init()
-	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
-	}()
-	sysUser := this.SysUser
-	if sysUser == nil {
-		br.Msg = "请重新登录"
-		return
-	}
-	file, _, err := this.GetFile("EntryFile")
-	if err != nil {
-		br.Msg = "获取文件失败"
-		br.ErrMsg = "获取文件失败,Err:" + err.Error()
-		return
-	}
-	path := "./static/数据导入_" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
-	defer file.Close()
-	err = this.SaveToFile("EntryFile", path)
-	if err != nil {
-		br.Msg = "文件保存失败"
-		br.ErrMsg = "文件保存失败,Err:" + err.Error()
-		return
-	}
-	if utils.RunMode == "debug" {
-		defer os.Remove(path)
-	}
-	xlFile, err := xlsx.OpenFile(path)
-	if err != nil {
-		fmt.Println(err.Error())
-		return
-	}
-
-	//超管账号可以查看分类下的所有频度数据
-	userId := sysUser.AdminId
-	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
-		userId = 0
-	}
-	//获取账户所拥有权限的分类id集合
-	classifyNameStrList, edbDataClassifyMap, err := data.GetEdbClassifyNameListByAdminId(int64(userId))
-	if err != nil {
-		br.Msg = "获取分类数据失败"
-		return
-	}
-
-	//导入成功数量
-	successCount := 0
-	//导入失败数据
-	failDatas := make([]*models.EdbdataImportFail, 0)
-
-	//指标map
-	targetMap := make(map[string]*models.Edbinfo)
-	defer func() {
-		for _, target := range targetMap {
-			//结束后,清除掉对应的缓存
-			key := "import:edbinfo:data:" + target.TradeCode
-			utils.Rc.Delete(key)
-
-			//将该指标的code加入到 “手工数据导入后刷新” 缓存
-			if utils.Re == nil {
-				err := utils.Rc.LPush(utils.CACHE_IMPORT_MANUAL_DATA, target.TradeCode)
-				if err != nil {
-					fmt.Println("CACHE_IMPORT_MANUAL_DATA LPush Err:" + err.Error())
-				}
-			}
-		}
-	}()
-
-	// 所有的指标数据map
-	edbCodeDataMap := make(map[string]map[string]string)
-
-	// 遍历sheet页读取
-	for _, sheet := range xlFile.Sheets {
-		fmt.Println("sheet name: ", sheet.Name)
-		//遍历行读取
-		maxRow := sheet.MaxRow
-		fmt.Println("maxRow:", maxRow)
-		fmt.Println("maxRow")
-		for i := 0; i < maxRow; i++ {
-			if i == 1 {
-				row := sheet.Row(i)
-				cells := row.Cells
-				if len(cells) < 6 {
-					br.ErrMsg = "导入文件异常,请下载最新导入模板文件"
-					br.Msg = "导入文件异常,请下载最新导入模板文件"
-					return
-				}
-				templateFail := false
-				if cells[0].Value != "品种分类" && cells[0].Value != "Species Category" {
-					templateFail = true
-				}
-				if cells[1].Value != "录入日期" && cells[1].Value != "Input Date" {
-					templateFail = true
-				}
-				if cells[2].Value != "指标名称" && cells[2].Value != "Indicator Name Indicator Name" {
-					templateFail = true
-				}
-				if cells[3].Value != "值" && cells[3].Value != "Value" {
-					templateFail = true
-				}
-				if cells[4].Value != "频度" && cells[4].Value != "Frequency" {
-					templateFail = true
-				}
-				if cells[5].Value != "单位" && cells[5].Value != "Unit" {
-					templateFail = true
-				}
-				if templateFail {
-					br.ErrMsg = "导入文件异常,请下载最新导入模板文件"
-					br.Msg = "导入文件异常,请下载最新导入模板文件"
-					return
-				}
-			}
-			if i > 1 {
-				row := sheet.Row(i)
-				cells := row.Cells
-				if len(cells) >= 6 {
-					classifyName := cells[0].Value //分类
-					if classifyName == "" {        //过滤空白行
-						continue
-					}
-					cell1 := cells[1].Value
-					//createDate := utils.ConvertToFormatDay(cell1) //录入日期
-					createDate := cell1
-					cell2 := cells[2].Value //指标名称
-					secName := utils.TrimStr(cell2)
-					frequency := cells[4].Value //频度
-					unit := cells[5].Value      //单位
-
-					closeVal := cells[3].Value //值
-					if strings.Contains(closeVal, "#N/A") {
-						continue
-					}
-
-					//校验表格中的日期格式
-					if strings.Contains(createDate, "-") {
-						//如果是带有 - 的普通日期格式文本
-						_, timeErr := time.Parse("2006-1-2", createDate)
-						if timeErr != nil {
-							failItem := new(models.EdbdataImportFail)
-							failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-							failItem.ClassifyName = classifyName
-							failItem.CreateDate = createDate
-							failItem.SecName = secName
-							failItem.Close = closeVal
-							failItem.Remark = "日期格式异常"
-							failItem.Frequency = frequency
-							failItem.Unit = unit
-							failDatas = append(failDatas, failItem)
-							//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
-							continue
-						}
-					} else if strings.Contains(createDate, "/") {
-						//如果是带有 / 的普通日期格式文本
-						createDateTime, timeErr := time.Parse("2006/1/2", createDate)
-						if timeErr != nil {
-							failItem := new(models.EdbdataImportFail)
-							failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-							failItem.ClassifyName = classifyName
-							failItem.CreateDate = createDate
-							failItem.SecName = secName
-							failItem.Close = closeVal
-							failItem.Remark = "日期格式异常"
-							failItem.Frequency = frequency
-							failItem.Unit = unit
-							failDatas = append(failDatas, failItem)
-							//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
-							continue
-						}
-						createDate = createDateTime.Format("2006-01-02")
-					} else {
-						//可能是excel的日期格式
-						_, tmpErr := strconv.Atoi(createDate)
-						if tmpErr != nil {
-							failItem := new(models.EdbdataImportFail)
-							failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-							failItem.ClassifyName = classifyName
-							failItem.CreateDate = createDate
-							failItem.SecName = secName
-							failItem.Close = closeVal
-							failItem.Remark = "日期格式异常"
-							failItem.Frequency = frequency
-							failItem.Unit = unit
-							failDatas = append(failDatas, failItem)
-							//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
-							continue
-						}
-						createDate = utils.ConvertToFormatDay(createDate) //录入日期
-					}
-
-					closeValFloat, err := cells[3].Float() //值
-
-					if err != nil {
-						failItem := new(models.EdbdataImportFail)
-						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-						failItem.ClassifyName = classifyName
-						failItem.CreateDate = createDate
-						failItem.SecName = secName
-						failItem.Close = cells[3].Value
-						failItem.Remark = "值类型异常"
-						failItem.Frequency = frequency
-						failItem.Unit = unit
-						failDatas = append(failDatas, failItem)
-						continue
-					}
-					newDecimal := decimal.NewFromFloat(closeValFloat)
-					newDecimal.Round(4)
-					closeVal = newDecimal.String()
-					if strings.Contains(closeVal, "#N/A") {
-						continue
-					}
-					//closeVal := closeValFloat.
-
-					//判断指标,类型,等数据是否正常
-					classifyName = strings.Trim(classifyName, " ")
-					frequency = utils.TrimStr(frequency)
-					unit = utils.TrimStr(unit)
-
-					// 成功数量超过20个指标,那就不导入了
-					if len(targetMap) >= 150 {
-						failItem := new(models.EdbdataImportFail)
-						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-						failItem.ClassifyName = classifyName
-						failItem.CreateDate = createDate
-						failItem.SecName = secName
-						failItem.Close = closeVal
-						failItem.Remark = "导入指标数量过多"
-						failItem.Frequency = frequency
-						failItem.Unit = unit
-						failDatas = append(failDatas, failItem)
-						//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
-						continue
-					}
-
-					if !strings.Contains(strings.Join(classifyNameStrList, ","), classifyName) {
-						failItem := new(models.EdbdataImportFail)
-						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-						failItem.ClassifyName = classifyName
-						failItem.CreateDate = createDate
-						failItem.SecName = secName
-						failItem.Close = closeVal
-						failItem.Remark = "没有该品种分类权限"
-						failItem.Frequency = frequency
-						failItem.Unit = unit
-						failDatas = append(failDatas, failItem)
-						continue
-					}
-					//fmt.Println(classifyName, createDate, secName, closeVal)
-
-					//获取指标分类信息
-					classify, ok := edbDataClassifyMap[classifyName]
-					if !ok {
-						failItem := new(models.EdbdataImportFail)
-						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-						failItem.ClassifyName = classifyName
-						failItem.CreateDate = createDate
-						failItem.SecName = secName
-						failItem.Close = closeVal
-						failItem.Remark = "指标分类不存在"
-						failItem.Frequency = frequency
-						failItem.Unit = unit
-						failDatas = append(failDatas, failItem)
-						//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
-						continue
-					}
-
-					//判断指标是否存在
-					target, ok := targetMap[secName]
-					if !ok {
-						tmpTarget, err := models.GetTargetBySecName(secName)
-						if err != nil {
-							//如果是找不到该指标,那么新增指标
-							if err.Error() == utils.ErrNoRow() {
-								if frequency == "" {
-									failItem := new(models.EdbdataImportFail)
-									failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-									failItem.ClassifyName = classifyName
-									failItem.CreateDate = createDate
-									failItem.SecName = secName
-									failItem.Close = closeVal
-									failItem.Remark = "新增指标失败,频度字段为空"
-									failItem.Frequency = frequency
-									failItem.Unit = unit
-									failDatas = append(failDatas, failItem)
-									continue
-								}
-								if unit == "" {
-									failItem := new(models.EdbdataImportFail)
-									failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-									failItem.ClassifyName = classifyName
-									failItem.CreateDate = createDate
-									failItem.SecName = secName
-									failItem.Close = closeVal
-									failItem.Remark = "新增指标失败,单位字段为空"
-									failItem.Frequency = frequency
-									failItem.Unit = unit
-									failDatas = append(failDatas, failItem)
-									continue
-								}
-								tmpErr := data.AddEdbInfo(secName, unit, frequency, "", sysUser.Mobile, classify.ClassifyId, sysUser.AdminId)
-								if tmpErr != nil {
-									fmt.Println("line 158")
-									failItem := new(models.EdbdataImportFail)
-									failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-									failItem.ClassifyName = classifyName
-									failItem.CreateDate = createDate
-									failItem.SecName = secName
-									failItem.Close = closeVal
-									failItem.Remark = "新增指标失败"
-									failItem.Frequency = frequency
-									failItem.Unit = unit
-									failDatas = append(failDatas, failItem)
-									continue
-								}
-								tmpTarget, tmpErr := models.GetTargetBySecName(secName)
-								target = tmpTarget
-								targetMap[secName] = target
-							} else {
-								fmt.Println("导入数据 获取指标:Err:" + err.Error())
-							}
-						} else {
-							target = tmpTarget
-							targetMap[secName] = target
-						}
-
-						//设置10分钟缓存,不允许其他地方删除
-						key := "import:edbinfo:data:" + target.TradeCode
-						utils.Rc.SetNX(key, 1, time.Second*600)
-					}
-
-					if target == nil {
-						fmt.Println("指标不存在")
-						failItem := new(models.EdbdataImportFail)
-						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
-						failItem.ClassifyName = classifyName
-						failItem.CreateDate = createDate
-						failItem.SecName = secName
-						failItem.Close = closeVal
-						failItem.Remark = "指标不存在"
-						failItem.Frequency = frequency
-						failItem.Unit = unit
-						failDatas = append(failDatas, failItem)
-						continue
-					}
-
-					//更新指标信息
-					updateCols := make([]string, 0)
-					//更新指标分类
-					if target.ClassifyId <= 0 && classify.ClassifyId > 0 {
-						target.ClassifyId = classify.ClassifyId
-						updateCols = append(updateCols, "ClassifyId")
-					}
-					if target.Frequency != frequency {
-						target.Frequency = frequency
-						target.NoticeTime = ""
-						updateCols = append(updateCols, "Frequency", "NoticeTime")
-					}
-					if target.Unit != unit {
-						target.Unit = unit
-						updateCols = append(updateCols, "Unit")
-					}
-					if len(updateCols) > 0 {
-						_ = target.Update(updateCols)
-					}
-
-					// 判断指标数据列表是否已经存在
-					tmpDataMap, ok := edbCodeDataMap[target.TradeCode]
-					if !ok {
-						tmpDataMap = make(map[string]string)
-						dataList, tmpErr := models.GetTargetsDataList(target.TradeCode)
-						if tmpErr != nil {
-							go alarm_msg.SendAlarmMsg("导入数据"+target.TradeCode+" 获取指标的数据失败,Err:"+err.Error(), 3)
-						}
-						for _, tmpData := range dataList {
-							tmpDataMap[tmpData.Dt] = tmpData.Close
-						}
-						edbCodeDataMap[target.TradeCode] = tmpDataMap
-					}
-
-					//判断数据是否已经存在
-					tmpVal, ok := tmpDataMap[createDate]
-					//数据已存在,进行更新操作
-					if ok {
-						if tmpVal != closeVal {
-							err = models.ModifyTargetsDataByImport(target.TradeCode, createDate, closeVal)
-							if err != nil {
-								go alarm_msg.SendAlarmMsg("导入数据 修改数据失败,Err:"+err.Error(), 3)
-								//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 修改数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
-							}
-						}
-					} else { //数据不存在,进行新增操作
-						if target.TradeCode != "" && createDate != "" && closeVal != "" {
-							models.AddTargetsDataByImport(target.TradeCode, createDate, closeVal)
-							if err != nil {
-								go alarm_msg.SendAlarmMsg("导入数据 新增数据失败,Err:"+err.Error(), 3)
-								//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
-							}
-							tmpDataMap[createDate] = closeVal
-							edbCodeDataMap[target.TradeCode] = tmpDataMap
-						}
-					}
-					successCount++
-				} else {
-					//br.ErrMsg = "请填写导入内容"
-					//br.Msg = "请填写导入内容"
-					//return
-				}
-			}
-		}
-	}
-	resp := models.EdbdataImportResp{
-		SuccessCount: successCount,
-		FailCount:    len(failDatas),
-	}
-	fmt.Println("failDatas:", len(failDatas))
-	if len(failDatas) > 0 {
-		//先删除导入失败记录
-		_ = models.DelEdbDataImportFail(sysUser.AdminId)
-		//错误信息字符串切片,最后作为发送邮件通知使用
-		failContents := make([]string, 0)
-		for _, v := range failDatas {
-			failContents = append(failContents, fmt.Sprint(v.SecName, "导入失败:", v.Remark))
-			err = models.AddEdbdataImportFail(v)
-			if err != nil {
-				go alarm_msg.SendAlarmMsg("导入数据 新增失败记录失败,Err:"+err.Error(), 3)
-				//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增失败记录失败:Err:"+err.Error(), utils.EmailSendToUsers)
-			}
-		}
-		//导入失败的话,最后统一邮件提醒就好啦,不需要每次都去提醒
-		go alarm_msg.SendAlarmMsg("导入数据 存在部分数据导入失败:"+strings.Join(failContents, ";"), 3)
-		//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 存在部分数据导入失败:"+strings.Join(failContents, ";"), utils.EmailSendToUsers)
-
-		if successCount == 0 {
-			resp.Status = -1
-			resp.Msg = "导入失败"
-		} else {
-			resp.Status = 1
-			resp.Msg = "存在部分导入失败"
-		}
-	} else {
-		resp.Status = 0
-	}
-	br.Msg = "导入成功"
-	br.Ret = 200
-	br.Success = true
-	br.Data = resp
-}
-
 // ImportFailListDownload
 // @Title 下载失败列表
 // @Description 下载失败列表
@@ -1288,29 +859,19 @@ func (this *TargetController) ImportFailListDownload() {
 	}
 	sheet, err := xlsxFile.AddSheet(SheetName)
 	headRow := sheet.AddRow()
-	if this.Lang == utils.EnLangVersion {
-		headRow.AddCell().SetValue("Species Category")
-		headRow.AddCell().SetValue("Input Date")
-		headRow.AddCell().SetValue("Indicator Name Indicator Name")
-		headRow.AddCell().SetValue("Value")
-		headRow.AddCell().SetValue("Frequency")
-		headRow.AddCell().SetValue("Unit")
-		headRow.AddCell().SetValue("Remark")
-	} else {
-		headRow.AddCell().SetValue("品种分类")
-		headRow.AddCell().SetValue("录入日期")
-		headRow.AddCell().SetValue("指标名称")
-		headRow.AddCell().SetValue("值")
-		headRow.AddCell().SetValue("频度")
-		headRow.AddCell().SetValue("单位")
-		headRow.AddCell().SetValue("备注")
-	}
+	headRow.AddCell().SetValue("品种/Variety")
+	headRow.AddCell().SetValue("指标名称/Indicator Name")
+	headRow.AddCell().SetValue("指标日期/Indicator Date")
+	headRow.AddCell().SetValue("值/Value")
+	headRow.AddCell().SetValue("频度/Frequency")
+	headRow.AddCell().SetValue("单位/Unit")
+	headRow.AddCell().SetValue("备注/Note")
 
 	for _, v := range item {
 		row := sheet.AddRow()
 		row.AddCell().SetValue(v.ClassifyName)
-		row.AddCell().SetValue(v.CreateDate)
 		row.AddCell().SetValue(v.SecName)
+		row.AddCell().SetValue(v.CreateDate)
 		row.AddCell().SetString(v.Close)
 		row.AddCell().SetValue(v.Frequency)
 		row.AddCell().SetValue(v.Unit)
@@ -3244,7 +2805,7 @@ func (this *TargetController) ImportTarget() {
 						failDatas = append(failDatas, failItem)
 						continue
 					}
-					err = models.AddEdbinfo(maxTradeCode, secName, unit, "手动", frequency, "", classify.ClassifyId, sysUser.AdminId)
+					err = models.AddEdbinfo(maxTradeCode, secName, unit, "手动", frequency, "", classify.ClassifyId, sysUser.AdminId, sysUser.RealName)
 					if err != nil {
 						failItem := &models.EdbImportFail{
 							ClassifyName: classifyName,
@@ -3901,3 +3462,457 @@ func (this *TargetController) ExcelDataEdit() {
 	//br.Data = resp
 	br.Data = item
 }
+
+//// ImportData
+//// @Title 导入数据
+//// @Description 导入数据
+//// @Param   EntryFile   query   file  true       "文件"
+//// @Success 200 Ret=200 录入成功
+//// @router /import/data [post]
+//func (c *ManualEdbController) ImportData() {
+//	br := new(models.BaseResponse).Init()
+//	defer func() {
+//		c.Data["json"] = br
+//		c.ServeJSON()
+//	}()
+//	sysUser := c.SysUser
+//	if sysUser == nil {
+//		br.Msg = "请重新登录"
+//		return
+//	}
+//	file, _, err := c.GetFile("EntryFile")
+//	if err != nil {
+//		br.Msg = "获取文件失败"
+//		br.ErrMsg = "获取文件失败,Err:" + err.Error()
+//		return
+//	}
+//	path := "./static/数据导入_" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+//	defer file.Close()
+//	err = c.SaveToFile("EntryFile", path)
+//	if err != nil {
+//		br.Msg = "文件保存失败"
+//		br.ErrMsg = "文件保存失败,Err:" + err.Error()
+//		return
+//	}
+//	if utils.RunMode == "debug" {
+//		defer os.Remove(path)
+//	}
+//	xlFile, err := xlsx.OpenFile(path)
+//	if err != nil {
+//		fmt.Println(err.Error())
+//		return
+//	}
+//
+//	//超管账号可以查看分类下的所有频度数据
+//	userId := sysUser.AdminId
+//	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
+//		userId = 0
+//	}
+//	//获取账户所拥有权限的分类id集合
+//	classifyNameStrList, edbDataClassifyMap, err := data.GetEdbClassifyNameListByAdminId(int64(userId))
+//	if err != nil {
+//		br.Msg = "获取分类数据失败"
+//		return
+//	}
+//
+//	//导入成功数量
+//	successCount := 0
+//	//导入失败数据
+//	failDatas := make([]*models.EdbdataImportFail, 0)
+//
+//	//指标map
+//	targetMap := make(map[string]*models.Edbinfo)
+//	defer func() {
+//		for _, target := range targetMap {
+//			//结束后,清除掉对应的缓存
+//			key := "import:edbinfo:data:" + target.TradeCode
+//			utils.Rc.Delete(key)
+//
+//			//将该指标的code加入到 “手工数据导入后刷新” 缓存
+//			if utils.Re == nil {
+//				err := utils.Rc.LPush(utils.CACHE_IMPORT_MANUAL_DATA, target.TradeCode)
+//				if err != nil {
+//					fmt.Println("CACHE_IMPORT_MANUAL_DATA LPush Err:" + err.Error())
+//				}
+//			}
+//		}
+//	}()
+//
+//	// 所有的指标数据map
+//	edbCodeDataMap := make(map[string]map[string]string)
+//
+//	// 遍历sheet页读取
+//	for _, sheet := range xlFile.Sheets {
+//		fmt.Println("sheet name: ", sheet.Name)
+//		//遍历行读取
+//		maxRow := sheet.MaxRow
+//		fmt.Println("maxRow:", maxRow)
+//		fmt.Println("maxRow")
+//		for i := 0; i < maxRow; i++ {
+//			if i == 1 {
+//				row := sheet.Row(i)
+//				cells := row.Cells
+//				if len(cells) < 6 {
+//					br.ErrMsg = "导入文件异常,请下载最新导入模板文件"
+//					br.Msg = "导入文件异常,请下载最新导入模板文件"
+//					return
+//				}
+//				templateFail := false
+//				if cells[0].Value != "品种分类" && cells[0].Value != "Species Category" {
+//					templateFail = true
+//				}
+//				if cells[1].Value != "录入日期" && cells[1].Value != "Input Date" {
+//					templateFail = true
+//				}
+//				if cells[2].Value != "指标名称" && cells[2].Value != "Indicator Name Indicator Name" {
+//					templateFail = true
+//				}
+//				if cells[3].Value != "值" && cells[3].Value != "Value" {
+//					templateFail = true
+//				}
+//				if cells[4].Value != "频度" && cells[4].Value != "Frequency" {
+//					templateFail = true
+//				}
+//				if cells[5].Value != "单位" && cells[5].Value != "Unit" {
+//					templateFail = true
+//				}
+//				if templateFail {
+//					br.ErrMsg = "导入文件异常,请下载最新导入模板文件"
+//					br.Msg = "导入文件异常,请下载最新导入模板文件"
+//					return
+//				}
+//			}
+//			if i > 1 {
+//				row := sheet.Row(i)
+//				cells := row.Cells
+//				if len(cells) >= 6 {
+//					classifyName := cells[0].Value //分类
+//					if classifyName == "" {        //过滤空白行
+//						continue
+//					}
+//					cell1 := cells[1].Value
+//					//createDate := utils.ConvertToFormatDay(cell1) //录入日期
+//					createDate := cell1
+//					cell2 := cells[2].Value //指标名称
+//					secName := utils.TrimStr(cell2)
+//					frequency := cells[4].Value //频度
+//					unit := cells[5].Value      //单位
+//
+//					closeVal := cells[3].Value //值
+//					if strings.Contains(closeVal, "#N/A") {
+//						continue
+//					}
+//
+//					//校验表格中的日期格式
+//					if strings.Contains(createDate, "-") {
+//						//如果是带有 - 的普通日期格式文本
+//						_, timeErr := time.Parse("2006-1-2", createDate)
+//						if timeErr != nil {
+//							failItem := new(models.EdbdataImportFail)
+//							failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//							failItem.ClassifyName = classifyName
+//							failItem.CreateDate = createDate
+//							failItem.SecName = secName
+//							failItem.Close = closeVal
+//							failItem.Remark = "日期格式异常"
+//							failItem.Frequency = frequency
+//							failItem.Unit = unit
+//							failDatas = append(failDatas, failItem)
+//							//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+//							continue
+//						}
+//					} else if strings.Contains(createDate, "/") {
+//						//如果是带有 / 的普通日期格式文本
+//						createDateTime, timeErr := time.Parse("2006/1/2", createDate)
+//						if timeErr != nil {
+//							failItem := new(models.EdbdataImportFail)
+//							failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//							failItem.ClassifyName = classifyName
+//							failItem.CreateDate = createDate
+//							failItem.SecName = secName
+//							failItem.Close = closeVal
+//							failItem.Remark = "日期格式异常"
+//							failItem.Frequency = frequency
+//							failItem.Unit = unit
+//							failDatas = append(failDatas, failItem)
+//							//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+//							continue
+//						}
+//						createDate = createDateTime.Format("2006-01-02")
+//					} else {
+//						//可能是excel的日期格式
+//						_, tmpErr := strconv.Atoi(createDate)
+//						if tmpErr != nil {
+//							failItem := new(models.EdbdataImportFail)
+//							failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//							failItem.ClassifyName = classifyName
+//							failItem.CreateDate = createDate
+//							failItem.SecName = secName
+//							failItem.Close = closeVal
+//							failItem.Remark = "日期格式异常"
+//							failItem.Frequency = frequency
+//							failItem.Unit = unit
+//							failDatas = append(failDatas, failItem)
+//							//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+//							continue
+//						}
+//						createDate = utils.ConvertToFormatDay(createDate) //录入日期
+//					}
+//
+//					closeValFloat, err := cells[3].Float() //值
+//
+//					if err != nil {
+//						failItem := new(models.EdbdataImportFail)
+//						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//						failItem.ClassifyName = classifyName
+//						failItem.CreateDate = createDate
+//						failItem.SecName = secName
+//						failItem.Close = cells[3].Value
+//						failItem.Remark = "值类型异常"
+//						failItem.Frequency = frequency
+//						failItem.Unit = unit
+//						failDatas = append(failDatas, failItem)
+//						continue
+//					}
+//					newDecimal := decimal.NewFromFloat(closeValFloat)
+//					newDecimal.Round(4)
+//					closeVal = newDecimal.String()
+//					if strings.Contains(closeVal, "#N/A") {
+//						continue
+//					}
+//					//closeVal := closeValFloat.
+//
+//					//判断指标,类型,等数据是否正常
+//					classifyName = strings.Trim(classifyName, " ")
+//					frequency = utils.TrimStr(frequency)
+//					unit = utils.TrimStr(unit)
+//
+//					// 成功数量超过20个指标,那就不导入了
+//					if len(targetMap) >= 150 {
+//						failItem := new(models.EdbdataImportFail)
+//						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//						failItem.ClassifyName = classifyName
+//						failItem.CreateDate = createDate
+//						failItem.SecName = secName
+//						failItem.Close = closeVal
+//						failItem.Remark = "导入指标数量过多"
+//						failItem.Frequency = frequency
+//						failItem.Unit = unit
+//						failDatas = append(failDatas, failItem)
+//						//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+//						continue
+//					}
+//
+//					if !strings.Contains(strings.Join(classifyNameStrList, ","), classifyName) {
+//						failItem := new(models.EdbdataImportFail)
+//						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//						failItem.ClassifyName = classifyName
+//						failItem.CreateDate = createDate
+//						failItem.SecName = secName
+//						failItem.Close = closeVal
+//						failItem.Remark = "没有该品种分类权限"
+//						failItem.Frequency = frequency
+//						failItem.Unit = unit
+//						failDatas = append(failDatas, failItem)
+//						continue
+//					}
+//					//fmt.Println(classifyName, createDate, secName, closeVal)
+//
+//					//获取指标分类信息
+//					classify, ok := edbDataClassifyMap[classifyName]
+//					if !ok {
+//						failItem := new(models.EdbdataImportFail)
+//						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//						failItem.ClassifyName = classifyName
+//						failItem.CreateDate = createDate
+//						failItem.SecName = secName
+//						failItem.Close = closeVal
+//						failItem.Remark = "指标分类不存在"
+//						failItem.Frequency = frequency
+//						failItem.Unit = unit
+//						failDatas = append(failDatas, failItem)
+//						//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+//						continue
+//					}
+//
+//					//判断指标是否存在
+//					target, ok := targetMap[secName]
+//					if !ok {
+//						tmpTarget, err := models.GetTargetBySecName(secName)
+//						if err != nil {
+//							//如果是找不到该指标,那么新增指标
+//							if err.Error() == utils.ErrNoRow() {
+//								if frequency == "" {
+//									failItem := new(models.EdbdataImportFail)
+//									failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//									failItem.ClassifyName = classifyName
+//									failItem.CreateDate = createDate
+//									failItem.SecName = secName
+//									failItem.Close = closeVal
+//									failItem.Remark = "新增指标失败,频度字段为空"
+//									failItem.Frequency = frequency
+//									failItem.Unit = unit
+//									failDatas = append(failDatas, failItem)
+//									continue
+//								}
+//								if unit == "" {
+//									failItem := new(models.EdbdataImportFail)
+//									failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//									failItem.ClassifyName = classifyName
+//									failItem.CreateDate = createDate
+//									failItem.SecName = secName
+//									failItem.Close = closeVal
+//									failItem.Remark = "新增指标失败,单位字段为空"
+//									failItem.Frequency = frequency
+//									failItem.Unit = unit
+//									failDatas = append(failDatas, failItem)
+//									continue
+//								}
+//								tmpErr := data.AddEdbInfo(secName, unit, frequency, "", sysUser.Mobile, classify.ClassifyId, sysUser.AdminId)
+//								if tmpErr != nil {
+//									fmt.Println("line 158")
+//									failItem := new(models.EdbdataImportFail)
+//									failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//									failItem.ClassifyName = classifyName
+//									failItem.CreateDate = createDate
+//									failItem.SecName = secName
+//									failItem.Close = closeVal
+//									failItem.Remark = "新增指标失败"
+//									failItem.Frequency = frequency
+//									failItem.Unit = unit
+//									failDatas = append(failDatas, failItem)
+//									continue
+//								}
+//								tmpTarget, tmpErr := models.GetTargetBySecName(secName)
+//								target = tmpTarget
+//								targetMap[secName] = target
+//							} else {
+//								fmt.Println("导入数据 获取指标:Err:" + err.Error())
+//							}
+//						} else {
+//							target = tmpTarget
+//							targetMap[secName] = target
+//						}
+//
+//						//设置10分钟缓存,不允许其他地方删除
+//						key := "import:edbinfo:data:" + target.TradeCode
+//						utils.Rc.SetNX(key, 1, time.Second*600)
+//					}
+//
+//					if target == nil {
+//						fmt.Println("指标不存在")
+//						failItem := new(models.EdbdataImportFail)
+//						failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+//						failItem.ClassifyName = classifyName
+//						failItem.CreateDate = createDate
+//						failItem.SecName = secName
+//						failItem.Close = closeVal
+//						failItem.Remark = "指标不存在"
+//						failItem.Frequency = frequency
+//						failItem.Unit = unit
+//						failDatas = append(failDatas, failItem)
+//						continue
+//					}
+//
+//					//更新指标信息
+//					updateCols := make([]string, 0)
+//					//更新指标分类
+//					if target.ClassifyId <= 0 && classify.ClassifyId > 0 {
+//						target.ClassifyId = classify.ClassifyId
+//						updateCols = append(updateCols, "ClassifyId")
+//					}
+//					if target.Frequency != frequency {
+//						target.Frequency = frequency
+//						target.NoticeTime = ""
+//						updateCols = append(updateCols, "Frequency", "NoticeTime")
+//					}
+//					if target.Unit != unit {
+//						target.Unit = unit
+//						updateCols = append(updateCols, "Unit")
+//					}
+//					if len(updateCols) > 0 {
+//						_ = target.Update(updateCols)
+//					}
+//
+//					// 判断指标数据列表是否已经存在
+//					tmpDataMap, ok := edbCodeDataMap[target.TradeCode]
+//					if !ok {
+//						tmpDataMap = make(map[string]string)
+//						dataList, tmpErr := models.GetTargetsDataList(target.TradeCode)
+//						if tmpErr != nil {
+//							go alarm_msg.SendAlarmMsg("导入数据"+target.TradeCode+" 获取指标的数据失败,Err:"+err.Error(), 3)
+//						}
+//						for _, tmpData := range dataList {
+//							tmpDataMap[tmpData.Dt] = tmpData.Close
+//						}
+//						edbCodeDataMap[target.TradeCode] = tmpDataMap
+//					}
+//
+//					//判断数据是否已经存在
+//					tmpVal, ok := tmpDataMap[createDate]
+//					//数据已存在,进行更新操作
+//					if ok {
+//						if tmpVal != closeVal {
+//							err = models.ModifyTargetsDataByImport(target.TradeCode, createDate, closeVal)
+//							if err != nil {
+//								go alarm_msg.SendAlarmMsg("导入数据 修改数据失败,Err:"+err.Error(), 3)
+//								//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 修改数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
+//							}
+//						}
+//					} else { //数据不存在,进行新增操作
+//						if target.TradeCode != "" && createDate != "" && closeVal != "" {
+//							models.AddTargetsDataByImport(target.TradeCode, createDate, closeVal)
+//							if err != nil {
+//								go alarm_msg.SendAlarmMsg("导入数据 新增数据失败,Err:"+err.Error(), 3)
+//								//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
+//							}
+//							tmpDataMap[createDate] = closeVal
+//							edbCodeDataMap[target.TradeCode] = tmpDataMap
+//						}
+//					}
+//					successCount++
+//				} else {
+//					//br.ErrMsg = "请填写导入内容"
+//					//br.Msg = "请填写导入内容"
+//					//return
+//				}
+//			}
+//		}
+//	}
+//	resp := models.EdbdataImportResp{
+//		SuccessCount: successCount,
+//		FailCount:    len(failDatas),
+//	}
+//	fmt.Println("failDatas:", len(failDatas))
+//	if len(failDatas) > 0 {
+//		//先删除导入失败记录
+//		_ = models.DelEdbDataImportFail(sysUser.AdminId)
+//		//错误信息字符串切片,最后作为发送邮件通知使用
+//		failContents := make([]string, 0)
+//		for _, v := range failDatas {
+//			failContents = append(failContents, fmt.Sprint(v.SecName, "导入失败:", v.Remark))
+//			err = models.AddEdbdataImportFail(v)
+//			if err != nil {
+//				go alarm_msg.SendAlarmMsg("导入数据 新增失败记录失败,Err:"+err.Error(), 3)
+//				//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增失败记录失败:Err:"+err.Error(), utils.EmailSendToUsers)
+//			}
+//		}
+//		//导入失败的话,最后统一邮件提醒就好啦,不需要每次都去提醒
+//		go alarm_msg.SendAlarmMsg("导入数据 存在部分数据导入失败:"+strings.Join(failContents, ";"), 3)
+//		//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 存在部分数据导入失败:"+strings.Join(failContents, ";"), utils.EmailSendToUsers)
+//
+//		if successCount == 0 {
+//			resp.Status = -1
+//			resp.Msg = "导入失败"
+//		} else {
+//			resp.Status = 1
+//			resp.Msg = "存在部分导入失败"
+//		}
+//	} else {
+//		resp.Status = 0
+//	}
+//	br.Msg = "导入成功"
+//	br.Ret = 200
+//	br.Success = true
+//	br.Data = resp
+//}

+ 14 - 0
models/data_manage/excel_style.go

@@ -210,3 +210,17 @@ type Ct struct {
 	Fa string `json:"fa"`
 	T  string `json:"t"`
 }
+
+// ManualEdbExcelStyleEditReq
+// @Description: 手工数据录入编辑(Excel样式)
+type ManualEdbExcelStyleEditReq struct {
+	EdbName string
+	Data    []struct {
+		Date  string
+		Value float64
+	}
+	TradeCode  string `description:"指标编码"`
+	Unit       string `description:"单位"`
+	Frequency  string `description:"频度"`
+	ClassifyId int    `description:"分类id"`
+}

+ 1 - 0
models/db.go

@@ -299,6 +299,7 @@ func initShEdbData() {
 		new(Edbinfo),                         //edb库的edbinfo表
 		new(data_manage.ExcelStyle),          //在线excel样式表
 		new(data_manage.ExcelEdbdataMapping), //excel样式和指标映射表
+		new(EdbinfoOpRecord),                 // 手工数据的操作日志
 	)
 }
 

+ 17 - 2
models/edbdata_import_fail.go

@@ -1,6 +1,9 @@
 package models
 
-import "github.com/beego/beego/v2/client/orm"
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+)
 
 type EdbdataImportFail struct {
 	Id           int `orm:"column(id);pk"`
@@ -20,6 +23,19 @@ func AddEdbdataImportFail(item *EdbdataImportFail) (err error) {
 	return err
 }
 
+// MultiAddEdbdataImportFail
+// @Description: 批量添加导入失败的信息
+// @author: Roc
+// @datetime 2024-07-30 19:48:06
+// @param items []*EdbdataImportFail
+// @return err error
+func MultiAddEdbdataImportFail(items []*EdbdataImportFail) (err error) {
+	o := orm.NewOrmUsingDB("edb")
+	_, err = o.InsertMulti(utils.MultiAddNum, items)
+
+	return err
+}
+
 // DelEdbDataImportFail 删除导入指标失败记录
 func DelEdbDataImportFail(userId int) (err error) {
 	o := orm.NewOrmUsingDB("edb")
@@ -27,4 +43,3 @@ func DelEdbDataImportFail(userId int) (err error) {
 	_, err = o.Raw(sql, userId).Exec()
 	return err
 }
-

+ 392 - 0
models/manual_edb.go

@@ -0,0 +1,392 @@
+package models
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+// TargetDetailResp 指标数据结构体
+type TargetDetailResp struct {
+	Detail       *EdbInfoItem
+	ClassifyList []*EdbdataClassify
+}
+
+// GetTargetByTradeCode
+// @Description: 根据手工指标编码获取指标信息
+// @author: Roc
+// @datetime 2024-07-16 14:18:10
+// @param tradeCode string
+// @return item *Edbinfo
+// @return err error
+func GetTargetByTradeCode(tradeCode string) (item *EdbInfoItem, err error) {
+	sql := `SELECT * FROM edbinfo WHERE TRADE_CODE = ?  `
+	o := orm.NewOrmUsingDB("edb")
+	err = o.Raw(sql, tradeCode).QueryRow(&item)
+	return
+}
+
+// GetCountManualUserClassify
+// @Description: 根据用户ID和分类ID获取关系数量
+// @author: Roc
+// @datetime 2024-07-16 14:27:58
+// @param sysUserId int
+// @param classifyId int
+// @return total int
+// @return err error
+func GetCountManualUserClassify(sysUserId, classifyId int) (total int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT count(1) ct FROM manual_user_classify WHERE admin_id=? AND classify_id = ? `
+	err = o.Raw(sql, sysUserId, classifyId).QueryRow(&total)
+
+	return
+}
+func GetManualClassifyByClassifyId(classifyId int) (item *EdbdataClassify, err error) {
+	o := orm.NewOrmUsingDB("edb")
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE classify_id = ?  `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+
+	return
+}
+
+// GetEdbDataListByCode
+// @Description: 通过指标ID获取所有数据
+// @author: Roc
+// @datetime 2024-07-16 15:32:41
+// @param tradeCode string
+// @return items []*Edbdata
+// @return err error
+func GetEdbDataListByCode(tradeCode string) (items []*Edbdata, err error) {
+	sql := ` SELECT  TRADE_CODE,DT,round(CLOSE,4) CLOSE,modify_time  FROM edbdata WHERE TRADE_CODE = ?  GROUP BY TRADE_CODE,DT ORDER BY DT DESC `
+	o := orm.NewOrmUsingDB("edb")
+	_, err = o.Raw(sql, tradeCode).QueryRows(&items)
+	return
+}
+
+// EdbInfoListItem
+type EdbInfoListItem struct {
+	TradeCode    string `orm:"column(TRADE_CODE);pk" description:"指标code"`
+	SecName      string `orm:"column(SEC_NAME);" description:"指标名称"`
+	Unit         string `orm:"column(UNIT);" description:"单位"`
+	Remark       string `orm:"column(REMARK);" description:"备注"`
+	Frequency    string `description:"频度"`
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	CreateDate   string `description:"创建时间"`
+	UserId       int    `description:"录入用户id"`
+	NoticeTime   string `description:"通知时间"`
+	Mobile       string `description:"录入者手机号"`
+	ModifyDate   string `description:"待更新日期"`
+	ModifyTime   string `description:"数据更新时间"`
+	Status       string `description:"状态:未完成/完成"`
+	UniqueCode   string
+	IsJoinEdb    int8    `description:"指标库是否已添加:0-否;1-是"`
+	UserName     string  `description:"录入用户名称"`
+	StartDate    string  `description:"数据开始日期"`
+	EndDate      string  `description:"数据结束日期"`
+	LatestValue  float64 `description:"指标最新值"`
+}
+
+// EdbListResp 指标数据结构体
+type EdbListResp struct {
+	List   []*EdbInfoListItem
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// GetEdbInfoList
+// @Description: 根据条件获取指标列表
+// @author: Roc
+// @datetime 2024-07-17 10:34:05
+// @param condition string
+// @param pars []interface{}
+// @return items []*Edbinfo
+// @return err error
+func GetEdbInfoList(condition string, pars []interface{}, startSize, pageSize int) (items []*EdbInfoListItem, err error) {
+	o := orm.NewOrmUsingDB("edb")
+	sql := `SELECT DISTINCT a.* FROM edbinfo AS a  WHERE a.REMARK='手动' `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY a.create_date DESC `
+
+	if pageSize > 0 {
+		sql += ` LIMIT ?,? `
+		pars = append(pars, startSize, pageSize)
+	}
+
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+
+	return
+}
+
+// GetCountEdbInfoList
+// @Description: 根据条件获取指标数量
+// @author: Roc
+// @datetime 2024-07-17 14:51:00
+// @param condition string
+// @param pars []interface{}
+// @return total int
+// @return err error
+func GetCountEdbInfoList(condition string, pars []interface{}) (total int, err error) {
+	o := orm.NewOrmUsingDB("edb")
+	sql := `SELECT COUNT(1) ct FROM edbinfo AS a  WHERE a.REMARK='手动' `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY a.create_date DESC `
+
+	err = o.Raw(sql, pars).QueryRow(&total)
+
+	return
+}
+
+// OnlyMultiAddEdbdata
+// @Description: 批量添加指标数据
+// @author: Roc
+// @datetime 2024-07-18 16:48:55
+// @param items []*Edbdata
+// @return err error
+func OnlyMultiAddEdbdata(items []*Edbdata) (err error) {
+	o := orm.NewOrmUsingDB("edb")
+	_, err = o.InsertMulti(utils.MultiAddNum, items)
+	return
+}
+
+// DelEdbdataByCodeAndDateList
+// @Description: 根据指标编码和日期列表批量删除指标的明细数据
+// @author: Roc
+// @datetime 2024-07-18 16:54:27
+// @param tradeCode string
+// @param dateList []string
+// @return err error
+func DelEdbdataByCodeAndDateList(tradeCode string, dateList []string) (err error) {
+	num := len(dateList)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrmUsingDB("edb")
+	sql := `delete from  edbdata AS a  WHERE a.TRADE_CODE=? and DT in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, tradeCode, dateList).Exec()
+
+	return
+}
+
+// UpdateManualIsJoinEdbStatus
+// @Description: 根据手工数据加入指标的状态
+// @author: Roc
+// @datetime 2024-07-22 11:29:13
+// @param edbCode string
+// @param isJoinEdb int 是否加入指标库
+// @return err error
+func UpdateManualIsJoinEdbStatus(edbCode string, isJoinEdb int8) (err error) {
+	o := orm.NewOrmUsingDB("edb")
+	sql := ` UPDATE edbinfo SET is_join_edb = ? WHERE TRADE_CODE =? `
+	_, err = o.Raw(sql, isJoinEdb, edbCode).Exec()
+	return
+}
+
+// BatchManualEdbReq 指标数据结构体
+type BatchManualEdbReq struct {
+	//IsJoinEdb      int      `form:"IsJoinEdb" description:"是否加到指标库,0:未加到指标库"`
+	FrequencyList  []string `description:"频度;枚举值:日度、周度、月度、季度、半年度、年度"`
+	Keyword        string   `description:"关键字"`
+	ClassifyIdList []int    `description:"所选品种id列表"`
+	UserIdList     []int    `description:"所选用户id列表"`
+	ListAll        bool     `form:"ListAll" json:"ListAll" description:"列表全选"`
+	TradeCodeList  []string `form:"TradeCodeList" json:"TradeCodeList" description:"全选为false时, 该数组为选中; 全选为true时, 该数组为不选的指标"`
+	PageSize       int      `form:"PageSize" json:"PageSize"`
+	CurrentIndex   int      `form:"CurrentIndex" form:"CurrentIndex"`
+}
+
+// DelManualIndexByCodeList
+// @Description: 根据指标编码列表删除指标
+// @author: Roc
+// @datetime 2024-07-30 14:10:12
+// @param codeList []string
+// @return err error
+func DelManualIndexByCodeList(codeList []string) (err error) {
+	num := len(codeList)
+	if num <= 0 {
+		return
+	}
+	to, err := orm.NewOrmUsingDB("edb").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	// 删除指标
+	sql := `DELETE FROM edbinfo WHERE TRADE_CODE  in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = to.Raw(sql, codeList).Exec()
+	if err != nil {
+
+	}
+
+	// 删除指标数据
+	sql = `DELETE FROM edbdata WHERE TRADE_CODE  in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = to.Raw(sql, codeList).Exec()
+	if err != nil {
+
+	}
+
+	return
+}
+
+// GetEdbinfoListBySecNameList
+// @Description: 根据指标名称获取列表数据
+// @author: Roc
+// @datetime 2024-07-30 19:14:25
+// @param secNameList []string
+// @return item []*Edbinfo
+// @return err error
+func GetEdbinfoListBySecNameList(secNameList []string) (items []*Edbinfo, err error) {
+	num := len(secNameList)
+	if num <= 0 {
+		return
+	}
+	sql := `SELECT * FROM edbinfo WHERE SEC_NAME in (` + utils.GetOrmInReplace(num) + ` ) AND REMARK='手动' `
+	o := orm.NewOrmUsingDB("edb")
+	_, err = o.Raw(sql, secNameList).QueryRows(&items)
+
+	return
+}
+
+// GetTargetsDataListByCodeList
+// @Description: 根据code列表获取指标数据列表
+// @author: Roc
+// @datetime 2024-07-30 19:19:36
+// @param tradeCodeList []string
+// @return items []*Edbdata
+// @return err error
+func GetTargetsDataListByCodeList(tradeCodeList []string) (items []*Edbdata, err error) {
+	num := len(tradeCodeList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("edb")
+	sql := `SELECT * FROM edbdata WHERE TRADE_CODE in (` + utils.GetOrmInReplace(num) + ` ) ORDER BY DT ASC `
+	_, err = o.Raw(sql, tradeCodeList).QueryRows(&items)
+
+	return
+}
+
+// EdbinfoOpRecord
+// @Description: 手工数据的操作日志
+type EdbinfoOpRecord struct {
+	EdbinfoOpRecordId int       `orm:"column(edbinfo_op_record_id);pk"`
+	TradeCode         string    `orm:"column(TRADE_CODE)" description:"指标编码"`
+	Remark            string    `orm:"column(remark)" description:"操作信息"`
+	UserId            int       `orm:"column(user_id)" description:"用户id"`
+	UserName          string    `orm:"column(user_name)" description:"用户姓名"`
+	CreateTime        time.Time `orm:"column(create_time)" description:"创建时间"`
+}
+
+// Remark备注:
+// 1、创建指标
+// 2、编辑指标
+// 3、更新数据
+// 4、数据资产由<xxx>转移给<xxx>
+
+// Create
+// @Description: 添加手工数据的操作日志
+// @author: Roc
+// @receiver m
+// @datetime 2024-07-30 16:25:55
+// @return err error
+func (m *EdbinfoOpRecord) Create() (err error) {
+	o := orm.NewOrmUsingDB("edb")
+	_, err = o.Insert(m)
+	return
+}
+
+// MulCreate
+// @Description: 批量添加手工数据的操作日志
+// @author: Roc
+// @receiver m
+// @datetime 2024-08-01 11:05:02
+// @param list []*EdbinfoOpRecord
+// @return err error
+func (m *EdbinfoOpRecord) MulCreate(list []*EdbinfoOpRecord) (err error) {
+	o := orm.NewOrmUsingDB("edb")
+	_, err = o.InsertMulti(utils.MultiAddNum, list)
+	return
+}
+
+// EdbinfoOpRecordItem
+// @Description: 手工数据的操作日志
+type EdbinfoOpRecordItem struct {
+	TradeCode  string `orm:"column(TRADE_CODE);pk" description:"指标编码"`
+	Remark     string `orm:"column(remark)" description:"操作信息"`
+	UserId     int    `orm:"column(user_id)" description:"用户id"`
+	UserName   string `orm:"column(user_name)" description:"用户姓名"`
+	CreateTime string `orm:"column(create_time)" description:"创建时间"`
+}
+
+// EdbinfoOpRecordListResp 指标数据结构体
+type EdbinfoOpRecordListResp struct {
+	List   []*EdbinfoOpRecordItem
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// GetEdbinfoOpRecordPageList
+// @Description: 根据指标编码获取手工数据的操作日志
+// @author: Roc
+// @datetime 2024-07-30 17:32:33
+// @param tradeCode string
+// @param startSize int
+// @param total int
+// @return pageSize int
+// @return items []*EdbinfoOpRecordItem
+// @return err error
+func GetEdbinfoOpRecordPageList(tradeCode string, startSize, pageSize int) (total int, items []*EdbinfoOpRecordItem, err error) {
+	o := orm.NewOrmUsingDB("edb")
+	sql := `SELECT  count(1) FROM edbinfo_op_record AS a  WHERE TRADE_CODE = ? `
+	err = o.Raw(sql, tradeCode).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT  a.* FROM edbinfo_op_record AS a  WHERE TRADE_CODE = ? ORDER BY a.create_time DESC LIMIT ?,?`
+	_, err = o.Raw(sql, tradeCode, startSize, pageSize).QueryRows(&items)
+
+	return
+}
+
+// GetManualEdbCountByCondition
+// @Description: 根据获取手工数据条数
+// @author: Roc
+// @datetime 2024-08-05 09:37:16
+// @param condition string
+// @param pars []interface{}
+// @return count int
+// @return err error
+func GetManualEdbCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("edb")
+	sql := ` SELECT COUNT(1) AS count FROM edbinfo WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+// DelEdbinfoOpRecordByTradeCode
+// @Description: 根据指标编码删除操作日志
+// @author: Roc
+// @datetime 2024-08-05 10:27:29
+// @param tradeCode string
+// @return err error
+func DelEdbinfoOpRecordByTradeCode(tradeCode string) (err error) {
+	o := orm.NewOrmUsingDB("edb")
+	sql := ` DELETE FROM edbinfo_op_record WHERE TRADE_CODE = ? `
+	_, err = o.Raw(sql, tradeCode).Exec()
+
+	return
+}

+ 188 - 22
models/target.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"context"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/utils"
 	"fmt"
@@ -139,18 +140,49 @@ func DeleteAllEdbData(tradeCode string) (err error) {
 }
 
 type Edbinfo struct {
-	TradeCode    string `orm:"column(TRADE_CODE);pk" description:"指标code"`
-	SecName      string `orm:"column(SEC_NAME);" description:"指标名称"`
-	Unit         string `orm:"column(UNIT);" description:"单位"`
-	Remark       string `orm:"column(REMARK);" description:"备注"`
-	Frequency    string `description:"频度"`
-	ClassifyId   int    `description:"分类id"`
-	ClassifyName string `description:"分类名称"`
-	CreateDate   string `description:"创建时间"`
-	UserId       int    `description:"录入用户id"`
-	UserName     string `description:"录入用户名称"`
-	NoticeTime   string `description:"通知时间"`
-	Mobile       string `description:"录入者手机号"`
+	TradeCode    string  `orm:"column(TRADE_CODE);pk" description:"指标code"`
+	SecName      string  `orm:"column(SEC_NAME);" description:"指标名称"`
+	Unit         string  `orm:"column(UNIT);" description:"单位"`
+	Remark       string  `orm:"column(REMARK);" description:"备注"`
+	Frequency    string  `orm:"column(frequency)" description:"频度"`
+	ClassifyId   int     `orm:"column(classify_id)" description:"分类id"`
+	ClassifyName string  `orm:"-" description:"分类名称"`
+	CreateDate   string  `orm:"column(create_date)" description:"创建时间"`
+	UserId       int     `orm:"column(user_id)" description:"录入用户id"`
+	UserName     string  `orm:"column(user_name)" description:"录入用户名称"`
+	NoticeTime   string  `orm:"column(notice_time)" description:"通知时间"`
+	Mobile       string  `orm:"column(mobile)" description:"录入者手机号"`
+	Sort         int     `orm:"column(sort)" description:"排序"`
+	ModifyTime   string  `description:"最近一次更新时间"`
+	IsJoinEdb    int8    `description:"指标库是否已添加:0-否;1-是"`
+	StartDate    string  `description:"数据开始日期"`
+	EndDate      string  `description:"数据结束日期"`
+	LatestValue  float64 `description:"指标最新值"`
+}
+
+func DeleteEdbinfoByTraceCodeList(tradeCodeList []string) (err error) {
+	if len(tradeCodeList) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("edb")
+	err = o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
+		var holder []string
+		for range tradeCodeList {
+			holder = append(holder, "?")
+		}
+		sql := ` DELETE FROM edbdata WHERE TRADE_CODE in (` + strings.Join(holder, ",") + `) `
+		_, err := txOrm.Raw(sql, tradeCodeList).Exec()
+		if err != nil {
+			return err
+		}
+		sql = ` DELETE FROM edbinfo WHERE TRADE_CODE in (` + strings.Join(holder, ",") + `)`
+		_, err = txOrm.Raw(sql, tradeCodeList).Exec()
+		if err != nil {
+			return err
+		}
+		return nil
+	})
+	return
 }
 
 func GetEdbinfoListCount(condition string, pars []interface{}, mobile string, roleType int) (count int, err error) {
@@ -176,7 +208,26 @@ func GetEdbinfoListCount(condition string, pars []interface{}, mobile string, ro
 	return
 }
 
-func GetEdbinfoList(condition string, pars []interface{}, startSize, pageSize int, mobile string, roleType int) (items []*Edbinfo, err error) {
+type EdbinfoItem struct {
+	TradeCode    string  `orm:"column(TRADE_CODE);pk" description:"指标code"`
+	SecName      string  `orm:"column(SEC_NAME);" description:"指标名称"`
+	Unit         string  `orm:"column(UNIT);" description:"单位"`
+	Remark       string  `orm:"column(REMARK);" description:"备注"`
+	Frequency    string  `description:"频度"`
+	ClassifyId   int     `description:"分类id"`
+	ClassifyName string  `description:"分类名称"`
+	CreateDate   string  `description:"创建时间"`
+	UserId       int     `description:"录入用户id"`
+	UserName     string  `description:"录入用户名称"`
+	NoticeTime   string  `description:"通知时间"`
+	Mobile       string  `description:"录入者手机号"`
+	ModifyTime   string  `description:"最近一次更新时间"`
+	StartDate    string  `description:"数据开始日期"`
+	EndDate      string  `description:"数据结束日期"`
+	LatestValue  float64 `description:"指标最新值"`
+}
+
+func GetEdbinfoItemList(condition string, pars []interface{}, startSize, pageSize int, mobile string, roleType int) (items []*EdbinfoItem, err error) {
 	o := orm.NewOrmUsingDB("edb")
 	sql := ``
 	if mobile != "" && roleType == 1 {
@@ -231,7 +282,7 @@ join edbdata b on a.TRADE_CODE=b.TRADE_CODE
 }
 
 type TargetListResp struct {
-	List   []*Edbinfo
+	List   []*EdbinfoItem
 	Paging *paging.PagingItem `description:"分页数据"`
 }
 
@@ -268,11 +319,25 @@ func GetEdbinfoByTradeCode(tradeCode string) (item *Edbinfo, err error) {
 	return
 }
 
-func AddEdbinfo(tradeCode, secName, unit, remark, frequency, noticeTime string, classifyId int, userId int) (err error) {
-	sql := `INSERT INTO edbinfo(TRADE_CODE, SEC_NAME,UNIT, REMARK,frequency, classify_id,notice_time,user_id,create_date) 
-			VALUES(?,?,?,?,?,?,?,?,now()) `
-	o := orm.NewOrmUsingDB("edb")
-	_, err = o.Raw(sql, tradeCode, secName, unit, remark, frequency, classifyId, noticeTime, userId).Exec()
+func AddEdbinfo(tradeCode, secName, unit, remark, frequency, noticeTime string, classifyId int, userId int, userName string) (err error) {
+	o := orm.NewOrmUsingDB("edb")
+	currTime := time.Now().Format(utils.FormatDateTime)
+	edbInfo := &Edbinfo{
+		TradeCode:  tradeCode,
+		SecName:    secName,
+		Unit:       unit,
+		Remark:     remark,
+		Frequency:  frequency,
+		ClassifyId: classifyId,
+		CreateDate: currTime,
+		UserId:     userId,
+		UserName:   userName,
+		NoticeTime: noticeTime,
+		Mobile:     "",
+		ModifyTime: currTime,
+		IsJoinEdb:  0,
+	}
+	_, err = o.Insert(edbInfo)
 	return
 }
 
@@ -323,6 +388,8 @@ type EdbdataClassify struct {
 	ClassifyName string
 	ParentId     int
 	EdbInfoTotal int
+	TradeCode    string
+	UniqueCode   string
 }
 
 func GetEdbdataClassifyByClassifyName(classifyName string) (item *EdbdataClassify, err error) {
@@ -337,6 +404,8 @@ type EdbdataClassifyList struct {
 	ClassifyName string
 	ParentId     int
 	Child        []*EdbdataClassify
+	TradeCode    string
+	UniqueCode   string
 }
 
 func GetEdbdataClassify(userId int64) (items []*EdbdataClassifyList, err error) {
@@ -1186,10 +1255,16 @@ type EdbInfoItem struct {
 	ClassifyName string     `description:"分类名称"`
 	CreateDate   string     `description:"创建时间"`
 	UserId       int        `description:"录入用户id"`
+	UserName     string     `description:"录入用户名称"`
 	NoticeTime   string     `description:"通知时间"`
 	Mobile       string     `description:"录入者手机号"`
 	ModifyDate   string     `description:"待更新日期"`
+	ModifyTime   string     `description:"最近一次更新时间"`
 	Status       string     `description:"状态:未完成/完成"`
+	IsJoinEdb    int8       `description:"指标库是否已添加:0-否;1-是"`
+	StartDate    string     `description:"数据开始日期"`
+	EndDate      string     `description:"数据结束日期"`
+	LatestValue  float64    `description:"指标最新值"`
 	DataList     []*Edbdata `description:"指标数据列表"`
 }
 
@@ -1467,14 +1542,14 @@ func GetEdbinfoListByCodeListByUserId(userIdList []int) (items []*Edbinfo, err e
 }
 
 // ModifyEdbinfoUserIdByCodeList 根据指标code列表修改创建人
-func ModifyEdbinfoUserIdByCodeList(edbCodeList []string, userId int) (err error) {
+func ModifyEdbinfoUserIdByCodeList(edbCodeList []string, userId int, userName string) (err error) {
 	num := len(edbCodeList)
 	if num <= 0 {
 		return
 	}
 	o := orm.NewOrmUsingDB("edb")
-	sql := `UPDATE edbinfo SET user_id=? WHERE TRADE_CODE in (` + utils.GetOrmInReplace(num) + `) `
-	_, err = o.Raw(sql, userId, edbCodeList).Exec()
+	sql := `UPDATE edbinfo SET user_id = ?,user_name = ? WHERE TRADE_CODE in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userId, userName, edbCodeList).Exec()
 	return
 }
 
@@ -1503,3 +1578,94 @@ func GetEdbInfoAdminList() (list []int, err error) {
 	_, err = o.Raw(sql).QueryRows(&list)
 	return
 }
+
+// GetAllChildManualEdbClassify
+// @Description: 获取手工数据中所有的子分类
+// @author: Roc
+// @datetime 2024-07-16 13:27:28
+// @return items []*EdbdataClassify
+// @return err error
+func GetAllChildManualEdbClassify() (items []*EdbdataClassify, err error) {
+	o := orm.NewOrmUsingDB("edb")
+
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE parent_id > 0 `
+	_, err = o.Raw(sql).QueryRows(&items)
+
+	return
+}
+
+// GetChildManualEdbClassifyByIdList
+// @Description: 获取手工数据中所有的子分类
+// @author: Roc
+// @datetime 2024-07-16 13:33:57
+// @param idList []int
+// @return items []*EdbdataClassify
+// @return err error
+func GetChildManualEdbClassifyByIdList(idList []int) (items []*EdbdataClassify, err error) {
+	num := len(idList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("edb")
+
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE classify_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, idList).QueryRows(&items)
+
+	return
+}
+
+// EdbinfoMaxMinDate
+// @Description: 手工指标的最小最大日期
+type EdbinfoMaxMinDate struct {
+	MinDate string
+	MaxDate string
+}
+
+// GetEdbdataMaxMinDate
+// @Description: 获取手工指标的最小最大日期
+// @author: Roc
+// @datetime 2024-08-01 14:27:20
+// @param tradeCode string
+// @return item EdbinfoMaxMinDate
+// @return err error
+func GetEdbdataMaxMinDate(tradeCode string) (item EdbinfoMaxMinDate, err error) {
+	o := orm.NewOrmUsingDB("edb")
+
+	sql := ` SELECT MIN(DT) min_date,MAX(DT) max_date FROM edbdata WHERE TRADE_CODE = ? `
+	err = o.Raw(sql, tradeCode).QueryRow(&item)
+
+	return
+}
+
+// GetEdbdataLatestValue
+// @Description: 获取手工数据的最新值
+// @author: Roc
+// @datetime 2024-08-02 10:33:22
+// @param tradeCode string
+// @return latestValue float64
+// @return err error
+func GetEdbdataLatestValue(tradeCode string) (latestValue float64, err error) {
+	o := orm.NewOrmUsingDB("edb")
+
+	sql := ` SELECT CLOSE FROM edbdata WHERE TRADE_CODE = ? ORDER BY DT DESC LIMIT 1`
+	err = o.Raw(sql, tradeCode).QueryRow(&latestValue)
+
+	return
+}
+
+// ModifyEdbinfoMaxMinDate
+// @Description: 修改手工指标的最小最大日期
+// @author: Roc
+// @datetime 2024-08-01 15:33:45
+// @param startDate string
+// @param endDate string
+// @param tradeCode string
+// @return err error
+func ModifyEdbinfoMaxMinDate(tradeCode, startDate, endDate string, latestValue float64) (err error) {
+	o := orm.NewOrmUsingDB("edb")
+
+	sql := ` UPDATE edbinfo SET start_date = ?, end_date = ?, latest_value = ? , modify_time = now() WHERE TRADE_CODE = ? `
+	_, err = o.Raw(sql, startDate, endDate, latestValue, tradeCode).Exec()
+
+	return
+}

+ 117 - 9
routers/commentsRouter.go

@@ -4975,6 +4975,123 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "ImportData",
+            Router: `/import/data`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "ClassifyEdbList",
+            Router: `/target/classify/edb/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "BatchAdd2Edb",
+            Router: `/target/edb/batch/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "BatchAddEdbCheck",
+            Router: `/target/edb/batch/add/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "NameCheck",
+            Router: `/target/edb/batch/add/name_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "BatchDel",
+            Router: `/target/edb/batch/del`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "BatchDelEdbCheck",
+            Router: `/target/edb/batch/del/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "BatchEdbList",
+            Router: `/target/edb/batch/list`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "EdbDetail",
+            Router: `/target/edb/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "EditExcelData",
+            Router: `/target/edb/excel_style/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "EdbList",
+            Router: `/target/edb/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "RecordList",
+            Router: `/target/edb/op/record/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ManualEdbController"],
+        beego.ControllerComments{
+            Method: "EdbSearch",
+            Router: `/target/edb/search`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:MyChartController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:MyChartController"],
         beego.ControllerComments{
             Method: "MyChartAdd",
@@ -9682,15 +9799,6 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["eta/eta_api/controllers:TargetController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:TargetController"],
-        beego.ControllerComments{
-            Method: "ImportData",
-            Router: `/import/data`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
     beego.GlobalControllerRouter["eta/eta_api/controllers:TargetController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:TargetController"],
         beego.ControllerComments{
             Method: "ImportFailListDownload",

+ 1 - 0
routers/router.go

@@ -104,6 +104,7 @@ func init() {
 		web.NSNamespace("/entry",
 			web.NSInclude(
 				&controllers.TargetController{},
+				&data_manage.ManualEdbController{},
 			),
 			web.NSInclude(
 				&controllers.TargetCommonController{},

+ 32 - 3
services/data/data_manage_permission/data_move.go

@@ -230,7 +230,7 @@ func GetMoveEdbChartList(source, subSource, userId int, keyword, classify string
 		if err != nil {
 			return
 		}
-		tmpList, tmpErr := models.GetEdbinfoList(condition, pars, startSize, pageSize, "", 0)
+		tmpList, tmpErr := models.GetEdbinfoItemList(condition, pars, startSize, pageSize, "", 0)
 		if tmpErr != nil {
 			err = tmpErr
 			return
@@ -487,7 +487,7 @@ func GetMoveEdbChartList(source, subSource, userId int, keyword, classify string
 
 // MoveEdbChart 转移指标/图表创建人
 // @param source 来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格
-func MoveEdbChart(source, subSource, oldUserId, newUserId int, isSelectAll bool, dataId, noDataId []string, keyword, classify string, opUserId int) (err error, errMsg string) {
+func MoveEdbChart(source, subSource, oldUserId, newUserId int, isSelectAll bool, dataId, noDataId []string, keyword, classify string, opUserId int, opUserName string) (err error, errMsg string) {
 	adminInfo, err := system.GetSysAdminById(newUserId)
 	if err != nil {
 		return
@@ -556,7 +556,12 @@ func MoveEdbChart(source, subSource, oldUserId, newUserId int, isSelectAll bool,
 				})
 			}
 			// 修改创建人
-			err = models.ModifyEdbinfoUserIdByCodeList(dataId, newUserId)
+			err = models.ModifyEdbinfoUserIdByCodeList(dataId, newUserId, adminInfo.RealName)
+
+			// 如果移动成功了,需要记录该指标的操作记录
+			if err == nil && len(tmpList) > 0 {
+				go afterMoveManualEdb(tmpList, adminInfo, opUserId, opUserName)
+			}
 		}
 
 	case 2: //钢联化工数据库
@@ -1383,3 +1388,27 @@ func GetMoveEdbChartCount(userId, countType int) (sourceMap map[int]int, err err
 
 	return
 }
+
+// afterMoveManualEdb
+// @Description: 手工数据移动后的操作
+// @author: Roc
+// @datetime 2024-08-01 13:55:59
+// @param tmpList []*models.Edbinfo
+// @param adminInfo *system.Admin
+// @param opUserId int
+// @param opUserName string
+func afterMoveManualEdb(tmpList []*models.Edbinfo, adminInfo *system.Admin, opUserId int, opUserName string) {
+	recordList := make([]*models.EdbinfoOpRecord, 0)
+	for _, tmpManualInfo := range tmpList {
+		remark := fmt.Sprintf("数据资产由%s转移给%s", tmpManualInfo.UserName, adminInfo.RealName)
+		recordList = append(recordList, &models.EdbinfoOpRecord{
+			TradeCode:  tmpManualInfo.TradeCode,
+			Remark:     remark,
+			UserId:     opUserId,
+			UserName:   opUserName,
+			CreateTime: time.Now(),
+		})
+	}
+	obj := models.EdbinfoOpRecord{}
+	_ = obj.MulCreate(recordList)
+}

+ 2 - 8
services/data/edb_classify.go

@@ -7,7 +7,6 @@ import (
 	"eta/eta_api/models/data_manage/cross_variety"
 	"eta/eta_api/models/data_manage/excel"
 	"eta/eta_api/models/system"
-	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/services/data_stat"
 	"eta/eta_api/utils"
@@ -919,13 +918,8 @@ func Delete(classifyId, edbInfoId int, sysUser *system.Admin, requestBody, reque
 
 		go data_stat.AddEdbDeleteLog(edbInfo, sysUser)
 
-		// 如果删除的指标是自定义分析的来源,那么还需要删除指标与excel的关系
-		if edbInfo.Source == utils.DATA_SOURCE_CALCULATE_ZDYFX {
-			tmpErr = excel.DeleteCustomAnalysisExcelEdbMappingByEdbInfoId(edbInfo.EdbInfoId)
-			if tmpErr != nil {
-				alarm_msg.SendAlarmMsg(fmt.Sprintf("删除指标时,需要删除与自定义分析的关系失败,指标ID:%d,Err:%s", edbInfo.EdbInfoId, tmpErr.Error()), 3)
-			}
-		}
+		// 删除指标后的操作
+		go handleByDelEdbInfo(edbInfo)
 
 		// 返回下一个表格的信息
 		{

+ 45 - 7
services/data/edb_info.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_api/cache"
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
+	"eta/eta_api/models/data_manage/excel"
 	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/services/elastic"
@@ -711,7 +712,7 @@ func EdbInfoRefresh(edbInfo *data_manage.EdbInfoView, refreshAll bool) (err erro
 }
 
 // AddEdbInfo 新增手工指标数据
-func AddEdbInfo(secName, unit, frequency, noticeTime, mobile string, classifyId, userId int) (err error) {
+func AddEdbInfo(secName, unit, frequency, noticeTime, mobile string, classifyId, userId int, userName string) (err error) {
 	tradeCode, err := models.GetMaxTradeCode()
 	if err != nil {
 		return
@@ -746,8 +747,10 @@ func AddEdbInfo(secName, unit, frequency, noticeTime, mobile string, classifyId,
 	}
 	// 先删除该指标编码的历史数据(避免上海删除指标时,没有删除该指标数据)
 	_ = models.DeleteAllEdbData(maxTradeCode)
+	// 先删除历史的操作日志
+	_ = models.DelEdbinfoOpRecordByTradeCode(maxTradeCode)
 	// 再次新增指标
-	err = models.AddEdbinfo(maxTradeCode, secName, unit, "手动", frequency, noticeTime, classifyId, userId)
+	err = models.AddEdbinfo(maxTradeCode, secName, unit, "手动", frequency, noticeTime, classifyId, userId, userName)
 	if err != nil {
 		err = errors.New("新增失败,Err:" + err.Error())
 		return
@@ -1909,11 +1912,7 @@ func EdbInfoAdd(source, subSource, classifyId int, edbCode, edbName, frequency,
 	//添加es
 	AddOrEditEdbInfoToEs(int(edbInfoId))
 
-	// 更新钢联化工状态为启用
-	if edbInfo.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
-		// 启动钢联的刷新
-		_ = data_manage.UpdateMysteelChemicalRefreshStatus(edbCode, 0)
-	}
+	go handleByAddEdbInfo(edbInfo)
 
 	return
 }
@@ -2927,3 +2926,42 @@ func GetEdbTerminalCodeBySource(source int, edbCode, stockCode string) (terminal
 	}
 	return
 }
+
+// handleByAddEdbInfo
+// @Description: 添加指标后的处理操作
+// @author: Roc
+// @datetime 2024-07-22 13:06:36
+// @param edbInfo *data_manage.EdbInfo
+func handleByAddEdbInfo(edbInfo *data_manage.EdbInfo) {
+	// 更新钢联化工状态为启用
+	if edbInfo.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
+		// 启动钢联的刷新
+		_ = data_manage.UpdateMysteelChemicalRefreshStatus(edbInfo.EdbCode, 0)
+	}
+
+	// 如果是手工数据,那么需要标记手工数据为已加入指标库
+	if edbInfo.Source == utils.DATA_SOURCE_MANUAL {
+		_ = models.UpdateManualIsJoinEdbStatus(edbInfo.EdbCode, 1)
+	}
+
+}
+
+// handleByDelEdbInfo
+// @Description: 删除指标后的处理操作
+// @author: Roc
+// @datetime 2024-07-22 13:06:36
+// @param edbInfo *data_manage.EdbInfo
+func handleByDelEdbInfo(edbInfo *data_manage.EdbInfo) {
+	// 如果删除的指标是自定义分析的来源,那么还需要删除指标与excel的关系
+	if edbInfo.Source == utils.DATA_SOURCE_CALCULATE_ZDYFX {
+		err := excel.DeleteCustomAnalysisExcelEdbMappingByEdbInfoId(edbInfo.EdbInfoId)
+		if err != nil {
+			utils.FileLog.Error(fmt.Sprintf("删除指标时,需要删除与自定义分析的关系失败,指标ID:%d,Err:%s", edbInfo.EdbInfoId, err.Error()), 3)
+		}
+	}
+
+	// 如果是手工数据,那么需要标记手工数据为未加入指标库
+	if edbInfo.Source == utils.DATA_SOURCE_MANUAL {
+		_ = models.UpdateManualIsJoinEdbStatus(edbInfo.EdbCode, 0)
+	}
+}

+ 1001 - 0
services/data/manual.go

@@ -1,10 +1,18 @@
 package data
 
 import (
+	"errors"
+	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
+	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/utils"
 	"fmt"
+	"github.com/shopspring/decimal"
+	"github.com/tealeg/xlsx"
+	"strconv"
+	"strings"
+	"time"
 )
 
 func GetManualSysUser(keyWord string) (list []*data_manage.ManualSysUser, err error) {
@@ -82,3 +90,996 @@ func GetManualSysUser(keyWord string) (list []*data_manage.ManualSysUser, err er
 	}
 	return
 }
+
+// GetManualEdbClassifyListByAdminId
+// @Description: 根据账户类型获取手工指标分类ID集合
+// @author: Roc
+// @datetime 2024-07-16 13:18:39
+// @param adminId int64
+// @return classifyIdList []int
+// @return err error
+func GetManualEdbClassifyListByAdminId(adminId int64) (classifyIdList []int, err error) {
+	var list []*models.EdbdataClassify
+	if adminId <= 0 {
+		list, err = models.GetAllChildManualEdbClassify()
+	} else {
+		userClassifyList, _ := models.GetManualUserClassify(int(adminId))
+		var userClassifyIdList []int
+		for _, v := range userClassifyList {
+			userClassifyIdList = append(userClassifyIdList, v.ClassifyId)
+		}
+		list, err = models.GetChildManualEdbClassifyByIdList(userClassifyIdList)
+	}
+	if err != nil {
+		return
+	}
+	for _, classify := range list {
+		classifyIdList = append(classifyIdList, classify.ClassifyId)
+	}
+
+	return
+}
+
+type ManualIndexSource2EdbReq struct {
+	EdbCode       string
+	EdbName       string
+	Frequency     string
+	Unit          string
+	ClassifyId    int
+	AdminId       int
+	AdminRealName string
+}
+
+// ManualIndexSource2Edb
+// @Description: 新增手工数据源到指标库
+// @author: Roc
+// @datetime 2024-07-26 13:23:19
+// @param req ManualIndexSource2EdbReq
+// @param lang string
+// @return edb *data_manage.EdbInfo
+// @return err error
+// @return errMsg string
+// @return skip bool
+func ManualIndexSource2Edb(req ManualIndexSource2EdbReq, lang string) (edb *data_manage.EdbInfo, err error, errMsg string, skip bool) {
+	if req.EdbCode == "" {
+		err = fmt.Errorf("指标ID为空")
+		return
+	}
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("ManualIndexSource2Edb新增失败, Err: %s", err.Error())
+			fmt.Println(tips)
+			utils.FileLog.Info(tips)
+		}
+	}()
+	source := utils.DATA_SOURCE_MANUAL
+
+	// 是否已有指标数据
+	dataList, e := data_manage.GetEdbDataAllByEdbCode(req.EdbCode, source, utils.DATA_SUB_SOURCE_EDB, utils.EDB_DATA_LIMIT)
+	if e != nil {
+		err = fmt.Errorf("获取指标数据失败, Err: %s", e.Error())
+		return
+	}
+
+	// 新增指标数据
+	if len(dataList) == 0 {
+		res, e := AddEdbData(source, req.EdbCode, req.Frequency)
+		if e != nil {
+			err = fmt.Errorf("index_lib: 新增指标数据失败, Err: %s", e.Error())
+			return
+		}
+		if res == nil {
+			err = fmt.Errorf("index_lib: 新增指标数据失败, res nil")
+			return
+		}
+		if res.Ret != 200 {
+			err = fmt.Errorf("index_lib: 新增指标数据失败, Ret: %d", res.Ret)
+			return
+		}
+	}
+
+	// 是否新增过指标
+	exist, e := data_manage.GetEdbInfoByEdbCode(source, req.EdbCode)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = fmt.Errorf("获取指标是否存在失败, err: %s", e.Error())
+		return
+	}
+	if exist != nil {
+		skip = true
+		return
+	}
+
+	// 开始结束时间
+	var startDate, endDate string
+	minMax, e := data_manage.GetEdbInfoMaxAndMinInfo(source, utils.DATA_SUB_SOURCE_EDB, req.EdbCode)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = fmt.Errorf("MinMax: 获取指标极值失败, err: %s", e.Error())
+		return
+	}
+	if minMax != nil {
+		startDate = minMax.MinDate
+		endDate = minMax.MaxDate
+	}
+
+	// 新增指标库
+	edbInfo, e, msg, _ := EdbInfoAdd(source, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, startDate, endDate, req.AdminId, req.AdminRealName, lang)
+	if e != nil {
+		errMsg = msg
+		err = fmt.Errorf("EdbInfo: 新增指标失败, err: %s", e.Error())
+		return
+	}
+	edb = edbInfo
+
+	// 新增es
+	go AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)
+
+	return
+}
+
+// ImportManualData
+// @Description: 数据导入
+// @author: Roc
+// @datetime 2024-08-01 11:27:21
+// @param path string
+// @param sysUser *system.Admin
+// @return successCount int
+// @return failCount int
+// @return err error
+// @return errMsg string
+func ImportManualData(path string, sysUser *system.Admin) (successCount, failCount int, err error, errMsg string) {
+	// 错误信息
+	errMsgList := make([]string, 0)
+	// 操作记录
+	recordMap := make(map[string]string)
+	defer func() {
+		recordList := make([]*models.EdbinfoOpRecord, 0)
+		for tradeCode, remark := range recordMap {
+			recordList = append(recordList, &models.EdbinfoOpRecord{
+				TradeCode:  tradeCode,
+				Remark:     remark,
+				UserId:     sysUser.AdminId,
+				UserName:   sysUser.RealName,
+				CreateTime: time.Now(),
+			})
+
+			// 修改最大最小值
+			go ModifyManualEdbMaxMinDate(tradeCode)
+		}
+		if len(recordList) > 0 {
+			go func() {
+				obj := models.EdbinfoOpRecord{}
+				_ = obj.MulCreate(recordList)
+			}()
+		}
+
+		// 错误信息记录
+		if len(errMsgList) > 0 {
+			utils.FileLog.Info("导入失败, errMsgList: %v", strings.Join(errMsgList, "\n"))
+		}
+	}()
+	errMsg = `导入失败`
+	xlFile, err := xlsx.OpenFile(path)
+	if err != nil {
+		fmt.Println(err.Error())
+		return
+	}
+	if len(xlFile.Sheets) <= 0 {
+		errMsg = "导入模板异常"
+		err = errors.New(errMsg)
+		return
+	}
+
+	//导入失败数据
+	failDataList := make([]*models.EdbdataImportFail, 0)
+	var indexDataList []ImportManualIndexData
+	// 指标名称列表
+	indexNameList := make([]string, 0)
+
+	// 模板校验,然后处理成标准化格式
+	for _, sheet := range xlFile.Sheets {
+		var tmpIndexDataList []ImportManualIndexData
+		var tmpFailDataList []*models.EdbdataImportFail
+		rowList := sheet.Rows
+		if len(rowList) <= 0 {
+			errMsg = sheet.Name + "页异常"
+			err = errors.New(errMsg)
+			return
+		}
+		headerCell := rowList[0].Cells
+		if len(headerCell) < 7 {
+			errMsg = sheet.Name + "页模板异常"
+			err = errors.New(errMsg)
+			return
+		}
+
+		templateName := headerCell[6].String()
+		switch templateName {
+		case "导入模板2/Import Template 2":
+			// 模板2需要走对应的取数逻辑
+			tmpIndexDataList, tmpFailDataList, err, errMsg = getDataByTemplate2(sheet, sysUser.AdminId)
+		default:
+			// 模板1需要走对应的取数逻辑
+			tmpIndexDataList, tmpFailDataList, err, errMsg = getDataByTemplate1(sheet, sysUser.AdminId)
+		}
+		indexDataList = append(indexDataList, tmpIndexDataList...)
+		failDataList = append(failDataList, tmpFailDataList...)
+	}
+
+	indexDataListMap := make(map[string]ImportManualIndexData)
+	for _, v := range indexDataList {
+		indexData, ok := indexDataListMap[v.IndexName]
+		if !ok {
+			// 没有就赋值
+			indexDataListMap[v.IndexName] = v
+			indexNameList = append(indexNameList, v.IndexName)
+			continue
+		}
+
+		indexData.Unit = v.Unit
+		indexData.ClassName = v.ClassName
+		indexData.Frequency = v.Frequency
+
+		indexData.DataMap = v.DataMap
+	}
+
+	if len(indexNameList) <= 0 {
+		return
+	}
+
+	//超管账号可以查看分类下的所有频度数据
+	userId := sysUser.AdminId
+	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
+		userId = 0
+	}
+	//获取账户所拥有权限的分类id集合
+	classifyNameStrList, edbDataClassifyMap, err := GetEdbClassifyNameListByAdminId(int64(userId))
+	if err != nil {
+		errMsg = "获取分类数据失败"
+		return
+	}
+
+	//指标map
+	targetMap := make(map[string]*models.Edbinfo)
+	defer func() {
+		for _, target := range targetMap {
+			//结束后,清除掉对应的缓存
+			key := "import:edbinfo:data:" + target.TradeCode
+			utils.Rc.Delete(key)
+
+			//将该指标的code加入到 “手工数据导入后刷新” 缓存
+			if utils.Re == nil {
+				err := utils.Rc.LPush(utils.CACHE_IMPORT_MANUAL_DATA, target.TradeCode)
+				if err != nil {
+					fmt.Println("CACHE_IMPORT_MANUAL_DATA LPush Err:" + err.Error())
+				}
+			}
+		}
+	}()
+
+	// 所有的指标数据map
+	edbCodeDataMap := make(map[string]map[string]string)
+
+	{
+		// 获取指标信息
+		manualIndexList, tmpErr := models.GetEdbinfoListBySecNameList(indexNameList)
+		if tmpErr != nil {
+			err = tmpErr
+			errMsg = "获取指标信息失败"
+			return
+		}
+
+		tradeCodeList := make([]string, 0)
+		for _, v := range manualIndexList {
+			targetMap[v.SecName] = v
+			tradeCodeList = append(tradeCodeList, v.TradeCode)
+			recordMap[v.TradeCode] = "更新数据"
+		}
+
+		// 获取明细数据
+		dataList, tmpErr := models.GetTargetsDataListByCodeList(tradeCodeList)
+		if tmpErr != nil {
+			err = tmpErr
+			errMsg = "获取指标明细数据失败"
+			return
+		}
+		for _, tmpData := range dataList {
+			_, ok := edbCodeDataMap[tmpData.TradeCode]
+			if !ok {
+				edbCodeDataMap[tmpData.TradeCode] = make(map[string]string)
+			}
+			edbCodeDataMap[tmpData.TradeCode][tmpData.Dt] = tmpData.Close
+		}
+	}
+
+	//// TODO 成功数量超过20个指标,那就不导入了
+	//if len(targetMap) >= 150 {
+	//	failItem := new(models.EdbdataImportFail)
+	//	failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+	//	failItem.ClassifyName = classifyName
+	//	failItem.CreateDate = createDate
+	//	failItem.SecName = secName
+	//	failItem.Close = closeVal
+	//	failItem.Remark = "导入指标数量过多"
+	//	failItem.Frequency = frequency
+	//	failItem.Unit = unit
+	//	failDataList = append(failDataList, failItem)
+	//	//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+	//	continue
+	//}
+
+	addDataList := make([]*models.Edbdata, 0)
+
+	for _, v := range indexDataListMap {
+		if len(v.DataMap) <= 0 {
+			continue
+		}
+		var tmpDate, tmpValue string
+		for date, val := range v.DataMap {
+			tmpDate = date
+			tmpValue = val
+			break
+		}
+		if !strings.Contains(strings.Join(classifyNameStrList, ","), v.ClassName) {
+			failItem := &models.EdbdataImportFail{
+				ClassifyName: v.ClassName,
+				CreateDate:   tmpDate,
+				SecName:      v.IndexName,
+				Close:        tmpValue,
+				Remark:       "没有该品种分类权限",
+				SysUserId:    fmt.Sprint(sysUser.AdminId),
+				Frequency:    v.Frequency,
+				Unit:         v.Unit,
+			}
+			failDataList = append(failDataList, failItem)
+			continue
+		}
+
+		//获取指标分类信息
+		classify, ok := edbDataClassifyMap[v.ClassName]
+		if !ok {
+			failItem := &models.EdbdataImportFail{
+				ClassifyName: v.ClassName,
+				CreateDate:   tmpDate,
+				SecName:      v.IndexName,
+				Close:        tmpValue,
+				Remark:       "指标分类不存在",
+				SysUserId:    fmt.Sprint(sysUser.AdminId),
+				Frequency:    v.Frequency,
+				Unit:         v.Unit,
+			}
+			failDataList = append(failDataList, failItem)
+			continue
+		}
+
+		target, ok := targetMap[v.IndexName]
+		if !ok {
+			if v.Frequency == "" {
+				failItem := &models.EdbdataImportFail{
+					ClassifyName: v.ClassName,
+					CreateDate:   tmpDate,
+					SecName:      v.IndexName,
+					Close:        tmpValue,
+					Remark:       "新增指标失败,频度字段为空",
+					SysUserId:    fmt.Sprint(sysUser.AdminId),
+					Frequency:    v.Frequency,
+					Unit:         v.Unit,
+				}
+				failDataList = append(failDataList, failItem)
+				continue
+			}
+			if v.Unit == "" {
+				failItem := &models.EdbdataImportFail{
+					ClassifyName: v.ClassName,
+					CreateDate:   tmpDate,
+					SecName:      v.IndexName,
+					Close:        tmpValue,
+					Remark:       "新增指标失败,单位字段为空",
+					SysUserId:    fmt.Sprint(sysUser.AdminId),
+					Frequency:    v.Frequency,
+					Unit:         v.Unit,
+				}
+				failDataList = append(failDataList, failItem)
+				continue
+			}
+			tmpErr := AddEdbInfo(v.IndexName, v.Unit, v.Frequency, "", sysUser.Mobile, classify.ClassifyId, sysUser.AdminId, sysUser.RealName)
+			if tmpErr != nil {
+				fmt.Println("line 158")
+
+				failItem := &models.EdbdataImportFail{
+					ClassifyName: v.ClassName,
+					CreateDate:   tmpDate,
+					SecName:      v.IndexName,
+					Close:        tmpValue,
+					Remark:       "新增指标失败",
+					SysUserId:    fmt.Sprint(sysUser.AdminId),
+					Frequency:    v.Frequency,
+					Unit:         v.Unit,
+				}
+				failDataList = append(failDataList, failItem)
+				continue
+			}
+			tmpTarget, tmpErr := models.GetTargetBySecName(v.IndexName)
+			target = tmpTarget
+			targetMap[v.IndexName] = target
+
+			recordMap[target.TradeCode] = "创建指标"
+		}
+
+		if target == nil {
+			fmt.Println("指标不存在")
+			failItem := &models.EdbdataImportFail{
+				ClassifyName: v.ClassName,
+				CreateDate:   tmpDate,
+				SecName:      v.IndexName,
+				Close:        tmpValue,
+				Remark:       "指标不存在",
+				SysUserId:    fmt.Sprint(sysUser.AdminId),
+				Frequency:    v.Frequency,
+				Unit:         v.Unit,
+			}
+			failDataList = append(failDataList, failItem)
+			continue
+		}
+
+		//设置10分钟缓存,不允许其他地方删除
+		key := "import:edbinfo:data:" + target.TradeCode
+		utils.Rc.SetNX(key, 1, time.Second*600)
+
+		//更新指标信息
+		{
+			updateCols := make([]string, 0)
+			//更新指标分类
+			if target.ClassifyId <= 0 && classify.ClassifyId > 0 {
+				target.ClassifyId = classify.ClassifyId
+				updateCols = append(updateCols, "ClassifyId")
+			}
+			if target.Frequency != v.Frequency {
+				target.Frequency = v.Frequency
+				target.NoticeTime = ""
+				updateCols = append(updateCols, "Frequency", "NoticeTime")
+			}
+			if target.Unit != v.Unit {
+				target.Unit = v.Unit
+				updateCols = append(updateCols, "Unit")
+			}
+			if len(updateCols) > 0 {
+				_ = target.Update(updateCols)
+			}
+		}
+
+		{
+			// 判断指标数据列表是否已经存在
+			tmpDataMap, ok := edbCodeDataMap[target.TradeCode]
+			if !ok {
+				tmpDataMap = make(map[string]string)
+				edbCodeDataMap[target.TradeCode] = tmpDataMap
+			}
+
+			for createDate, closeVal := range v.DataMap {
+				//判断数据是否已经存在
+				tmpVal, ok := tmpDataMap[createDate]
+				//数据已存在,进行更新操作
+				if ok {
+					if tmpVal != closeVal {
+						edbCodeDataMap[target.TradeCode][createDate] = closeVal
+						tmpErr := models.ModifyTargetsDataByImport(target.TradeCode, createDate, closeVal)
+						if tmpErr != nil {
+							errMsgList = append(errMsgList, fmt.Sprintf("%s修改数据失败,日期:%s,值:%v,Err:%s", target.TradeCode, createDate, closeVal, tmpErr.Error()))
+						}
+					}
+				} else { //数据不存在,进行新增操作
+					if target.TradeCode != "" && createDate != "" && closeVal != "" {
+						addDataList = append(addDataList, &models.Edbdata{
+							TradeCode:  target.TradeCode,
+							Dt:         createDate,
+							Close:      closeVal,
+							ModifyTime: time.Now(),
+						})
+						edbCodeDataMap[target.TradeCode][createDate] = closeVal
+					}
+				}
+				successCount++
+			}
+		}
+	}
+
+	// 批量添加明细数据
+	if len(addDataList) > 0 {
+		tmpErr := models.OnlyMultiAddEdbdata(addDataList)
+		if tmpErr != nil {
+			fmt.Println("line 221")
+			errMsgList = append(errMsgList, fmt.Sprintf("批量添加明细数据失败,Err:%s", tmpErr.Error()))
+		}
+	}
+
+	// 失败数量
+	failCount = len(failDataList)
+	//fmt.Println("failDataList:", len(failDataList))
+	if failCount > 0 {
+		//先删除导入失败记录
+		_ = models.DelEdbDataImportFail(sysUser.AdminId)
+
+		// 批量添加导入失败记录
+		err = models.MultiAddEdbdataImportFail(failDataList)
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("导入数据 新增失败记录失败,Err:"+err.Error(), 3)
+			//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增失败记录失败:Err:"+err.Error(), utils.EmailSendToUsers)
+		}
+
+		{
+			//错误信息字符串切片,最后作为发送邮件通知使用
+			failContents := make([]string, 0)
+			for _, v := range failDataList {
+				failContents = append(failContents, fmt.Sprint(v.SecName, "导入失败:", v.Remark))
+			}
+			utils.FileLog.Info("导入数据 存在部分数据导入失败:" + strings.Join(failContents, ";"))
+			//导入失败的话,最后统一邮件提醒就好啦,不需要每次都去提醒
+			go alarm_msg.SendAlarmMsg("导入数据 存在部分数据导入失败:"+strings.Join(failContents, ";"), 3)
+		}
+	}
+
+	return
+}
+
+// ImportManualIndexData
+// @Description: excel模板后的内容
+type ImportManualIndexData struct {
+	IndexName string            `description:"指标名称"`
+	Unit      string            `description:"单位"`
+	ClassName string            `description:"所属品种"`
+	Frequency string            `description:"频度"`
+	DataMap   map[string]string `description:"时间数据"`
+}
+
+// getDataByTemplate1
+// @Description: 根据模板1获取数据
+// @author: Roc
+// @datetime 2024-07-24 16:17:45
+// @param sheet *xlsx.Sheet
+// @return indexDataList []ImportManualIndexData
+// @return err error
+// @return errMsg string
+func getDataByTemplate1(sheet *xlsx.Sheet, sysUserId int) (indexDataList []ImportManualIndexData, failDataList []*models.EdbdataImportFail, err error, errMsg string) {
+	fmt.Println("sheet name: ", sheet.Name)
+	indexDataList = make([]ImportManualIndexData, 0)
+	indexDataListMap := make(map[string]ImportManualIndexData, 0)
+	failDataList = make([]*models.EdbdataImportFail, 0)
+
+	//遍历行读取
+	maxRow := sheet.MaxRow
+	fmt.Println("maxRow:", maxRow)
+
+	// 表头信息
+	if maxRow <= 2 {
+		errMsg = "模板异常1"
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 表头校验
+	{
+		headerRow := sheet.Row(1)
+		cells := headerRow.Cells
+		if len(cells) < 6 {
+			errMsg = "导入文件异常,请下载最新导入模板文件"
+			err = errors.New(errMsg)
+			return
+		}
+
+		templateFail := false
+		if cells[0].Value != "品种/Variety" {
+			templateFail = true
+		}
+		if cells[1].Value != "指标名称/Indicator Name" {
+			templateFail = true
+		}
+		if cells[2].Value != "指标日期/Indicator Date" {
+			templateFail = true
+		}
+		if cells[3].Value != "值/Value" {
+			templateFail = true
+		}
+		if cells[4].Value != "频度/Frequency" {
+			templateFail = true
+		}
+		if cells[5].Value != "单位/Unit" {
+			templateFail = true
+		}
+		if templateFail {
+			errMsg = "导入文件异常,请下载最新导入模板文件"
+			err = errors.New(errMsg)
+			return
+		}
+	}
+
+	for i := 2; i < maxRow; i++ {
+		row := sheet.Row(i)
+		cells := row.Cells
+		if len(cells) < 6 {
+			errMsg = "导入文件异常,请下载最新导入模板文件"
+			err = errors.New(errMsg)
+			return
+		}
+
+		classifyName := strings.TrimSpace(cells[0].Value) //分类
+		if classifyName == "" {                           //过滤空白行
+			continue
+		}
+		// 指标名称
+		cell1 := cells[1].Value
+		indexName := strings.TrimSpace(cell1)
+		if indexName == "" { //过滤空白行
+			continue
+		}
+		//createDate := utils.ConvertToFormatDay(cell1) //录入日期
+		createDate := cells[2].Value                      //指标日期
+		frequency := strings.TrimSpace(cells[4].String()) //频度
+		unit := strings.TrimSpace(cells[5].String())      //单位
+
+		closeVal := cells[3].Value //值
+		if strings.Contains(closeVal, "#N/A") {
+			continue
+		}
+
+		currDate, tmpErr := getExcelDate(createDate)
+		if tmpErr != nil {
+			failDataList = append(failDataList, &models.EdbdataImportFail{
+				//Id:           0,
+				ClassifyName: classifyName,
+				CreateDate:   createDate,
+				SecName:      indexName,
+				Close:        closeVal,
+				Remark:       "日期格式异常",
+				SysUserId:    strconv.Itoa(sysUserId),
+				Frequency:    frequency,
+				Unit:         unit,
+			})
+			continue
+		}
+
+		closeValFloat, tmpErr := cells[3].Float() //值
+		if tmpErr != nil {
+			failDataList = append(failDataList, &models.EdbdataImportFail{
+				//Id:           0,
+				ClassifyName: classifyName,
+				CreateDate:   currDate,
+				SecName:      indexName,
+				Close:        cells[3].Value,
+				Remark:       "值类型异常",
+				SysUserId:    strconv.Itoa(sysUserId),
+				Frequency:    frequency,
+				Unit:         unit,
+			})
+			continue
+		}
+		newDecimal := decimal.NewFromFloat(closeValFloat)
+		newDecimal.Round(4)
+		closeVal = newDecimal.String()
+		if strings.Contains(closeVal, "#N/A") {
+			continue
+		}
+
+		_, ok := indexDataListMap[indexName]
+		if !ok {
+			indexDataListMap[indexName] = ImportManualIndexData{
+				IndexName: indexName,
+				Unit:      unit,
+				ClassName: classifyName,
+				Frequency: frequency,
+				DataMap:   make(map[string]string),
+			}
+		}
+
+		indexDataListMap[indexName].DataMap[currDate] = closeVal
+	}
+
+	for _, v := range indexDataListMap {
+		indexDataList = append(indexDataList, v)
+	}
+
+	return
+}
+
+// getDataByTemplate2
+// @Description: 根据模板2获取数据
+// @author: Roc
+// @datetime 2024-07-24 16:17:56
+// @param sheet *xlsx.Sheet
+// @return indexDataList []ImportManualIndexData
+// @return err error
+// @return errMsg string
+func getDataByTemplate2(sheet *xlsx.Sheet, sysUserId int) (indexDataList []ImportManualIndexData, failDataList []*models.EdbdataImportFail, err error, errMsg string) {
+	fmt.Println("sheet name: ", sheet.Name)
+	indexDataList = make([]ImportManualIndexData, 0)
+	failDataList = make([]*models.EdbdataImportFail, 0)
+
+	//遍历行读取
+	maxRow := sheet.MaxRow
+	fmt.Println("maxRow:", maxRow)
+
+	varietyList := make([]string, 0)
+	indexNameList := make([]string, 0)
+	unitList := make([]string, 0)
+	frequencyList := make([]string, 0)
+
+	// make(map[指标下标]map[日期]值)
+	indexDateValueMap := make(map[int]map[string]string)
+
+	// 表头信息
+	if maxRow <= 4 {
+		errMsg = "模板异常1"
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 表头处理
+	for i := 1; i <= 4; i++ {
+		row := sheet.Row(i)
+		cells := row.Cells
+		//if len(cells) < 1 {
+		//	errMsg = "模板异常2"
+		//	err = errors.New(errMsg)
+		//	return
+		//}
+
+		switch i {
+		case 1:
+			for k, v := range cells {
+				if k == 0 {
+					continue
+				}
+				varietyList = append(varietyList, strings.TrimSpace(v.String()))
+			}
+		case 2:
+			for k, v := range cells {
+				if k == 0 {
+					continue
+				}
+				indexNameList = append(indexNameList, strings.TrimSpace(v.String()))
+			}
+		case 3:
+			for k, v := range cells {
+				if k == 0 {
+					continue
+				}
+				unitList = append(unitList, strings.TrimSpace(v.String()))
+			}
+		case 4:
+			for k, v := range cells {
+				if k == 0 {
+					continue
+				}
+				frequencyList = append(frequencyList, strings.TrimSpace(v.String()))
+			}
+		}
+	}
+
+	maxNameIndex := len(indexNameList) - 1
+	maxUnitIndex := len(unitList) - 1
+	maxClassNameIndex := len(varietyList) - 1
+	maxFrequencyIndex := len(frequencyList) - 1
+
+	// 数据处理
+	for i := 5; i < maxRow; i++ {
+		row := sheet.Row(i)
+		cells := row.Cells
+		//if len(cells) < 1 {
+		//	errMsg = "模板异常2"
+		//	err = errors.New(errMsg)
+		//	return
+		//}
+		// 当前日期
+		var currDate string
+
+		// 日期是否异常,异常的话,就跳过,进入下一行数据处理
+		var dateErr bool
+
+		// 数据处理
+		for k, v := range cells {
+			if k == 0 {
+				tmpCurrDate, tmpErr := getExcelDate(v.Value)
+				if tmpErr != nil {
+					// TODO 错误数据记录
+					//failItem := new(models.EdbdataImportFail)
+					//failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+					//failItem.ClassifyName = classifyName
+					//failItem.CreateDate = createDate
+					//failItem.SecName = secName
+					//failItem.Close = closeVal
+					//failItem.Remark = "日期格式异常"
+					//failItem.Frequency = frequency
+					//failItem.Unit = unit
+					//failDataList = append(failDataList, failItem)
+					//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+					dateErr = true
+				}
+
+				currDate = tmpCurrDate
+				continue
+			}
+			key := k - 1
+
+			// 日期异常,所以不处理该行了
+			if dateErr {
+				var indexName, unit, classifyName, frequency string
+				if key <= maxNameIndex {
+					indexName = indexNameList[key]
+				}
+				if key <= maxUnitIndex {
+					unit = unitList[key]
+				}
+				if key <= maxClassNameIndex {
+					classifyName = varietyList[key]
+				}
+				if key <= maxFrequencyIndex {
+					frequency = frequencyList[key]
+				}
+
+				failDataList = append(failDataList, &models.EdbdataImportFail{
+					//Id:           0,
+					ClassifyName: classifyName,
+					CreateDate:   currDate,
+					SecName:      indexName,
+					Close:        v.Value,
+					Remark:       "日期格式异常",
+					SysUserId:    strconv.Itoa(sysUserId),
+					Frequency:    frequency,
+					Unit:         unit,
+				})
+
+				continue
+			}
+
+			_, ok := indexDateValueMap[key]
+			if !ok {
+				indexDateValueMap[key] = make(map[string]string)
+			}
+
+			closeVal := v.Value //值
+			// 没有数据,说明是空串
+			if strings.Contains(closeVal, "#N/A") {
+				indexDateValueMap[key][currDate] = ""
+				continue
+			}
+
+			closeValFloat, tmpErr := v.Float() //值
+			if tmpErr != nil {
+				// TODO 错误数据记录
+				//failItem := new(models.EdbdataImportFail)
+				//failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+				//failItem.ClassifyName = classifyName
+				//failItem.CreateDate = createDate
+				//failItem.SecName = secName
+				//failItem.Close = cells[3].Value
+				//failItem.Remark = "值类型异常"
+				//failItem.Frequency = frequency
+				//failItem.Unit = unit
+				//failDataList = append(failDataList, failItem)
+				indexDateValueMap[key][currDate] = ""
+				continue
+			}
+
+			newDecimal := decimal.NewFromFloat(closeValFloat)
+			newDecimal.Round(4)
+			closeVal = newDecimal.String()
+			if strings.Contains(closeVal, "#N/A") {
+				indexDateValueMap[key][currDate] = ""
+				continue
+			}
+			indexDateValueMap[key][currDate] = closeVal
+		}
+
+	}
+
+	for i, indexName := range indexNameList {
+		var unit, classifyName, frequency string
+		if i <= maxUnitIndex {
+			unit = unitList[i]
+		}
+		if i <= maxClassNameIndex {
+			classifyName = varietyList[i]
+		}
+		if i <= maxFrequencyIndex {
+			frequency = frequencyList[i]
+		}
+		indexData := ImportManualIndexData{
+			IndexName: indexName,
+			Unit:      unit,
+			ClassName: classifyName,
+			Frequency: frequency,
+			DataMap:   indexDateValueMap[i],
+		}
+		indexDataList = append(indexDataList, indexData)
+	}
+
+	return
+}
+
+// getExcelDate
+// @Description: 获取excel的日期
+// @author: Roc
+// @datetime 2024-07-23 17:26:12
+// @param createDate string
+// @return newCreateDate string
+// @return err error
+func getExcelDate(createDate string) (newCreateDate string, err error) {
+	if strings.Contains(createDate, "-") {
+		//如果是带有 - 的普通日期格式文本
+		_, err = time.Parse("2006-1-2", createDate)
+		if err == nil {
+			newCreateDate = createDate
+		}
+	} else if strings.Contains(createDate, "/") {
+		//如果是带有 / 的普通日期格式文本
+		createDateTime, timeErr := time.Parse("2006/1/2", createDate)
+		if timeErr != nil {
+			err = timeErr
+		} else {
+			newCreateDate = createDateTime.Format("2006-01-02")
+		}
+	} else {
+		//可能是excel的日期格式
+		_, tmpErr := strconv.Atoi(createDate)
+		if tmpErr != nil {
+			err = tmpErr
+		} else {
+			newCreateDate = utils.ConvertToFormatDay(createDate) //录入日期
+		}
+	}
+
+	return
+}
+
+// ModifyManualEdbMaxMinDate
+// @Description: 修改手动录入的edb数据的最大最小日期
+// @author: Roc
+// @datetime 2024-08-01 15:34:31
+// @param tradeCode string
+func ModifyManualEdbMaxMinDate(tradeCode string) {
+	// 获取最大最小日期
+	item, err := models.GetEdbdataMaxMinDate(tradeCode)
+	if err != nil {
+		return
+	}
+
+	// 最新值
+	latestValue, err := models.GetEdbdataLatestValue(tradeCode)
+	if err != nil {
+		return
+	}
+
+	// 修改指标的最大最小日期和最新值
+	err = models.ModifyEdbinfoMaxMinDate(tradeCode, item.MinDate, item.MaxDate, latestValue)
+
+	return
+}
+
+// GetUserManualClassifyIdList
+// @Description: 获取用户手动录入的分类id列表
+// @author: Roc
+// @datetime 2024-08-02 15:09:11
+// @param userId int
+// @return classifyIdList []int
+// @return err error
+func GetUserManualClassifyIdList(userId int) (classifyIdList []int, err error) {
+	classifyIdList = make([]int, 0)
+
+	// 获取有用权限的分类
+	classifyList, err := models.GetEdbdataClassify(int64(userId))
+	if err != nil {
+		return
+	}
+
+	if len(classifyList) > 0 {
+		for _, v := range classifyList {
+			classifyIdList = append(classifyIdList, v.ClassifyId)
+			if v.Child != nil && len(v.Child) > 0 {
+				for _, v2 := range v.Child {
+					classifyIdList = append(classifyIdList, v2.ClassifyId)
+				}
+			}
+		}
+	}
+
+	return
+}

+ 1 - 1
services/target.go

@@ -41,7 +41,7 @@ func AddEdbItem(secName, unit, frequency string, classifyId int, sysUser *system
 		errMsg = "指标名称已存在"
 		return
 	}
-	err = models.AddEdbinfo(maxTradeCode, secName, unit, "手动", frequency, "", classifyId, sysUser.AdminId)
+	err = models.AddEdbinfo(maxTradeCode, secName, unit, "手动", frequency, "", classifyId, sysUser.AdminId, sysUser.RealName)
 	if err != nil {
 		errMsg = "新增失败,Err:" + err.Error()
 		return

BIN
static/template/导入模板1.xlsx


BIN
static/template/导入模板2.xlsx


+ 3 - 0
utils/constants.go

@@ -465,3 +465,6 @@ const (
 	EdbBaseCalculateRjz                  = 16 // 日均值->16
 
 )
+
+// MultiAddNum 批量插入的数据量
+const MultiAddNum = 500