Ver código fonte

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

Roc 4 meses atrás
pai
commit
db847015b9
57 arquivos alterados com 9272 adições e 578 exclusões
  1. 7 7
      controllers/data_manage/chart_classify.go
  2. 2 2
      controllers/data_manage/correlation/correlation_chart_classify.go
  3. 2 2
      controllers/data_manage/cross_variety/classify.go
  4. 458 0
      controllers/data_manage/data_approve/data_approve.go
  5. 126 0
      controllers/data_manage/data_approve/data_approve_flow.go
  6. 265 10
      controllers/data_manage/edb_info.go
  7. 527 2
      controllers/data_manage/edb_info_share.go
  8. 764 0
      controllers/data_manage/edb_public.go
  9. 1191 0
      controllers/data_manage/edb_public_classify.go
  10. 4 4
      controllers/data_manage/future_good/future_good_chart_classify.go
  11. 4 4
      controllers/data_manage/line_equation/line_chart_classify.go
  12. 4 4
      controllers/data_manage/line_feature/classify.go
  13. 1 1
      controllers/data_manage/predict_edb_info.go
  14. 2 2
      controllers/data_manage/range_analysis/chart_classify.go
  15. 349 18
      controllers/fix.go
  16. 3 0
      models/business_conf.go
  17. 100 19
      models/data_manage/chart_classify.go
  18. 8 2
      models/data_manage/chart_info.go
  19. 223 0
      models/data_manage/data_approve/data_approve.go
  20. 198 0
      models/data_manage/data_approve/data_approve_flow.go
  21. 115 0
      models/data_manage/data_approve/data_approve_message.go
  22. 90 0
      models/data_manage/data_approve/data_approve_node.go
  23. 152 0
      models/data_manage/data_approve/data_approve_record.go
  24. 57 0
      models/data_manage/data_approve/data_approve_relation.go
  25. 21 0
      models/data_manage/data_approve/request/approve.go
  26. 22 0
      models/data_manage/data_approve/request/approve_flow.go
  27. 5 0
      models/data_manage/data_approve/request/approve_message.go
  28. 88 0
      models/data_manage/data_approve/response/approve.go
  29. 46 0
      models/data_manage/data_approve/response/approve_flow.go
  30. 24 0
      models/data_manage/data_approve/response/approve_message.go
  31. 24 6
      models/data_manage/edb_classify.go
  32. 132 48
      models/data_manage/edb_info.go
  33. 134 0
      models/data_manage/edb_info_share.go
  34. 257 0
      models/data_manage/public_edb_classify.go
  35. 68 0
      models/data_manage/public_edb_info.go
  36. 20 11
      models/data_manage/request/edb_info_share.go
  37. 55 0
      models/data_manage/request/edb_public.go
  38. 7 0
      models/data_manage/response/edb_info_share.go
  39. 297 0
      routers/commentsRouter.go
  40. 9 0
      routers/router.go
  41. 59 25
      services/data/chart_classify.go
  42. 1199 0
      services/data/data_approve/approve.go
  43. 174 0
      services/data/data_approve/approve_flow.go
  44. 89 0
      services/data/data_approve/approve_message.go
  45. 31 0
      services/data/data_approve/approve_node.go
  46. 37 0
      services/data/data_approve/constant.go
  47. 2 2
      services/data/data_manage_permission/data_move.go
  48. 34 20
      services/data/edb_classify.go
  49. 2 2
      services/data/edb_info.go
  50. 135 0
      services/data/edb_info_share.go
  51. 44 0
      services/data/edb_public.go
  52. 850 0
      services/data/edb_public_classify.go
  53. 1 1
      services/edb_info_replace.go
  54. 726 0
      services/elastic/edb_info.go
  55. 0 381
      services/elastic/elastic.go
  56. 11 3
      utils/constants.go
  57. 17 2
      utils/elastic.go

+ 7 - 7
controllers/data_manage/chart_classify.go

@@ -89,21 +89,21 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 		}
 	}
 
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT)
+	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_DEFAULT})
+	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_DEFAULT}, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -162,13 +162,13 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT, adminInfo.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
 	}
 
-	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT)
+	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT, adminInfo.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
@@ -221,14 +221,14 @@ func (this *ChartClassifyController) ChartClassifyItems() {
 		this.ServeJSON()
 	}()
 
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_DEFAULT, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT)
+	classifyAll, err := data_manage.GetChartClassifyAll(utils.CHART_SOURCE_DEFAULT, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()

+ 2 - 2
controllers/data_manage/correlation/correlation_chart_classify.go

@@ -60,7 +60,7 @@ func (this *CorrelationChartClassifyController) ChartClassifyList() {
 
 	nodeAll := make([]*data_manage.ChartClassifyItems, 0)
 	// 查询分类节点
-	rootList, err := data_manage.GetChartClassifyByParentId(parentId, utils.CHART_SOURCE_CORRELATION)
+	rootList, err := data_manage.GetChartClassifyByParentId(parentId, utils.CHART_SOURCE_CORRELATION, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
@@ -154,7 +154,7 @@ func (this *CorrelationChartClassifyController) ChartClassifyItems() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_CORRELATION)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_CORRELATION, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()

+ 2 - 2
controllers/data_manage/cross_variety/classify.go

@@ -53,14 +53,14 @@ func (c *ClassifyController) List() {
 		source = utils.CHART_SOURCE_CROSS_HEDGING
 	}
 
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_CROSS_HEDGING)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_CROSS_HEDGING, c.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	allChartInfo, err := data_manage.GetChartInfoAll([]int{source})
+	allChartInfo, err := data_manage.GetChartInfoAll([]int{source}, c.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()

+ 458 - 0
controllers/data_manage/data_approve/data_approve.go

@@ -0,0 +1,458 @@
+package data_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/controllers"
+	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/data_manage/data_approve/request"
+	"eta_gn/eta_api/models/data_manage/data_approve/response"
+	dataApproveServ "eta_gn/eta_api/services/data/data_approve"
+	"eta_gn/eta_api/utils"
+	"fmt"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+// DataApproveController
+// @Description: 数据资产审批
+type DataApproveController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 审批列表
+// @Description 审批列表
+// @Param   PageSize			query	int		true	"每页数据条数"
+// @Param   CurrentIndex		query	int		true	"当前页页码"
+// @Param   ListType			query   int     true	"列表类型:1-待处理;2-已处理;3-我发起的"
+// @Param   ClassifyId			query	int		false	"分类ID"
+// @Param   Keyword				query	string	false	"搜索关键词"
+// @Param   ApproveState		query	int		false	"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"
+// @Param   TimeType			query	int		false	"时间类型:1-提交时间;2-处理时间;3-审批时间"
+// @Param   StartTime			query	string	false	"开始时间"
+// @Param   EndTime				query	string	false	"结束时间"
+// @Param   SortField			query	int		false	"排序字段:1-提交时间;2-处理时间;3-审批时间"
+// @Param   SortRule			query	int		false	"排序方式: 1-正序; 2-倒序(默认)"
+// @Success 200 {object} report_approve.DataApproveListResp
+// @router /list [get]
+func (this *DataApproveController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	listType, _ := this.GetInt("ListType")
+	approveState, _ := this.GetInt("ApproveState")
+	timeType, _ := this.GetInt("TimeType")
+	startTime := this.GetString("StartTime")
+	endTime := this.GetString("EndTime")
+	sortField, _ := this.GetInt("SortField")
+	sortRule, _ := this.GetInt("SortRule")
+	classifyId, _ := this.GetInt("ClassifyId")
+	keyword := this.GetString("Keyword")
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize10
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize := paging.StartIndex(currentIndex, pageSize)
+
+	var list []*response.DataApproveItemOrmResp
+	var total int
+	var msg string
+	var err error
+
+	switch listType {
+	case 1:
+		list, total, msg, err = dataApproveServ.ProcessingDataApprove(sysUser.AdminId, classifyId, timeType, sortField, sortRule, startSize, pageSize, sysUser.RealName, startTime, endTime, keyword)
+	case 2:
+		list, total, msg, err = dataApproveServ.SolvedDataApprove(sysUser.AdminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize, sysUser.RealName, startTime, endTime, keyword)
+	case 3:
+		list, total, msg, err = dataApproveServ.MyApplyDataApproves(sysUser.AdminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize, sysUser.RealName, startTime, endTime, keyword)
+	default:
+		br.Msg = "列表类型错误"
+		return
+	}
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批列表失败"
+		}
+		br.ErrMsg = "获取审批列表失败, Err: " + err.Error()
+		return
+	}
+
+	resp := new(response.DataApproveListResp)
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.List = list
+	resp.Paging = page
+
+	br.Msg = "获取审批列表成功"
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+}
+
+// Approve
+// @Title 通过审批
+// @Description 通过审批
+// @Param	request	body report_approve.DataApprovePassReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /approve [post]
+func (this *DataApproveController) Approve() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.DataApprovePassReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.DataApproveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, DataApproveId: %d", req.DataApproveId)
+		return
+	}
+
+	// 通过审批
+	msg, err := dataApproveServ.PassDataApprove(req.DataApproveId, sysUser.AdminId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "通过审批失败, Err: " + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Detail
+// @Title 审批详情
+// @Description 审批详情
+// @Param   DataApproveId  query  int  true  "审批ID"
+// @Success 200 {object} report_approve.DataApproveDetail
+// @router /detail [get]
+func (this *DataApproveController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	approveId, _ := this.GetInt("DataApproveId")
+	if approveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, DataApproveId: %d", approveId)
+		return
+	}
+
+	resp, msg, err := dataApproveServ.GetApproveDetail(approveId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批详情失败"
+		}
+		br.ErrMsg = "获取审批详情失败, Err: " + err.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Refuse
+// @Title 驳回审批
+// @Description 驳回审批
+// @Param	request	body request.DataApproveRefuseReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /refuse [post]
+func (this *DataApproveController) Refuse() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.DataApproveRefuseReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.DataApproveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, DataApproveId: %d", req.DataApproveId)
+		return
+	}
+	maxStrLen := 500
+	approveLen := len([]rune(req.ApproveRemark))
+	if approveLen > maxStrLen {
+		br.Msg = fmt.Sprintf("审批驳回原因不能超过%d字", maxStrLen)
+		return
+	}
+	msg, err := dataApproveServ.DataApproveRefuse(req.DataApproveId, sysUser.AdminId, req.ApproveRemark)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "驳回审批失败, Err: " + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Cancel
+// @Title 撤销审批
+// @Description 撤销审批
+// @Param	request	body report_approve.DataApproveCancelReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /cancel [post]
+func (this *DataApproveController) Cancel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.DataApproveCancelReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.DataApproveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, DataApproveId: %d", req.DataApproveId)
+		return
+	}
+
+	// 撤销审批
+	msg, e := dataApproveServ.DataApproveCancel(req.DataApproveId, sysUser.AdminId, sysUser.RealName)
+	if e != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "撤销审批失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// MessageList
+// @Title 审批消息列表
+// @Description 审批消息列表
+// @Param   PageSize			query	int		true	"每页数据条数"
+// @Param   CurrentIndex		query	int		true	"当前页页码"
+// @Success 200 {object} report_approve.DataApproveMessageListResp
+// @router /message/list [get]
+func (this *DataApproveController) MessageList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	currentIndex, _ := this.GetInt("currentIndex")
+	pageSize, _ := this.GetInt("pageSize")
+	// 分页
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	resp := new(response.DataApproveMessageListResp)
+	resp.List = make([]*response.DataApproveMessageItem, 0)
+	list, total, unRead, msg, err := dataApproveServ.GetDataApproveMessage(sysUser.AdminId, startSize, pageSize)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批消息失败"
+		}
+		br.ErrMsg = "获取审批消息失败, Err: " + err.Error()
+		return
+	}
+	resp.List = list
+	resp.UnreadTotal = unRead
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// MessageRead
+// @Title 消息已读
+// @Description 消息已读
+// @Param	request	body report_approve.DataApproveMessageReadReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /message/read [post]
+func (this *DataApproveController) MessageRead() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.DataApproveMessageReadReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MessageId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MessageId: %d", req.MessageId)
+		return
+	}
+
+	msg, err := dataApproveServ.ReadBiMessage(req.MessageId, sysUser.AdminId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "消息已读失败, Err: " + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// CheckApproveOpen
+// @Title 校验是否开启审批
+// @Description 校验是否开启审批
+// @Param	request	body report_approve.DataApproveCheckApproveOpenReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /check_open [post]
+func (this *DataApproveController) CheckApproveOpen() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.DataApproveCheckApproveOpenReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验是否开启了审批流
+	opening, e := dataApproveServ.CheckOpenApprove(req.DataType)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "校验数据资产是否开启审批流失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = opening
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 126 - 0
controllers/data_manage/data_approve/data_approve_flow.go

@@ -0,0 +1,126 @@
+package data_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/controllers"
+	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/data_manage/data_approve/request"
+	DataApprove "eta_gn/eta_api/services/data/data_approve"
+)
+
+type DataApproveFlowController struct {
+	controllers.BaseAuthController
+}
+
+// Save
+// @Title 保存审批流
+// @Description 保存审批流
+// @Param	request	body request.DataApproveFlowSaveReq true "type json string"
+// @Success 200 {object} report_approve.ReportApproveFlowDetailItem
+// @router /flow/save [post]
+func (c *DataApproveFlowController) Save() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req *request.DataApproveFlowSaveReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = "参数解析失败, err:" + err.Error()
+		return
+	}
+	//req.FlowName = strings.TrimSpace(req.FlowName)
+	req.FlowName = `审批`
+	switch req.DataType {
+	case 1:
+		req.FlowName = "指标审批"
+	case 2:
+		req.FlowName = "图表审批"
+
+	}
+	if req.FlowName == "" {
+		br.Msg = "审批流名称不能为空"
+		return
+	}
+
+	if len([]rune(req.FlowName)) > 20 {
+		br.Msg = "审批流名称最多输入20个字符"
+		return
+	}
+	if req.DataType <= 0 {
+		br.Msg = "请选择审批类型"
+		return
+	}
+
+	ok, msg, err := DataApprove.SaveDataApproveFlow(req)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "编辑审批流失败"
+		}
+		br.ErrMsg = "编辑审批流失败, err:" + err.Error()
+		return
+	}
+	if !ok {
+		br.Msg = msg
+		return
+	}
+
+	br.Msg = "编辑审批流成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// Detail
+// @Title 审批流详情
+// @Description 审批流详情
+// @Param	request	body request.DataApproveFlowRemoveResp true "type json string"
+// @Param   DataType			query	int		false	"排序字段:1-指标审批;2-图表审批"
+// @Success 200 {object} report_approve.ReportApproveFlowDetailItem
+// @router /flow/detail [get]
+func (c *DataApproveFlowController) Detail() {
+	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
+	}
+	dataType, _ := c.GetInt("DataType")
+	if dataType <= 0 {
+		br.Msg = "审批流不存在"
+		return
+	}
+	detail, msg, err := DataApprove.GetDataApproveFlowDetail(dataType)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批流详情失败"
+		}
+		br.ErrMsg = "获取审批流详情失败, err:" + err.Error()
+		return
+	}
+	if detail == nil {
+		br.Msg = "审批流不存在"
+		return
+	}
+
+	br.Data = detail
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取审批流详情成功"
+}

+ 265 - 10
controllers/data_manage/edb_info.go

@@ -1853,8 +1853,14 @@ func (this *EdbInfoController) EdbInfoFilterByEs() {
 	newKeyWord := strings.Split(keyWord, " ")
 	keyWordArr = append(keyWordArr, newKeyWord...)
 
+	sortMap := make(map[string]string)
+	// 如果没有搜索关键词,则默认根据指标编码倒序排序
+	if keyWord == `` {
+		sortMap["EdbInfoId"] = `desc`
+	}
+
 	// 普通的搜索
-	total, edbInfoList, err = elastic.SearchEdbInfoData(keyWord, startSize, pageSize, filterSource, source, frequency, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, collectEdbInfoIdList, edbTypeList, edbInfoType, edbAuth, this.SysUser.AdminId)
+	total, edbInfoList, err = elastic.SearchEdbInfoData(keyWord, startSize, pageSize, filterSource, source, frequency, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, collectEdbInfoIdList, edbTypeList, edbInfoType, edbAuth, this.SysUser.AdminId, sortMap)
 
 	if err != nil {
 		edbInfoList = make([]*data_manage.EdbInfoList, 0)
@@ -3207,7 +3213,7 @@ func (this *EdbInfoController) AllEdbInfoByEs() {
 		keyWordArr = append(keyWordArr, newKeyWord...)
 
 		// 普通的搜索
-		total, edbInfoList, err = elastic.SearchEdbInfoData(keyWord, startSize, pageSize, filterSource, source, frequency, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, []int{}, []int{1, 2}, -1, 0, this.SysUser.AdminId)
+		total, edbInfoList, err = elastic.SearchEdbInfoData(keyWord, startSize, pageSize, filterSource, source, frequency, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, []int{}, []int{1, 2}, -1, 0, this.SysUser.AdminId, map[string]string{})
 		isEs = true
 	} else {
 		var condition string
@@ -3797,11 +3803,19 @@ func (this *EdbInfoController) EdbChartList() {
 	pars = append(pars, 0)
 
 	// 指标类型
-	edbType, _ := this.GetInt("EdbType", 0)
+	edbType, _ := this.GetInt("EdbType", 1)
 	if edbType > 0 {
 		condition += ` AND edb_type = ? `
 		pars = append(pars, edbType)
 	}
+	switch edbType {
+	case utils.EdbTypeBase:
+		condition += ` AND edb_type = ? `
+		pars = append(pars, edbType)
+	case utils.EdbTypeCalculate:
+		condition += ` AND edb_type = ? AND sys_user_id = ? `
+		pars = append(pars, edbType, sysUser.AdminId)
+	}
 
 	// 分类筛选
 	classifyId, _ := this.GetInt("ClassifyId")
@@ -3827,13 +3841,6 @@ func (this *EdbInfoController) EdbChartList() {
 		pars = append(pars, adminId)
 	}
 
-	// 只看我的
-	isOnlyMe, _ := this.GetBool("IsOnlyMe")
-	if isOnlyMe {
-		condition += ` AND sys_user_id = ? `
-		pars = append(pars, sysUser.AdminId)
-	}
-
 	// 无权限指标 和 无权限指标分类id
 	noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, err := data_manage_permission.GetUserAllEdbAndClassifyNoPermissionList(this.SysUser.AdminId, utils.EDB_INFO_TYPE, edbType)
 	if err != nil {
@@ -4587,3 +4594,251 @@ func (this *EdbInfoController) ChartImageSetBySvg() {
 	br.Success = true
 	br.Msg = "保存成功"
 }
+
+// EdbInfoFilterByEs
+// @Title 指标筛选接口
+// @Description 指标筛选接口
+// @Param   KeyWord   query   string  false       "搜索关键词:指标ID/指标名称"
+// @Param   FilterSource   query   int  false       "搜索来源:1:其他搜索,2:累计值转月值搜索,3:变频,4:基础指标,5:同比"
+// @Param   Frequency   query   string  false       "频度"
+// @Param   IsAddPredictEdb   query   bool  false       "是否查询添加预测指标"
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   EdbType   query   int  false       "指标类型:0-基础和计算;1-基础指标;2-计算指标;3-衍生指标"
+// @Param   EdbAuth   query   int  false       "指标权限:0-全部;1-我的;2-公共"
+// @Param   EdbCollect   query   int  false       "指标收藏状态:0-全部;1-已收藏"
+// @Success 200 {object} data_manage.EdbInfoList
+// @router /edb_info/batch_move [get]
+func (this *EdbInfoController) BatchMoveEdb() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	// TODO 移动指标
+	var err error
+	req := data_manage.EsEdbReq{}
+	err = this.ParseForm(&req)
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误"
+		return
+	}
+	var total int64
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	keyWord := this.GetString("KeyWord")
+	keyWord = strings.TrimSpace(keyWord) //移除字符串首尾空格
+	filterSource, _ := this.GetInt("FilterSource")
+	if filterSource <= 0 {
+		filterSource = 1
+	}
+	//指标来源
+	source, _ := this.GetInt("Source")
+
+	frequency := this.GetString("Frequency") //频度
+
+	//isAddPredictEdb, _ := this.GetBool("IsAddPredictEdb") //是否查询添加预测指标
+
+	// 指标类型数组:1-基础指标;2-计算指标;3-预测指标
+	edbTypeList := make([]int, 0)
+	edbInfoType := -1                            // 指标范围
+	edbTypeStr := this.GetString("EdbType", "0") // 指标类型:0-基础和计算;1-基础指标;2-计算指标;3-预测指标
+	{
+		if edbTypeStr == `` || edbTypeStr == `0` {
+			edbTypeList = []int{1, 2}
+			edbInfoType = 0
+		} else {
+			var hasEdb, hasPredictEdb bool
+			tmpEdbTypeList := strings.Split(edbTypeStr, `,`)
+			for _, v := range tmpEdbTypeList {
+				edbType, err := strconv.Atoi(v)
+				if err != nil {
+					br.Msg = "EdbType异常"
+					br.ErrMsg = "EdbType异常,Err:" + err.Error()
+					return
+				}
+
+				// 指标类型
+				switch edbType {
+				case 1, 2:
+					hasEdb = true
+					edbTypeList = append(edbTypeList, edbType)
+				case 3:
+					hasPredictEdb = true
+					edbTypeList = []int{1, 2}
+				}
+			}
+
+			// 只有数据查看和指标加工
+			if hasEdb && !hasPredictEdb {
+				edbInfoType = 0
+			} else if !hasEdb && hasPredictEdb {
+				// 只有预测指标
+				edbInfoType = 1
+			}
+		}
+	}
+
+	edbAuth, _ := this.GetInt("EdbAuth", 0) // 指标权限范围,0-全部;1-我的;2-公共
+
+	edbCollect, _ := this.GetInt("EdbCollect", 0) // 指标收藏状态:0-全部;1-已收藏
+
+	var edbInfoList []*data_manage.EdbInfoList
+
+	// 无权限指标 和 无权限指标分类id(只考虑)
+	noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, err := data_manage_permission.GetUserAllEdbAndClassifyNoPermissionListV2(this.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+		return
+	}
+
+	// 收藏的指标id
+	collectEdbInfoIdList := make([]int, 0)
+	if edbCollect == 1 {
+		collectEdbInfoIdList, err = data_manage.GetUserAllCollectEdbInfoIdList(this.SysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取收藏指标配置数据失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	var keyWordArr []string
+	keyWordArr = append(keyWordArr, keyWord)
+
+	newKeyWord := strings.Split(keyWord, " ")
+	keyWordArr = append(keyWordArr, newKeyWord...)
+
+	sortMap := make(map[string]string)
+	// 如果没有搜索关键词,则默认根据指标编码倒序排序
+	if keyWord == `` {
+		sortMap["EdbInfoId"] = `desc`
+	}
+
+	// 普通的搜索
+	total, edbInfoList, err = elastic.SearchEdbInfoData(keyWord, startSize, pageSize, filterSource, source, frequency, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, collectEdbInfoIdList, edbTypeList, edbInfoType, edbAuth, this.SysUser.AdminId, sortMap)
+
+	if err != nil {
+		edbInfoList = make([]*data_manage.EdbInfoList, 0)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+
+	edbInfoListLen := len(edbInfoList)
+
+	classifyIdList := make([]int, 0)
+	for i := 0; i < edbInfoListLen; i++ {
+		edbInfoList[i].ConvertToResp()
+		edbInfoList[i].EdbNameAlias = edbInfoList[i].EdbName
+		classifyIdList = append(classifyIdList, edbInfoList[i].ClassifyId)
+	}
+
+	// 当前列表中的分类map
+	classifyMap := make(map[int]*data_manage.EdbClassify)
+	if edbInfoListLen > 0 {
+		classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range classifyList {
+			classifyMap[v.ClassifyId] = v
+		}
+
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+			return
+		}
+
+		// 因为是ES查找的,所以需要重新查一下指标的信息,主要是为了把是否授权字段找出来
+		{
+			edbInfoIdList := make([]int, 0)
+			for i := 0; i < edbInfoListLen; i++ {
+				edbInfoIdList = append(edbInfoIdList, edbInfoList[i].EdbInfoId)
+				tmpEdbInfo := edbInfoList[i]
+				if currClassify, ok := classifyMap[tmpEdbInfo.ClassifyId]; ok {
+					edbInfoList[i].HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(tmpEdbInfo.IsJoinPermission, currClassify.IsJoinPermission, tmpEdbInfo.EdbInfoId, tmpEdbInfo.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+				}
+			}
+
+			tmpEdbList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取所有有权限的指标失败,Err:" + err.Error()
+				return
+			}
+			edbInfoMap := make(map[int]*data_manage.EdbInfo)
+			for _, v := range tmpEdbList {
+				edbInfoMap[v.EdbInfoId] = v
+			}
+
+			for i := 0; i < edbInfoListLen; i++ {
+				tmpEdbInfo, ok := edbInfoMap[edbInfoList[i].EdbInfoId]
+				if !ok {
+					continue
+				}
+				edbInfoList[i].IsJoinPermission = tmpEdbInfo.IsJoinPermission
+			}
+		}
+
+		// 权限校验
+		for i := 0; i < edbInfoListLen; i++ {
+			tmpEdbInfoItem := edbInfoList[i]
+			if currClassify, ok := classifyMap[tmpEdbInfoItem.ClassifyId]; ok {
+				edbInfoList[i].HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(tmpEdbInfoItem.IsJoinPermission, currClassify.IsJoinPermission, tmpEdbInfoItem.EdbInfoId, tmpEdbInfoItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+		}
+	}
+
+	for i := 0; i < edbInfoListLen; i++ {
+		for j := 0; j < edbInfoListLen; j++ {
+			if (edbInfoList[i].EdbNameAlias == edbInfoList[j].EdbNameAlias) &&
+				(edbInfoList[i].EdbInfoId != edbInfoList[j].EdbInfoId) &&
+				!(strings.Contains(edbInfoList[i].EdbName, edbInfoList[i].SourceName)) {
+				edbInfoList[i].EdbName = edbInfoList[i].EdbName + "(" + edbInfoList[i].SourceName + ")"
+			}
+		}
+	}
+	//新增搜索词记录
+	{
+		searchKeyword := new(data_manage.SearchKeyword)
+		searchKeyword.KeyWord = keyWord
+		searchKeyword.CreateTime = time.Now()
+		go data_manage.AddSearchKeyword(searchKeyword)
+	}
+
+	// 不返回无权限的指标
+	respList := make([]*data_manage.EdbInfoList, 0)
+	for _, v := range edbInfoList {
+		if v.HaveOperaAuth {
+			respList = append(respList, v)
+		}
+	}
+
+	resp := data_manage.EdbInfoFilterDataResp{
+		Paging: page,
+		List:   respList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 527 - 2
controllers/data_manage/edb_info_share.go

@@ -8,6 +8,11 @@ import (
 	"eta_gn/eta_api/models/data_manage/request"
 	"eta_gn/eta_api/models/data_manage/response"
 	"eta_gn/eta_api/services/data"
+	"eta_gn/eta_api/services/elastic"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strings"
 )
 
 // EdbInfoShareController 数据管理
@@ -86,8 +91,8 @@ func (c *EdbInfoShareController) UserList() {
 }
 
 // Save
-// @Title 保存指标指标设置共享的详情
-// @Description 获取指标详情接口
+// @Title 单个指标设置共享
+// @Description 单个指标设置共享
 // @Param	request	body request.SetEdbInfoShareReq true "type json string"
 // @Success 200 {object} data_manage.EdbInfo
 // @router /edb_info/share/save [post]
@@ -128,3 +133,523 @@ func (c *EdbInfoShareController) Save() {
 	br.Success = true
 	br.Msg = "保存成功"
 }
+
+// Tree
+// @Title 获取共享指标的分类/指标树
+// @Description 获取共享指标的分类/指标树
+// @Success 200 {object} response.EdbShareListResp
+// @router /edb_info/share/tree [get]
+func (c *EdbInfoShareController) Tree() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	resp := response.EdbShareListResp{}
+
+	// 我共享的
+	{
+		sendList, err := data.GetAllShareEdbListByFromUserId(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取我共享的指标列表信息失败,Err:" + err.Error()
+			return
+		}
+		nodeList, err := data.GetEdbClassifyItemListByShareEdbInfoQueryList(sendList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取我共享的指标列表分类结构信息失败,Err:" + err.Error()
+			return
+		}
+		resp.Send = nodeList
+	}
+
+	// TODO 不确定加了用户这个顶级,会不会对前端造成一定影响
+	// 我收到的
+	{
+		sendList, err := data.GetAllShareEdbListByReceivedUserId(sysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取我共享的指标列表信息失败,Err:" + err.Error()
+			return
+		}
+		nodeList, err := data.GetEdbClassifyItemListByShareEdbInfoQueryList(sendList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取我共享的指标列表分类结构信息失败,Err:" + err.Error()
+			return
+		}
+
+		receivedMap := make(map[int]int)
+		var receivedList data_manage.EdbClassifyItemList
+		for _, v := range nodeList {
+			index, ok := receivedMap[v.SysUserId]
+			if !ok {
+				index = len(receivedMap)
+				item := &data_manage.EdbClassifyItems{
+					ClassifyId:       v.SysUserId,
+					EdbInfoId:        0,
+					ClassifyType:     0,
+					ClassifyName:     v.SysUserRealName,
+					ClassifyNameEn:   "",
+					ParentId:         0,
+					RootId:           0,
+					Level:            0,
+					Sort:             0,
+					UniqueCode:       "",
+					Source:           0,
+					SourceName:       "",
+					SysUserId:        v.SysUserId,
+					SysUserRealName:  v.SysUserRealName,
+					StartDate:        "",
+					EdbCode:          "",
+					EdbType:          0,
+					Children:         []*data_manage.EdbClassifyItems{},
+					Button:           data_manage.EdbClassifyItemsButton{},
+					IsJoinPermission: 0,
+					HaveOperaAuth:    false,
+					ClassifyIdPath:   "",
+				}
+				receivedList = append(receivedList, item)
+			}
+			receivedList[index].Children = append(receivedList[index].Children, v)
+		}
+
+		resp.Received = receivedList
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// List
+// @Title 指标列表接口
+// @Description 指标列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   int  true       "分类id"
+// @Param   FilterSource   query   int  false       "共享指标的列表数据来源,0:我共享的;1:别人共享给我的"
+// @Success 200 {object} response.EdbInfoChartListResp
+// @router /edb_info/share/list [get]
+func (c *EdbInfoShareController) List() {
+	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
+	}
+
+	// 分页
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	filterSource, _ := c.GetInt("FilterSource")
+
+	var total int
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	// 基础指标
+	var condition string
+	var pars []interface{}
+	condition += ` AND edb_info_type = ? `
+	pars = append(pars, 0)
+
+	// 指标类型
+	edbType, _ := c.GetInt("EdbType", 0)
+	if edbType > 0 {
+		condition += ` AND edb_type = ? `
+		pars = append(pars, edbType)
+	}
+
+	// 分类筛选
+	classifyId, _ := c.GetInt("ClassifyId")
+	if classifyId > 0 {
+		childClassify, e, _ := data.GetChildClassifyByClassifyId(classifyId)
+		if e != nil && !utils.IsErrNoRow(e) {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
+			return
+		}
+		var classifyIds []int
+		for _, v := range childClassify {
+			classifyIds = append(classifyIds, v.ClassifyId)
+		}
+		condition += fmt.Sprintf(` AND b.classify_id IN (%s) `, utils.GetOrmInReplace(len(classifyIds)))
+		pars = append(pars, classifyIds)
+	}
+
+	switch filterSource {
+	case 1: // 别人共享给我的
+		condition += ` AND a.sys_user_id = ? AND b.sys_user_id != ?  `
+		pars = append(pars, sysUser.AdminId, sysUser.AdminId)
+	default: // 我共享的
+		condition += ` AND b.sys_user_id = ? `
+		pars = append(pars, sysUser.AdminId)
+	}
+
+	obj := data_manage.EdbInfoShare{}
+
+	dataCount, respList, err := obj.GetShareEdbInfoListPageList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = fmt.Sprintf("获取分享指标列表失败, %v", err)
+		return
+	}
+
+	page = paging.GetPaging(currentIndex, pageSize, int(dataCount))
+
+	resp := response.EdbInfoChartListResp{
+		Paging: page,
+		List:   respList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// ListByEs
+// @Title 指标筛选接口
+// @Description 指标筛选接口
+// @Success 200 {object} data_manage.EdbInfoList
+// @Param	request	body request.SearchEdbInfoShareReq true "type json string"
+// @Success 200 {object} data_manage.EdbInfoFilterDataResp
+// @router /edb_info/share/list/es [post]
+func (c *EdbInfoShareController) ListByEs() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	var req request.SearchEdbInfoShareReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	pageSize := req.PageSize
+	currentIndex := req.CurrentIndex
+
+	var total int64
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	keyword := req.Keyword
+	keyword = strings.TrimSpace(keyword) //移除字符串首尾空格
+
+	//指标来源
+	sourceList := req.SourceList
+
+	edbInfoType := 0        // 普通指标
+	edbTypeList := []int{2} // 普通指标中的计算指标
+
+	// 指标分享状态:1-未共享;2-已共享。可多选,多选用英文,隔开;默认是未共享
+	edbShareList := req.EdbShareList
+	if len(edbShareList) <= 0 {
+		edbShareList = []int{1}
+	}
+	edbShare := 1 // 0:全部,1:未共享,2:已共享
+	lenEdbShareList := len(edbShareList)
+	if len(edbShareList) > 0 {
+		if lenEdbShareList > 1 {
+			edbShare = 0
+		} else {
+			edbShare = edbShareList[0]
+		}
+	}
+
+	// 指标分享状态:1-未共享;2-已共享。可多选,多选用英文,隔开;默认是未共享
+	edbClassifyIdList := req.ClassifyIdList
+
+	edbAuth := 1 // 选择范围是:只有我的指标
+
+	var edbInfoList []*data_manage.EdbInfoList
+
+	sortMap := make(map[string]string)
+	// 如果没有搜索关键词,则默认根据指标编码倒序排序
+	if keyword == `` {
+		sortMap["EdbInfoId"] = `desc`
+	}
+	total, edbInfoList, err = elastic.SearchEdbInfoDataByShared(keyword, startSize, pageSize, edbShare, sourceList, edbClassifyIdList, edbTypeList, edbInfoType, edbAuth, c.SysUser.AdminId, sortMap)
+	if err != nil {
+		edbInfoList = make([]*data_manage.EdbInfoList, 0)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+
+	edbInfoListLen := len(edbInfoList)
+
+	// 因为是ES查找的,所以需要重新查一下指标的信息,主要是为了把是否授权字段找出来
+	if len(edbInfoList) > 0 {
+		edbInfoIdList := make([]int, 0)
+		for _, v := range edbInfoList {
+			v.ConvertToResp()
+			v.EdbNameAlias = v.EdbName
+			v.HaveOperaAuth = true
+			edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+		}
+
+		tmpEdbList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标失败,Err:" + err.Error()
+			return
+		}
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		for _, v := range tmpEdbList {
+			edbInfoMap[v.EdbInfoId] = v
+		}
+
+		for _, v := range edbInfoList {
+			tmpEdbInfo, ok := edbInfoMap[v.EdbInfoId]
+			if !ok {
+				continue
+			}
+			v.IsJoinPermission = tmpEdbInfo.IsJoinPermission
+		}
+	}
+
+	for i := 0; i < edbInfoListLen; i++ {
+		for j := 0; j < edbInfoListLen; j++ {
+			if (edbInfoList[i].EdbNameAlias == edbInfoList[j].EdbNameAlias) &&
+				(edbInfoList[i].EdbInfoId != edbInfoList[j].EdbInfoId) &&
+				!(strings.Contains(edbInfoList[i].EdbName, edbInfoList[i].SourceName)) {
+				edbInfoList[i].EdbName = edbInfoList[i].EdbName + "(" + edbInfoList[i].SourceName + ")"
+			}
+		}
+	}
+
+	resp := data_manage.EdbInfoFilterDataResp{
+		Paging: page,
+		List:   edbInfoList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// BatchSave
+// @Title 批量指标设置共享
+// @Description 批量指标设置共享
+// @Param	request	body request.SetEdbSharePermissionReq true "type json string"
+// @Success 200 {object} data_manage.EdbInfo
+// @router /edb_info/share/batch_save [post]
+func (c *EdbInfoShareController) BatchSave() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.SetEdbSharePermissionReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	// 选中的指标id列表
+	selectEdbInfoIdList := make([]int, 0)
+
+	// 选择所有指标,所以需要通过es获取数据
+	if req.IsSelectAll {
+		allEsEdbInfoIdList, err := getAllEdbInfoIdListByShared(req, c.SysUser.AdminId)
+		if err != nil {
+			br.Msg = "设置失败!"
+			br.ErrMsg = "设置失败,Err:" + err.Error()
+			return
+		}
+
+		if len(req.NoEdbIdList) <= 0 {
+			selectEdbInfoIdList = allEsEdbInfoIdList
+		} else {
+			noEdbIdMap := make(map[int]bool)
+			for _, v := range req.NoEdbIdList {
+				noEdbIdMap[v] = true
+			}
+
+			for _, v := range allEsEdbInfoIdList {
+				if _, ok := noEdbIdMap[v]; !ok {
+					// 如果不在未选中的指标id列表中,那么就加入到选中的指标id列表
+					selectEdbInfoIdList = append(selectEdbInfoIdList, v)
+				}
+			}
+		}
+	} else {
+		selectEdbInfoIdList = req.EdbIdList
+	}
+
+	if len(selectEdbInfoIdList) > 30 {
+		br.Msg = `指标数量不能超过30个`
+		br.IsSendEmail = false
+		return
+	}
+
+	// 设置
+	{
+
+		obj := data_manage.EdbInfoShare{}
+		err = obj.SaveEdbInfoShare(selectEdbInfoIdList, req.UserIdList, req.ShareType)
+		if err != nil {
+			br.Msg = `保存失败`
+			br.ErrMsg = `保存失败:` + err.Error()
+			return
+		}
+
+		// 更新es
+		for _, edbInfoId := range selectEdbInfoIdList {
+			data.AddOrEditEdbInfoToEs(edbInfoId)
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+}
+
+// getAllEdbInfoIdListByShared
+// @Description: 获取所有的指标id列表
+// @author: Roc
+// @datetime 2024-12-04 15:43:14
+// @param req request.SetEdbChartPermissionReq
+// @param userId int
+// @return edbInfoIdList []int
+// @return err error
+func getAllEdbInfoIdListByShared(req request.SetEdbSharePermissionReq, userId int) (edbInfoIdList []int, err error) {
+	keyword := req.Keyword
+	keyword = strings.TrimSpace(keyword) //移除字符串首尾空格
+
+	//指标来源
+	sourceList := req.SourceList
+
+	edbInfoType := 0        // 普通指标
+	edbTypeList := []int{2} // 普通指标中的计算指标
+
+	// 指标分享状态:1-未共享;2-已共享。可多选,多选用英文,隔开;默认是未共享
+	edbShareList := req.EdbShareList
+	if len(edbShareList) <= 0 {
+		edbShareList = []int{1}
+	}
+	edbShare := 1 // 0:全部,1:未共享,2:已共享
+	lenEdbShareList := len(edbShareList)
+	if len(edbShareList) > 0 {
+		if lenEdbShareList > 1 {
+			edbShare = 0
+		} else {
+			edbShare = edbShareList[0]
+		}
+	}
+
+	// 指标分享状态:1-未共享;2-已共享。可多选,多选用英文,隔开;默认是未共享
+	edbClassifyIdList := req.ClassifyIdList
+
+	edbAuth := 1 // 选择范围是:只有我的指标
+
+	sortMap := make(map[string]string)
+	// 如果没有搜索关键词,则默认根据指标编码倒序排序
+	if keyword == `` {
+		sortMap["EdbInfoId"] = `desc`
+	}
+	_, edbInfoList, err := getAllEdbInfoDataByShared(keyword, 1, edbShare, sourceList, edbClassifyIdList, edbTypeList, edbInfoType, edbAuth, userId, sortMap)
+	if err != nil {
+		return
+	}
+
+	// 返回指标id列表
+	for _, v := range edbInfoList {
+		edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+	}
+
+	return
+}
+
+// getAllEdbInfoDataByShared
+// @Description: 获取所有的指标列表(设置共享的时候)
+// @author: Roc
+// @datetime 2024-12-04 15:27:53
+// @param keyword string
+// @param currPage int
+// @param edbShare int
+// @param sourceList []int
+// @param classifyIdList []int
+// @param edbTypeList []int
+// @param edbInfoType int
+// @param edbAuth int
+// @param sysUserId int
+// @param sortMap map[string]string
+// @return total int64
+// @return list []*data_manage.EdbInfoList
+// @return err error
+func getAllEdbInfoDataByShared(keyword string, currPage, edbShare int, sourceList, classifyIdList, edbTypeList []int, edbInfoType, edbAuth, sysUserId int, sortMap map[string]string) (total int64, list []*data_manage.EdbInfoList, err error) {
+	// 每页获取数据的数量
+	pageSize := 5000
+	var startSize int
+	if currPage <= 0 {
+		currPage = 1
+	}
+	startSize = paging.StartIndex(currPage, pageSize)
+
+	total, list, err = elastic.SearchEdbInfoDataByShared(keyword, startSize, pageSize, edbShare, sourceList, classifyIdList, edbTypeList, edbInfoType, edbAuth, sysUserId, sortMap)
+	if err != nil {
+		return
+	}
+
+	page := paging.GetPaging(currPage, pageSize, int(total))
+	if !page.IsEnd {
+		_, nextList, tmpErr := getAllEdbInfoDataByShared(keyword, page.NextIndex, edbShare, sourceList, classifyIdList, edbTypeList, edbInfoType, edbAuth, sysUserId, sortMap)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		list = append(list, nextList...)
+	}
+
+	return
+}

+ 764 - 0
controllers/data_manage/edb_public.go

@@ -0,0 +1,764 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/controllers"
+	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/data_manage"
+	"eta_gn/eta_api/models/data_manage/request"
+	"eta_gn/eta_api/services/data"
+	dataApproveSerice "eta_gn/eta_api/services/data/data_approve"
+	"eta_gn/eta_api/services/elastic"
+	"eta_gn/eta_api/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strconv"
+	"strings"
+)
+
+// EdbPublicController 公共指标
+type EdbPublicController struct {
+	controllers.BaseAuthController
+}
+
+// RemoveCheck
+// @Title 删除检测接口
+// @Description 删除检测接口
+// @Param	request	body data_manage.ClassifyDeleteCheckReq true "type json string"
+// @Success 200 Ret=200 检测成功
+// @router /edb_public/remove/check [post]
+func (c *EdbPublicController) RemoveCheck() {
+	// TODO
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req data_manage.ClassifyDeleteCheckReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ClassifyId < 0 && req.EdbInfoId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+	deleteStatus, tipsMsg, tableList, err, errMsg := data.DeleteEdbPublicCheck(req.EdbInfoId, c.SysUser)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+	if c.Lang == "en" {
+		if utils.ViperConfig.InConfig(tipsMsg) {
+			tipsMsg = utils.ViperConfig.GetString(tipsMsg)
+		}
+	}
+
+	//var deleteStatus int
+	//var tipsMsg string
+	////删除公共分类
+	//if req.ClassifyId > 0 && req.EdbInfoId == 0 {
+	//	//判断公共分类下,是否含有指标
+	//	count, err := data_manage.GetEdbInfoCountByClassifyId(req.ClassifyId)
+	//	if err != nil {
+	//		br.Msg = "删除失败"
+	//		br.ErrMsg = "公共分类下是否含有指标失败,Err:" + err.Error()
+	//		return
+	//	}
+	//
+	//	if count > 0 {
+	//		deleteStatus = 1
+	//		tipsMsg = "若目录关联指标不可删除"
+	//	}
+	//}
+	//
+	//if deleteStatus != 1 && req.EdbInfoId == 0 {
+	//	classifyCount, err := data_manage.GetClassifyCountByClassifyId(req.ClassifyId)
+	//	if err != nil && !utils.IsErrNoRow(err) {
+	//		br.Msg = "删除失败"
+	//		br.ErrMsg = "公共分类下是否含有指标失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	if classifyCount > 0 {
+	//		deleteStatus = 2
+	//		tipsMsg = "确认删除当前目录及包含的子目录吗"
+	//	}
+	//}
+	//
+	////删除指标
+	//if req.EdbInfoId > 0 {
+	//	//判断指标是否用于作图,如果用于作图,则不可删除
+	//	chartCount, err := data_manage.GetChartEdbMappingCount(req.EdbInfoId)
+	//	if err != nil && !utils.IsErrNoRow(err) {
+	//		br.Msg = "删除失败"
+	//		br.ErrMsg = "判断指标是否被用于作图失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	if chartCount > 0 {
+	//		deleteStatus = 3
+	//		tipsMsg = "当前指标已用作画图,不可删除"
+	//	}
+	//	//判断指标是否用于计算
+	//	{
+	//		calculateCount, err := data_manage.GetEdbInfoCalculateMappingCount(req.EdbInfoId)
+	//		if err != nil && !utils.IsErrNoRow(err) {
+	//			br.Msg = "删除失败"
+	//			br.ErrMsg = "判断指标是否被用于计算失败,GetEdbInfoCalculateCount Err:" + err.Error()
+	//			return
+	//		}
+	//		if calculateCount > 0 {
+	//			deleteStatus = 4
+	//			tipsMsg = "当前指标已用作,指标运算,不可删除"
+	//		}
+	//	}
+	//}
+
+	resp := new(data_manage.ClassifyDeleteCheckResp)
+	resp.DeleteStatus = deleteStatus
+	resp.TipsMsg = tipsMsg
+	resp.TableList = tableList
+	br.Ret = 200
+	br.Msg = "检测成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// Remove
+// @Title 删除公共分类/指标
+// @Description 删除公共分类/指标接口
+// @Param	request	body data_manage.DeleteEdbClassifyReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /edb_public/remove [post]
+func (c *EdbPublicController) Remove() {
+	// TODO
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage.DeleteEdbClassifyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ClassifyId < 0 && req.EdbInfoId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	nextItem, _, err, errMsg := data.Delete(req.ClassifyId, req.EdbInfoId, sysUser, string(c.Ctx.Input.RequestBody), c.Ctx.Input.URI())
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+
+	resp := data_manage.AddEdbInfoResp{}
+	if nextItem != nil {
+		resp = data_manage.AddEdbInfoResp{
+			EdbInfoId:  nextItem.EdbInfoId,
+			UniqueCode: nextItem.UniqueCode,
+		}
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+	br.Data = resp
+}
+
+// Save
+// @Title 单个指标设置公开
+// @Description 单个指标设置公开
+// @Param	request	body request.SetEdbInfoShareReq true "type json string"
+// @Success 200 {object} data_manage.EdbInfo
+// @router /edb_info/public/save [post]
+func (c *EdbPublicController) Save() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.SetEdbPublicReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if len(req.EdbInfoList) <= 0 {
+		br.Msg = `请选择指标`
+		br.IsSendEmail = false
+	}
+
+	// 待处理的资产
+	dataPublicItemList := make([]dataApproveSerice.SetDataPublicItem, 0)
+
+	// 校验是否重复存在已公开、已提交的指标
+	{
+		edbInfoIdList := make([]int, 0)
+		for _, item := range req.EdbInfoList {
+			edbInfoIdList = append(edbInfoIdList, item.EdbInfoId)
+
+			dataPublicItemList = append(dataPublicItemList, dataApproveSerice.SetDataPublicItem{
+				DataId:     item.EdbInfoId,
+				ClassifyId: item.ClassifyId,
+			})
+		}
+
+		list, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+		if err != nil {
+			br.Msg = "保存失败!"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range list {
+			if v.PublicStatus != utils.EdbPublicDefault {
+				br.Msg = `选择指标中存在已经公开/提交审批的指标,请仅选择未公开指标!`
+				br.IsSendEmail = false
+				return
+			}
+		}
+	}
+
+	// 校验是否开启了审批流
+	opening, e := dataApproveSerice.CheckOpenApprove(dataApproveSerice.DataTypeEdb)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "校验指标公开是否开启审批流失败, Err: " + e.Error()
+		return
+	}
+
+	// 是否忽略审批
+	var isIgnoreApprove bool
+	{
+		businessConf, e := models.GetBusinessConfByKey(models.IgnoreEdbApproveUserId)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取商家配置失败, Err: " + e.Error()
+			return
+		}
+		ignoreEdbApproveUserIdList := strings.Split(businessConf.ConfVal, `,`)
+		if utils.InArrayByStr(ignoreEdbApproveUserIdList, strconv.Itoa(c.SysUser.AdminId)) {
+			isIgnoreApprove = true
+		}
+	}
+
+	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoList[0].EdbInfoId)
+	if err != nil {
+		br.Msg = "获取指标失败"
+		br.ErrMsg = "获取指标失败:" + err.Error()
+		return
+	}
+	title := edbInfo.EdbName
+	if len(req.EdbInfoList) > 1 {
+		title += `等指标`
+	}
+	title += `公开审批`
+
+	// 没开启审批流、或者无需审批
+	if !opening || isIgnoreApprove {
+		err = dataApproveSerice.UpdatePublicByDataList(dataApproveSerice.DataTypeEdb, dataApproveSerice.DataApproveStatePass, dataPublicItemList)
+	} else {
+
+		_, err = dataApproveSerice.SubmitDataApprove(dataApproveSerice.DataTypeEdb, dataPublicItemList, title, strings.TrimSpace(req.Description), c.SysUser.AdminId, c.SysUser.RealName)
+		if err != nil {
+			br.Msg = "提交审批失败"
+			br.ErrMsg = "提交审批失败, Err: " + err.Error()
+			return
+		}
+	}
+
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+}
+
+// Cancel
+// @Title 撤销指标公开
+// @Description 撤销指标公开
+// @Param   EdbInfoId   query   int  true       "指标id"
+// @Success 200 {object} data_manage.EdbInfo
+// @router /edb_info/public/cancel [post]
+func (c *EdbPublicController) Cancel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	// TODO 单个指标撤销的时候,需要校验状态,然后撤销
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	edbInfoId, _ := c.GetInt("EdbInfoId")
+	if edbInfoId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误"
+		return
+	}
+
+	var req request.SetEdbPublicReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if len(req.EdbInfoList) <= 0 {
+		br.Msg = `请选择指标`
+		br.IsSendEmail = false
+	}
+
+	// 待处理的资产
+	dataPublicItemList := make([]dataApproveSerice.SetDataPublicItem, 0)
+
+	// 校验是否重复存在已公开、已提交的指标
+	{
+		edbInfoIdList := make([]int, 0)
+		for _, item := range req.EdbInfoList {
+			edbInfoIdList = append(edbInfoIdList, item.EdbInfoId)
+
+			dataPublicItemList = append(dataPublicItemList, dataApproveSerice.SetDataPublicItem{
+				DataId:     item.EdbInfoId,
+				ClassifyId: item.ClassifyId,
+			})
+		}
+
+		list, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+		if err != nil {
+			br.Msg = "保存失败!"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range list {
+			if v.PublicStatus != utils.EdbPublicDefault {
+				br.Msg = `选择指标中存在已经公开/提交审批的指标,请仅选择未公开指标!`
+				br.IsSendEmail = false
+				return
+			}
+		}
+	}
+
+	// 校验是否开启了审批流
+	opening, e := dataApproveSerice.CheckOpenApprove(dataApproveSerice.DataTypeEdb)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "校验指标公开是否开启审批流失败, Err: " + e.Error()
+		return
+	}
+
+	// 是否忽略审批
+	var isIgnoreApprove bool
+	{
+		businessConf, e := models.GetBusinessConfByKey(models.IgnoreEdbApproveUserId)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取商家配置失败, Err: " + e.Error()
+			return
+		}
+		ignoreEdbApproveUserIdList := strings.Split(businessConf.ConfVal, `,`)
+		if utils.InArrayByStr(ignoreEdbApproveUserIdList, strconv.Itoa(c.SysUser.AdminId)) {
+			isIgnoreApprove = true
+		}
+	}
+
+	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoList[0].EdbInfoId)
+	if err != nil {
+		br.Msg = "获取指标失败"
+		br.ErrMsg = "获取指标失败:" + err.Error()
+		return
+	}
+	title := edbInfo.EdbName
+	if len(req.EdbInfoList) > 1 {
+		title += `等指标`
+	}
+	title += `公开审批`
+
+	// 没开启审批流、或者无需审批
+	if !opening || isIgnoreApprove {
+		err = dataApproveSerice.UpdatePublicByDataList(dataApproveSerice.DataTypeEdb, dataApproveSerice.DataApproveStatePass, dataPublicItemList)
+	} else {
+
+		_, err = dataApproveSerice.SubmitDataApprove(dataApproveSerice.DataTypeEdb, dataPublicItemList, title, strings.TrimSpace(req.Description), c.SysUser.AdminId, c.SysUser.RealName)
+		if err != nil {
+			br.Msg = "提交审批失败"
+			br.ErrMsg = "提交审批失败, Err: " + err.Error()
+			return
+		}
+	}
+
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+}
+
+// ListByEs
+// @Title 指标筛选接口
+// @Description 指标筛选接口
+// @Success 200 {object} data_manage.EdbInfoList
+// @Param	request	body request.SearchPublicEdbReq true "type json string"
+// @Success 200 {object} data_manage.EdbInfoFilterDataResp
+// @router /edb_info/public/list/es [post]
+func (c *EdbPublicController) ListByEs() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	var req request.SearchPublicEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	pageSize := req.PageSize
+	currentIndex := req.CurrentIndex
+
+	var total int64
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	// 获取查询参数
+	keyword, searchEdbPublicList, sourceList, edbClassifyIdList, edbTypeList, edbInfoType, edbAuth, sortMap := getSearchPar(req)
+
+	total, edbInfoList, err := elastic.SearchEdbInfoDataByPublic(keyword, startSize, pageSize, searchEdbPublicList, sourceList, edbClassifyIdList, edbTypeList, edbInfoType, edbAuth, c.SysUser.AdminId, sortMap)
+	if err != nil {
+		edbInfoList = make([]*data_manage.EdbInfoList, 0)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, int(total))
+
+	edbInfoListLen := len(edbInfoList)
+
+	// 因为是ES查找的,所以需要重新查一下指标的信息,主要是为了把是否授权字段找出来
+	if len(edbInfoList) > 0 {
+		edbInfoIdList := make([]int, 0)
+		for _, v := range edbInfoList {
+			v.ConvertToResp()
+			v.EdbNameAlias = v.EdbName
+			v.HaveOperaAuth = true
+			edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+		}
+
+		tmpEdbList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标失败,Err:" + err.Error()
+			return
+		}
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		for _, v := range tmpEdbList {
+			edbInfoMap[v.EdbInfoId] = v
+		}
+
+		for _, v := range edbInfoList {
+			tmpEdbInfo, ok := edbInfoMap[v.EdbInfoId]
+			if !ok {
+				continue
+			}
+			v.IsJoinPermission = tmpEdbInfo.IsJoinPermission
+		}
+	}
+
+	for i := 0; i < edbInfoListLen; i++ {
+		for j := 0; j < edbInfoListLen; j++ {
+			if (edbInfoList[i].EdbNameAlias == edbInfoList[j].EdbNameAlias) &&
+				(edbInfoList[i].EdbInfoId != edbInfoList[j].EdbInfoId) &&
+				!(strings.Contains(edbInfoList[i].EdbName, edbInfoList[i].SourceName)) {
+				edbInfoList[i].EdbName = edbInfoList[i].EdbName + "(" + edbInfoList[i].SourceName + ")"
+			}
+		}
+	}
+
+	resp := data_manage.EdbInfoFilterDataResp{
+		Paging: page,
+		List:   edbInfoList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// AllListByEs
+// @Title 指标筛选接口
+// @Description 指标筛选接口
+// @Success 200 {object} data_manage.EdbInfoList
+// @Param	request	body request.SearchEdbInfoShareReq true "type json string"
+// @Success 200 {object} data_manage.EdbInfoFilterDataResp
+// @router /edb_info/public/list/es/all [post]
+func (c *EdbPublicController) AllListByEs() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	var req request.AllSearchPublicEdbReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	// 选择所有指标,所以需要通过es获取数据
+
+	edbInfoList := make([]*data_manage.EdbInfoList, 0)
+	tmpEdbInfoList, err := getAllEdbInfoListByPublic(req, c.SysUser.AdminId)
+
+	// 如果有过滤指标,那么就过滤吧
+	if len(req.NoEdbIdList) > 0 {
+		noEdbIdMap := make(map[int]bool)
+		for _, v := range req.NoEdbIdList {
+			noEdbIdMap[v] = true
+		}
+
+		for _, v := range tmpEdbInfoList {
+			if _, ok := noEdbIdMap[v.EdbInfoId]; !ok {
+				// 如果不在未选中的指标id列表中,那么就加入到选中的指标id列表
+				edbInfoList = append(edbInfoList, v)
+			}
+		}
+	} else {
+		edbInfoList = tmpEdbInfoList
+	}
+
+	edbInfoListLen := len(edbInfoList)
+
+	// 因为是ES查找的,所以需要重新查一下指标的信息,主要是为了把是否授权字段找出来
+	if len(edbInfoList) > 0 {
+
+		edbInfoIdList := make([]int, 0)
+		for _, v := range edbInfoList {
+			v.ConvertToResp()
+			v.EdbNameAlias = v.EdbName
+			v.HaveOperaAuth = true
+			edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+		}
+
+		tmpEdbList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标失败,Err:" + err.Error()
+			return
+		}
+		edbInfoMap := make(map[int]*data_manage.EdbInfo)
+		for _, v := range tmpEdbList {
+			edbInfoMap[v.EdbInfoId] = v
+		}
+
+		for _, v := range edbInfoList {
+			tmpEdbInfo, ok := edbInfoMap[v.EdbInfoId]
+			if !ok {
+				continue
+			}
+			v.IsJoinPermission = tmpEdbInfo.IsJoinPermission
+		}
+	}
+
+	for i := 0; i < edbInfoListLen; i++ {
+		for j := 0; j < edbInfoListLen; j++ {
+			if (edbInfoList[i].EdbNameAlias == edbInfoList[j].EdbNameAlias) &&
+				(edbInfoList[i].EdbInfoId != edbInfoList[j].EdbInfoId) &&
+				!(strings.Contains(edbInfoList[i].EdbName, edbInfoList[i].SourceName)) {
+				edbInfoList[i].EdbName = edbInfoList[i].EdbName + "(" + edbInfoList[i].SourceName + ")"
+			}
+		}
+	}
+
+	resp := data_manage.EdbInfoFilterDataResp{
+		List: edbInfoList,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// getSearchPar
+// @Description: 获取查询参数
+// @author: Roc
+// @datetime 2024-12-05 14:13:25
+// @param req request.SearchPublicEdbReq
+// @return keyword string
+// @return searchEdbPublicList []int
+// @return sourceList []int
+// @return classifyIdList []int
+// @return edbTypeList []int
+// @return edbInfoType int
+// @return edbAuth int
+// @return sortMap map[string]string
+func getSearchPar(req request.SearchPublicEdbReq) (keyword string, searchEdbPublicList, sourceList, classifyIdList, edbTypeList []int, edbInfoType, edbAuth int, sortMap map[string]string) {
+	keyword = req.Keyword
+	keyword = strings.TrimSpace(keyword) //移除字符串首尾空格
+
+	//指标来源
+	sourceList = req.SourceList
+
+	// 选择的分类
+	classifyIdList = req.ClassifyIdList
+
+	// 指标公开状态:1:未公开,2:已提交;3:已公开。可多选,默认是未公开
+	edbPublicList := req.EdbPublicList
+	if len(edbPublicList) <= 0 {
+		edbPublicList = []int{1}
+	}
+
+	edbInfoType = 0        // 普通指标
+	edbTypeList = []int{2} // 普通指标中的计算指标
+	edbAuth = 1            // 选择范围是:只有我的指标
+
+	searchEdbPublicList = make([]int, 0) // 0:全部,1:未公开,2:已提交;3:已公开
+	if len(edbPublicList) > 0 && !utils.InArrayByInt(edbPublicList, 0) {
+		// 不含全部
+		for _, v := range edbPublicList {
+			switch v {
+			case 1: // 未公开
+				searchEdbPublicList = append(searchEdbPublicList, utils.EdbPublicDefault)
+			case 2: // 已提交
+				searchEdbPublicList = append(searchEdbPublicList, utils.EdbPublicCommit, utils.EdbPublicReject)
+			case 3: // 已公开
+				searchEdbPublicList = append(searchEdbPublicList, utils.EdbPublicSuccess)
+
+			}
+		}
+	} else {
+		searchEdbPublicList = []int{0, 1, 2, 3}
+	}
+
+	sortMap = make(map[string]string)
+	// 如果没有搜索关键词,则默认根据指标编码倒序排序
+	if keyword == `` {
+		sortMap["EdbInfoId"] = `desc`
+	}
+
+	return
+
+}
+
+// getAllEdbInfoListByPublic
+// @Description: 获取所有的指标列表
+// @author: Roc
+// @datetime 2024-12-04 15:43:14
+// @param req request.SetEdbChartPermissionReq
+// @param userId int
+// @return edbInfoIdList []*data_manage.EdbInfoList
+// @return err error
+func getAllEdbInfoListByPublic(req request.AllSearchPublicEdbReq, userId int) (edbInfoList []*data_manage.EdbInfoList, err error) {
+	// 获取查询参数
+	keyword, searchEdbPublicList, sourceList, edbClassifyIdList, edbTypeList, edbInfoType, edbAuth, sortMap := getSearchPar(req.SearchPublicEdbReq)
+
+	_, edbInfoList, err = getAllEdbInfoDataByPublic(keyword, 1, searchEdbPublicList, sourceList, edbClassifyIdList, edbTypeList, edbInfoType, edbAuth, userId, sortMap)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// getAllEdbInfoDataByShared
+// @Description: 获取所有的指标列表(设置公开的时候)
+// @author: Roc
+// @datetime 2024-12-04 15:27:53
+// @param keyword string
+// @param currPage int
+// @param edbShare int
+// @param sourceList []int
+// @param classifyIdList []int
+// @param edbTypeList []int
+// @param edbInfoType int
+// @param edbAuth int
+// @param sysUserId int
+// @param sortMap map[string]string
+// @return total int64
+// @return list []*data_manage.EdbInfoList
+// @return err error
+func getAllEdbInfoDataByPublic(keyword string, currPage int, searchEdbPublicList, sourceList, classifyIdList, edbTypeList []int, edbInfoType, edbAuth, sysUserId int, sortMap map[string]string) (total int64, list []*data_manage.EdbInfoList, err error) {
+	// 每页获取数据的数量
+	pageSize := 5000
+	var startSize int
+	if currPage <= 0 {
+		currPage = 1
+	}
+	startSize = paging.StartIndex(currPage, pageSize)
+
+	total, list, err = elastic.SearchEdbInfoDataByPublic(keyword, startSize, pageSize, searchEdbPublicList, sourceList, classifyIdList, edbTypeList, edbInfoType, edbAuth, sysUserId, sortMap)
+	if err != nil {
+		return
+	}
+
+	page := paging.GetPaging(currPage, pageSize, int(total))
+	if !page.IsEnd {
+		_, nextList, tmpErr := getAllEdbInfoDataByPublic(keyword, page.NextIndex, searchEdbPublicList, sourceList, classifyIdList, edbTypeList, edbInfoType, edbAuth, sysUserId, sortMap)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		list = append(list, nextList...)
+	}
+
+	return
+}

+ 1191 - 0
controllers/data_manage/edb_public_classify.go

@@ -0,0 +1,1191 @@
+package data_manage
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/controllers"
+	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/data_manage"
+	"eta_gn/eta_api/models/data_manage/request"
+	"eta_gn/eta_api/models/system"
+	"eta_gn/eta_api/services/data"
+	"eta_gn/eta_api/services/data/data_manage_permission"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"sort"
+)
+
+// EdbPublicClassifyController 数据管理-公共分类模块
+type EdbPublicClassifyController struct {
+	controllers.BaseAuthController
+}
+
+// SimpleList
+// @Title 单层公共分类列表
+// @Description 单层公共分类列表
+// @Success 200 {object} data_manage.EdbClassifyListResp
+// @router /edb_public/classify/simple [get]
+func (c *EdbPublicClassifyController) SimpleList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 公共分类来源筛选
+	// 目前只有数据加工会涉及到公共分类
+	classifyType := utils.EdbClassifyTypeCalculate
+
+	// 默认查一级公共分类和一级公共分类下的指标信息,
+	// 如果是 子级公共分类,查询该子级公共分类的下一级公共分类和指标信息
+	// 增加标识判断是文件夹还是指标列表
+	parentId, _ := c.GetInt("ParentId")
+
+	edbPublicClassifyObj := data_manage.EdbPublicClassify{}
+	rootList, err := edbPublicClassifyObj.GetEdbClassifyItemsByParentId(parentId, int8(classifyType))
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
+
+	var sortList data_manage.EdbClassifyItemList
+	if parentId > 0 {
+		// 指标类型(基础指标,预测指标)
+		edbType := 0
+		switch classifyType {
+		case utils.EdbClassifyTypeBase:
+			edbType = 1
+		case utils.EdbClassifyTypeCalculate:
+			edbType = 2
+		}
+
+		allEdbInfo, err := data_manage.GetEdbInfoByPublicClassifyId(parentId, 0, edbType)
+		if err != nil {
+			br.Msg = "获取指标数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+			return
+		}
+
+		if len(allEdbInfo) > 0 {
+			// 查询当前公共分类信息
+			for _, v := range allEdbInfo {
+				v.HaveOperaAuth = true
+				button := data.GetEdbOpButton(c.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE, v.HaveOperaAuth)
+				button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+				v.Button = button
+				v.Children = make([]*data_manage.EdbClassifyItems, 0)
+				v.ParentId = parentId
+				nodeAll = append(nodeAll, v)
+			}
+		}
+
+	}
+	if len(rootList) > 0 {
+		// 已授权公共分类id
+		permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(c.SysUser.AdminId, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权公共分类id数据失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range rootList {
+			// 公共分类设定了权限且无权限, 那么忽略掉该节点
+			if v.IsJoinPermission == 1 && !utils.InArrayByInt(permissionClassifyIdList, v.ClassifyId) {
+				continue
+			}
+
+			// 数据权限
+			v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+			// 按钮权限
+			button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+			v.Button = button
+			v.Children = make([]*data_manage.EdbClassifyItems, 0)
+			nodeAll = append(nodeAll, v)
+		}
+	}
+	if len(nodeAll) > 0 {
+		//根据sort值排序
+		sortList = nodeAll
+		sort.Sort(sortList)
+	}
+
+	language := `CN`
+	// 指标显示的语言
+	{
+		configDetail, _ := system.GetConfigDetailByCode(c.SysUser.AdminId, system.EdbLanguageVar)
+		if configDetail != nil {
+			language = configDetail.ConfigValue
+		} else {
+			configDetail, _ = system.GetDefaultConfigDetailByCode(system.EdbLanguageVar)
+			if configDetail != nil {
+				language = configDetail.ConfigValue
+			}
+		}
+	}
+
+	// 是否允许添加一级公共分类
+	canOpClassify := true
+	button := data.GetEdbClassifyOpButton(c.SysUser, 0, true)
+	if !button.AddButton {
+		canOpClassify = false
+	}
+
+	resp := new(data_manage.EdbClassifyListResp)
+	resp.AllNodes = sortList
+	resp.Language = language
+	resp.CanOpClassify = canOpClassify
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// ClassifyTree
+// @Title 多层公共分类列表树
+// @Description 多层公共分类列表树
+// @Success 200 {object} data_manage.EdbClassifyListResp
+// @router /edb_public/classify/tree [get]
+func (c *EdbPublicClassifyController) ClassifyTree() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 公共分类来源筛选
+	classifyType := utils.EdbClassifyTypeCalculate
+
+	edbPublicClassifyObj := data_manage.EdbPublicClassify{}
+	allList, err := edbPublicClassifyObj.GetAllEdbClassifyByType(int8(classifyType))
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	var sortList data_manage.EdbClassifyItemList
+	if len(allList) > 0 {
+		for k, v := range allList {
+			// 数据权限
+			v.HaveOperaAuth = true
+			// 按钮权限
+			button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+			allList[k].Button = button
+		}
+		allList = data.GetClassifyTreeRecursive(allList, 0)
+		//根据sort值排序
+		sortList = allList
+		sort.Sort(sortList)
+	}
+	language := `CN`
+
+	// 是否允许添加一级公共分类
+	canOpClassify := true
+	button := data.GetEdbClassifyOpButton(c.SysUser, 0, true)
+	if !button.AddButton {
+		canOpClassify = false
+	}
+
+	resp := new(data_manage.EdbClassifyListResp)
+	resp.AllNodes = sortList
+	resp.Language = language
+	resp.CanOpClassify = canOpClassify
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// AddEdbClassify
+// @Title 新增公共分类
+// @Description 新增公共分类接口
+// @Param	request	body data_manage.AddEdbClassifyReq true "type json string"
+// @Success 200 Ret=200 保存成功
+// @router /edb_public/classify/add [post]
+func (c *EdbPublicClassifyController) AddClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req data_manage.AddEdbClassifyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "请输入公共分类名称"
+		br.IsSendEmail = false
+		return
+	}
+	if req.ParentId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+	// 公共分类来源筛选
+	classifyType := utils.EdbClassifyTypeCalculate
+
+	//添加指标
+	_, err, errMsg := data.AddEdbPublicClassify(req.ClassifyName, req.ParentId, req.Level, uint8(classifyType), c.SysUser.AdminId, c.SysUser.RealName)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = errMsg + ";Err:" + err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+	//count, err := data_manage.GetEdbClassifyCount(req.ClassifyName, req.ParentId)
+	//if err != nil {
+	//	br.Msg = "判断名称是否已存在失败"
+	//	br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+	//	return
+	//}
+	//if count > 0 {
+	//	br.Msg = "公共分类名称已存在,请重新输入"
+	//	br.IsSendEmail = false
+	//	return
+	//}
+	////获取该层级下最大的排序数
+	//maxSort, err := data_manage.GetEdbClassifyMaxSort(req.ParentId, req.ClassifyType)
+	//
+	//classify := new(data_manage.EdbClassify)
+	//classify.ClassifyType = req.ClassifyType
+	//classify.ParentId = req.ParentId
+	//classify.ClassifyName = req.ClassifyName
+	//classify.HasData = 0
+	//classify.CreateTime = time.Now()
+	//classify.ModifyTime = time.Now()
+	//classify.SysUserId = c.SysUser.AdminId
+	//classify.SysUserRealName = c.SysUser.RealName
+	//classify.Level = req.Level + 1
+	//timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	//classify.UniqueCode = utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
+	//classify.Sort = maxSort
+	//
+	//_, err = data_manage.AddEdbClassify(classify)
+	//if err != nil {
+	//	br.Msg = "保存公共分类失败"
+	//	br.ErrMsg = "保存公共分类失败,Err:" + err.Error()
+	//	return
+	//}
+	br.Ret = 200
+	br.Msg = "新增成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// EditEdbClassify
+// @Title 修改公共分类
+// @Description 修改公共分类接口
+// @Param	request	body data_manage.EditEdbClassifyReq true "type json string"
+// @Success 200 Ret=200 修改成功
+// @router /edb_public/classify/edit [post]
+func (c *EdbPublicClassifyController) EditEdbClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req data_manage.EditEdbClassifyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "请输入公共分类名称"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.ClassifyId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data.EditEdbPublicClassify(req.ClassifyId, req.ClassifyName, c.SysUser)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = errMsg + ";Err:" + err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+	br.Ret = 200
+	br.Msg = "修改成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// DeleteEdbClassifyCheck
+// @Title 删除检测接口
+// @Description 删除检测接口
+// @Param	request	body request.PublicClassifyDeleteCheckReq true "type json string"
+// @Success 200 Ret=200 检测成功
+// @router /edb_public/classify/delete/check [post]
+func (c *EdbPublicClassifyController) DeleteClassifyCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	var req request.PublicClassifyDeleteCheckReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ClassifyId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+	deleteStatus, tipsMsg, _, tableList, err, errMsg := data.DeleteEdbPublicClassifyCheck(req.ClassifyId, c.SysUser)
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+	if c.Lang == "en" {
+		if utils.ViperConfig.InConfig(tipsMsg) {
+			tipsMsg = utils.ViperConfig.GetString(tipsMsg)
+		}
+	}
+
+	//var deleteStatus int
+	//var tipsMsg string
+	////删除公共分类
+	//if req.ClassifyId > 0 && req.EdbInfoId == 0 {
+	//	//判断公共分类下,是否含有指标
+	//	count, err := data_manage.GetEdbInfoCountByClassifyId(req.ClassifyId)
+	//	if err != nil {
+	//		br.Msg = "删除失败"
+	//		br.ErrMsg = "公共分类下是否含有指标失败,Err:" + err.Error()
+	//		return
+	//	}
+	//
+	//	if count > 0 {
+	//		deleteStatus = 1
+	//		tipsMsg = "若目录关联指标不可删除"
+	//	}
+	//}
+	//
+	//if deleteStatus != 1 && req.EdbInfoId == 0 {
+	//	classifyCount, err := data_manage.GetClassifyCountByClassifyId(req.ClassifyId)
+	//	if err != nil && !utils.IsErrNoRow(err) {
+	//		br.Msg = "删除失败"
+	//		br.ErrMsg = "公共分类下是否含有指标失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	if classifyCount > 0 {
+	//		deleteStatus = 2
+	//		tipsMsg = "确认删除当前目录及包含的子目录吗"
+	//	}
+	//}
+	//
+	////删除指标
+	//if req.EdbInfoId > 0 {
+	//	//判断指标是否用于作图,如果用于作图,则不可删除
+	//	chartCount, err := data_manage.GetChartEdbMappingCount(req.EdbInfoId)
+	//	if err != nil && !utils.IsErrNoRow(err) {
+	//		br.Msg = "删除失败"
+	//		br.ErrMsg = "判断指标是否被用于作图失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	if chartCount > 0 {
+	//		deleteStatus = 3
+	//		tipsMsg = "当前指标已用作画图,不可删除"
+	//	}
+	//	//判断指标是否用于计算
+	//	{
+	//		calculateCount, err := data_manage.GetEdbInfoCalculateMappingCount(req.EdbInfoId)
+	//		if err != nil && !utils.IsErrNoRow(err) {
+	//			br.Msg = "删除失败"
+	//			br.ErrMsg = "判断指标是否被用于计算失败,GetEdbInfoCalculateCount Err:" + err.Error()
+	//			return
+	//		}
+	//		if calculateCount > 0 {
+	//			deleteStatus = 4
+	//			tipsMsg = "当前指标已用作,指标运算,不可删除"
+	//		}
+	//	}
+	//}
+
+	resp := new(data_manage.ClassifyDeleteCheckResp)
+	resp.DeleteStatus = deleteStatus
+	resp.TipsMsg = tipsMsg
+	resp.TableList = tableList
+	br.Ret = 200
+	br.Msg = "检测成功"
+	br.Success = true
+	br.Data = resp
+}
+
+// DeleteEdbClassify
+// @Title 删除公共分类/指标
+// @Description 删除公共分类/指标接口
+// @Param	request	body request.PublicClassifyDeleteCheckReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /edb_public/classify/delete [post]
+func (c *EdbPublicClassifyController) DeleteClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.PublicClassifyDeleteCheckReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ClassifyId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	nextItem, _, err, errMsg := data.DeleteEdbPublicClassify(req.ClassifyId, sysUser, string(c.Ctx.Input.RequestBody), c.Ctx.Input.URI())
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+
+	resp := data_manage.AddEdbInfoResp{}
+	if nextItem != nil {
+		resp = data_manage.AddEdbInfoResp{
+			EdbInfoId:  nextItem.EdbInfoId,
+			UniqueCode: nextItem.UniqueCode,
+		}
+	}
+
+	br.Ret = 200
+	br.Msg = "删除成功"
+	br.Success = true
+	br.IsAddLog = true
+	br.Data = resp
+}
+
+// ListV2
+// @Title 公共分类列表
+// @Description 公共分类列表接口
+// @Success 200 {object} data_manage.EdbClassifyListResp
+// @router /edb_public/classify/list [get]
+func (c *EdbPublicClassifyController) ListV2() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 公共分类来源筛选
+	classifyType, _ := c.GetInt("ClassifyType", utils.EdbClassifyTypeBase) // 默认指标库的
+	if classifyType != utils.EdbClassifyTypeBase && classifyType != utils.EdbClassifyTypeCalculate {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("指标公共分类类型有误, ClassifyType: %d", classifyType)
+		return
+	}
+	edbType := utils.EdbTypeBase
+	if classifyType == utils.EdbClassifyTypeCalculate {
+		edbType = utils.EdbTypeCalculate
+	}
+
+	rootList, err := data_manage.GetEdbClassifyByParentId(0, int8(classifyType), c.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	//classifyAll, err := data_manage.GetEdbClassifyAll()
+	classifyAll, err := data_manage.GetChildEdbClassifyByClassifyType(classifyType, c.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	// 公共分类map
+	classifyMap := make(map[int]*data_manage.EdbClassifyItems)
+	for _, v := range classifyAll {
+		classifyMap[v.ClassifyId] = v
+	}
+
+	// 已授权公共分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(c.SysUser.AdminId, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权公共分类id数据失败,Err:" + err.Error()
+		return
+	}
+
+	// 获取当前账号的不可见指标
+	obj := data_manage.EdbInfoNoPermissionAdmin{}
+	confList, err := obj.GetAllListByAdminId(c.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+		return
+	}
+	noPermissionEdbInfoIdMap := make(map[int]bool)
+	for _, v := range confList {
+		noPermissionEdbInfoIdMap[v.EdbInfoId] = true
+	}
+	//allEdbInfo, err := data_manage.GetEdbInfoAll(utils.EDB_INFO_TYPE)
+	allEdbInfo, err := data_manage.GetEdbInfoByTypes(utils.EDB_INFO_TYPE, edbType)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	edbInfoMap := make(map[int][]*data_manage.EdbClassifyItems)
+	if len(allEdbInfo) > 0 {
+		// 获取所有有权限的指标和公共分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(c.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和公共分类失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range allEdbInfo {
+			// 如果指标不可见,那么就不返回该指标
+			if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
+				continue
+			}
+			// 数据权限
+			if classifyInfo, ok := classifyMap[v.ClassifyId]; ok {
+				v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+
+			button := data.GetEdbOpButton(c.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE, v.HaveOperaAuth)
+			button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+			v.Button = button
+			edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+		}
+	}
+	rootChildMap := make(map[int][]*data_manage.EdbClassifyItems)
+	for _, v := range classifyAll {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+		v.Button = button
+
+		rootChildMap[v.ParentId] = append(rootChildMap[v.ParentId], v)
+		if existItems, ok := edbInfoMap[v.ClassifyId]; ok {
+			v.Children = existItems
+		} else {
+			items := make([]*data_manage.EdbClassifyItems, 0)
+			v.Children = items
+		}
+	}
+	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
+	for _, v := range rootList {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+		v.Button = button
+
+		if existItems, ok := rootChildMap[v.ClassifyId]; ok {
+			v.Children = existItems
+		} else {
+			items := make([]*data_manage.EdbClassifyItems, 0)
+			v.Children = items
+		}
+		nodeAll = append(nodeAll, v)
+	}
+	resp := new(data_manage.EdbClassifyListResp)
+	resp.AllNodes = nodeAll
+	resp.CanOpClassify = true
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// Items
+// @Title 获取所有公共分类接口-不包含指标
+// @Description 获取所有公共分类接口-不包含指标
+// @Success 200 {object} data_manage.EdbClassifyListResp
+// @router /edb_public/classify/items [get]
+func (c *EdbPublicClassifyController) Items() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 公共分类来源筛选
+	classifyType, _ := c.GetInt("ClassifyType", utils.EdbClassifyTypeBase) // 默认指标库的
+	if classifyType != utils.EdbClassifyTypeBase && classifyType != utils.EdbClassifyTypeCalculate {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("指标公共分类类型有误, ClassifyType: %d", classifyType)
+		return
+	}
+	//edbType := utils.EdbTypeBase
+	//if classifyType == utils.EdbClassifyTypeCalculate {
+	//	edbType = utils.EdbTypeCalculate
+	//}
+
+	rootList, err := data_manage.GetEdbClassifyByParentId(0, int8(classifyType), c.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	//classifyAll, err := data_manage.GetEdbClassifyAll()
+	classifyAll, err := data_manage.GetChildEdbClassifyByClassifyType(classifyType, c.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
+	for k := range rootList {
+		rootNode := rootList[k]
+		data.EdbClassifyItemsMakeTree(classifyAll, rootNode)
+		nodeAll = append(nodeAll, rootNode)
+	}
+	resp := new(data_manage.EdbClassifyListResp)
+	resp.AllNodes = nodeAll
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// EdbClassifyMove
+// @Title 公共分类移动接口
+// @Description 公共分类移动接口
+// @Success 200 {object} data_manage.MoveEdbClassifyReq
+// @router /edb_classify/move [post]
+func (c *EdbPublicClassifyController) EdbClassifyMove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var req data_manage.MoveEdbClassifyReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ClassifyId <= 0 && req.EdbInfoId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "请选择拖动目标,公共分类目录或者指标"
+		return
+	}
+
+	// 公共分类来源筛选
+	classifyType := req.ClassifyType // 默认指标库的
+	if classifyType != utils.EdbClassifyTypeBase && classifyType != utils.EdbClassifyTypeCalculate {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("指标公共分类类型有误, ClassifyType: %d", classifyType)
+		return
+	}
+
+	err, errMsg := data.MoveEdbClassify(req, sysUser, uint8(classifyType))
+	if errMsg != `` {
+		br.Msg = errMsg
+		br.ErrMsg = errMsg
+		if err != nil {
+			br.ErrMsg = err.Error()
+		} else {
+			br.IsSendEmail = false
+		}
+		return
+	}
+	////判断公共分类是否存在
+	//edbClassifyInfo, err := data_manage.GetEdbClassifyById(req.ClassifyId)
+	//if err != nil {
+	//	br.Msg = "移动失败"
+	//	br.ErrMsg = "获取公共分类信息失败,Err:" + err.Error()
+	//	return
+	//}
+	//updateCol := make([]string, 0)
+	//
+	////判断上级id是否一致,如果不一致的话,那么需要移动该公共分类层级
+	//if edbClassifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 {
+	//	parentEdbClassifyInfo, err := data_manage.GetEdbClassifyById(req.ParentClassifyId)
+	//	if err != nil {
+	//		br.Msg = "移动失败"
+	//		br.ErrMsg = "获取上级公共分类信息失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	edbClassifyInfo.ParentId = parentEdbClassifyInfo.ClassifyId
+	//	edbClassifyInfo.Level = parentEdbClassifyInfo.Level + 1
+	//	edbClassifyInfo.ModifyTime = time.Now()
+	//	updateCol = append(updateCol, "ParentId", "Level", "ModifyTime")
+	//}
+	//
+	////如果有传入 上一个兄弟节点公共分类id
+	//if req.PrevClassifyId > 0 {
+	//	prevClassify, err := data_manage.GetEdbClassifyById(req.PrevClassifyId)
+	//	if err != nil {
+	//		br.Msg = "移动失败"
+	//		br.ErrMsg = "获取上一个兄弟节点公共分类信息失败,Err:" + err.Error()
+	//		return
+	//	}
+	//
+	//	//如果是移动在两个兄弟节点之间
+	//	if req.NextClassifyId > 0 {
+	//		//下一个兄弟节点
+	//		nextClassify, err := data_manage.GetEdbClassifyById(req.NextClassifyId)
+	//		if err != nil {
+	//			br.Msg = "移动失败"
+	//			br.ErrMsg = "获取下一个兄弟节点公共分类信息失败,Err:" + err.Error()
+	//			return
+	//		}
+	//		//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+	//		if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == edbClassifyInfo.Sort {
+	//			//变更兄弟节点的排序
+	//			updateSortStr := `sort + 2`
+	//			_ = data_manage.UpdateEdbClassifySortByParentId(prevClassify.ParentId, prevClassify.ClassifyId, prevClassify.Sort, updateSortStr)
+	//		} else {
+	//			//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+	//			if nextClassify.Sort-prevClassify.Sort == 1 {
+	//				//变更兄弟节点的排序
+	//				updateSortStr := `sort + 1`
+	//				_ = data_manage.UpdateEdbClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
+	//			}
+	//		}
+	//	}
+	//
+	//	edbClassifyInfo.Sort = prevClassify.Sort + 1
+	//	edbClassifyInfo.ModifyTime = time.Now()
+	//	updateCol = append(updateCol, "Sort", "ModifyTime")
+	//} else {
+	//	firstClassify, err := data_manage.GetFirstEdbClassifyByParentId(edbClassifyInfo.ParentId)
+	//	if err != nil && !utils.IsErrNoRow(err) {
+	//		br.Msg = "移动失败"
+	//		br.ErrMsg = "获取获取当前父级公共分类下的排序第一条的公共分类信息失败,Err:" + err.Error()
+	//		return
+	//	}
+	//
+	//	//如果该公共分类下存在其他公共分类,且第一个其他公共分类的排序等于0,那么需要调整排序
+	//	if firstClassify != nil && firstClassify.ChartClassifyId > 0 && firstClassify.Sort == 0 {
+	//		updateSortStr := ` sort + 1 `
+	//		_ = data_manage.UpdateEdbClassifySortByParentId(firstClassify.ParentId, firstClassify.ClassifyId-1, 0, updateSortStr)
+	//	}
+	//
+	//	edbClassifyInfo.Sort = 0 //那就是排在第一位
+	//	edbClassifyInfo.ModifyTime = time.Now()
+	//	updateCol = append(updateCol, "Sort", "ModifyTime")
+	//}
+	//
+	////更新
+	//if len(updateCol) > 0 {
+	//	err = edbClassifyInfo.Update(updateCol)
+	//	if err != nil {
+	//		br.Msg = "移动失败"
+	//		br.ErrMsg = "修改失败,Err:" + err.Error()
+	//		return
+	//	}
+	//}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "移动成功"
+}
+
+// ItemsV2
+// @Title 公共分类列表
+// @Description 公共分类列表接口
+// @Success 200 {object} data_manage.EdbClassifyListResp
+// @router /edb_public/classify/items/v2 [get]
+func (c *EdbPublicClassifyController) ItemsV2() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 公共分类来源筛选
+	classifyType, _ := c.GetInt("ClassifyType", utils.EdbClassifyTypeBase) // 默认指标库的
+	if classifyType != utils.EdbClassifyTypeBase && classifyType != utils.EdbClassifyTypeCalculate {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("指标公共分类类型有误, ClassifyType: %d", classifyType)
+		return
+	}
+	//edbType := utils.EdbTypeBase
+	//if classifyType == utils.EdbClassifyTypeCalculate {
+	//	edbType = utils.EdbTypeCalculate
+	//}
+
+	rootList, err := data_manage.GetEdbClassifyByParentId(0, int8(classifyType), c.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	//classifyAll, err := data_manage.GetEdbClassifyAll()
+	classifyAll, err := data_manage.GetChildEdbClassifyByClassifyType(classifyType, c.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	// 已授权公共分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(c.SysUser.AdminId, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权公共分类id数据失败,Err:" + err.Error()
+		return
+	}
+	//allEdbInfo, err := data_manage.GetEdbInfoAll(0)
+	//if err != nil && !utils.IsErrNoRow(err) {
+	//	br.Msg = "获取失败"
+	//	br.ErrMsg = "获取数据失败,Err:" + err.Error()
+	//	return
+	//}
+	//edbInfoMap := make(map[int][]*data_manage.EdbClassifyItems)
+	//for _, v := range allEdbInfo {
+	//	button := data.GetEdbOpButton(c.SysUser, v.SysUserId)
+	//	button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+	//	v.Button = button
+	//	edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+	//}
+	rootChildMap := make(map[int][]*data_manage.EdbClassifyItems)
+	for _, v := range classifyAll {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+		v.Button = button
+
+		rootChildMap[v.ParentId] = append(rootChildMap[v.ParentId], v)
+		//if existItems, ok := edbInfoMap[v.ClassifyId]; ok {
+		//	v.Children = existItems
+		//} else {
+		//	items := make([]*data_manage.EdbClassifyItems, 0)
+		//	v.Children = items
+		//}
+	}
+	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
+	for _, v := range rootList {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+		v.Button = button
+
+		if existItems, ok := rootChildMap[v.ClassifyId]; ok {
+			v.Children = existItems
+		} else {
+			items := make([]*data_manage.EdbClassifyItems, 0)
+			v.Children = items
+		}
+		nodeAll = append(nodeAll, v)
+	}
+	language := `CN`
+	// 指标显示的语言
+	{
+		configDetail, _ := system.GetConfigDetailByCode(c.SysUser.AdminId, system.EdbLanguageVar)
+		if configDetail != nil {
+			language = configDetail.ConfigValue
+		} else {
+			configDetail, _ = system.GetDefaultConfigDetailByCode(system.EdbLanguageVar)
+			if configDetail != nil {
+				language = configDetail.ConfigValue
+			}
+		}
+	}
+
+	// 是否允许添加一级公共分类
+	canOpClassify := true
+	//button := data.GetEdbClassifyOpButton(c.SysUser, 0)
+	//if !button.AddButton {
+	//	canOpClassify = false
+	//}
+
+	resp := data_manage.EdbClassifyListResp{
+		AllNodes:      nodeAll,
+		CanOpClassify: canOpClassify,
+		Language:      language,
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// ClassifyEdbInfoList
+// @Title 获取公共分类下指标接口
+// @Description 获取公共分类下指标接口
+// @Param   ClassifyId   query   int  true       "公共分类id"
+// @Success 200 {object} data_manage.EdbClassifyListResp
+// @router /edb_public/classify/edb_info/list [get]
+func (c *EdbPublicClassifyController) ClassifyEdbInfoList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+
+	classifyId, _ := c.GetInt("ClassifyId")
+	if classifyId <= 0 {
+		br.Msg = "参数错误,请刷新页面"
+		return
+	}
+
+	classifyInfo, err := data_manage.GetEdbClassifyById(classifyId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取公共分类信息失败,Err:" + err.Error()
+		return
+	}
+
+	// 获取当前账号的不可见指标
+	obj := data_manage.EdbInfoNoPermissionAdmin{}
+	confList, err := obj.GetAllListByAdminId(c.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+		return
+	}
+	noPermissionEdbInfoIdMap := make(map[int]bool)
+	for _, v := range confList {
+		noPermissionEdbInfoIdMap[v.EdbInfoId] = true
+	}
+
+	// 指标类型(基础指标,预测指标)
+	edbType := 0
+	switch classifyInfo.ClassifyType {
+	case utils.EdbClassifyTypeBase:
+		edbType = 1
+	case utils.EdbClassifyTypeCalculate:
+		edbType = 2
+	}
+	// 无权限指标 和 无权限指标公共分类id
+	noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, err := data_manage_permission.GetUserAllEdbAndClassifyNoPermissionList(c.SysUser.AdminId, utils.EDB_INFO_TYPE, edbType)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取不可见指标配置数据失败,Err:" + err.Error()
+		return
+	}
+
+	allEdbInfo, err := data_manage.GetEdbInfoByClassifyId(classifyId, utils.EDB_INFO_TYPE, edbType, 0, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	list := make([]*data_manage.EdbClassifyItems, 0)
+
+	if len(allEdbInfo) > 0 {
+		// 获取所有有权限的指标和公共分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(c.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和公共分类失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range allEdbInfo {
+			// 如果指标不可见,那么就不返回该指标
+			if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
+				continue
+			}
+			v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			button := data.GetEdbOpButton(c.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE, v.HaveOperaAuth)
+			button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+			v.Button = button
+
+			list = append(list, v)
+		}
+	}
+
+	resp := new(data_manage.ClassifyEdbInfoListResp)
+	resp.EdbInfoList = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// ItemsV3
+// @Title 公共分类列表
+// @Description 公共分类列表接口
+// @Success 200 {object} data_manage.EdbClassifyListResp
+// @router /edb_public/classify/items/v3 [get]
+func (c *EdbPublicClassifyController) ItemsV3() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	// 公共分类来源筛选
+	classifyType, _ := c.GetInt("ClassifyType", utils.EdbClassifyTypeBase) // 默认指标库的
+	if classifyType != utils.EdbClassifyTypeBase && classifyType != utils.EdbClassifyTypeCalculate {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("指标公共分类类型有误, ClassifyType: %d", classifyType)
+		return
+	}
+	//edbType := utils.EdbTypeBase
+	//if classifyType == utils.EdbClassifyTypeCalculate {
+	//	edbType = utils.EdbTypeCalculate
+	//}
+
+	// TODO:9级改造
+	rootList, err := data_manage.GetEdbClassifyByParentId(0, int8(classifyType), c.SysUser.AdminId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	rootTwoList, err := data_manage.GetEdbClassifyByParentIdTwo(int8(classifyType))
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	classifyAll, err := data_manage.GetEdbClassifyAllV2(int8(classifyType))
+	if err != nil && !utils.IsErrNoRow(err) {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	// 已授权公共分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(c.SysUser.AdminId, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权公共分类id数据失败,Err:" + err.Error()
+		return
+	}
+
+	rootTwoMap := make(map[int][]*data_manage.EdbClassifyItems)
+	for _, v := range rootTwoList {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+		v.Button = button
+
+		rootTwoMap[v.ParentId] = append(rootTwoMap[v.ParentId], v)
+	}
+	rootTwoChildMap := make(map[int][]*data_manage.EdbClassifyItems)
+	for _, v := range classifyAll {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+		v.Button = button
+		if v.Level == 3 {
+			rootTwoChildMap[v.ParentId] = append(rootTwoChildMap[v.ParentId], v)
+		}
+	}
+
+	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
+	for _, v := range rootList {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+		v.Button = button
+
+		if existItems, ok := rootTwoMap[v.ClassifyId]; ok {
+			v.Children = existItems
+			for _, item := range existItems {
+				// 数据权限
+				v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+				// 按钮权限
+				button := data.GetEdbClassifyOpButton(c.SysUser, item.SysUserId, v.HaveOperaAuth)
+				item.Button = button
+
+				if existItems, ok := rootTwoChildMap[item.ClassifyId]; ok {
+					for _, existItem := range existItems {
+						// 数据权限
+						v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+						// 按钮权限
+						button := data.GetEdbClassifyOpButton(c.SysUser, v.SysUserId, v.HaveOperaAuth)
+						button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+						existItem.Button = button
+					}
+					item.Children = existItems
+				} else {
+					items := make([]*data_manage.EdbClassifyItems, 0)
+					item.Children = items
+				}
+			}
+		} else {
+			items := make([]*data_manage.EdbClassifyItems, 0)
+			v.Children = items
+		}
+		nodeAll = append(nodeAll, v)
+	}
+	language := `CN`
+	// 指标显示的语言
+	{
+		configDetail, _ := system.GetConfigDetailByCode(c.SysUser.AdminId, system.EdbLanguageVar)
+		if configDetail != nil {
+			language = configDetail.ConfigValue
+		} else {
+			configDetail, _ = system.GetDefaultConfigDetailByCode(system.EdbLanguageVar)
+			if configDetail != nil {
+				language = configDetail.ConfigValue
+			}
+		}
+	}
+
+	// 是否允许添加一级公共分类
+	canOpClassify := true
+	button := data.GetEdbClassifyOpButton(c.SysUser, 0, true)
+	if !button.AddButton {
+		canOpClassify = false
+	}
+
+	resp := new(data_manage.EdbClassifyListResp)
+	resp.AllNodes = nodeAll
+	resp.Language = language
+	resp.CanOpClassify = canOpClassify
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 4 - 4
controllers/data_manage/future_good/future_good_chart_classify.go

@@ -66,14 +66,14 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 		return
 	}
 
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_FUTURE_GOOD, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT})
+	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_FUTURE_GOOD, utils.CHART_SOURCE_FUTURE_GOOD_PROFIT}, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -107,7 +107,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD, adminInfo.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
@@ -149,7 +149,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyItems() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_FUTURE_GOOD, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()

+ 4 - 4
controllers/data_manage/line_equation/line_chart_classify.go

@@ -63,14 +63,14 @@ func (this *LineEquationChartClassifyController) ChartClassifyList() {
 
 	source := utils.CHART_SOURCE_LINE_EQUATION
 
-	rootList, err := data_manage.GetChartClassifyByParentId(0, source)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, source, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	allChartInfo, err := data_manage.GetChartInfoAll([]int{source})
+	allChartInfo, err := data_manage.GetChartInfoAll([]int{source}, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -112,7 +112,7 @@ func (this *LineEquationChartClassifyController) ChartClassifyList() {
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	// 获取所有的分类
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_EQUATION)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_EQUATION, adminInfo.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
@@ -154,7 +154,7 @@ func (this *LineEquationChartClassifyController) ChartClassifyItems() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_EQUATION)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_EQUATION, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()

+ 4 - 4
controllers/data_manage/line_feature/classify.go

@@ -63,14 +63,14 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyList() {
 
 	source := utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION
 
-	rootList, err := data_manage.GetChartClassifyByParentId(0, source)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, source, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY})
+	allChartInfo, err := data_manage.GetChartInfoAll([]int{utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY}, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
@@ -112,7 +112,7 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyList() {
 // getChartClassifyListForMe 获取我创建的图表
 func getChartClassifyListForMe(adminInfo system.Admin, resp *data_manage.ChartClassifyListResp) (errMsg string, err error) {
 	// 获取所有的分类
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, adminInfo.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		errMsg = "获取失败"
 		return
@@ -154,7 +154,7 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyItems() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()

+ 1 - 1
controllers/data_manage/predict_edb_info.go

@@ -1104,7 +1104,7 @@ func (this *PredictEdbInfoController) FilterByEs() {
 		newKeyWord := strings.Split(keyWord, " ")
 		keyWordArr = append(keyWordArr, newKeyWord...)
 
-		total, edbInfoList, err = elastic.SearchEdbInfoData(keyWord, startSize, pageSize, filterSource, source, frequency, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, []int{}, []int{1, 2}, 1, 0, this.SysUser.AdminId)
+		total, edbInfoList, err = elastic.SearchEdbInfoData(keyWord, startSize, pageSize, filterSource, source, frequency, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, []int{}, []int{1, 2}, 1, 0, this.SysUser.AdminId, map[string]string{})
 
 		isEs = true
 	} else {

+ 2 - 2
controllers/data_manage/range_analysis/chart_classify.go

@@ -59,7 +59,7 @@ func (this *RangeChartClassifyController) ChartClassifyList() {
 
 	nodeAll := make([]*data_manage.ChartClassifyItems, 0)
 	// 查询分类节点
-	rootList, err := data_manage.GetChartClassifyByParentId(parentId, utils.CHART_SOURCE_RANGE_ANALYSIS)
+	rootList, err := data_manage.GetChartClassifyByParentId(parentId, utils.CHART_SOURCE_RANGE_ANALYSIS, this.SysUser.AdminId)
 	if err != nil && !utils.IsErrNoRow(err) {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
@@ -153,7 +153,7 @@ func (this *RangeChartClassifyController) ChartClassifyItems() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_RANGE_ANALYSIS)
+	rootList, err := data_manage.GetChartClassifyByParentId(0, utils.CHART_SOURCE_RANGE_ANALYSIS, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()

+ 349 - 18
controllers/fix.go

@@ -16,24 +16,36 @@ import (
 // @author: Roc
 // @datetime 2024-12-02 09:29:56
 func init() {
-	// ### 1、先修复分类完整路径
-	//initFixClassifyPath()
+	// ### 1、先修复指标分类完整路径
+	//initFixEdbClassifyPath()
 
 	// ### 2、再修复个人分类、删除不存在指标的分类
 	// ### 2.1 数据加工
-	//initFixSelfClassify(utils.EdbClassifyTypeCalculate)
+	//initFixSelfEdbClassify(utils.EdbClassifyTypeCalculate)
 	//
 	//// ### 2.2 衍生指标
-	//initFixSelfClassify(utils.EdbClassifyTypePredict)
+	//initFixSelfEdbClassify(utils.EdbClassifyTypePredict)
 	//
+
+	// 开始图表数据了
+
+	// ### 3、修复图表分类完整路径
+	//initFixChartClassifyPath()
+
+	// ### 4、修复图表分类完整路径
+	//initFixSelfChartClassify()
+
+	// ### 5、修复ES数据
+	//initEs()
+
 	//fmt.Println("修复完成")
 }
 
-// initFixClassifyPath
+// initFixEdbClassifyPath
 // @Description: 修复分类完整路径
 // @author: Roc
 // @datetime 2024-11-26 15:40:57
-func initFixClassifyPath() {
+func initFixEdbClassifyPath() {
 	allList := make([]*data_manage.EdbClassifyItems, 0)
 	allList, e := data_manage.GetEdbClassifyByClassifyTypes([]int{utils.EdbClassifyTypeBase, utils.EdbClassifyTypePredict, utils.EdbClassifyTypeCalculate}, 0)
 	if e != nil {
@@ -49,12 +61,12 @@ func initFixClassifyPath() {
 	sort.Sort(sortList)
 
 	for _, v := range sortList {
-		updatePath(v, "", "")
+		updateEdbPath(v, "", "")
 	}
 	fmt.Println("修复分类路径完成")
 }
 
-func updatePath(item *data_manage.EdbClassifyItems, classifyNamePath, classifyIdPath string) {
+func updateEdbPath(item *data_manage.EdbClassifyItems, classifyNamePath, classifyIdPath string) {
 	if classifyNamePath == `` {
 		classifyNamePath = item.ClassifyName
 		classifyIdPath = fmt.Sprint(item.ClassifyId)
@@ -68,16 +80,16 @@ func updatePath(item *data_manage.EdbClassifyItems, classifyNamePath, classifyId
 	}
 	if item.Children != nil {
 		for _, v := range item.Children {
-			updatePath(v, classifyNamePath, classifyIdPath)
+			updateEdbPath(v, classifyNamePath, classifyIdPath)
 		}
 	}
 }
 
-// initFixUserClassify
+// initFixSelfEdbClassify
 // @Description: initFixUserClassify
 // @author: Roc
 // @datetime 2024-11-29 16:57:54
-func initFixSelfClassify(classifyType int) {
+func initFixSelfEdbClassify(classifyType int) {
 	// 指标数据明细
 	condition := ` AND edb_info_type = 0 and edb_type = 2 `
 	if classifyType == utils.EdbClassifyTypePredict {
@@ -161,7 +173,7 @@ func initFixSelfClassify(classifyType int) {
 	for userId, sysUserName := range edbUserMap {
 		classifyRelationMap := make(map[int]int)
 		for _, v := range nodeAll {
-			createNewClassify(userId, 0, 0, 0, sysUserName, ``, ``, v, classifyRelationMap)
+			createNewEdbClassify(userId, 0, 0, 0, sysUserName, ``, ``, v, classifyRelationMap)
 		}
 		userClassifyIdMap[userId] = classifyRelationMap
 	}
@@ -189,11 +201,11 @@ func initFixSelfClassify(classifyType int) {
 	}
 
 	// ##### 3、开始删除没有指标的分类
-	deleteNullClassify(classifyType)
+	deleteNullEdbClassify(classifyType)
 	return
 }
 
-func deleteNullClassify(classifyType int) {
+func deleteNullEdbClassify(classifyType int) {
 	// 指标列表数据
 	condition := ` AND edb_info_type = 0 and edb_type = 2 `
 	if classifyType == utils.EdbClassifyTypePredict {
@@ -269,7 +281,7 @@ func deleteNullClassify(classifyType int) {
 	}
 }
 
-// createNewClassify
+// createNewEdbClassify
 // @Description: 创建分类
 // @author: Roc
 // @datetime 2024-11-29 17:57:47
@@ -282,7 +294,7 @@ func deleteNullClassify(classifyType int) {
 // @param parentClassifyIdPath string
 // @param node *data_manage.EdbClassifyItems
 // @param classifyRelationMap map[int]int
-func createNewClassify(userId, parentId, rootId, level int, sysUserName, parentClassifyNamePath, parentClassifyIdPath string, node *data_manage.EdbClassifyItems, classifyRelationMap map[int]int) {
+func createNewEdbClassify(userId, parentId, rootId, level int, sysUserName, parentClassifyNamePath, parentClassifyIdPath string, node *data_manage.EdbClassifyItems, classifyRelationMap map[int]int) {
 	var classifyNamePath, classifyIdPath string
 
 	if parentId > 0 {
@@ -339,12 +351,331 @@ func createNewClassify(userId, parentId, rootId, level int, sysUserName, parentC
 		return
 	}
 	for _, child := range node.Children {
-		createNewClassify(userId, classifyInfo.ClassifyId, rootId, level, sysUserName, classifyNamePath, classifyInfo.ClassifyIdPath, child, classifyRelationMap)
+		createNewEdbClassify(userId, classifyInfo.ClassifyId, rootId, level, sysUserName, classifyNamePath, classifyInfo.ClassifyIdPath, child, classifyRelationMap)
 	}
 
 	return
 }
 
+// initFixChartClassifyPath
+// @Description: 修复图表分类完整路径
+// @author: Roc
+// @datetime 2024-11-26 15:40:57
+func initFixChartClassifyPath() {
+	fmt.Println("开始修复图表分类路径,请稍等...")
+	allList := make([]*data_manage.ChartClassifyItems, 0)
+	allList, e := data_manage.GetAllChartClassify()
+	if e != nil {
+		fmt.Println("获取分类失败", e)
+		return
+	}
+
+	allList = data.GetChartClassifyTreeRecursive(allList, 0)
+	//根据sort值排序
+
+	for _, v := range allList {
+		updateChartPath(v, "", "")
+	}
+	fmt.Println("修复图表分类路径完成")
+}
+
+// initFixSelfChartClassify
+// @Description: 修复用户图表分类信息
+// @author: Roc
+// @datetime 2024-11-29 16:57:54
+func initFixSelfChartClassify() {
+	fmt.Println("修复用户图表分类信息开始,请稍后...")
+	// 图表数据明细
+	condition := ``
+
+	pars := make([]interface{}, 0)
+	chartList, err := data_manage.GetChartListByCondition(condition, pars, 0, 1000000)
+	if err != nil {
+		fmt.Println("查找用户图表列表数据失败", err.Error())
+		return
+	}
+
+	chartClassifyIdMap := make(map[int]bool)
+	classifyIdList := make([]int, 0)
+
+	edbUserMap := make(map[int]string)
+
+	for _, v := range chartList {
+		if _, ok := chartClassifyIdMap[v.ChartClassifyId]; !ok {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+			chartClassifyIdMap[v.ChartClassifyId] = true
+		}
+
+		edbUserMap[v.SysUserId] = v.SysUserRealName
+	}
+
+	// 获取所有图表的分类
+	classifyList, err := data_manage.GetAllChartClassify()
+	if err != nil {
+		fmt.Println("获取图表分类失败", err.Error())
+		return
+	}
+
+	hasClassifyIdStrList := make([]string, 0)
+	for _, v := range classifyList {
+		// 判断当前分类id是否加到指标中,如果加进去了,那么才处理
+		_, ok := chartClassifyIdMap[v.ChartClassifyId]
+		if !ok {
+			continue
+		}
+		hasClassifyIdStrList = append(hasClassifyIdStrList, v.ChartClassifyIdPath)
+	}
+	classifyIdStrList := strings.Split(strings.Join(hasClassifyIdStrList, ","), ",")
+	classifyIdMap := make(map[string]bool)
+	for _, v := range classifyIdStrList {
+		classifyIdMap[v] = true
+	}
+	newClassifyList := make([]*data_manage.ChartClassifyItems, 0)
+	newClassifyMap := make(map[string]bool)
+	for _, v := range classifyList {
+		classifyIdStr := fmt.Sprint(v.ChartClassifyId)
+
+		// 是否在关联指标的map里面,如果不在的话,那么就过滤
+		_, ok := classifyIdMap[classifyIdStr]
+		if !ok {
+			continue
+		}
+
+		// 是否已经加到需要关联指标分类的map里面,如果已经在了,那么也过滤
+		_, ok = newClassifyMap[classifyIdStr]
+		if ok {
+			continue
+		}
+
+		newClassifyMap[classifyIdStr] = true
+		newClassifyList = append(newClassifyList, v)
+	}
+
+	rootList, err := data_manage.GetAllChartClassifyByParentId(0)
+	nodeAll := make([]*data_manage.ChartClassifyItems, 0)
+	for k := range rootList {
+		rootNode := rootList[k]
+		data.ChartClassifyItemsMakeTreeV2(newClassifyList, rootNode)
+		nodeAll = append(nodeAll, rootNode)
+	}
+
+	// 创建新的分类
+	// [用户id][原分类id][新分类id]
+	userClassifyIdMap := make(map[int]map[int]int)
+	for userId, sysUserName := range edbUserMap {
+		classifyRelationMap := make(map[int]int)
+		for _, v := range nodeAll {
+			createNewChartClassify(userId, 0, 0, 0, sysUserName, ``, ``, v, classifyRelationMap)
+		}
+		userClassifyIdMap[userId] = classifyRelationMap
+	}
+
+	// ##### 第二步,图表数据迁移
+
+	// 指标数据迁移
+	for _, v := range chartList {
+		userClassifyMap, ok := userClassifyIdMap[v.SysUserId]
+		if !ok {
+			fmt.Println("找不到该用户所属的分类,userId:", v.SysUserId)
+			continue
+		}
+
+		newClassifyId, ok := userClassifyMap[v.ChartClassifyId]
+		if !ok {
+			fmt.Println("找不到该用户所属的图表分类,classifyId:", v.ChartClassifyId)
+			continue
+		}
+		// 开始迁移指标数据
+		err = data_manage.UpdateClassifyIdByChartInfoId(v.ChartInfoId, newClassifyId)
+		if err != nil {
+			fmt.Println("图表数据迁移失败", err.Error())
+		}
+	}
+
+	// ##### 3、开始删除没有图表的分类
+	deleteNullChartClassify()
+
+	fmt.Println("修复用户图表分类信息完成")
+	return
+}
+
+func deleteNullChartClassify() {
+	// 图表数据明细
+	condition := ``
+
+	pars := make([]interface{}, 0)
+	chartList, err := data_manage.GetChartListByCondition(condition, pars, 0, 1000000)
+	if err != nil {
+		fmt.Println("查找指标加工数据失败", err.Error())
+		return
+	}
+
+	chartClassifyIdMap := make(map[int]bool)
+	classifyIdList := make([]int, 0)
+
+	for _, v := range chartList {
+		if _, ok := chartClassifyIdMap[v.ChartClassifyId]; !ok {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+			chartClassifyIdMap[v.ChartClassifyId] = true
+		}
+	}
+
+	// 获取所有数据加工的分类
+	classifyList, err := data_manage.GetAllChartClassify()
+	if err != nil {
+		fmt.Println("获取数据加工分类失败", err.Error())
+		return
+	}
+
+	// 存在图表的分类
+	hasEdbClassifyList := make([]*data_manage.ChartClassifyItems, 0)
+	for _, v := range classifyList {
+		if _, ok := chartClassifyIdMap[v.ChartClassifyId]; ok {
+			hasEdbClassifyList = append(hasEdbClassifyList, v)
+		}
+	}
+
+	// 待删除的分类id集合
+	deleteClassifyIdMap := make(map[int]int)
+	// 全部的分类id集合
+	for _, v := range classifyList {
+		deleteClassifyIdMap[v.ChartClassifyId] = v.ChartClassifyId
+	}
+
+	// 存在指标的的分类id集合
+	hasClassifyIdStrList := make([]string, 0)
+	for _, v := range hasEdbClassifyList {
+		hasClassifyIdStrList = append(hasClassifyIdStrList, v.ChartClassifyIdPath)
+	}
+	classifyIdStrList := strings.Split(strings.Join(hasClassifyIdStrList, ","), ",")
+	for _, v := range classifyIdStrList {
+		classifyId, err := strconv.Atoi(v)
+		if err != nil {
+			fmt.Println("分类字符串转int失败,", err.Error())
+			return
+		}
+		delete(deleteClassifyIdMap, classifyId)
+	}
+
+	// 删除空分类
+	if len(deleteClassifyIdMap) > 0 {
+		deleteClassifyIdList := make([]int, 0)
+		for _, v := range deleteClassifyIdMap {
+			deleteClassifyIdList = append(deleteClassifyIdList, v)
+		}
+
+		err = data_manage.DelChartClassifyByIdList(deleteClassifyIdList)
+		if err != nil {
+			fmt.Println("删除空分类失败", err.Error())
+			return
+		}
+	}
+}
+
+// createNewChartClassify
+// @Description: 创建图表分类
+// @author: Roc
+// @datetime 2024-11-29 17:57:47
+// @param userId int
+// @param parentId int
+// @param rootId int
+// @param level int
+// @param sysUserName string
+// @param parentClassifyNamePath string
+// @param parentClassifyIdPath string
+// @param node *data_manage.EdbClassifyItems
+// @param classifyRelationMap map[int]int
+func createNewChartClassify(userId, parentId, rootId, level int, sysUserName, parentClassifyNamePath, parentClassifyIdPath string, node *data_manage.ChartClassifyItems, classifyRelationMap map[int]int) {
+	var classifyNamePath, classifyIdPath string
+
+	if parentId > 0 {
+		classifyNamePath = fmt.Sprint(parentClassifyNamePath, "|", node.ChartClassifyName)
+		classifyIdPath = fmt.Sprint(parentClassifyIdPath, ",")
+	} else {
+		classifyNamePath = node.ChartClassifyName
+	}
+
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	classifyInfo := &data_manage.ChartClassify{
+		ChartClassifyId:   0,
+		ChartClassifyName: node.ChartClassifyName,
+		ParentId:          parentId,
+		HasData:           1,
+		CreateTime:        time.Now(),
+		ModifyTime:        time.Now(),
+		SysUserId:         userId,
+		SysUserRealName:   sysUserName,
+		Level:             level + 1,
+		UniqueCode:        utils.MD5(utils.CHART_PREFIX + "_" + timestamp),
+		Sort:              node.Sort,
+		Source:            node.Source,
+		//IsJoinPermission:      0,
+		ChartClassifyNameEn:   node.ChartClassifyNameEn,
+		RootId:                rootId,
+		ChartClassifyNamePath: classifyNamePath,
+		ChartClassifyIdPath:   "",
+	}
+	_, err := data_manage.AddChartClassify(classifyInfo)
+	if err != nil {
+		fmt.Println("创建分类失败:", err.Error())
+		return
+	}
+
+	updateCols := []string{"ChartClassifyIdPath"}
+	// 更改分类id完整路径path
+	classifyInfo.ChartClassifyIdPath = fmt.Sprint(classifyIdPath, classifyInfo.ChartClassifyId)
+
+	if rootId <= 0 {
+		rootId = classifyInfo.ChartClassifyId
+		classifyInfo.RootId = classifyInfo.ChartClassifyId
+		updateCols = append(updateCols, "RootId")
+	}
+
+	_ = classifyInfo.Update(updateCols)
+
+	classifyRelationMap[node.ChartClassifyId] = classifyInfo.ChartClassifyId
+
+	level = classifyInfo.Level
+
+	if node.Children == nil {
+		return
+	}
+	if len(node.Children) <= 0 {
+		return
+	}
+	for _, child := range node.Children {
+		createNewChartClassify(userId, classifyInfo.ChartClassifyId, rootId, level, sysUserName, classifyNamePath, classifyInfo.ChartClassifyIdPath, child, classifyRelationMap)
+	}
+
+	return
+}
+
+// updateChartPath
+// @Description: 更新图表分类的完整路径
+// @author: Roc
+// @datetime 2024-12-09 10:30:16
+// @param item *data_manage.ChartClassifyItems
+// @param classifyNamePath string
+// @param classifyIdPath string
+func updateChartPath(item *data_manage.ChartClassifyItems, classifyNamePath, classifyIdPath string) {
+	if classifyNamePath == `` {
+		classifyNamePath = item.ChartClassifyName
+		classifyIdPath = fmt.Sprint(item.ChartClassifyId)
+	} else {
+		classifyNamePath = fmt.Sprint(classifyNamePath, "|", item.ChartClassifyName)
+		classifyIdPath = fmt.Sprint(classifyIdPath, ",", item.ChartClassifyId)
+	}
+	err := data_manage.UpdateChartClassify(item.ChartClassifyId, classifyNamePath, classifyIdPath)
+	if err != nil {
+		fmt.Println(item.ChartClassifyId, ";更新失败", err)
+	}
+	if item.Children != nil {
+		for _, v := range item.Children {
+			updateChartPath(v, classifyNamePath, classifyIdPath)
+		}
+	}
+}
+
 // initEs
 // @Description: 修复ES中的指标和图表数据
 // @author: Roc
@@ -353,7 +684,7 @@ func initEs() {
 	// 更新ES中的指标数据
 	data.AddOrEditAllEdbInfoToEs()
 	// 更新es中的图表数据
-	data.AddAllChartInfo()
+	//data.AddAllChartInfo()
 
 	fmt.Println("全部es数据修复完成")
 }

+ 3 - 0
models/business_conf.go

@@ -56,6 +56,9 @@ const (
 
 	BusinessConfEdbStopRefreshRule = "EdbStopRefreshRule" // 是否停止指标刷新规则
 	BusinessConfOuterReportApiUrl  = "OuterReportApiUrl"  // 智力共享-报告API地址
+
+	IgnoreEdbApproveUserId   = `IgnoreEdbApproveUserId`   // 忽略指标审批用户id集合
+	IgnoreChartApproveUserId = `IgnoreChartApproveUserId` //忽略图表审批用户id集合
 )
 
 const (

+ 100 - 19
models/data_manage/chart_classify.go

@@ -8,21 +8,23 @@ import (
 )
 
 type ChartClassify struct {
-	ChartClassifyId     int       `orm:"column(chart_classify_id);pk" gorm:"primaryKey" `
-	ChartClassifyName   string    `description:"分类名称"`
-	ParentId            int       `description:"父级id"`
-	HasData             int       `description:"是否含有指标数据"`
-	CreateTime          time.Time `description:"创建时间"`
-	ModifyTime          time.Time `description:"修改时间"`
-	SysUserId           int       `description:"创建人id"`
-	SysUserRealName     string    `description:"创建人姓名"`
-	Level               int       `description:"层级"`
-	UniqueCode          string    `description:"唯一编码"`
-	Sort                int       `description:"排序字段,越小越靠前,默认值:10"`
-	Source              int       `description:"1:ETA图库;2:商品价格曲线"`
-	IsJoinPermission    int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
-	ChartClassifyNameEn string    `description:"英文分类名称"`
-	RootId              int       `description:"顶级ID"`
+	ChartClassifyId       int       `orm:"column(chart_classify_id);pk" gorm:"primaryKey" `
+	ChartClassifyName     string    `description:"分类名称"`
+	ParentId              int       `description:"父级id"`
+	HasData               int       `description:"是否含有指标数据"`
+	CreateTime            time.Time `description:"创建时间"`
+	ModifyTime            time.Time `description:"修改时间"`
+	SysUserId             int       `description:"创建人id"`
+	SysUserRealName       string    `description:"创建人姓名"`
+	Level                 int       `description:"层级"`
+	UniqueCode            string    `description:"唯一编码"`
+	Sort                  int       `description:"排序字段,越小越靠前,默认值:10"`
+	Source                int       `description:"1:ETA图库;2:商品价格曲线"`
+	IsJoinPermission      int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	ChartClassifyNameEn   string    `description:"英文分类名称"`
+	RootId                int       `description:"顶级ID"`
+	ChartClassifyNamePath string    `description:"分类名称的完整路径,格式为:父级分类名称|当前分类名称"`
+	ChartClassifyIdPath   string    `description:"分类的完整路径,格式为:父级ID,当前ID"`
 }
 
 func AddChartClassify(item *ChartClassify) (lastId int64, err error) {
@@ -102,9 +104,13 @@ type DeleteChartClassifyReq struct {
 
 // GetChartClassifyByParentId
 // @param source int 1:ETA图库;2:商品价格曲线;3:相关性图表
-func GetChartClassifyByParentId(parentId, source int) (items []*ChartClassifyItems, err error) {
+func GetChartClassifyByParentId(parentId, source, sysUserId int) (items []*ChartClassifyItems, err error) {
 	o := global.DmSQL["data"]
-	sql := ` SELECT * FROM chart_classify WHERE parent_id=? AND source = ? order by sort asc,chart_classify_id asc`
+	sql := ` SELECT * FROM chart_classify WHERE parent_id=? AND source = ? `
+	if sysUserId > 0 {
+		sql += fmt.Sprintf(` AND sys_user_id = %d `, sysUserId)
+	}
+	sql += `  order by sort asc,chart_classify_id asc `
 	err = o.Raw(sql, parentId, source).Scan(&items).Error
 
 	return
@@ -112,14 +118,42 @@ func GetChartClassifyByParentId(parentId, source int) (items []*ChartClassifyIte
 
 // GetChartClassifyAll
 // @param source int 1:ETA图库;2:商品价格曲线;3:相关性图表
-func GetChartClassifyAll(source int) (items []*ChartClassifyItems, err error) {
+func GetChartClassifyAll(source, sysUserId int) (items []*ChartClassifyItems, err error) {
 	o := global.DmSQL["data"]
-	sql := ` SELECT * FROM chart_classify WHERE parent_id<>0 AND source = ? order by sort asc,chart_classify_id asc`
+	sql := ` SELECT * FROM chart_classify WHERE parent_id<>0 AND source = ?`
+	if sysUserId > 0 {
+		sql += fmt.Sprintf(` AND sys_user_id = %d `, sysUserId)
+	}
+	sql += ` order by sort asc,chart_classify_id asc `
 	err = o.Raw(sql, source).Scan(&items).Error
 
 	return
 }
 
+// GetAllChartClassify
+// @Description: 获取所有类型的图表分类
+// @author: Roc
+// @datetime 2024-12-09 10:11:46
+// @return items []*ChartClassifyItems
+// @return err error
+func GetAllChartClassify() (items []*ChartClassifyItems, err error) {
+	o := global.DmSQL["data"]
+	sql := ` SELECT * FROM chart_classify order by sort asc,chart_classify_id asc`
+	err = o.Raw(sql).Scan(&items).Error
+
+	return
+}
+
+// GetChartClassifyByParentId
+// @param source int 1:ETA图库;2:商品价格曲线;3:相关性图表
+func GetAllChartClassifyByParentId(parentId int) (items []*ChartClassifyItems, err error) {
+	o := global.DmSQL["data"]
+	sql := ` SELECT * FROM chart_classify WHERE parent_id=?  order by sort asc,chart_classify_id asc`
+	err = o.Raw(sql, parentId).Scan(&items).Error
+
+	return
+}
+
 type ChartClassifyItems struct {
 	ChartClassifyId     int `description:"分类id"`
 	ChartInfoId         int `description:"指标id"`
@@ -144,6 +178,7 @@ type ChartClassifyItems struct {
 	Button              ChartClassifyItemsButton `gorm:"-" description:"按钮权限"`
 	IsJoinPermission    int                      `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
 	HaveOperaAuth       bool                     `description:"是否有数据权限,默认:false"`
+	ChartClassifyIdPath string                   `description:"分类的完整路径,格式为:父级ID,当前ID"`
 }
 
 // ChartClassifyItemsButton 操作按钮
@@ -388,3 +423,49 @@ func DeleteChartClassifyByIds(ids []int) (err error) {
 	err = o.Exec(sql, ids).Error
 	return
 }
+
+// UpdateChartClassify
+// @Description: 更新图表分类的基础信息
+// @author: Roc
+// @datetime 2024-12-09 10:29:51
+// @param classifyId int
+// @param classifyNamePath string
+// @param classifyIdPath string
+// @return err error
+func UpdateChartClassify(classifyId int, classifyNamePath, classifyIdPath string) (err error) {
+	sql := `UPDATE chart_classify SET chart_classify_name_path = ?,chart_classify_id_path = ? WHERE chart_classify_id = ?`
+
+	err = global.DmSQL["data"].Exec(sql, classifyNamePath, classifyIdPath, classifyId).Error
+
+	return
+}
+
+// UpdateClassifyIdByChartInfoId
+// @Description: 根据图表id更新所属分类id
+// @author: Roc
+// @datetime 2024-11-29 17:54:44
+// @param edbInfoId int
+// @param edbClassifyId int
+// @return err error
+func UpdateClassifyIdByChartInfoId(chartInfoId, chartClassifyId int) (err error) {
+	sql := ` UPDATE chart_info SET chart_classify_id = ? WHERE  chart_info_id=? `
+	err = global.DmSQL["data"].Exec(sql, chartClassifyId, chartInfoId).Error
+	return
+}
+
+// DelChartClassifyByIdList
+// @Description: 根据id删除图表分类
+// @author: Roc
+// @datetime 2024-12-02 09:27:26
+// @param idList []int
+// @return err error
+func DelChartClassifyByIdList(idList []int) (err error) {
+	num := len(idList)
+	if num <= 0 {
+		return
+	}
+	sql := `DELETE  FROM chart_classify  WHERE chart_classify_id IN (?) `
+	err = global.DmSQL["data"].Exec(sql, idList).Error
+
+	return
+}

+ 8 - 2
models/data_manage/chart_info.go

@@ -87,7 +87,7 @@ type ChartInfoItem struct {
 
 // GetChartInfoAll 用于分类展示
 // @param source int 1:ETA图库;2:商品价格曲线
-func GetChartInfoAll(sourceList []int) (items []*ChartClassifyItems, err error) {
+func GetChartInfoAll(sourceList []int, sysUserId int) (items []*ChartClassifyItems, err error) {
 	num := len(sourceList)
 	if num <= 0 {
 		return
@@ -96,7 +96,13 @@ func GetChartInfoAll(sourceList []int) (items []*ChartClassifyItems, err error)
 	o := global.DmSQL["data"]
 	sql := ` SELECT chart_info_id,chart_classify_id,chart_name AS chart_classify_name,chart_name_en AS chart_classify_name_en,
              unique_code,sys_user_id,sys_user_real_name,date_type,start_date,end_date,chart_type,calendar,season_start_date,season_end_date,source
-            FROM chart_info WHERE source in (` + utils.GetOrmInReplace(num) + `)  ORDER BY sort asc,chart_info_id ASC `
+            FROM chart_info WHERE source in (` + utils.GetOrmInReplace(num) + `)  `
+
+	if sysUserId > 0 {
+		sql += ` AND sys_user_id = ? `
+	}
+
+	sql += ` ORDER BY sort asc,chart_info_id ASC `
 	err = o.Raw(sql, sourceList).Scan(&items).Error
 
 	return

+ 223 - 0
models/data_manage/data_approve/data_approve.go

@@ -0,0 +1,223 @@
+package data_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+type DataApprove struct {
+	DataApproveId int       `gorm:"column:data_approve_id;primary_key"`
+	Title         string    `gorm:"column:title"`
+	DataType      int       `gorm:"column:data_type"`
+	State         int       `gorm:"column:state"` //  '审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回'
+	FlowId        int       `gorm:"column:flow_id"`
+	FlowVersion   int       `gorm:"column:flow_version"`
+	StartNodeId   int       `gorm:"column:start_node_id"`
+	CurrNodeId    int       `gorm:"column:curr_node_id"`
+	ApplyUserId   int       `gorm:"column:apply_user_id"`
+	ApplyUserName string    `gorm:"column:apply_user_name"`
+	ApproveRemark string    `gorm:"column:approve_remark"`
+	ApproveTime   time.Time `gorm:"column:approve_time"`
+	CreateTime    time.Time `gorm:"column:create_time"`
+	ModifyTime    time.Time `gorm:"column:update_time"`
+}
+
+var DataApproveCols = struct {
+	DataApproveId string
+	Title         string
+	DataType      string // 资产类型:1:指标、2:图表
+	State         string //  '审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回'
+	FlowId        string
+	FlowVersion   string
+	StartNodeId   string
+	CurrNodeId    string
+	ApplyUserId   string
+	ApplyUserName string
+	ApproveRemark string
+	ApproveTime   string
+	CreateTime    string
+	ModifyTime    string
+}{
+	DataApproveId: "data_approve_id",
+	Title:         "title",
+	DataType:      "data_type",
+	State:         "state",
+	FlowId:        "flow_id",
+	FlowVersion:   "flow_version",
+	StartNodeId:   "start_node_id",
+	CurrNodeId:    "curr_node_id",
+	ApplyUserId:   "apply_user_id",
+	ApplyUserName: "apply_user_name",
+	ApproveRemark: "approve_remark",
+	ApproveTime:   "approve_time",
+	CreateTime:    "create_time",
+	ModifyTime:    "modify_time",
+}
+
+type DataApproveItemOrm struct {
+	DataApproveId       int       `description:"审批ID"`
+	DataApproveRecordId int       `description:"审批记录ID"`
+	Title               string    `description:"审批标题"`
+	DataType            int       `description:"资产类型"`
+	State               int       `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	RecordState         int       `description:"审批记录状态:1-待审批;2-已通过;3-已驳回"`
+	FlowId              int       `description:"审批流ID"`
+	FlowVersion         int       `description:"审批流版本"`
+	StartNodeId         int       `description:"开始节点ID"`
+	CurrNodeId          int       `description:"当前节点ID"`
+	ApplyUserId         int       `description:"申请人ID"`
+	ApplyUserName       string    `description:"申请人姓名"`
+	ApproveRemark       string    `description:"审批备注"`
+	ApproveTime         time.Time `description:"审批时间"`
+	HandleTime          time.Time `description:"处理时间"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"修改时间"`
+	NodeState           int       `description:"当前节点审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回" json:"-"`
+	NodeApproveTime     time.Time `description:"当前节点审批时间" json:"-"`
+}
+
+func (b *DataApprove) TableName() string {
+	return "data_approve"
+}
+
+func (b *DataApprove) Update(cols []string) (err error) {
+	db := global.DmSQL["data"]
+	err = db.Model(b).Select(cols).Updates(b).Error
+	return
+}
+
+func (b *DataApprove) Create() (err error) {
+	db := global.DmSQL["data"]
+	err = db.Create(b).Error
+	return
+}
+
+// AddDataApprove
+// @Description: 添加审批单
+// @author: Roc
+// @datetime 2024-12-06 09:46:04
+// @param dataApprove *DataApprove
+// @param relationList []*DataApproveRelation
+// @return err error
+func AddDataApprove(dataApprove *DataApprove, relationList []*DataApproveRelation) (err error) {
+	db := global.DmSQL["data"].Begin()
+	defer func() {
+		if err != nil {
+			db.Rollback()
+		} else {
+			db.Commit()
+		}
+	}()
+
+	err = db.Create(dataApprove).Error
+	if err != nil {
+		return
+	}
+
+	if len(relationList) > 0 {
+		for _, v := range relationList {
+			v.DataApproveId = dataApprove.DataApproveId
+		}
+		err = db.CreateInBatches(relationList, utils.MultiAddNum).Error
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+func GetDataApproveByFlowIdAndVersionId(dataFlowId int, flowVersion int) (item []*DataApprove, err error) {
+	db := global.DmSQL["data"]
+	err = db.Where("flow_id = ? AND flow_version = ?", dataFlowId, flowVersion).Find(&item).Error
+	return
+}
+
+func GetDataApproveById(DataApproveId int) (item *DataApprove, err error) {
+	db := global.DmSQL["data"]
+	err = db.Where("data_approve_id = ?", DataApproveId).First(&item).Error
+	return
+}
+
+// GetApprovingDataApproveCount 获取待处理的审批分页列表总数
+func GetApprovingDataApproveCount(cond string, pars []interface{}) (count int, err error) {
+	base := fmt.Sprintf(`SELECT a.data_approve_record_id
+		FROM data_approve_record AS a
+		JOIN data_approve AS b ON a.data_approve_id = b.data_approve_id AND a.node_id = b.curr_node_id
+		WHERE 1 = 1 %s`, cond)
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM (%s) t`, base)
+	err = global.DmSQL["data"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+// GetApprovingDataApprovePageList 获取待处理的审批列表-分页
+func GetApprovingDataApprovePageList(cond string, pars []interface{}, orderRule string, startSize, pageSize int) (items []*DataApproveItemOrm, err error) {
+	order := `ORDER BY a.create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT a.data_approve_record_id, a.state AS record_state, b.*
+		FROM data_approve_record AS a
+		JOIN data_approve AS b ON a.data_approve_id = b.data_approve_id AND a.node_id = b.curr_node_id
+		WHERE 1 = 1 %s %s
+		LIMIT ?,?`, cond, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+// GetApprovedDataApproveCount 获取已处理的审批分页列表总数
+func GetApprovedDataApproveCount(cond string, pars []interface{}) (count int, err error) {
+	base := fmt.Sprintf(`SELECT a.data_approve_record_id
+		FROM data_approve_record AS a
+		JOIN data_approve AS b ON a.data_approve_id = b.data_approve_id
+		WHERE 1 = 1 %s`, cond)
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM (%s) t`, base)
+	err = global.DmSQL["data"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+// GetApprovedDataApprovePageList 获取已处理的审批列表-分页
+func GetApprovedDataApprovePageList(cond string, pars []interface{}, orderRule string, startSize, pageSize int) (items []*DataApproveItemOrm, err error) {
+	order := `ORDER BY a.create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT a.data_approve_record_id, a.node_state AS record_state,a.node_state,a.node_approve_time, a.node_approve_time AS handle_time, b.*
+		FROM data_approve_record AS a
+		JOIN data_approve AS b ON a.data_approve_id = b.data_approve_id
+		WHERE 1 = 1 %s %s
+		LIMIT ?,?`, cond, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+// GetApplyDataApproveCount 获取我发起的审批分页列表总数
+func GetApplyDataApproveCount(cond string, pars []interface{}) (count int, err error) {
+	base := fmt.Sprintf(`SELECT a.* FROM data_approve AS a WHERE 1 = 1 %s`, cond)
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM (%s) t`, base)
+	err = global.DmSQL["data"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+// GetApplyDataApprovePageList 获取我发起的审批列表-分页
+func GetApplyDataApprovePageList(cond string, pars []interface{}, orderRule string, startSize, pageSize int) (items []*DataApproveItemOrm, err error) {
+	order := `ORDER BY a.create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT a.* FROM data_approve AS a WHERE 1 = 1 %s %s LIMIT ?,?`, cond, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func GetDataApproveCountByState(state int) (count int, err error) {
+	db := global.DmSQL["data"]
+	sql := `SELECT COUNT(*) FROM data_approve WHERE state = ?`
+	err = db.Raw(sql, state).Scan(&count).Error
+	return
+}

+ 198 - 0
models/data_manage/data_approve/data_approve_flow.go

@@ -0,0 +1,198 @@
+package data_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"fmt"
+	"time"
+)
+
+type DataApproveFlow struct {
+	DataApproveFlowId int       `gorm:"column:data_approve_flow_id;primaryKey"`
+	FlowName          string    `gorm:"column:flow_name"`
+	DataType          int       `gorm:"column:data_type"`
+	Remark            string    `gorm:"column:remark"`
+	CurrVersion       int       `gorm:"column:curr_version"`
+	CreateTime        time.Time `gorm:"column:create_time"`
+	ModifyTime        time.Time `gorm:"column:modify_time"`
+}
+
+var DataApproveFlowCols = struct {
+	DataApproveFlowId string
+	FlowName          string
+	DataType          string // 资产类型:1:指标、2:图表
+	CurrVersion       string
+	CreateTime        string
+	ModifyTime        string
+}{
+	DataApproveFlowId: "data_approve_flow_id",
+	FlowName:          "flow_name",
+	DataType:          "data_type",
+	CurrVersion:       "curr_version",
+	CreateTime:        "create_time",
+	ModifyTime:        "modify_time",
+}
+
+func (b *DataApproveFlow) TableName() string {
+	return "data_approve_flow"
+}
+
+func (b *DataApproveFlow) Add(node []*DataApproveNode) (err error) {
+	prevNodes := make([]*DataApproveNode, 0)
+	o := global.DmSQL["data"].Begin()
+	defer func() {
+		if err != nil {
+			o.Rollback()
+		} else {
+			o.Commit()
+		}
+
+		// 更新每个节点的下一个节点信息, 放在事务中会更新失败
+		if e := UpdateNextNodes(prevNodes); e != nil {
+			err = fmt.Errorf("UpdatePrevNodes err: %s", e.Error())
+			return
+		}
+	}()
+
+	err = o.Create(b).Error
+	if err != nil {
+		err = fmt.Errorf("insert approve err: %v", err)
+		return
+	}
+
+	nodesLen := len(node)
+	if nodesLen == 0 {
+		return
+	}
+	prevId := 0
+	prevNode := new(DataApproveNode)
+	for k, v := range node {
+		v.DataApproveFlowId = b.DataApproveFlowId
+		v.PrevNodeId = prevId
+		err = o.Create(v).Error
+		if err != nil {
+			err = fmt.Errorf("insert node err: %v", err)
+			return
+		}
+		prevId = v.DataApproveNodeId
+
+		// 下一个节点
+		if prevNode != nil && k > 0 && k < nodesLen {
+			prevNode.NextNodeId = v.DataApproveNodeId
+			prevNodes = append(prevNodes, prevNode)
+		}
+		prevNode = v
+	}
+	return
+}
+
+func (b *DataApproveFlow) Update(cols []string, node []*DataApproveNode) (err error) {
+	prevNodes := make([]*DataApproveNode, 0)
+	o := global.DmSQL["data"].Begin()
+	defer func() {
+		if err != nil {
+			o.Rollback()
+		} else {
+			o.Commit()
+		}
+
+		// 更新每个节点的下一个节点信息, 放在事务中会更新失败
+		if e := UpdateNextNodes(prevNodes); e != nil {
+			err = fmt.Errorf("UpdatePrevNodes err: %s", e.Error())
+			return
+		}
+	}()
+	err = o.Model(b).Select(cols).Updates(b).Error
+	if err != nil {
+		return
+	}
+
+	nodesLen := len(node)
+	if nodesLen == 0 {
+		return
+	}
+	prevId := 0
+	prevNode := new(DataApproveNode)
+	for k, v := range node {
+		v.DataApproveFlowId = b.DataApproveFlowId
+		v.PrevNodeId = prevId
+		err = o.Create(v).Error
+		if err != nil {
+			err = fmt.Errorf("insert node err: %v", err)
+			return
+		}
+		prevId = v.DataApproveNodeId
+
+		// 下一个节点
+		if prevNode != nil && k > 0 && k < nodesLen {
+			prevNode.NextNodeId = v.DataApproveNodeId
+			prevNodes = append(prevNodes, prevNode)
+		}
+		prevNode = v
+	}
+	
+	return
+}
+
+func (b *DataApproveFlow) Delete() error {
+	return global.DmSQL["data"].Delete(b).Error
+}
+
+func (m *DataApproveFlow) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *DataApproveFlow, err error) {
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s `, m.TableName(), condition, order)
+	err = global.DmSQL["data"].Raw(sql, pars...).First(&item).Error
+	return
+}
+
+func GetDataApproveFlowById(DataApproveFlowId int) (item *DataApproveFlow, err error) {
+	err = global.DmSQL["data"].Where("data_approve_flow_id = ?", DataApproveFlowId).First(&item).Error
+	return
+}
+
+// GetDataApproveFlowByDataType
+// @Description: 根据数据类型获取审核流
+// @author: Roc
+// @datetime 2024-12-05 16:06:52
+// @param dataType int
+// @return item *DataApproveFlow
+// @return err error
+func GetDataApproveFlowByDataType(dataType int) (item *DataApproveFlow, err error) {
+	err = global.DmSQL["data"].Where("data_type = ?", dataType).First(&item).Error
+	return
+}
+
+func GetDataApproveFlowByClassifyId(classifyId int) (item *DataApproveFlow, err error) {
+	err = global.DmSQL["data"].Where("classify_id = ?", classifyId).First(&item).Error
+	return
+}
+
+func GetDataApproveFlowByCondition(condition string, pars []interface{}, startSize, pageSize int) (items []*DataApproveFlow, err error) {
+	o := global.DmSQL["data"]
+	sql := "SELECT * FROM data_approve_flow WHERE 1=1 "
+	if condition != "" {
+		sql += condition
+	}
+	sql += " LIMIT ?,?"
+	pars = append(pars, startSize, pageSize)
+	err = o.Raw(sql, pars...).Scan(&items).Error
+	return
+}
+
+func GetDataApproveFlowCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := global.DmSQL["data"]
+	sql := "SELECT COUNT(*) AS count FROM data_approve_flow WHERE 1=1 "
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func UpdateFlowClassifyName(classifyId int, classifyName string) (err error) {
+	o := global.DmSQL["data"]
+	err = o.Model(&DataApproveFlow{}).Where("classify_id = ?", classifyId).Update("classify_name", classifyName).Error
+	return
+}

+ 115 - 0
models/data_manage/data_approve/data_approve_message.go

@@ -0,0 +1,115 @@
+package data_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type DataApproveMessage struct {
+	Id            int       `gorm:"primaryKey;column:id"`
+	SendUserId    int       `gorm:"column:send_user_id"`    // 发送人Id
+	ReceiveUserId int       `gorm:"column:receive_user_id"` // 接收者Id
+	Content       string    `gorm:"column:content"`         // 消息内容
+	Remark        string    `gorm:"column:remark"`          // 备注信息
+	DataApproveId int       `gorm:"column:data_approve_id"` // 审批Id
+	ApproveState  int       `gorm:"column:approve_state"`   // 审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回
+	IsRead        int       `gorm:"column:is_read"`         // 是否已读:0-未读;1-已读
+	CreateTime    time.Time `gorm:"column:create_time"`     // 创建时间
+	ModifyTime    time.Time `gorm:"column:modify_time"`     // 修改时间
+}
+
+var DataApproveMessageCols = struct {
+	Id            string
+	SendUserId    string
+	ReceiveUserId string
+	Content       string
+	Remark        string
+	DataApproveId string
+	ApproveState  string
+	IsRead        string
+	CreateTime    string
+	ModifyTime    string
+}{
+	Id:            "id",
+	SendUserId:    "send_user_id",
+	ReceiveUserId: "receive_user_id",
+	Content:       "content",
+	Remark:        "remark",
+	DataApproveId: "data_approve_id",
+	ApproveState:  "approve_state",
+	IsRead:        "is_read",
+	CreateTime:    "create_time",
+	ModifyTime:    "modify_time",
+}
+
+func (r *DataApproveMessage) TableName() string {
+	return "data_approve_message"
+}
+
+func (r *DataApproveMessage) Create() (err error) {
+	o := global.DmSQL["data"]
+	err = o.Create(r).Error
+	return err
+}
+
+func (m *DataApproveMessage) PrimaryId() string {
+	return DataApproveMessageCols.Id
+}
+
+func (r *DataApproveMessage) CreateMulti(items []*DataApproveMessage) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := global.DmSQL["data"]
+	err = o.CreateInBatches(items, utils.MultiAddNum).Error
+	return
+}
+
+func (m *DataApproveMessage) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = global.DmSQL["data"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func (m *DataApproveMessage) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*DataApproveMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *DataApproveMessage) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*DataApproveMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *DataApproveMessage) GetItemById(id int) (item *DataApproveMessage, err error) {
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? `, m.TableName(), m.PrimaryId())
+	err = global.DmSQL["data"].Raw(sql, id).First(&item).Error
+	return
+}
+
+func (m *DataApproveMessage) Update(cols []string) (err error) {
+	err = global.DmSQL["data"].Model(m).Select(cols).Updates(m).Error
+	return
+}

+ 90 - 0
models/data_manage/data_approve/data_approve_node.go

@@ -0,0 +1,90 @@
+package data_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type DataApproveNode struct {
+	DataApproveNodeId int       `gorm:"column:data_approve_node_id;primaryKey"`
+	DataApproveFlowId int       `gorm:"column:data_approve_flow_id"`
+	PrevNodeId        int       `gorm:"column:prev_node_id"`
+	NextNodeId        int       `gorm:"column:next_node_id"`
+	NodeType          int       `gorm:"column:node_type"`
+	ApproveType       int       `gorm:"column:approve_type"`
+	Users             string    `gorm:"column:users"`
+	CurrVersion       int       `gorm:"column:curr_version"`
+	CreatedTime       time.Time `gorm:"column:created_time"`
+}
+
+var DataApproveNodeCols = struct {
+	DataApproveNodeId string
+	DataApproveFlowId string
+	PrevNodeId        string
+	NextNodeId        string
+	NodeType          string
+	ApproveType       string
+	Users             string
+	CurrVersion       string
+	CreatedTime       string
+}{
+	DataApproveNodeId: "data_approve_node_id",
+	DataApproveFlowId: "data_approve_flow_id",
+	PrevNodeId:        "prev_node_id",
+	NextNodeId:        "next_node_id",
+	NodeType:          "node_type",
+	ApproveType:       "approve_type",
+	Users:             "users",
+	CurrVersion:       "curr_version",
+	CreatedTime:       "created_time",
+}
+
+func (b *DataApproveNode) TableName() string {
+	return "data_approve_node"
+}
+
+func (m *DataApproveNode) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*DataApproveNode, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY created_time DESC, data_approve_node_id ASC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func UpdateNextNodes(nodes []*DataApproveNode) (err error) {
+	if len(nodes) == 0 {
+		return
+	}
+	updateCols := []string{"NextNodeId"}
+	for _, v := range nodes {
+		e := global.DmSQL["data"].Select(updateCols).Updates(v).Error
+		if e != nil {
+			err = fmt.Errorf("prev node update err: %v", e)
+			return
+		}
+	}
+	return
+}
+
+func GetDataApproveNodeByCondition(condition string, pars []interface{}) (node []*DataApproveNode, err error) {
+	o := global.DmSQL["data"]
+	sql := "SELECT * FROM data_approve_node WHERE 1=1 "
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).Find(&node).Error
+	return
+}
+
+func GetDataApproveNodeByFlowIdAndVersionId(flowId int, versionId int) (node []*DataApproveNode, err error) {
+	err = global.DmSQL["data"].Model(&DataApproveNode{}).Where("data_approve_flow_id =? AND curr_version =?", flowId, versionId).Scan(&node).Error
+	return
+}

+ 152 - 0
models/data_manage/data_approve/data_approve_record.go

@@ -0,0 +1,152 @@
+package data_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type DataApproveRecord struct {
+	DataApproveRecordId int       `gorm:"column:data_approve_record_id;primary_key"`
+	DataApproveId       int       `gorm:"column:data_approve_id"`
+	State               int       `gorm:"column:state"`
+	NodeId              int       `gorm:"column:node_id"`
+	NodeType            int       `gorm:"column:node_type"`
+	PrevNodeId          int       `gorm:"column:prev_node_id"`
+	NextNodeId          int       `gorm:"column:next_node_id"`
+	ApproveType         int       `gorm:"column:approve_type"`
+	ApproveUserId       int       `gorm:"column:approve_user_id"`
+	ApproveUserName     string    `gorm:"column:approve_user_name"`
+	ApproveUserSort     int       `gorm:"column:approve_user_sort"`
+	ApproveRemark       string    `gorm:"column:approve_remark"`
+	ApproveTime         time.Time `gorm:"column:approve_time"`
+	CreateTime          time.Time `gorm:"column:create_time"`
+	ModifyTime          time.Time `gorm:"column:modify_time"`
+	NodeState           int       `gorm:"column:node_state"`
+	NodeApproveUserId   int       `gorm:"column:node_approve_user_id"`
+	NodeApproveUserName string    `gorm:"column:node_approve_user_name"`
+	NodeApproveTime     time.Time `gorm:"column:node_approve_time"`
+}
+
+var DataApproveRecordCols = struct {
+	DataApproveRecordId string
+	DataApproveId       string
+	State               string
+	NodeId              string
+	NodeType            string
+	PrevNodeId          string
+	NextNodeId          string
+	ApproveType         string
+	ApproveUserId       string
+	ApproveUserName     string
+	ApproveUserSort     string
+	ApproveRemark       string
+	ApproveTime         string
+	CreateTime          string
+	ModifyTime          string
+	NodeState           string
+	NodeApproveUserId   string
+	NodeApproveUserName string
+	NodeApproveTime     string
+}{
+	DataApproveRecordId: "data_approve_record_id",
+	DataApproveId:       "data_approve_id",
+	State:               "state",
+	NodeId:              "node_id",
+	NodeType:            "node_type",
+	PrevNodeId:          "prev_node_id",
+	NextNodeId:          "next_node_id",
+	ApproveType:         "approve_type",
+	ApproveUserId:       "approve_user_id",
+	ApproveUserName:     "approve_user_name",
+	ApproveUserSort:     "approve_user_sort",
+	ApproveRemark:       "approve_remark",
+	ApproveTime:         "approve_time",
+	CreateTime:          "create_time",
+	ModifyTime:          "modify_time",
+	NodeState:           "node_state",
+	NodeApproveUserId:   "node_approve_user_id",
+	NodeApproveUserName: "node_approve_user_name",
+	NodeApproveTime:     "node_approve_time",
+}
+
+func (b *DataApproveRecord) TableName() string {
+	return "data_approve_record"
+}
+
+func (b *DataApproveRecord) Create() (err error) {
+	o := global.DmSQL["data"]
+	err = o.Create(b).Error
+	return
+}
+
+func (b *DataApproveRecord) CreateMulti(items []*DataApproveRecord) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := global.DmSQL["data"]
+	err = o.CreateInBatches(items, utils.MultiAddNum).Error
+	return
+}
+
+func (b *DataApproveRecord) Update(cols []string) (err error) {
+	o := global.DmSQL["data"]
+	err = o.Model(b).Select(cols).Updates(b).Error
+	return
+}
+
+func GetDataApproveRecordByCondition(condition string, pars []interface{}) (record *DataApproveRecord, err error) {
+	o := global.DmSQL["data"]
+	sql := `SELECT * FROM data_approve_record WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).First(&record).Error
+	return
+}
+
+func GetDataApproveRecordItemsByCondition(condition string, pars []interface{}) (items []*DataApproveRecord, err error) {
+	order := `ORDER BY create_time DESC`
+	sql := fmt.Sprintf(`SELECT * FROM data_approve_record WHERE 1=1 %s %s`, condition, order)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (b *DataApproveRecord) UpdateNodeState(DataApproveId, nodeId, nodeState, nodeApproveUserId int, nodeApproveUserName string, nodeApproveTime time.Time) (err error) {
+	pars := make([]interface{}, 0)
+	pars = append(pars, nodeState, nodeApproveUserId, nodeApproveUserName, nodeApproveTime)
+
+	// 更新条件
+	whereParas := []interface{}{DataApproveId, nodeId}
+	pars = append(pars, whereParas...)
+
+	sql := fmt.Sprintf(`UPDATE %s SET node_state=?,node_approve_user_id=?,node_approve_user_name=?,node_approve_time=? WHERE data_approve_id = ? AND node_id = ?`, b.TableName())
+	err = global.DmSQL["data"].Exec(sql, pars...).Error
+	return
+}
+
+func (m *DataApproveRecord) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*DataApproveRecord, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["data"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *DataApproveRecord) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *DataApproveRecord, err error) {
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = global.DmSQL["data"].Raw(sql, pars...).First(&item).Error
+	return
+}

+ 57 - 0
models/data_manage/data_approve/data_approve_relation.go

@@ -0,0 +1,57 @@
+package data_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"time"
+)
+
+type DataApproveRelation struct {
+	DataApproveRelationId int       `gorm:"column:data_approve_relation_id;primary_key"`
+	DataApproveId         int       `gorm:"column:data_approve_id"`
+	DataId                int       `gorm:"column:data_id"`
+	ClassifyId            int       `gorm:"column:classify_id"`
+	CreateTime            time.Time `gorm:"column:create_time"`
+}
+
+var DataApproveRelationCols = struct {
+	DataApproveRelationId string
+	DataApproveId         string
+	DataId                string // 资产类型:1:指标、2:图表
+	ClassifyId            string //
+	CreateTime            string
+}{
+	DataApproveRelationId: "data_approve_relation_id",
+	DataApproveId:         "data_approve_id",
+	DataId:                "data_id",
+	ClassifyId:            "classify_id",
+	CreateTime:            "create_time",
+}
+
+func (b *DataApproveRelation) TableName() string {
+	return "data_approve_relation"
+}
+
+func (b *DataApproveRelation) Update(cols []string) (err error) {
+	db := global.DmSQL["data"]
+	err = db.Model(b).Select(cols).Updates(b).Error
+	return
+}
+
+func (b *DataApproveRelation) Create() (err error) {
+	db := global.DmSQL["data"]
+	err = db.Create(b).Error
+	return
+}
+
+// GetListByDataApproveId
+// @Description: 根据审批id获取关联的资产(指标、图表)
+// @author: Roc
+// @datetime 2024-12-05 17:23:39
+// @param dataApproveId int
+// @return dataIdList []int
+// @return err error
+func (b *DataApproveRelation) GetListByDataApproveId(dataApproveId int) (dataIdList []*DataApproveRelation, err error) {
+	sql := `SELECT * FROM data_approve_relation AS a WHERE data_approve_id = ? `
+	err = global.DmSQL["data"].Raw(sql, dataApproveId).Scan(&dataIdList).Error
+	return
+}

+ 21 - 0
models/data_manage/data_approve/request/approve.go

@@ -0,0 +1,21 @@
+package request
+
+type DataApprovePassReq struct {
+	DataApproveId int `description:"审批ID"`
+}
+
+// DataApproveRefuseReq 审批驳回请求体
+type DataApproveRefuseReq struct {
+	DataApproveId int    `description:"审批ID"`
+	ApproveRemark string `description:"驳回理由"`
+}
+
+// DataApproveCancelReq 撤销审批请求体
+type DataApproveCancelReq struct {
+	DataApproveId int `description:"审批ID"`
+}
+
+// DataApproveCheckApproveOpenReq 校验当前资产是否打开审批请求体
+type DataApproveCheckApproveOpenReq struct {
+	DataType int `description:"资产类型"`
+}

+ 22 - 0
models/data_manage/data_approve/request/approve_flow.go

@@ -0,0 +1,22 @@
+package request
+
+type DataApproveFlowSaveReq struct {
+	DataType int
+	FlowName string
+	Nodes    []Node
+}
+
+type Node struct {
+	ApproveType int `description:"审批类型: 1-依次审批, 2-会签, 3-或签"`
+	Users       []User
+}
+
+type User struct {
+	UserId   int    `description:"用户ID"`
+	UserName string `description:"用户名"`
+	UserType string `description:"用户类型: user-用户 role-角色"`
+}
+
+type DataApproveFlowRemoveResp struct {
+	DataApproveFlowId int
+}

+ 5 - 0
models/data_manage/data_approve/request/approve_message.go

@@ -0,0 +1,5 @@
+package request
+
+type DataApproveMessageReadReq struct {
+	MessageId int `description:"审批消息ID"`
+}

+ 88 - 0
models/data_manage/data_approve/response/approve.go

@@ -0,0 +1,88 @@
+package response
+
+// DataApproveDetail 审批详情信息
+type DataApproveDetail struct {
+	Approve          *DataApproveDetailItem    `description:"审批信息"`
+	ApproveFlowNodes []*DataApproveDetailNodes `description:"审批节点信息"`
+	DataList         []DataApproveDetailData   `description:"指标/图表列表"`
+}
+
+// DataApproveDetailData 审批详情-报告信息
+type DataApproveDetailData struct {
+	DataId       int    `description:"数据ID"`
+	DataName     string `description:"数据名称"`
+	DataCode     string `description:"数据code"`
+	DataClassify int    `description:"数据所属分类"`
+}
+
+// DataApproveDetailItem 审批详情-审批信息
+type DataApproveDetailItem struct {
+	DataApproveId int    `description:"审批ID"`
+	State         int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	FlowId        int    `description:"审批流ID"`
+	FlowVersion   int    `description:"审批流版本"`
+	StartNodeId   int    `description:"开始节点ID"`
+	CurrNodeId    int    `description:"当前节点ID"`
+	ApplyUserId   int    `description:"申请人ID"`
+	ApplyUserName string `description:"申请人姓名"`
+	ApproveTime   string `description:"审批时间"`
+	CreateTime    string `description:"创建时间"`
+	ModifyTime    string `description:"修改时间"`
+}
+
+// DataApproveDetailNodes 审批详情-节点信息
+type DataApproveDetailNodes struct {
+	DataApproveNodeId int                          `description:"看板审批节点ID"`
+	DataApproveFlowId int                          `description:"看板审批流ID"`
+	PrevNodeId        int                          `description:"上一个节点ID(0为开始节点)"`
+	NextNodeId        int                          `description:"下一个节点ID(0为结束节点)"`
+	NodeType          int                          `description:"节点类型:0-审批;1-抄送"`
+	ApproveType       int                          `description:"审批类型:1-依次审批;2-会签;3-或签"`
+	Users             []*DataApproveDetailNodeUser `description:"审批人信息"`
+}
+
+// DataApproveDetailNodeUser 审批详情-节点用户信息
+type DataApproveDetailNodeUser struct {
+	DataApproveNodeUserReq
+	ApproveRecord *DataApproveDetailNodeUserRecord `description:"用户审批记录"`
+}
+
+// DataApproveNodeUserReq 报告审批节点用户请求体
+type DataApproveNodeUserReq struct {
+	UserType string `description:"审批人类型: user-用户; role-角色"`
+	UserId   int    `description:"用户/角色ID"`
+	UserName string `description:"用户/角色姓名"`
+	Sort     int    `description:"排序"`
+}
+
+// DataApproveDetailNodeUserRecord 审批详情-节点用户审批记录
+type DataApproveDetailNodeUserRecord struct {
+	DataApproveRecordId int    `description:"审批记录ID"`
+	State               int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	ApproveUserId       int    `description:"审批人ID"`
+	ApproveUserName     string `description:"审批人姓名"`
+	ApproveRemark       string `description:"审批备注"`
+	ApproveTime         string `description:"审批时间"`
+}
+
+type DataApproveItemOrmResp struct {
+	DataApproveId       int    `description:"审批ID"`
+	DataApproveRecordId int    `description:"审批记录ID"`
+	Title               string `description:"审批标题"`
+	DataType            int    `description:"自查类型"`
+	State               int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	RecordState         int    `description:"审批记录状态:1-待审批;2-已通过;3-已驳回"`
+	FlowId              int    `description:"审批流ID"`
+	FlowVersion         int    `description:"审批流版本"`
+	StartNodeId         int    `description:"开始节点ID"`
+	CurrNodeId          int    `description:"当前节点ID"`
+	ApplyUserId         int    `description:"申请人ID"`
+	ApplyUserName       string `description:"申请人姓名"`
+	ApproveRemark       string `description:"审批备注"`
+	ApproveTime         string `description:"审批时间"`
+	HandleTime          string `description:"处理时间"`
+	CreateTime          string `description:"创建时间"`
+	ModifyTime          string `description:"修改时间"`
+	NodeState           int    `description:"当前节点审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回" json:"-"`
+	NodeApproveTime     string `description:"当前节点审批时间" json:"-"`
+}

+ 46 - 0
models/data_manage/data_approve/response/approve_flow.go

@@ -0,0 +1,46 @@
+package response
+
+import (
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type DataApproveFlowItem struct {
+	DataApproveFlowId int    `description:"主键"`
+	FlowName          string `description:"bi审批流程名称"`
+	DataType          int    `description:"资产类型"`
+	ClassifyName      string `description:"分类名称"`
+	CurrVersion       int    `description:"当前版本"`
+	CreateTime        string `description:"创建时间"`
+	ModifyTime        string `description:"修改时间"`
+}
+
+type DataApproveFlowListResp struct {
+	List   []*DataApproveFlowItem
+	Paging *paging.PagingItem
+}
+
+type DataApproveFlowDetailResp struct {
+	DataApproveFlowItem `description:"审批流信息"`
+	Nodes               []*DataApproveNodeItem `description:"节点信息"`
+}
+
+type DataApproveNodeUser struct {
+	UserType string `description:"审批人类型: user-用户; role-角色"`
+	UserId   int    `description:"用户/角色ID"`
+	UserName string `description:"用户/角色姓名"`
+	Sort     int    `description:"排序"`
+}
+type DataApproveNodeItem struct {
+	DataApproveNodeId int                    `description:"BI审批节点ID"`
+	DataApproveFlowId int                    `description:"BI审批流ID"`
+	PrevNodeId        int                    `description:"上一个节点ID(0为开始节点)"`
+	NextNodeId        int                    `description:"下一个节点ID(0为结束节点)"`
+	NodeType          int                    `description:"节点类型:0-审批;1-抄送"`
+	ApproveType       int                    `description:"审批类型:1-依次审批;2-会签;3-或签"`
+	Users             []*DataApproveNodeUser `description:"审批人信息"`
+}
+
+type DataApproveListResp struct {
+	List   []*DataApproveItemOrmResp
+	Paging *paging.PagingItem
+}

+ 24 - 0
models/data_manage/data_approve/response/approve_message.go

@@ -0,0 +1,24 @@
+package response
+
+import "github.com/rdlucklib/rdluck_tools/paging"
+
+// DataApproveMessageListResp 审批消息列表响应体
+type DataApproveMessageListResp struct {
+	List        []*DataApproveMessageItem
+	Paging      *paging.PagingItem `description:"分页数据"`
+	UnreadTotal int                `description:"消息未读数"`
+}
+
+// DataApproveMessageItem 报告审批消息信息
+type DataApproveMessageItem struct {
+	Id            int
+	SendUserId    int    `description:"发送人ID"`
+	ReceiveUserId int    `description:"接收者ID"`
+	Content       string `description:"消息内容"`
+	Remark        string `description:"备注信息"`
+	DataApproveId int    `description:"审批ID"`
+	ApproveState  int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	IsRead        int    `description:"是否已读:0-未读;1-已读"`
+	CreateTime    string `description:"创建时间"`
+	ModifyTime    string `description:"修改时间"`
+}

+ 24 - 6
models/data_manage/edb_classify.go

@@ -51,9 +51,9 @@ type AddEdbClassifyReq struct {
 // @param classifyType uint8
 // @return count int
 // @return err error
-func GetEdbClassifyCount(classifyName string, parentId int, classifyType uint8) (count int, err error) {
-	sql := `SELECT COUNT(1) AS count FROM edb_classify WHERE parent_id=? AND classify_name=? AND classify_type = ? `
-	err = global.DmSQL["data"].Raw(sql, parentId, classifyName, classifyType).Scan(&count).Error
+func GetEdbClassifyCount(classifyName string, parentId, sysUserId int, classifyType uint8) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM edb_classify WHERE parent_id=? AND classify_name=? AND classify_type = ? AND sys_user_id = ?  `
+	err = global.DmSQL["data"].Raw(sql, parentId, classifyName, classifyType, sysUserId).Scan(&count).Error
 
 	return
 }
@@ -67,9 +67,9 @@ func GetEdbClassifyCount(classifyName string, parentId int, classifyType uint8)
 // @param classifyType uint8
 // @return count int
 // @return err error
-func GetEdbClassifyEnCount(classifyNameEn string, parentId int, classifyType uint8) (count int, err error) {
-	sql := `SELECT COUNT(1) AS count FROM edb_classify WHERE parent_id=? AND classify_name_en = ? AND classify_type = ? `
-	err = global.DmSQL["data"].Raw(sql, parentId, classifyNameEn, classifyType).Scan(&count).Error
+func GetEdbClassifyEnCount(classifyNameEn string, parentId, sysUserId int, classifyType uint8) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM edb_classify WHERE parent_id=? AND classify_name_en = ? AND classify_type = ? AND sys_user_id = ? `
+	err = global.DmSQL["data"].Raw(sql, parentId, classifyNameEn, classifyType, sysUserId).Scan(&count).Error
 
 	return
 }
@@ -675,3 +675,21 @@ func GetChildEdbClassifyListByParentId(classifyIdPath, orderStr string) (items [
 
 	return
 }
+
+// GetEdbClassifyItemsByIdList
+// @Description: 根据分类id列表获取分类列表
+// @author: Roc
+// @datetime 2024-03-29 10:30:21
+// @param classifyId int
+// @return item *EdbClassify
+// @return err error
+func GetEdbClassifyItemsByIdList(classifyIdList []int) (item []*EdbClassifyItems, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	sql := `SELECT * FROM edb_classify WHERE classify_id in (` + utils.GetOrmInReplace(num) + `) `
+	err = global.DmSQL["data"].Raw(sql, classifyIdList).Scan(&item).Error
+
+	return
+}

+ 132 - 48
models/data_manage/edb_info.go

@@ -20,54 +20,56 @@ import (
 )
 
 type EdbInfo struct {
-	EdbInfoId        int       `gorm:"primaryKey" `
-	EdbInfoType      int       `description:"指标类型,0:普通指标,1:预测指标"`
-	SourceName       string    `description:"来源名称"`
-	Source           int       `description:"来源id"`
-	EdbCode          string    `description:"指标编码"`
-	EdbName          string    `description:"指标名称"`
-	EdbNameEn        string    `description:"英文指标名称"`
-	EdbNameSource    string    `description:"指标名称来源"`
-	Frequency        string    `description:"频率"`
-	Unit             string    `description:"单位"`
-	UnitEn           string    `description:"英文单位"`
-	StartDate        time.Time `description:"起始日期"`
-	EndDate          time.Time `description:"终止日期"`
-	ClassifyId       int       `description:"分类id"`
-	SysUserId        int
-	SysUserRealName  string
-	UniqueCode       string `description:"指标唯一编码"`
-	CreateTime       time.Time
-	ModifyTime       time.Time
-	BaseModifyTime   time.Time
-	MinValue         float64 `description:"指标最小值"`
-	MaxValue         float64 `description:"指标最大值"`
-	CalculateFormula string  `description:"计算公式"`
-	EdbType          int     `description:"指标类型:1:基础指标,2:计算指标"`
-	Sort             int     `description:"排序字段"`
-	LatestDate       string  `description:"数据最新日期(实际日期)"`
-	LatestValue      float64 `description:"数据最新值(实际值)"`
-	EndValue         float64 `description:"数据的最新值(预测日期的最新值)"`
-	MoveType         int     `description:"移动方式:1:领先(默认),2:滞后"`
-	MoveFrequency    string  `description:"移动频度"`
-	NoUpdate         int8    `description:"是否停止更新,0:继续更新;1:停止更新"`
-	ServerUrl        string  `description:"服务器地址"`
-	ChartImage       string  `description:"图表图片"`
-	Calendar         string  `description:"公历/农历" orm:"default(公历);"`
-	DataDateType     string  `orm:"column(data_date_type);size(255);null;default(交易日)"`
-	ManualSave       int     `description:"是否有手动保存过上下限: 0-否; 1-是"`
-	EmptyType        int     `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
-	MaxEmptyType     int     `description:"MAX、MIN公式空值处理类型(1、等于0;2、跳过空值)"`
-	TerminalCode     string  `description:"终端编码,用于配置在机器上"`
-	DataUpdateTime   string  `description:"最近一次数据发生变化的时间"`
-	ErDataUpdateDate string  `description:"本次更新,数据发生变化的最早日期"`
-	SourceIndexName  string  `description:"数据源中的指标名称"`
-	SubSource        int     `description:"子数据来源:0:经济数据库,1:日期序列"`
-	SubSourceName    string  `description:"子数据来源名称"`
-	IndicatorCode    string  `description:"指标代码"`
-	StockCode        string  `description:"证券代码"`
-	Extra            string  `description:"指标额外配置"`
-	IsJoinPermission int     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	EdbInfoId           int       `gorm:"primaryKey" `
+	EdbInfoType         int       `description:"指标类型,0:普通指标,1:预测指标"`
+	SourceName          string    `description:"来源名称"`
+	Source              int       `description:"来源id"`
+	EdbCode             string    `description:"指标编码"`
+	EdbName             string    `description:"指标名称"`
+	EdbNameEn           string    `description:"英文指标名称"`
+	EdbNameSource       string    `description:"指标名称来源"`
+	Frequency           string    `description:"频率"`
+	Unit                string    `description:"单位"`
+	UnitEn              string    `description:"英文单位"`
+	StartDate           time.Time `description:"起始日期"`
+	EndDate             time.Time `description:"终止日期"`
+	ClassifyId          int       `description:"分类id"`
+	SysUserId           int
+	SysUserRealName     string
+	UniqueCode          string `description:"指标唯一编码"`
+	CreateTime          time.Time
+	ModifyTime          time.Time
+	BaseModifyTime      time.Time
+	MinValue            float64 `description:"指标最小值"`
+	MaxValue            float64 `description:"指标最大值"`
+	CalculateFormula    string  `description:"计算公式"`
+	EdbType             int     `description:"指标类型:1:基础指标,2:计算指标"`
+	Sort                int     `description:"排序字段"`
+	LatestDate          string  `description:"数据最新日期(实际日期)"`
+	LatestValue         float64 `description:"数据最新值(实际值)"`
+	EndValue            float64 `description:"数据的最新值(预测日期的最新值)"`
+	MoveType            int     `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency       string  `description:"移动频度"`
+	NoUpdate            int8    `description:"是否停止更新,0:继续更新;1:停止更新"`
+	ServerUrl           string  `description:"服务器地址"`
+	ChartImage          string  `description:"图表图片"`
+	Calendar            string  `description:"公历/农历" orm:"default(公历);"`
+	DataDateType        string  `orm:"column(data_date_type);size(255);null;default(交易日)"`
+	ManualSave          int     `description:"是否有手动保存过上下限: 0-否; 1-是"`
+	EmptyType           int     `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
+	MaxEmptyType        int     `description:"MAX、MIN公式空值处理类型(1、等于0;2、跳过空值)"`
+	TerminalCode        string  `description:"终端编码,用于配置在机器上"`
+	DataUpdateTime      string  `description:"最近一次数据发生变化的时间"`
+	ErDataUpdateDate    string  `description:"本次更新,数据发生变化的最早日期"`
+	SourceIndexName     string  `description:"数据源中的指标名称"`
+	SubSource           int     `description:"子数据来源:0:经济数据库,1:日期序列"`
+	SubSourceName       string  `description:"子数据来源名称"`
+	IndicatorCode       string  `description:"指标代码"`
+	StockCode           string  `description:"证券代码"`
+	Extra               string  `description:"指标额外配置"`
+	IsJoinPermission    int     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	PublicStatus        int     `description:"公开状态;0:未公开;1:审批中;2:已驳回;3:已公开"`
+	EdbPublicClassifyId int     `description:"指标公开分类id"`
 }
 
 type EdbInfoFullClassify struct {
@@ -411,6 +413,8 @@ type EdbInfoList struct {
 	CollectClassifyIdList []int                   `description:"所属收藏分类id列表" gorm:"-"`
 	SharedUserIdList      []int                   `description:"共享用户id列表" gorm:"-"`
 	PublicStatus          int                     `description:"公开状态;0:未公开;1:审批中;2:已驳回;3:已公开"`
+	EdbPublicClassifyId   int                     `description:"指标公开分类id"`
+	PublicTime            time.Time               `description:"设置公开的时间"`
 }
 
 type EdbDataInsertConfigItem struct {
@@ -497,6 +501,17 @@ func GetEdbInfoByCondition(condition string, pars []interface{}) (item *EdbInfoL
 	return
 }
 
+func GetEdbInfoEsByCondition(condition string, pars []interface{}) (item *EdbInfoEs, err error) {
+	o := global.DmSQL["data"]
+	sql := ` SELECT * FROM edb_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).First(&item).Error
+
+	return
+}
+
 func GetEdbDataCountByCondition(condition string, pars []interface{}, source, subSource int) (count int, err error) {
 	o := global.DmSQL["data"]
 	tableName := GetEdbDataTableName(source, subSource)
@@ -1289,6 +1304,69 @@ func GetEdbInfoFilterList(condition string, pars []interface{}, startSize, pageS
 	return
 }
 
+// EdbInfoEs 写入es的指标数据结构
+type EdbInfoEs struct {
+	EdbInfoId             int        `orm:"column(edb_info_id);pk" gorm:"primaryKey" `
+	EdbInfoType           int        `description:"指标类型,0:普通指标,1:预测指标"`
+	SourceName            string     `description:"来源名称"`
+	Source                int        `description:"来源id"`
+	EdbCode               string     `description:"指标编码"`
+	EdbNameEn             string     `description:"英文指标名称"`
+	EdbName               string     `description:"指标名称"`
+	Frequency             string     `description:"频率"`
+	FrequencyEn           string     `description:"英文频率"`
+	Unit                  string     `description:"单位"`
+	UnitEn                string     `description:"英文单位"`
+	StartDate             string     `description:"起始日期"`
+	EndDate               string     `description:"终止日期"`
+	LatestDate            string     `description:"数据最新日期(实际日期)"`
+	LatestValue           float64    `description:"数据最新值(实际值)"`
+	EndValue              float64    `description:"数据的最新值(预测日期的最新值)"`
+	ClassifyId            int        `description:"分类id"`
+	UniqueCode            string     `description:"指标唯一编码"`
+	SysUserId             int        `description:"创建人id"`
+	SysUserRealName       string     `description:"创建人姓名"`
+	ModifyTime            string     `description:"最新修改时间"`
+	CreateTime            string     `description:"创建时间"`
+	EdbNameAlias          string     `json:"-" description:"指标名称,别名"`
+	EdbType               int        `description:"指标类型:1:基础指标,2:计算指标"`
+	ChartImage            string     `description:"图表图片"`
+	RuleType              int        `description:"预测规则,1:最新,2:固定值"`
+	FixedValue            float64    `description:"固定值"`
+	IsEnEdb               bool       `description:"是否展示英文标识"`
+	DataDateType          string     `description:"数据日期类型,枚举值:交易日、自然日"`
+	SubSource             int        `description:"子数据来源:0:经济数据库,1:日期序列"`
+	SubSourceName         string     `description:"子数据来源名称"`
+	IndicatorCode         string     `description:"指标代码"`
+	StockCode             string     `description:"证券代码"`
+	NoUpdate              int8       `description:"是否停止更新,0:继续更新;1:停止更新"`
+	IsJoinPermission      int        `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth         bool       `description:"是否有数据权限,默认:false"`
+	IsSupplierStop        int        `description:"是否供应商停更:1:停更,0:未停更"`
+	CollectClassifyIdList []int      `description:"所属收藏分类id列表" gorm:"-"`
+	SharedUserIdList      []int      `description:"共享用户id列表" gorm:"-"`
+	PublicStatus          int        `description:"公开状态;0:未公开;1:审批中;2:已驳回;3:已公开"`
+	EdbPublicClassifyId   int        `description:"指标公开分类id"`
+	PublicTime            *time.Time `description:"设置公开的时间"`
+}
+
+// GetEsEdbInfo 获取指指标列表数据接口
+func GetEsEdbInfo(condition string, pars []interface{}, startSize, pageSize int) (total int64, list []*EdbInfoEs, err error) {
+	o := global.DmSQL["data"]
+
+	sql := ` SELECT count(1) total FROM edb_info where 1=1 ` + condition + ` ORDER BY edb_info_id DESC `
+	err = o.Raw(sql, pars...).Scan(&total).Error
+	if err != nil {
+		return
+	}
+
+	sql = ` SELECT * FROM edb_info where 1=1 ` + condition + ` ORDER BY edb_info_id DESC  LIMIT ?,? `
+	pars = append(pars, startSize, pageSize)
+	err = o.Raw(sql, pars...).Scan(&list).Error
+
+	return
+}
+
 // SetEdbInfoImageReq 设置指标图片
 type SetEdbInfoImageReq struct {
 	EdbInfoId int    `description:"指标ID"`
@@ -2065,3 +2143,9 @@ func UpdateClassifyIdByEdbInfoId(edbInfoId, edbClassifyId int) (err error) {
 	err = global.DmSQL["data"].Exec(sql, edbClassifyId, edbInfoId).Error
 	return
 }
+
+// SetEdbInfoImageReq 设置指标图片
+type EsEdbReq struct {
+	KeyWord  string `description:"关键字" form:"KeyWord"`
+	ImageUrl string `description:"指标图片地址" form:"ImageUrl"`
+}

+ 134 - 0
models/data_manage/edb_info_share.go

@@ -1,6 +1,7 @@
 package data_manage
 
 import (
+	sql2 "database/sql"
 	"eta_gn/eta_api/global"
 	"eta_gn/eta_api/utils"
 	"fmt"
@@ -52,6 +53,7 @@ func (m EdbInfoShare) GetListByEdbInfoId(edbInfoId int) (items []*EdbInfoShare,
 // @param shareType int8
 // @return err error
 func (m EdbInfoShare) SaveEdbInfoShare(edbInfoIdList, userIdList []int, shareType int8) (err error) {
+	// TODO 保存之前,得先做关联校验
 	addList := make([]*EdbInfoShare, 0)
 	for _, edbInfoId := range edbInfoIdList {
 		for _, userId := range userIdList {
@@ -91,3 +93,135 @@ func (m EdbInfoShare) SaveEdbInfoShare(edbInfoIdList, userIdList []int, shareTyp
 
 	return
 }
+
+// ShareEdbInfoQuery
+// @Description: 共享指标
+type ShareEdbInfoQuery struct {
+	EdbInfo
+	ShareType string    `gorm:"column:share_type" description:"共享类型"`
+	ShareTime time.Time `gorm:"column:share_time" description:"设置共享时间"`
+}
+
+// GetAllSharedEdbInfoListByFromUserId
+// @Description: 获取所有我共享出去的指标列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-03 09:56:41
+// @param sysUserId int
+// @return list []*ShareEdbInfoQuery
+// @return err error
+func (m EdbInfoShare) GetAllSharedEdbInfoListByFromUserId(sysUserId int) (list []*ShareEdbInfoQuery, err error) {
+	sql := `SELECT b."edb_info_id",
+       MAX(a.share_type) AS share_type,
+MAX(a.create_time) as share_time,
+MAX(b."edb_code") AS "edb_code",
+MAX(b."edb_name") "edb_name",
+MAX(b."edb_info_type") "edb_info_type",
+MAX(b."edb_type") "edb_type",
+MAX(b."source") "source",
+MAX(b."source_name") "source_name",
+MAX(b."frequency") "frequency",
+MAX(b."unit") "unit",
+MAX(b."classify_id") "classify_id",
+MAX(b."create_time") "create_time",
+MAX(b."unique_code") "unique_code",
+MAX(b."chart_image") "chart_image",
+MAX(b."modify_time") "modify_time",
+MAX(b."start_date") "start_date",
+MAX(b."sort") AS "sort"
+ FROM edb_info_share AS a 
+     JOIN edb_info AS b ON a.edb_info_id = b.edb_info_id
+	  WHERE 1=1 AND b.sys_user_id = ?
+	  GROUP BY b.edb_info_id
+ORDER BY share_time DESC`
+	err = global.DmSQL["data"].Raw(sql, sysUserId).Scan(&list).Error
+	return
+}
+
+// GetAllSharedEdbInfoListByReceivedUserId
+// @Description: 获取所有我收到的共享的指标列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-03 09:56:41
+// @param sysUserId int
+// @return list []*ShareEdbInfoQuery
+// @return err error
+func (m EdbInfoShare) GetAllSharedEdbInfoListByReceivedUserId(sysUserId int) (list []*ShareEdbInfoQuery, err error) {
+	sql := `SELECT b."edb_info_id",
+       MAX(a.share_type) AS share_type,
+MAX(a.create_time) as share_time,
+MAX(b."edb_code") AS "edb_code",
+MAX(b."edb_name") "edb_name",
+MAX(b."edb_info_type") "edb_info_type",
+MAX(b."edb_type") "edb_type",
+MAX(b."source") "source",
+MAX(b."source_name") "source_name",
+MAX(b."frequency") "frequency",
+MAX(b."unit") "unit",
+MAX(b."classify_id") "classify_id",
+MAX(b."create_time") "create_time",
+MAX(b."unique_code") "unique_code",
+MAX(b."chart_image") "chart_image",
+MAX(b."modify_time") "modify_time",
+MAX(b."start_date") "start_date",
+MAX(b."sort") AS "sort"
+ FROM edb_info_share AS a 
+     JOIN edb_info AS b ON a.edb_info_id = b.edb_info_id
+	  WHERE 1=1 AND a.sys_user_id = ? AND b.sys_user_id != ?
+	  GROUP BY b.edb_info_id
+ORDER BY share_time DESC`
+	err = global.DmSQL["data"].Raw(sql, sysUserId, sysUserId).Scan(&list).Error
+	return
+}
+
+// GetShareEdbInfoListPageList
+// @Description: 获取分享的指标列表(分页)
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-03 14:42:12
+// @param condition string
+// @param pars []interface{}
+// @param startSize int
+// @param pageSize int
+// @return total int32
+// @return list []*EdbInfoList
+// @return err error
+func (m EdbInfoShare) GetShareEdbInfoListPageList(condition string, pars []interface{}, startSize, pageSize int) (total int32, list []*EdbInfoList, err error) {
+	baseSql := `SELECT b."edb_info_id",
+       MAX(a.share_type) AS share_type,
+MAX(a.create_time) as share_time,
+MAX(b."edb_code") AS "edb_code",
+MAX(b."edb_name") "edb_name",
+MAX(b."edb_info_type") "edb_info_type",
+MAX(b."edb_type") "edb_type",
+MAX(b."source") "source",
+MAX(b."source_name") "source_name",
+MAX(b."frequency") "frequency",
+MAX(b."unit") "unit",
+MAX(b."classify_id") "classify_id",
+MAX(b."create_time") "create_time",
+MAX(b."unique_code") "unique_code",
+MAX(b."chart_image") "chart_image",
+MAX(b."modify_time") "modify_time",
+MAX(b."start_date") "start_date",
+MAX(b."sort") AS "sort"
+  FROM edb_info_share AS a 
+     JOIN edb_info AS b ON a.edb_info_id = b.edb_info_id
+	  WHERE 1=1 `
+
+	baseSql += condition
+	baseSql += ` GROUP BY b.edb_info_id `
+
+	totalSql := `SELECT COUNT(1) AS total FROM (` + baseSql + `) AS d`
+	var totalNull sql2.NullInt32
+	err = global.DmSQL["data"].Raw(totalSql, pars...).Scan(&totalNull).Error
+	if err != nil {
+		return
+	}
+	total = totalNull.Int32
+
+	sql := baseSql + ` ORDER BY share_time DESC LIMIT ?,? `
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["data"].Raw(sql, pars...).Scan(&list).Error
+	return
+}

+ 257 - 0
models/data_manage/public_edb_classify.go

@@ -0,0 +1,257 @@
+package data_manage
+
+import (
+	"eta_gn/eta_api/global"
+	"fmt"
+	"time"
+)
+
+// EdbPublicClassify
+// @Description: 公共分类
+type EdbPublicClassify struct {
+	EdbPublicClassifyId       int       `gorm:"primaryKey" `
+	ClassifyType              uint8     `description:"分类类型,0:普通指标分类,1:预测指标分类,2:指标加工的分类(普通指标的计算指标)"`
+	EdbPublicClassifyName     string    `description:"分类名称"`
+	ParentId                  int       `description:"父级id"`
+	HasData                   int       `description:"是否含有指标数据"`
+	RootId                    int       `description:"顶级id"`
+	CreateTime                time.Time `description:"创建时间"`
+	ModifyTime                time.Time `description:"修改时间"`
+	SysUserId                 int       `description:"创建人id"`
+	SysUserRealName           string    `description:"创建人姓名"`
+	Level                     int       `description:"层级"`
+	UniqueCode                string    `description:"唯一编码"`
+	Sort                      int       `description:"排序字段,越小越靠前,默认值:10"`
+	LastModifyUserId          int       `description:"最后修改人ID"`
+	LastModifyUserRealName    string    `description:"最后修改人姓名"`
+	EdbPublicClassifyNamePath string    `description:"分类名称的完整路径,格式为:父级分类名称|当前分类名称"`
+	EdbPublicClassifyIdPath   string    `description:"分类的完整路径,格式为:父级ID,当前ID"`
+}
+
+func (m EdbPublicClassify) ToEdbClassifyItems() *EdbClassifyItems {
+	return &EdbClassifyItems{
+		ClassifyId: m.EdbPublicClassifyId,
+		//EdbInfoId:        0,
+		ClassifyType:   m.ClassifyType,
+		ClassifyName:   m.EdbPublicClassifyName,
+		ClassifyNameEn: m.EdbPublicClassifyName,
+		ParentId:       m.ParentId,
+		RootId:         m.RootId,
+		Level:          m.Level,
+		Sort:           m.Sort,
+		UniqueCode:     m.UniqueCode,
+		//Source:           0,
+		//SourceName:       "",
+		SysUserId:       m.SysUserId,
+		SysUserRealName: m.SysUserRealName,
+		//StartDate:        "",
+		//EdbCode:          "",
+		//EdbType:          0,
+		//Children:         nil,
+		//Button:           EdbClassifyItemsButton{},
+		//IsJoinPermission: 0,
+		//HaveOperaAuth:    false,
+		ClassifyIdPath: m.EdbPublicClassifyIdPath,
+	}
+}
+
+// Add
+// @Description: 添加分类
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-04 17:00:18
+// @return err error
+func (m *EdbPublicClassify) Add() (err error) {
+	err = global.DmSQL["data"].Create(m).Error
+
+	return
+}
+
+// Update
+// @Description: 更新分类基础信息
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-04 17:01:51
+// @param cols []string
+// @return err error
+func (m *EdbPublicClassify) Update(cols []string) (err error) {
+	err = global.DmSQL["data"].Select(cols).Updates(m).Error
+
+	return
+}
+
+// GetEdbClassifyById
+// @Description: 根据id获取分类
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-04 16:56:15
+// @param classifyId int
+// @return item *EdbPublicClassify
+// @return err error
+func (m EdbPublicClassify) GetEdbClassifyById(classifyId int) (item *EdbPublicClassify, err error) {
+	sql := `SELECT * FROM edb_public_classify WHERE edb_public_classify_id=? `
+	err = global.DmSQL["data"].Raw(sql, classifyId).First(&item).Error
+
+	return
+}
+
+// GetEdbClassifyListByParentId
+// @Description: 根据父级id获取下级分类列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-03 13:57:48
+// @param parentId int
+// @param classifyType int8
+// @return items []*EdbPublicClassify
+// @return err error
+func (m EdbPublicClassify) GetEdbClassifyListByParentId(parentId int, classifyType int8) (items []*EdbPublicClassify, err error) {
+	o := global.DmSQL["data"]
+	sql := `SELECT * FROM edb_public_classify WHERE parent_id=? AND classify_type = ? order by sort asc,edb_public_classify_id asc `
+	err = o.Raw(sql, parentId, classifyType).Find(&items).Error
+
+	return
+}
+
+// GetEdbClassifyItemsByParentId
+// @Description: 根据父级id获取下级分类列表(结构型的)
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-03 13:56:18
+// @param parentId int
+// @param classifyType int8
+// @return items []*EdbClassifyItems
+// @return err error
+func (m EdbPublicClassify) GetEdbClassifyItemsByParentId(parentId int, classifyType int8) (items []*EdbClassifyItems, err error) {
+	list, err := m.GetEdbClassifyListByParentId(parentId, classifyType)
+	if err != nil {
+		return
+	}
+
+	for _, v := range list {
+		items = append(items, v.ToEdbClassifyItems())
+	}
+
+	return
+}
+
+// GetEdbClassifyListByParentId
+// @Description: 根据父级id获取下级分类列表
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-03 13:57:48
+// @param parentId int
+// @param classifyType int8
+// @return items []*EdbPublicClassify
+// @return err error
+func (m EdbPublicClassify) GetEdbClassifyListByType(classifyType int8) (items []*EdbPublicClassify, err error) {
+	o := global.DmSQL["data"]
+	sql := `SELECT * FROM edb_public_classify WHERE classify_type = ? order by sort asc,edb_public_classify_id asc `
+	err = o.Raw(sql, classifyType).Find(&items).Error
+
+	return
+}
+
+// GetAllEdbClassifyByType 根据类型获取分类列表
+func (m EdbPublicClassify) GetAllEdbClassifyByType(classifyType int8) (items []*EdbClassifyItems, err error) {
+	list, err := m.GetEdbClassifyListByType(int8(classifyType))
+	if err != nil {
+		return
+	}
+
+	for _, v := range list {
+		items = append(items, v.ToEdbClassifyItems())
+	}
+
+	return
+}
+
+func (m EdbPublicClassify) GetEdbClassifyCount(classifyName string, parentId int, classifyType uint8) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM edb_public_classify WHERE parent_id=? AND edb_public_classify_name=? AND classify_type = ?  `
+	err = global.DmSQL["data"].Raw(sql, parentId, classifyName, classifyType).Scan(&count).Error
+
+	return
+}
+
+// UpdateEdbClassifyNameAndNamePath
+// @Description: 更新分类信息
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-05 09:27:33
+// @param cols []string
+// @param oldClassifyNamePath string
+// @param newClassifyNamePath string
+// @return err error
+func (m *EdbPublicClassify) UpdateEdbClassifyNameAndNamePath(cols []string, oldClassifyNamePath, newClassifyNamePath string) (err error) {
+	tx := global.DmSQL["data"].Begin()
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	// 变更分类信息
+	err = tx.Select(cols).Updates(m).Error
+	if err != nil {
+		return
+	}
+
+	// 更改子分类的完整的路径
+	if oldClassifyNamePath != `` && newClassifyNamePath != `` {
+		sql := `UPDATE edb_public_classify SET edb_public_classify_name_path = REPLACE(edb_public_classify_name_path,?,?) WHERE edb_public_classify_id_path LIKE ?`
+		err = tx.Exec(sql, oldClassifyNamePath, newClassifyNamePath, fmt.Sprint(m.EdbPublicClassifyIdPath+`,%`)).Error
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// GetEdbClassifyMaxSort 获取分类下最大的排序数
+func (m EdbPublicClassify) GetEdbClassifyMaxSort(parentId int, classifyType uint8) (sort int, err error) {
+	sql := `SELECT COALESCE(Max(sort), 0) AS sort FROM edb_public_classify WHERE parent_id=? AND classify_type=? `
+	err = global.DmSQL["data"].Raw(sql, parentId, classifyType).Scan(&sort).Error
+
+	return
+}
+
+// GetEdbInfoCountByClassifyIdList
+// @Description: 根据公共分类id集合获取名下指标数量
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-05 09:59:56
+// @param classifyIdList []int
+// @return count int
+// @return err error
+func (m EdbPublicClassify) GetEdbInfoCountByClassifyIdList(classifyIdList []int) (count int, err error) {
+	if len(classifyIdList) <= 0 {
+		return
+	}
+	sql := `SELECT COUNT(1) total FROM edb_info  WHERE edb_public_classify_id IN (?) `
+	err = global.DmSQL["data"].Raw(sql, classifyIdList).Scan(&count).Error
+
+	return
+}
+
+func (m *EdbPublicClassify) GetAllChildClassifyIdList() (items []int, err error) {
+	sql := ` SELECT edb_public_classify_id FROM edb_public_classify  WHERE edb_public_classify_id_path LIKE ?  ORDER BY create_time DESC `
+	err = global.DmSQL["data"].Raw(sql, fmt.Sprint(m.EdbPublicClassifyIdPath+`,%`)).Scan(&items).Error
+
+	return
+}
+
+// BatchesDel
+// @Description: 根据分类id批量删除
+// @author: Roc
+// @receiver m
+// @datetime 2024-12-05 11:13:06
+// @param classifyIdList []int
+// @return err error
+func (m *EdbPublicClassify) BatchesDel(classifyIdList []int) (err error) {
+	sql := ` DELETE FROM edb_public_classify  WHERE edb_public_classify_id IN (?) `
+	err = global.DmSQL["data"].Exec(sql, classifyIdList).Error
+
+	return
+}

+ 68 - 0
models/data_manage/public_edb_info.go

@@ -0,0 +1,68 @@
+package data_manage
+
+import (
+	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/utils"
+)
+
+// GetEdbInfoByPublicClassifyId
+// @Description: 根据公共分类id获取指标列表
+// @author: Roc
+// @datetime 2024-12-03 14:09:32
+// @param classifyId int
+// @param edbInfoType int
+// @param edbType int
+// @return items []*EdbClassifyItems
+// @return err error
+func GetEdbInfoByPublicClassifyId(classifyId, edbInfoType, edbType int) (items []*EdbClassifyItems, err error) {
+	o := global.DmSQL["data"]
+	sql := ` SELECT edb_info_id,classify_id,edb_name AS classify_name,edb_name_en AS classify_name_en,unique_code,source_name,source,sys_user_id,sys_user_real_name,start_date,edb_code,edb_type, sort,is_join_permission FROM edb_info WHERE edb_public_classify_id = ? AND edb_info_type = ?`
+
+	pars := []interface{}{classifyId, edbInfoType}
+
+	// 如果筛选了指标类型,那么就根据条件来
+	if edbType > 0 {
+		sql += ` AND edb_type = ? `
+		pars = append(pars, edbType)
+	}
+
+	sql += ` order by sort asc,edb_info_id asc `
+	err = o.Raw(sql, pars...).Scan(&items).Error
+
+	return
+}
+
+// UpdatePublicEdbSuccess
+// @Description: 更新指标的公开成功状态
+// @author: Roc
+// @datetime 2024-12-06 13:37:01
+// @param edbInfoId int
+// @param classifyId int
+// @return err error
+func UpdatePublicEdbSuccess(edbInfoId, classifyId int) (err error) {
+	sql := `UPDATE edb_info set public_status = ?,edb_public_classify_id = ? ,modify_time=now(),public_time = now()  WHERE edb_info_id  = ?`
+	err = global.DmSQL["data"].Exec(sql, utils.EdbPublicSuccess, classifyId, edbInfoId).Error
+
+	return
+}
+
+// UpdatePublicEdb
+// @Description: 更新指标的公开状态
+// @author: Roc
+// @datetime 2024-12-06 11:10:53
+// @param edbInfoIdList []int
+// @param status int
+// @return err error
+func UpdatePublicEdb(edbInfoIdList []int, status int) (err error) {
+	if len(edbInfoIdList) <= 0 {
+		return
+	}
+	sql := `UPDATE edb_info set public_status = ?,modify_time=now() `
+	if status == utils.EdbPublicSuccess {
+		sql += `,public_time = now() `
+	}
+	sql += ` WHERE edb_info_id in (?) `
+	err = global.DmSQL["data"].Exec(sql, status, edbInfoIdList).Error
+
+	return
+}

+ 20 - 11
models/data_manage/request/edb_info_share.go

@@ -8,16 +8,25 @@ type SetEdbInfoShareReq struct {
 	ShareType  int8  `description:"分享类型,1:仅查看;2:可编辑"`
 }
 
-// SetEdbChartPermissionReq
+// SearchEdbInfoShareReq
+// @Description: 获取指标列表(设置共享的时候)请求结构体
+type SearchEdbInfoShareReq struct {
+	EdbShareList   []int  `description:"指标分享状态:1-未共享;2-已共享。可多选,默认是未共享"`
+	SourceList     []int  `description:"来源id"`
+	Keyword        string `description:"关键字"`
+	ClassifyIdList []int  `description:"分类选择,如果不指定分类,那么就是所有分类"`
+	CurrentIndex   int    `description:"当前页页码,从1开始"`
+	PageSize       int    `description:"每页数据条数"`
+}
+
+// SetEdbSharePermissionReq
 // @Description: 设置数据权限请求
-type SetEdbChartPermissionReq struct {
-	Source       int      `description:"来源id"`
-	SubSource    int      `description:"子来源id"`
-	UserId       int      `description:"用户筛选"`
-	DataIdList   []string `description:"指标/图表/表格唯一id列表"`
-	NoDataIdList []string `description:"指标/图表/表格唯一id列表"`
-	UserList     []int    `description:"赋权用户id列表,如果为空,说明要给这些指标移除权限管控"`
-	IsSelectAll  bool     `description:"是否选择所有指标"`
-	Classify     string   `description:"分类id,支持多选,用英文,隔开"`
-	Keyword      string   `description:"关键字"`
+type SetEdbSharePermissionReq struct {
+	SearchEdbInfoShareReq
+	EdbIdList   []int `description:"选中的指标id列表"`
+	NoEdbIdList []int `description:"未选中的指标id列表"`
+	IsSelectAll bool  `description:"是否选择所有指标"`
+
+	UserIdList []int `description:"分享用户id列表,如果为空,说明要给该指标移除分享人"`
+	ShareType  int8  `description:"分享类型,1:仅查看;2:可编辑"`
 }

+ 55 - 0
models/data_manage/request/edb_public.go

@@ -0,0 +1,55 @@
+package request
+
+// PublicClassifyDeleteCheckReq
+// @Description: 公共分类删除请求
+type PublicClassifyDeleteCheckReq struct {
+	ClassifyId int `description:"分类id"`
+}
+
+// SetEdbPublicReq
+// @Description: 设置指标公开的请求
+type SetEdbPublicReq struct {
+	EdbInfoList []SetEdbPublicEdbReq `description:"待设置的指标"`
+	Description string               `description:"备注"`
+}
+
+// CancelEdbPublicReq
+// @Description: 撤销指标公开的请求
+type CancelEdbPublicReq struct {
+	EdbInfoId   int    `description:"待设置的指标"`
+	Description string `description:"备注"`
+}
+
+type SetEdbPublicEdbReq struct {
+	EdbInfoId  int `description:"指标id列表"`
+	ClassifyId int `description:"公共分类id"`
+}
+
+// SearchPublicEdbReq
+// @Description: 获取指标列表(设置公开的时候)请求结构体
+type SearchPublicEdbReq struct {
+	EdbPublicList  []int  `description:"指标公开状态:1:未公开,2:已提交;3:已公开。可多选,默认是未公开"`
+	SourceList     []int  `description:"来源id"`
+	Keyword        string `description:"关键字"`
+	ClassifyIdList []int  `description:"分类选择,如果不指定分类,那么就是所有分类"`
+	CurrentIndex   int    `description:"当前页页码,从1开始"`
+	PageSize       int    `description:"每页数据条数"`
+}
+
+// AllSearchPublicEdbReq
+// @Description: 获取所有指标列表(设置公开的时候)请求结构体
+type AllSearchPublicEdbReq struct {
+	SearchPublicEdbReq
+	EdbIdList   []int `description:"选中的指标id列表"`
+	NoEdbIdList []int `description:"未选中的指标id列表"`
+	IsSelectAll bool  `description:"是否选择所有指标"`
+}
+
+// SetPublicEdbPermissionReq
+// @Description: 设置数据权限请求
+type SetPublicEdbPermissionReq struct {
+	SearchPublicEdbReq
+	EdbIdList   []int `description:"选中的指标id列表"`
+	NoEdbIdList []int `description:"未选中的指标id列表"`
+	IsSelectAll bool  `description:"是否选择所有指标"`
+}

+ 7 - 0
models/data_manage/response/edb_info_share.go

@@ -8,3 +8,10 @@ type EdbInfoShareUserResp struct {
 	ShareType int8                        `description:"分享类型,1:仅查看;2:可编辑"`
 	List      []*data_manage.EdbInfoShare `description:"分享用户列表"`
 }
+
+// EdbShareListResp
+// @Description: 共享列表
+type EdbShareListResp struct {
+	Send     data_manage.EdbClassifyItemList
+	Received data_manage.EdbClassifyItemList `description:"收到的共享"`
+}

+ 297 - 0
routers/commentsRouter.go

@@ -862,6 +862,96 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "Approve",
+            Router: `/approve`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "Cancel",
+            Router: `/cancel`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "CheckApproveOpen",
+            Router: `/check_open`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "MessageList",
+            Router: `/message/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "MessageRead",
+            Router: `/message/read`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveController"],
+        beego.ControllerComments{
+            Method: "Refuse",
+            Router: `/refuse`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveFlowController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveFlowController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/flow/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveFlowController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_approve:DataApproveFlowController"],
+        beego.ControllerComments{
+            Method: "Save",
+            Router: `/flow/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
         beego.ControllerComments{
             Method: "MoveAllEdbChartUser",
@@ -3742,6 +3832,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "BatchMoveEdb",
+            Router: `/edb_info/batch_move`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
             Method: "EdbChartList",
@@ -4183,6 +4282,33 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"],
+        beego.ControllerComments{
+            Method: "BatchSave",
+            Router: `/edb_info/share/batch_save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/edb_info/share/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"],
+        beego.ControllerComments{
+            Method: "ListByEs",
+            Router: `/edb_info/share/list/es`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"],
         beego.ControllerComments{
             Method: "Save",
@@ -4192,6 +4318,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"],
+        beego.ControllerComments{
+            Method: "Tree",
+            Router: `/edb_info/share/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbInfoShareController"],
         beego.ControllerComments{
             Method: "UserList",
@@ -4201,6 +4336,168 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "EdbClassifyMove",
+            Router: `/edb_classify/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "AddClassify",
+            Router: `/edb_public/classify/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "DeleteClassify",
+            Router: `/edb_public/classify/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "DeleteClassifyCheck",
+            Router: `/edb_public/classify/delete/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "ClassifyEdbInfoList",
+            Router: `/edb_public/classify/edb_info/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "EditEdbClassify",
+            Router: `/edb_public/classify/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "Items",
+            Router: `/edb_public/classify/items`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "ItemsV2",
+            Router: `/edb_public/classify/items/v2`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "ItemsV3",
+            Router: `/edb_public/classify/items/v3`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "ListV2",
+            Router: `/edb_public/classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "SimpleList",
+            Router: `/edb_public/classify/simple`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicClassifyController"],
+        beego.ControllerComments{
+            Method: "ClassifyTree",
+            Router: `/edb_public/classify/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"],
+        beego.ControllerComments{
+            Method: "Cancel",
+            Router: `/edb_info/public/cancel`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"],
+        beego.ControllerComments{
+            Method: "ListByEs",
+            Router: `/edb_info/public/list/es`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"],
+        beego.ControllerComments{
+            Method: "AllListByEs",
+            Router: `/edb_info/public/list/es/all`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"],
+        beego.ControllerComments{
+            Method: "Save",
+            Router: `/edb_info/public/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/edb_public/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:EdbPublicController"],
+        beego.ControllerComments{
+            Method: "RemoveCheck",
+            Router: `/edb_public/remove/check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:FactorEdbSeriesController"] = append(beego.GlobalControllerRouter["eta_gn/eta_api/controllers/data_manage:FactorEdbSeriesController"],
         beego.ControllerComments{
             Method: "Add",

+ 9 - 0
routers/router.go

@@ -14,6 +14,7 @@ import (
 	"eta_gn/eta_api/controllers/data_manage"
 	"eta_gn/eta_api/controllers/data_manage/correlation"
 	"eta_gn/eta_api/controllers/data_manage/cross_variety"
+	"eta_gn/eta_api/controllers/data_manage/data_approve"
 	"eta_gn/eta_api/controllers/data_manage/data_manage_permission"
 	"eta_gn/eta_api/controllers/data_manage/excel"
 	future_good2 "eta_gn/eta_api/controllers/data_manage/future_good"
@@ -161,6 +162,14 @@ func init() {
 				&data_manage.EdbCollectController{},
 				&data_manage.EdbCollectClassifyController{},
 				&data_manage.EdbInfoShareController{},
+				&data_manage.EdbPublicController{},
+				&data_manage.EdbPublicClassifyController{},
+			),
+			web.NSNamespace("/data_approve",
+				web.NSInclude(
+					&data_approve.DataApproveController{},
+					&data_approve.DataApproveFlowController{},
+				),
 			),
 		),
 		web.NSNamespace("/my_chart",

+ 59 - 25
services/data/chart_classify.go

@@ -57,6 +57,40 @@ func ChartClassifyItemsMakeTree(sysUser *system.Admin, allNode []*data_manage.Ch
 	}
 }
 
+func ChartClassifyItemsMakeTreeV2(allNode []*data_manage.ChartClassifyItems, node *data_manage.ChartClassifyItems) {
+	//node.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(node.IsJoinPermission, node.ChartClassifyId, permissionClassifyIdList)
+	//button := GetChartClassifyOpButton(sysUser, node.SysUserId, node.HaveOperaAuth)
+	//node.Button = button
+
+	childs, _ := chartClassifyHaveChild(allNode, node) //判断节点是否有子节点并返回
+	if len(childs) > 0 {
+		//for _, child := range childs {
+		//child.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(child.IsJoinPermission, child.ChartClassifyId, permissionClassifyIdList)
+		//childButton := GetChartClassifyOpButton(sysUser, child.SysUserId, child.HaveOperaAuth)
+		//if child.Level == 3 {
+		//	childButton.AddButton = false //第三级的话,默认图表都是没有添加按钮的
+		//}
+		//child.Button = childButton
+		//node.Children = append(node.Children, child)
+		//}
+		node.Children = append(node.Children, childs[0:]...) //添加子节点
+		for _, v := range childs {
+			//v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ChartClassifyId, permissionClassifyIdList)
+			//查询子节点的子节点,并添加到子节点
+			_, has := chartClassifyHaveChild(allNode, v)
+			if has {
+				ChartClassifyItemsMakeTreeV2(allNode, v) //递归添加节点
+			} else {
+				childrenArr := make([]*data_manage.ChartClassifyItems, 0)
+				v.Children = childrenArr
+			}
+		}
+	} else {
+		childrenArr := make([]*data_manage.ChartClassifyItems, 0)
+		node.Children = childrenArr
+	}
+}
+
 // GetChartClassifyOpButton 获取ETA图库分类的操作权限
 func GetChartClassifyOpButton(sysUser *system.Admin, belongUserId int, haveOperaAuth bool) (button data_manage.ChartClassifyItemsButton) {
 	// 没有数据权限就直接返回
@@ -175,26 +209,26 @@ func AddChartClassify(chartClassifyName string, parentId, level, source int, lan
 	isSendEmail = true
 	errMsg = "保存分类失败"
 
-	// 校验分类名称相同的数量
-	{
-		var count int
-		switch lang {
-		case utils.EnLangVersion:
-			count, err = data_manage.GetChartClassifyEnCount(chartClassifyName, parentId, source)
-		default:
-			count, err = data_manage.GetChartClassifyCount(chartClassifyName, parentId, source)
-		}
-		if err != nil {
-			errMsg = "判断名称是否已存在失败"
-			return
-		}
-		if count > 0 {
-			errMsg = "分类名称已存在,请重新输入"
-			err = errors.New(errMsg)
-			isSendEmail = false
-			return
-		}
-	}
+	// 校验分类名称相同的数量(eta2.3,图表名称允许重复)
+	//{
+	//	var count int
+	//	switch lang {
+	//	case utils.EnLangVersion:
+	//		count, err = data_manage.GetChartClassifyEnCount(chartClassifyName, parentId, source)
+	//	default:
+	//		count, err = data_manage.GetChartClassifyCount(chartClassifyName, parentId, source)
+	//	}
+	//	if err != nil {
+	//		errMsg = "判断名称是否已存在失败"
+	//		return
+	//	}
+	//	if count > 0 {
+	//		errMsg = "分类名称已存在,请重新输入"
+	//		err = errors.New(errMsg)
+	//		isSendEmail = false
+	//		return
+	//	}
+	//}
 
 	if level > 6 {
 		errMsg = `最高只支持添加6级分类`
@@ -236,7 +270,7 @@ func AddChartClassify(chartClassifyName string, parentId, level, source int, lan
 	classifyInfo.SysUserRealName = sysUser.RealName
 	classifyInfo.Level = level + 1
 	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
-	classifyInfo.UniqueCode = utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
+	classifyInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
 	classifyInfo.Sort = maxSort + 1
 	classifyInfo.Source = source
 	classifyInfo.RootId = rootId
@@ -254,10 +288,10 @@ func AddChartClassify(chartClassifyName string, parentId, level, source int, lan
 		}
 	}
 
-	// 目前只有ETA图库需要继承分类权限
-	if classifyInfo.Source == utils.CHART_SOURCE_DEFAULT {
-		go data_manage_permission.InheritParentClassify(5, classifyInfo.Source, classifyInfo.ChartClassifyId, classifyInfo.ParentId, classifyInfo.ChartClassifyName)
-	}
+	//// 目前只有ETA图库需要继承分类权限
+	//if classifyInfo.Source == utils.CHART_SOURCE_DEFAULT {
+	//	go data_manage_permission.InheritParentClassify(5, classifyInfo.Source, classifyInfo.ChartClassifyId, classifyInfo.ParentId, classifyInfo.ChartClassifyName)
+	//}
 
 	return
 }

+ 1199 - 0
services/data/data_approve/approve.go

@@ -0,0 +1,1199 @@
+package data_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/models/data_manage"
+	dataApproveModel "eta_gn/eta_api/models/data_manage/data_approve"
+	"eta_gn/eta_api/models/data_manage/data_approve/response"
+	"eta_gn/eta_api/services/data"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"sort"
+	"strings"
+	"time"
+)
+
+var (
+	timeField   = map[int]string{1: fmt.Sprintf("a.%s", dataApproveModel.DataApproveRecordCols.CreateTime), 2: fmt.Sprintf("a.%s", dataApproveModel.DataApproveRecordCols.NodeApproveTime), 3: fmt.Sprintf("b.%s", dataApproveModel.DataApproveCols.ApproveTime)}
+	myTimeField = map[int]string{1: dataApproveModel.DataApproveCols.CreateTime, 3: dataApproveModel.DataApproveCols.ApproveTime}
+	orderRules  = map[int]string{1: "ASC", 2: "DESC"}
+)
+
+func PassDataApprove(approveId int, adminId int) (msg string, err error) {
+	approveItem, e := dataApproveModel.GetDataApproveById(approveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批不存在, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		return
+	}
+
+	if approveItem.State != DataApproveStateApproving {
+		msg = "审批状态有误, 请刷新页面"
+		err = fmt.Errorf("审批状态有误, State: %d", approveItem.State)
+		return
+	}
+
+	var ApprovePars []interface{}
+	ApproveCond := ` AND data_approve_id =? AND approve_user_id =? AND state =? `
+	ApprovePars = append(ApprovePars, approveId, adminId, DataApproveStateApproving)
+
+	recordItem, er := dataApproveModel.GetDataApproveRecordByCondition(ApproveCond, ApprovePars)
+	if er != nil {
+		if utils.IsErrNoRow(er) {
+			msg = "无权审批"
+			err = er
+			return
+		}
+		msg = "操作失败"
+		return
+	}
+
+	// 查询审批流和审批流节点
+	flowItem, e := dataApproveModel.GetDataApproveFlowById(approveItem.FlowId)
+	if e != nil {
+		err = fmt.Errorf("获取审批流失败, Err: %s", e.Error())
+		return
+	}
+	nodePars := make([]interface{}, 0)
+	nodeCond := ` AND data_approve_flow_id =? AND curr_version =? `
+	nodePars = append(nodePars, flowItem.DataApproveFlowId, flowItem.CurrVersion)
+	nodeItems, e := dataApproveModel.GetDataApproveNodeByCondition(nodeCond, nodePars)
+	if e != nil {
+		err = fmt.Errorf("ApproveNodes GetItemsByCondition err: %s", e.Error())
+		return
+	}
+	if len(nodeItems) == 0 {
+		err = fmt.Errorf("无审批节点")
+		return
+	}
+	nodeMap := make(map[int]*dataApproveModel.DataApproveNode)
+	for _, v := range nodeItems {
+		nodeMap[v.DataApproveNodeId] = v
+	}
+
+	// 取出审批记录的节点
+	currNodeItem := nodeMap[recordItem.NodeId]
+	if currNodeItem == nil {
+		err = fmt.Errorf("当前节点信息有误")
+		return
+	}
+	currNode, e := FormatDataApproveNode2Item(currNodeItem)
+	if e != nil {
+		err = fmt.Errorf("当前节点信息有误, Err: %s", e.Error())
+		return
+	}
+	now := time.Now().Local()
+	recordItem.State = DataApproveStatePass
+	recordItem.ApproveTime = now
+	recordItem.ModifyTime = now
+	recordItem.NodeState = DataApproveStatePass
+	recordItem.NodeApproveUserId = recordItem.ApproveUserId
+	recordItem.NodeApproveUserName = recordItem.ApproveUserName
+	recordItem.NodeApproveTime = now
+
+	recordCols := []string{"State", "ApproveTime", "ModifyTime", "NodeState", "NodeApproveUserId", "NodeApproveUserName", "NodeApproveTime"}
+	lastApprove := false
+
+	// 依次审批
+	if currNode.ApproveType == NodeApproveTypeRoll {
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		// 检查依次审批情况
+		sort.Slice(currNode.Users, func(k, j int) bool {
+			return currNode.Users[k].Sort < currNode.Users[j].Sort
+		})
+		userLen := len(currNode.Users)
+		//lastRoll := false
+		nextUser := new(response.DataApproveNodeUser) // 下一个审批人, 为nil则表示当前审批人即为最后
+		for k, v := range currNode.Users {
+			// 当前审批人
+			if v.UserId == adminId && recordItem.ApproveUserSort == v.Sort {
+				if (k + 1) < userLen {
+					nextUser = currNode.Users[k+1]
+				}
+			}
+		}
+		// 当前节点下一个审批人, 生成下一个审批记录且return
+		if nextUser.UserId > 0 {
+			newRecord := new(dataApproveModel.DataApproveRecord)
+			newRecord.DataApproveId = recordItem.DataApproveId
+			newRecord.State = DataApproveStateApproving
+			newRecord.NodeId = currNode.DataApproveNodeId
+			newRecord.PrevNodeId = currNode.PrevNodeId
+			newRecord.NextNodeId = currNode.NextNodeId
+			newRecord.ApproveType = currNode.ApproveType
+			newRecord.ApproveUserId = nextUser.UserId
+			newRecord.ApproveUserName = nextUser.UserName
+			newRecord.ApproveUserSort = nextUser.Sort
+			newRecord.CreateTime = now
+			newRecord.ModifyTime = now
+			newRecord.NodeState = DataApproveStateApproving
+			if e = newRecord.Create(); e != nil {
+				err = fmt.Errorf("生成审批记录失败, Err: %s", e.Error())
+				return
+			}
+
+			// 推送审批消息
+			go func() {
+				messageItem := new(dataApproveModel.DataApproveMessage)
+				messageItem.SendUserId = approveItem.ApplyUserId
+				messageItem.ReceiveUserId = nextUser.UserId
+				messageItem.Content = "您有新的待办任务"
+				messageItem.Remark = fmt.Sprintf("%s提交的【%s】需要您审批,请及时处理", approveItem.ApplyUserName, approveItem.Title)
+				messageItem.DataApproveId = approveItem.DataApproveId
+				messageItem.ApproveState = DataApproveStateApproving
+				messageItem.CreateTime = now
+				messageItem.ModifyTime = now
+				if e = messageItem.Create(); e != nil {
+					utils.FileLog.Info(fmt.Sprintf("PassDataApprove message err: %s", e.Error()))
+					return
+				}
+			}()
+			return
+		}
+
+		// 更新审批当前节点并进入下一个节点
+		if currNode.NextNodeId > 0 {
+			nextNode := nodeMap[currNode.NextNodeId]
+			approveItem.CurrNodeId = currNode.NextNodeId
+			approveItem.ModifyTime = now
+			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
+				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
+				return
+			}
+			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.DataApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.Title)
+			return
+		} else {
+			// 最后一个节点
+			lastApprove = true
+		}
+	}
+
+	// 会签
+	if currNode.ApproveType == NodeApproveTypeAll {
+		// 查询其他审批人是否已审批
+		otherCond := ` AND data_approve_id =? AND node_id =? AND approve_user_id <> ? `
+		otherPars := make([]interface{}, 0)
+		otherPars = append(otherPars, approveItem.DataApproveId, recordItem.NodeId, adminId)
+		otherRecords, e := dataApproveModel.GetDataApproveRecordItemsByCondition(otherCond, otherPars)
+		if e != nil {
+			err = fmt.Errorf("获取节点审批记录失败, Err: %s", e.Error())
+			return
+		}
+		otherPass := true
+		for _, v := range otherRecords {
+			if v.State != DataApproveStatePass {
+				otherPass = false
+			}
+		}
+
+		// 其他人未审批, 仅更新当前审批记录
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		// 其他人已审批且为最后节点
+		if otherPass && currNode.NextNodeId == 0 {
+			lastApprove = true
+		}
+
+		// 其他人已审批且不为最后节点, 进入下一节点
+		if otherPass && currNode.NextNodeId > 0 {
+			nextNode := nodeMap[currNode.NextNodeId]
+			approveItem.CurrNodeId = currNode.NextNodeId
+			approveItem.ModifyTime = now
+			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
+				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
+				return
+			}
+			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.DataApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.Title)
+			return
+		}
+	}
+
+	// 或签
+	if currNode.ApproveType == NodeApproveTypeAny {
+		// 需检查一下审批的当前节点和记录的节点是否匹配, 不匹配可能是因为另外的审批人已通过, 所以此处应给提示
+		// 前端也有做相应的判断,但是两个人同时进入审批详情页时就可能出现这种情况
+		if approveItem.CurrNodeId != recordItem.NodeId {
+			msg = "该节点已完成审批, 请刷新页面"
+			return
+		}
+
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		// 将该审批的同一个节点的记录标记为已审批
+		if e = recordItem.UpdateNodeState(recordItem.DataApproveId, recordItem.NodeId, recordItem.NodeState, recordItem.NodeApproveUserId, recordItem.NodeApproveUserName, recordItem.NodeApproveTime); e != nil {
+			err = fmt.Errorf("更新同一节点的其他审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		if currNode.NextNodeId == 0 {
+			lastApprove = true
+		}
+		if currNode.NextNodeId > 0 {
+			nextNode := nodeMap[currNode.NextNodeId]
+			approveItem.CurrNodeId = currNode.NextNodeId
+			approveItem.ModifyTime = now
+			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
+				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
+				return
+			}
+			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.DataApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.Title)
+			return
+		}
+	}
+
+	// 最后一个审批, 更新审批记录、审批、报告状态、推送消息给申请人
+	if lastApprove {
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+		approveItem.State = DataApproveStatePass
+		approveItem.ApproveTime = now
+		approveItem.ModifyTime = now
+		approveCols := []string{"State", "ApproveTime", "ModifyTime"}
+		if e = approveItem.Update(approveCols); e != nil {
+			err = fmt.Errorf("更新审批信息失败, Err: %s", e.Error())
+			return
+		}
+		if e = updateDataApproveState(approveItem, DataApproveStatePass); e != nil {
+			err = fmt.Errorf("更新报告审批状态失败, Err: %s", e.Error())
+			return
+		}
+
+		go func() {
+			messageItem := new(dataApproveModel.DataApproveMessage)
+			messageItem.SendUserId = adminId
+			messageItem.ReceiveUserId = approveItem.ApplyUserId
+			messageItem.Content = "您提交的审批已通过"
+			messageItem.Remark = fmt.Sprintf("您提交的【%s】已通过", approveItem.Title)
+			messageItem.DataApproveId = approveItem.DataApproveId
+			messageItem.ApproveState = DataApproveStatePass
+			messageItem.CreateTime = now
+			messageItem.ModifyTime = now
+			if e = messageItem.Create(); e != nil {
+				utils.FileLog.Info(fmt.Sprintf("PassDataApprove message err: %s", e.Error()))
+				return
+			}
+		}()
+	}
+	return
+
+}
+
+// BuildNextNodeRecordAndMsg 生成下一个节点的审批记录并推送消息
+func BuildNextNodeRecordAndMsg(approveNodeItem *dataApproveModel.DataApproveNode, approveId, sysAdminId int, sysAdminName, title string) (err error) {
+	if approveNodeItem == nil {
+		err = fmt.Errorf("approve node nil")
+		return
+	}
+
+	// 根据节点审批方式生成审批记录
+	now := time.Now().Local()
+	approveNode, e := FormatDataApproveNode2Item(approveNodeItem)
+	if e != nil {
+		err = fmt.Errorf("FormatDataApproveNode2Item err: %s", e.Error())
+		return
+	}
+	if len(approveNode.Users) == 0 {
+		err = fmt.Errorf("审批节点用户有误")
+		return
+	}
+	newRecords := make([]*dataApproveModel.DataApproveRecord, 0)
+	sort.Slice(approveNode.Users, func(k, j int) bool {
+		return approveNode.Users[k].Sort < approveNode.Users[j].Sort
+	})
+	for _, u := range approveNode.Users {
+		r := new(dataApproveModel.DataApproveRecord)
+		r.DataApproveId = approveId
+		r.State = DataApproveStateApproving
+		r.NodeId = approveNode.DataApproveNodeId
+		r.PrevNodeId = approveNode.PrevNodeId
+		r.NextNodeId = approveNode.NextNodeId
+		r.ApproveType = approveNode.ApproveType
+		r.ApproveUserId = u.UserId
+		r.ApproveUserName = u.UserName
+		r.ApproveUserSort = u.Sort
+		r.CreateTime = now
+		r.ModifyTime = now
+		r.NodeState = DataApproveStateApproving // 当前节点审批状态
+		newRecords = append(newRecords, r)
+		// 依次审批仅生成一条记录
+		if approveNode.ApproveType == NodeApproveTypeRoll {
+			break
+		}
+	}
+
+	recordOb := new(dataApproveModel.DataApproveRecord)
+	if e = recordOb.CreateMulti(newRecords); e != nil {
+		err = fmt.Errorf("生成节点审批记录失败, Err: %s", e.Error())
+		return
+	}
+
+	// 推送审批消息
+	go func() {
+		messageOb := new(dataApproveModel.DataApproveMessage)
+		messages := make([]*dataApproveModel.DataApproveMessage, 0)
+		for _, v := range newRecords {
+			m := new(dataApproveModel.DataApproveMessage)
+			m.SendUserId = sysAdminId
+			m.ReceiveUserId = v.ApproveUserId
+			m.Content = "您有新的待办任务"
+			m.Remark = fmt.Sprintf("%s提交的【%s】需要您审批,请及时处理", sysAdminName, title)
+			m.DataApproveId = approveId
+			m.ApproveState = DataApproveStateApproving
+			m.CreateTime = now
+			m.ModifyTime = now
+			messages = append(messages, m)
+		}
+		e = messageOb.CreateMulti(messages)
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("BuildNextNodeRecordAndMsg messages err: %s", e.Error()))
+			return
+		}
+	}()
+
+	return
+}
+
+// updateDataApproveState 更新待审批资产的审批状态
+func updateDataApproveState(dataApprove *dataApproveModel.DataApprove, state int) (err error) {
+	// TODO 根据审批单去通过、驳回公开图库申请
+	obj := dataApproveModel.DataApproveRelation{}
+	dataList, err := obj.GetListByDataApproveId(dataApprove.DataApproveId)
+	if err != nil {
+		return
+	}
+
+	dataItemList := make([]SetDataPublicItem, 0)
+	for _, v := range dataList {
+		dataItemList = append(dataItemList, SetDataPublicItem{ClassifyId: v.ClassifyId, DataId: v.DataId})
+	}
+
+	err = UpdatePublicByDataList(dataApprove.DataType, state, dataItemList)
+
+	return
+}
+
+// UpdatePublicByDataList
+// @Description: 更新公共资产权限
+// @author: Roc
+// @datetime 2024-12-06 13:44:20
+// @param dataType int
+// @param dataApproveState int
+// @param dataList []SetDataPublicItem
+// @return err error
+func UpdatePublicByDataList(dataType, dataApproveState int, dataList []SetDataPublicItem) (err error) {
+	dataIdList := make([]int, 0)
+	for _, v := range dataList {
+		dataIdList = append(dataIdList, v.DataId)
+	}
+	switch dataType {
+	case DataTypeEdb:
+		switch dataApproveState {
+		case DataApproveStateApproving:
+			err = data_manage.UpdatePublicEdb(dataIdList, utils.EdbPublicSuccess)
+		case DataApproveStatePass:
+			for _, dataItem := range dataList {
+				err = data_manage.UpdatePublicEdbSuccess(dataItem.DataId, dataItem.ClassifyId)
+			}
+		case DataApproveStateRefuse:
+			err = data_manage.UpdatePublicEdb(dataIdList, utils.EdbPublicReject)
+		case DataApproveStateCancel:
+			err = data_manage.UpdatePublicEdb(dataIdList, utils.EdbPublicDefault)
+		}
+
+		// 更新ES
+		for _, dataId := range dataIdList {
+			data.AddOrEditEdbInfoToEs(dataId)
+		}
+	// 指标库
+	case DataTypeChart:
+		// 图库
+		// TODO
+	}
+
+	return
+}
+
+func ProcessingDataApprove(adminId, dataType, timeType, sortField, sortRule, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.DataApproveItemOrmResp, respTotal int, msg string, err error) {
+	cond := fmt.Sprintf(` AND a.%s = ? AND b.%s = ? AND a.%s = ?`, dataApproveModel.DataApproveRecordCols.State, dataApproveModel.DataApproveCols.State, dataApproveModel.DataApproveRecordCols.ApproveUserId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, DataApproveStateApproving, DataApproveStateApproving, adminId)
+	order := ""
+
+	// 筛选条件
+	if dataType > 0 {
+		cond += fmt.Sprintf(` AND b.%s = ?`, dataApproveModel.DataApproveCols.DataType)
+		pars = append(pars, dataType)
+	}
+	if timeType <= 0 {
+		timeType = 1
+	}
+	if timeType == 1 && startTime != "" && endTime != "" {
+		_, e := time.Parse(utils.FormatDate, startTime)
+		if e != nil {
+			msg = "开始时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
+		if e != nil {
+			msg = "结束时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime = tmpEndTime.AddDate(0, 0, 1)
+		cond += fmt.Sprintf(` AND (b.%s BETWEEN ? AND ?)`, dataApproveModel.DataApproveCols.CreateTime)
+		pars = append(pars, startTime, tmpEndTime)
+	}
+	keyword = strings.TrimSpace(keyword)
+	if keyword != "" {
+		kw := fmt.Sprint("%", keyword, "%")
+		cond += fmt.Sprintf(` AND b.%s LIKE ?`, dataApproveModel.DataApproveCols.Title)
+		pars = append(pars, kw)
+	}
+	if sortField > 0 && sortRule > 0 {
+		orderField := timeField[sortField]
+		if orderField == "" {
+			msg = "时间排序字段有误"
+			return
+		}
+		orderRule := orderRules[sortRule]
+		if orderRule == "" {
+			msg = "时间排序方式有误"
+			return
+		}
+		order = fmt.Sprintf("%s %s", orderField, orderRule)
+	}
+	total, e := dataApproveModel.GetApprovingDataApproveCount(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovingDataApproveCount err: %s", e.Error())
+		return
+	}
+	list, e := dataApproveModel.GetApprovingDataApprovePageList(cond, pars, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovingDataApprovePageList err: %s", e.Error())
+		return
+	}
+
+	respList = toDataApproveItemOrmResp(list)
+	respTotal = total
+	return
+}
+
+// SolvedDataApprove 已处理的审批
+func SolvedDataApprove(adminId, dataType, timeType, sortField, sortRule, approveState, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.DataApproveItemOrmResp, respTotal int, msg string, err error) {
+	cond := fmt.Sprintf(` AND a.%s = ? AND a.%s IN (?)`, dataApproveModel.DataApproveRecordCols.ApproveUserId, dataApproveModel.DataApproveRecordCols.NodeState)
+	pars := make([]interface{}, 0)
+	pars = append(pars, adminId, []int{DataApproveStatePass, DataApproveStateRefuse})
+	order := ""
+
+	// 筛选条件
+	if dataType > 0 {
+		cond += fmt.Sprintf(` AND b.%s = ?`, dataApproveModel.DataApproveCols.DataType)
+		pars = append(pars, dataType)
+	}
+	if timeType > 0 && startTime != "" && endTime != "" {
+		_, e := time.Parse(utils.FormatDate, startTime)
+		if e != nil {
+			msg = "开始时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
+		if e != nil {
+			msg = "结束时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime = tmpEndTime.AddDate(0, 0, 1)
+		cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, timeField[timeType])
+		pars = append(pars, startTime, tmpEndTime)
+	}
+	keyword = strings.TrimSpace(keyword)
+	if keyword != "" {
+		kw := fmt.Sprint("%", keyword, "%")
+		cond += fmt.Sprintf(` AND b.%s LIKE ?`, dataApproveModel.DataApproveCols.Title)
+		pars = append(pars, kw)
+	}
+	if sortField > 0 && sortRule > 0 {
+		orderField := timeField[sortField]
+		if orderField == "" {
+			msg = "时间排序字段有误"
+			return
+		}
+		orderRule := orderRules[sortRule]
+		if orderRule == "" {
+			msg = "时间排序方式有误"
+			return
+		}
+		order = fmt.Sprintf("%s %s", orderField, orderRule)
+	}
+	if approveState > 0 {
+		cond += fmt.Sprintf(` AND a.%s = ?`, dataApproveModel.DataApproveRecordCols.NodeState)
+		pars = append(pars, approveState)
+	}
+	total, e := dataApproveModel.GetApprovedDataApproveCount(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovedDataApproveCount err: %s", e.Error())
+		return
+	}
+	list, e := dataApproveModel.GetApprovedDataApprovePageList(cond, pars, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovedDataApprovePageList err: %s", e.Error())
+		return
+	}
+
+	for _, v := range list {
+		// 这个时候的状态,用审批状态
+		v.RecordState = v.NodeState
+		v.ApproveTime = v.NodeApproveTime
+	}
+	respList = toDataApproveItemOrmResp(list)
+	respTotal = total
+	return
+}
+
+func MyApplyDataApproves(adminId, dataType, timeType, sortField, sortRule, approveState, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.DataApproveItemOrmResp, respTotal int, msg string, err error) {
+	cond := fmt.Sprintf(` AND a.%s = ?`, dataApproveModel.DataApproveCols.ApplyUserId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, adminId)
+	order := ""
+
+	// 筛选条件
+	if dataType > 0 {
+		cond += fmt.Sprintf(` AND a.%s = ?`, dataApproveModel.DataApproveCols.DataType)
+		pars = append(pars, dataType)
+	}
+	if timeType > 0 && startTime != "" && endTime != "" {
+		_, e := time.Parse(utils.FormatDate, startTime)
+		if e != nil {
+			msg = "开始时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
+		if e != nil {
+			msg = "结束时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTimeStr := tmpEndTime.AddDate(0, 0, 1).Format(utils.FormatDate)
+		cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, myTimeField[timeType])
+		pars = append(pars, startTime, tmpEndTimeStr)
+	}
+	keyword = strings.TrimSpace(keyword)
+	if keyword != "" {
+		kw := fmt.Sprint("%", keyword, "%")
+		cond += fmt.Sprintf(` AND a.%s LIKE ?`, dataApproveModel.DataApproveCols.Title)
+		pars = append(pars, kw)
+	}
+	if sortField > 0 && sortRule > 0 {
+		orderField := myTimeField[sortField]
+		if orderField == "" {
+			msg = "时间排序字段有误"
+			return
+		}
+		orderRule := orderRules[sortRule]
+		if orderRule == "" {
+			msg = "时间排序方式有误"
+			return
+		}
+		order = fmt.Sprintf("%s %s", orderField, orderRule)
+	}
+	if approveState > 0 {
+		cond += fmt.Sprintf(` AND a.%s = ?`, dataApproveModel.DataApproveRecordCols.State)
+		pars = append(pars, approveState)
+	}
+	total, e := dataApproveModel.GetApplyDataApproveCount(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApplyDataApproveCount err: %s", e.Error())
+		return
+	}
+	respTotal = total
+	list, e := dataApproveModel.GetApplyDataApprovePageList(cond, pars, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApplyDataApprovePageList err: %s", e.Error())
+		return
+	}
+	respList = toDataApproveItemOrmResp(list)
+	return
+}
+
+func GetApproveDetail(approveId int) (resp *response.DataApproveDetail, msg string, err error) {
+	approveItem, e := dataApproveModel.GetDataApproveById(approveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批已被删除, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "获取失败"
+		err = fmt.Errorf("GetItemById err: %s", e.Error())
+		return
+	}
+
+	// 审批信息
+	detail := new(response.DataApproveDetail)
+	detail.Approve = new(response.DataApproveDetailItem)
+	detail.Approve.DataApproveId = approveItem.DataApproveId
+	detail.Approve.State = approveItem.State
+	detail.Approve.FlowId = approveItem.FlowId
+	detail.Approve.FlowVersion = approveItem.FlowVersion
+	detail.Approve.StartNodeId = approveItem.StartNodeId
+	detail.Approve.CurrNodeId = approveItem.CurrNodeId
+	detail.Approve.ApplyUserId = approveItem.ApplyUserId
+	detail.Approve.ApplyUserName = approveItem.ApplyUserName
+	detail.Approve.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.ApproveTime)
+	detail.Approve.CreateTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.CreateTime)
+	detail.Approve.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.ModifyTime)
+
+	// 审批节点
+	nodeOb := new(dataApproveModel.DataApproveNode)
+	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, dataApproveModel.DataApproveNodeCols.DataApproveFlowId, dataApproveModel.DataApproveNodeCols.CurrVersion)
+	nodePars := make([]interface{}, 0)
+	nodePars = append(nodePars, approveItem.FlowId, approveItem.FlowVersion)
+	nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetItemsByCondition err: %s", e.Error())
+		return
+	}
+
+	// 审批记录
+	recordOb := new(dataApproveModel.DataApproveRecord)
+	recordCond := fmt.Sprintf(` AND %s = ?`, dataApproveModel.DataApproveRecordCols.DataApproveId)
+	recordPars := make([]interface{}, 0)
+	recordPars = append(recordPars, approveItem.DataApproveId)
+	recordItems, e := recordOb.GetItemsByCondition(recordCond, recordPars, []string{}, fmt.Sprintf("%s DESC", dataApproveModel.DataApproveRecordCols.ApproveTime))
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetItemsByCondition err: %s", e.Error())
+		return
+	}
+	recordMap := make(map[string]*dataApproveModel.DataApproveRecord)
+	for _, v := range recordItems {
+		k := fmt.Sprintf("%d-%d", v.NodeId, v.ApproveUserId)
+		recordMap[k] = v
+	}
+
+	// 审批流节点详情
+	detail.ApproveFlowNodes = make([]*response.DataApproveDetailNodes, 0)
+	for _, v := range nodeItems {
+		t := new(response.DataApproveDetailNodes)
+		t.DataApproveNodeId = v.DataApproveNodeId
+		t.DataApproveFlowId = v.DataApproveFlowId
+		t.PrevNodeId = v.PrevNodeId
+		t.NextNodeId = v.NextNodeId
+		t.NodeType = v.NodeType
+		t.ApproveType = v.ApproveType
+		t.Users = make([]*response.DataApproveDetailNodeUser, 0)
+		us := make([]*response.DataApproveNodeUserReq, 0)
+		if v.Users != "" {
+			e = json.Unmarshal([]byte(v.Users), &us)
+			if e != nil {
+				msg = "获取失败"
+				err = fmt.Errorf("json.Unmarshal err: %s", e.Error())
+				return
+			}
+		}
+		for _, vu := range us {
+			u := new(response.DataApproveDetailNodeUser)
+			u.UserType = vu.UserType
+			u.UserId = vu.UserId
+			u.UserName = vu.UserName
+			u.Sort = vu.Sort
+			// 审批记录
+			k := fmt.Sprintf("%d-%d", v.DataApproveNodeId, vu.UserId)
+			r := recordMap[k]
+			if r != nil {
+				u.ApproveRecord = new(response.DataApproveDetailNodeUserRecord)
+				u.ApproveRecord.DataApproveRecordId = r.DataApproveRecordId
+				u.ApproveRecord.State = r.State
+				u.ApproveRecord.ApproveUserId = r.ApproveUserId
+				u.ApproveRecord.ApproveUserName = r.ApproveUserName
+				u.ApproveRecord.ApproveRemark = r.ApproveRemark
+				u.ApproveRecord.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, r.ApproveTime)
+			}
+			t.Users = append(t.Users, u)
+		}
+		sort.Slice(t.Users, func(k, j int) bool {
+			return t.Users[k].Sort < t.Users[j].Sort
+		})
+		detail.ApproveFlowNodes = append(detail.ApproveFlowNodes, t)
+	}
+
+	// 返回审批数据明细
+	dataList := make([]response.DataApproveDetailData, 0)
+	{
+		obj := new(dataApproveModel.DataApproveRelation)
+		dataItemList, tmpErr := obj.GetListByDataApproveId(approveItem.DataApproveId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		dataIdList := make([]int, 0)
+		dataIdClassifyIdMap := make(map[int]int)
+		for _, v := range dataItemList {
+			dataIdList = append(dataIdList, v.DataId)
+			dataIdClassifyIdMap[v.DataId] = v.ClassifyId
+		}
+
+		switch approveItem.DataType {
+		case DataTypeEdb: // 指标库
+			tmpList, tmpErr := data_manage.GetEdbInfoByIdList(dataIdList)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			for _, v := range tmpList {
+				item := response.DataApproveDetailData{
+					DataId:       v.EdbInfoId,
+					DataName:     v.EdbName,
+					DataCode:     v.UniqueCode,
+					DataClassify: dataIdClassifyIdMap[v.EdbInfoId],
+				}
+				dataList = append(dataList, item)
+			}
+		case DataTypeChart: // 图库
+			tmpList, tmpErr := data_manage.GetChartInfoByIdList(dataIdList)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			for _, v := range tmpList {
+				item := response.DataApproveDetailData{
+					DataId:       v.ChartInfoId,
+					DataName:     v.ChartName,
+					DataCode:     v.UniqueCode,
+					DataClassify: dataIdClassifyIdMap[v.ChartInfoId],
+				}
+				dataList = append(dataList, item)
+			}
+		}
+	}
+
+	detail.DataList = dataList
+	resp = detail
+	return
+}
+
+func DataApproveRefuse(DataApproveId, adminId int, approveRemark string) (msg string, err error) {
+	approveItem, e := dataApproveModel.GetDataApproveById(DataApproveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批不存在, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		err = fmt.Errorf("GetDataApproveById err: %s", e.Error())
+		return
+	}
+	if approveItem.State != DataApproveStateApproving {
+		msg = "审批状态有误, 请刷新页面"
+		err = fmt.Errorf("审批状态有误, State: %d", approveItem.State)
+		return
+	}
+
+	// 校验审批记录和审批
+	recordOb := new(dataApproveModel.DataApproveRecord)
+	recordCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ?`, dataApproveModel.DataApproveRecordCols.DataApproveId, dataApproveModel.DataApproveRecordCols.ApproveUserId, dataApproveModel.DataApproveRecordCols.State)
+	recordPars := make([]interface{}, 0)
+	recordPars = append(recordPars, approveItem.DataApproveId, adminId, DataApproveStateApproving)
+	recordItem, e := recordOb.GetItemByCondition(recordCond, recordPars, "")
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "无权审批"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		err = fmt.Errorf("GetItemByCondition err: %s", e.Error())
+		return
+	}
+
+	// 驳回审批
+	if e = refuseDataApprove(approveItem, recordItem, approveRemark, adminId); e != nil {
+		msg = "操作失败"
+		err = fmt.Errorf("RefuseDataApprove err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// refuseDataApprove 驳回审批
+func refuseDataApprove(approveItem *dataApproveModel.DataApprove, recordItem *dataApproveModel.DataApproveRecord, approveRemark string, sysAdminId int) (err error) {
+	if approveItem == nil {
+		err = fmt.Errorf("审批信息有误")
+		return
+	}
+	if recordItem == nil {
+		err = fmt.Errorf("审批记录有误")
+		return
+	}
+
+	// 更新审批记录
+	now := time.Now().Local()
+	recordItem.State = DataApproveStateRefuse
+	recordItem.ApproveRemark = approveRemark
+	recordItem.ApproveTime = now
+	recordItem.ModifyTime = now
+
+	recordItem.NodeState = DataApproveStateRefuse
+	recordItem.NodeApproveUserId = recordItem.ApproveUserId
+	recordItem.NodeApproveUserName = recordItem.ApproveUserName
+	recordItem.NodeApproveTime = now
+
+	recordCols := []string{"State", "ApproveRemark", "ApproveTime", "ModifyTime", "NodeState", "NodeApproveUserId", "NodeApproveUserName", "NodeApproveTime"}
+	if e := recordItem.Update(recordCols); e != nil {
+		err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+		return
+	}
+
+	// 将该审批的同一个节点的记录标记为已审批
+	if e := recordItem.UpdateNodeState(recordItem.DataApproveId, recordItem.NodeId, recordItem.NodeState, recordItem.NodeApproveUserId, recordItem.NodeApproveUserName, recordItem.NodeApproveTime); e != nil {
+		err = fmt.Errorf("更新同一节点的其他审批记录状态失败, Err: %s", e.Error())
+		return
+	}
+
+	// 驳回-更新审批, 报告状态, 推送消息
+	approveItem.State = DataApproveStateRefuse
+	approveItem.ApproveRemark = approveRemark
+	approveItem.ApproveTime = now
+	approveItem.ModifyTime = now
+	approveCols := []string{"State", "ApproveRemark", "ApproveTime", "ModifyTime"}
+	if e := approveItem.Update(approveCols); e != nil {
+		err = fmt.Errorf("更新审批状态失败, Err: %s", e.Error())
+		return
+	}
+
+	if e := updateDataApproveState(approveItem, DataApproveStateRefuse); e != nil {
+		err = fmt.Errorf("更新报告状态失败, Err: %s", e.Error())
+		return
+	}
+
+	// 推送驳回消息给申请人
+	go func() {
+		messageItem := new(dataApproveModel.DataApproveMessage)
+		messageItem.SendUserId = sysAdminId
+		messageItem.ReceiveUserId = approveItem.ApplyUserId
+		messageItem.Content = "您提交的审批被驳回"
+		messageItem.Remark = fmt.Sprintf("您提交的【%s】已被驳回", approveItem.Title)
+		messageItem.DataApproveId = approveItem.DataApproveId
+		messageItem.ApproveState = DataApproveStateRefuse
+		messageItem.CreateTime = now
+		messageItem.ModifyTime = now
+		if e := messageItem.Create(); e != nil {
+			utils.FileLog.Info(fmt.Sprintf("ApproveData message err: %s", e.Error()))
+			return
+		}
+	}()
+	return
+}
+
+func DataApproveCancel(DataApproveId, adminId int, adminName string) (msg string, err error) {
+	approveItem, e := dataApproveModel.GetDataApproveById(DataApproveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批已被删除, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		err = fmt.Errorf("GetDataApproveById err: %s", e.Error())
+		return
+	}
+	if approveItem.ApplyUserId != adminId {
+		msg = "非申请人不可撤销"
+		err = fmt.Errorf("非申请人不可撤销")
+		return
+	}
+
+	// 撤销审批
+	e = cancelDataApprove(approveItem, approveItem.DataApproveId, adminId, adminName)
+	if e != nil {
+		msg = "操作失败"
+		err = fmt.Errorf("cancelDataApprove err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// cancelDataApprove 撤回审批
+func cancelDataApprove(item *dataApproveModel.DataApprove, approveId, sysAdminId int, sysAdminName string) (err error) {
+	// todo
+	//// 默认内部审批, 如果是走的第三方审批, 那么仅修改状态
+	//confMap, e := models.GetBusinessConf()
+	//if e != nil {
+	//	err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
+	//	return
+	//}
+	//openMap := map[string]bool{"false": false, "true": true}
+	//openApprove := openMap[confMap[models.BusinessConfIsDataApprove]]
+	//if !openApprove {
+	//	//err = fmt.Errorf("未开启审批")
+	//	return
+	//}
+
+	// 修改审批信息状态
+	approveItem, e := dataApproveModel.GetDataApproveById(approveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			err = e
+			return
+		}
+		err = fmt.Errorf("approve GetItemById err: %s", e.Error())
+		return
+	}
+	if approveItem.State == DataApproveStateCancel {
+		return
+	}
+	approveItem.State = DataApproveStateCancel
+	approveItem.ModifyTime = time.Now()
+	cols := []string{"State", "ModifyTime"}
+	if e = approveItem.Update(cols); e != nil {
+		err = fmt.Errorf("approve Update err: %s", e.Error())
+		return
+	}
+
+	// 修改报告状态
+	e = updateDataApproveState(approveItem, DataApproveStateCancel)
+	if e != nil {
+		err = fmt.Errorf("更新报告审批撤回失败, Err: %s", e.Error())
+		return
+	}
+
+	// 推送撤回消息
+	go func() {
+		recordOb := new(dataApproveModel.DataApproveRecord)
+		recordCond := fmt.Sprintf(` AND %s = ?`, dataApproveModel.DataApproveRecordCols.DataApproveId)
+		recordPars := make([]interface{}, 0)
+		recordPars = append(recordPars, approveId)
+		recordItems, e := recordOb.GetItemsByCondition(recordCond, recordPars, []string{}, "")
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("approve record GetItemsByCondition err: %s", e.Error()))
+			return
+		}
+
+		messageOb := new(dataApproveModel.DataApproveMessage)
+		messages := make([]*dataApproveModel.DataApproveMessage, 0)
+		for _, v := range recordItems {
+			m := new(dataApproveModel.DataApproveMessage)
+			m.SendUserId = sysAdminId
+			m.ReceiveUserId = v.ApproveUserId
+			m.Content = fmt.Sprintf("%s提交的【%s】已撤回", sysAdminName, approveItem.Title)
+			m.DataApproveId = approveId
+			m.ApproveState = DataApproveStateCancel
+			m.CreateTime = time.Now().Local()
+			m.ModifyTime = time.Now().Local()
+			messages = append(messages, m)
+		}
+		e = messageOb.CreateMulti(messages)
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("CancelDataApprove messages err: %s", e.Error()))
+			return
+		}
+	}()
+	return
+}
+
+// CheckOpenApprove 校验报告是否开启了审批流
+func CheckOpenApprove(dataType int) (opening bool, err error) {
+	// 查询对应分类是否有审批流
+	flowOb := new(dataApproveModel.DataApproveFlow)
+	flowCond := fmt.Sprintf(` AND %s = ?`, dataApproveModel.DataApproveFlowCols.DataType)
+	flowPars := make([]interface{}, 0)
+	flowPars = append(flowPars, dataType)
+	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			return
+		}
+		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
+		return
+	}
+
+	// 查看审批节点
+	if flowItem.DataApproveFlowId > 0 {
+
+		nodeOb := new(dataApproveModel.DataApproveNode)
+		nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ? `, dataApproveModel.DataApproveNodeCols.DataApproveFlowId, dataApproveModel.DataApproveNodeCols.CurrVersion)
+		nodePars := make([]interface{}, 0)
+		nodePars = append(nodePars, flowItem.DataApproveFlowId, flowItem.CurrVersion)
+		nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
+		if e != nil {
+			err = e
+			return
+		}
+
+		// 如果有审批节点,那么就确实有审批流,那么就返回true
+		if len(nodeItems) > 0 {
+			opening = true
+			return
+		}
+	}
+
+	return
+}
+
+type SetDataPublicItem struct {
+	DataId     int
+	ClassifyId int
+}
+
+// SubmitDataApprove
+// @Description: 提交审批
+// @author: Roc
+// @datetime 2024-12-06 10:13:40
+// @param dataType int
+// @param dataIdList []int
+// @param title string
+// @param description string
+// @param sysAdminId int
+// @param sysAdminName string
+// @return approveId int
+// @return err error
+func SubmitDataApprove(dataType int, dataList []SetDataPublicItem, title, description string, sysAdminId int, sysAdminName string) (approveId int, err error) {
+	// 查询审批流
+	flowOb := new(dataApproveModel.DataApproveFlow)
+	flowCond := fmt.Sprintf(` AND %s = ?`, dataApproveModel.DataApproveFlowCols.DataType)
+	flowPars := make([]interface{}, 0)
+	flowPars = append(flowPars, dataType)
+	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
+	if e != nil {
+		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
+		return
+	}
+
+	// 查询审批节点
+	nodeOb := new(dataApproveModel.DataApproveNode)
+	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, dataApproveModel.DataApproveNodeCols.DataApproveFlowId, dataApproveModel.DataApproveNodeCols.CurrVersion)
+	nodePars := make([]interface{}, 0)
+	nodePars = append(nodePars, flowItem.DataApproveFlowId, flowItem.CurrVersion)
+	nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
+	if e != nil {
+		err = fmt.Errorf("ApproveNodes GetItemsByCondition err: %s", e.Error())
+		return
+	}
+	if len(nodeItems) == 0 {
+		err = fmt.Errorf("无审批节点")
+		return
+	}
+
+	// 取出首个节点
+	firstNodeItem := new(dataApproveModel.DataApproveNode)
+	for _, v := range nodeItems {
+		if v.PrevNodeId == 0 {
+			firstNodeItem = v
+			continue
+		}
+	}
+	if firstNodeItem == nil {
+		err = fmt.Errorf("首个审批节点有误")
+		return
+	}
+
+	// 审批信息
+	now := time.Now().Local()
+	newApprove := new(dataApproveModel.DataApprove)
+	newApprove.Title = title
+	newApprove.ApproveRemark = description
+	newApprove.DataType = dataType
+	newApprove.State = DataApproveStateApproving
+	newApprove.FlowId = flowItem.DataApproveFlowId
+	newApprove.FlowVersion = flowItem.CurrVersion
+	newApprove.StartNodeId = firstNodeItem.DataApproveNodeId
+	newApprove.CurrNodeId = firstNodeItem.DataApproveNodeId
+	newApprove.ApplyUserId = sysAdminId
+	newApprove.ApplyUserName = sysAdminName
+	newApprove.CreateTime = now
+	newApprove.ModifyTime = now
+
+	relationList := make([]*dataApproveModel.DataApproveRelation, 0)
+	for _, dataItem := range dataList {
+		relationList = append(relationList, &dataApproveModel.DataApproveRelation{
+			DataApproveRelationId: 0,
+			DataApproveId:         0,
+			DataId:                dataItem.DataId,
+			ClassifyId:            dataItem.ClassifyId,
+			CreateTime:            now,
+		})
+	}
+	e = dataApproveModel.AddDataApprove(newApprove, relationList)
+	if e != nil {
+		err = fmt.Errorf("生成审批信息失败, Err: %s", e.Error())
+		return
+	}
+
+	approveId = newApprove.DataApproveId
+
+	// 生成节点审批记录
+	err = BuildNextNodeRecordAndMsg(firstNodeItem, newApprove.DataApproveId, sysAdminId, sysAdminName, newApprove.Title)
+
+	return
+}
+
+func toDataApproveItemOrmResp(src []*dataApproveModel.DataApproveItemOrm) (res []*response.DataApproveItemOrmResp) {
+	for _, v := range src {
+		r := new(response.DataApproveItemOrmResp)
+		r.DataApproveId = v.DataApproveId
+		r.DataApproveRecordId = v.DataApproveRecordId
+		r.Title = v.Title
+		r.DataType = v.DataType
+		r.State = v.State
+		r.RecordState = v.RecordState
+		r.FlowId = v.FlowId
+		r.FlowVersion = v.FlowVersion
+		r.StartNodeId = v.StartNodeId
+		r.CurrNodeId = v.CurrNodeId
+		r.ApplyUserId = v.ApplyUserId
+		r.ApplyUserName = v.ApplyUserName
+		r.ApproveRemark = v.ApproveRemark
+		r.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, v.ApproveTime)
+		r.HandleTime = utils.TimeTransferString(utils.FormatDateTime, v.HandleTime)
+		r.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
+		r.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, v.ModifyTime)
+		r.NodeState = v.NodeState
+		res = append(res, r)
+	}
+	return
+}
+
+// CheckHasDataApproving
+// @Description: 查询是否还存在带审批的审批单
+// @author: Roc
+// @datetime 2024-12-06 10:43:00
+// @return ok bool
+// @return err error
+func CheckHasDataApproving() (ok bool, err error) {
+	count, err := dataApproveModel.GetDataApproveCountByState(DataApproveStateApproving)
+	if err != nil {
+		return
+	}
+	if count > 0 {
+		ok = true
+	}
+	return
+}

+ 174 - 0
services/data/data_approve/approve_flow.go

@@ -0,0 +1,174 @@
+package data_approve
+
+import (
+	"encoding/json"
+	DataApprove "eta_gn/eta_api/models/data_manage/data_approve"
+	"eta_gn/eta_api/models/data_manage/data_approve/request"
+	"eta_gn/eta_api/models/data_manage/data_approve/response"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+// SaveDataApproveFlow 保存审批流
+func SaveDataApproveFlow(flow *request.DataApproveFlowSaveReq) (ok bool, msg string, err error) {
+
+	flowInfo, err := DataApprove.GetDataApproveFlowByDataType(flow.DataType)
+	if err != nil {
+		if !utils.IsErrNoRow(err) {
+			msg = "保存审批流失败, 查找审批流失败"
+			return
+		}
+	}
+
+	if flowInfo.DataApproveFlowId <= 0 {
+		// 之前没有过记录,所以走新增
+		var remark string
+		switch flow.DataType {
+		case 1:
+			remark = `指标审批`
+		case 2:
+			remark = `图表审批`
+		}
+		t := &DataApprove.DataApproveFlow{
+			FlowName:    flow.FlowName,
+			DataType:    flow.DataType,
+			Remark:      remark,
+			CurrVersion: 1,
+			CreateTime:  time.Now(),
+			ModifyTime:  time.Now(),
+		}
+		flowNodeItems := make([]*DataApprove.DataApproveNode, 0)
+		for _, node := range flow.Nodes {
+			flowNode := new(DataApprove.DataApproveNode)
+			flowNode.ApproveType = node.ApproveType
+			flowNode.CurrVersion = t.CurrVersion
+			userBytes, er := json.Marshal(node.Users)
+			if er != nil {
+				err = er
+				msg = "保存审批流失败"
+				return
+			}
+			flowNode.Users = string(userBytes)
+			flowNode.CreatedTime = time.Now()
+			flowNodeItems = append(flowNodeItems, flowNode)
+		}
+		err = t.Add(flowNodeItems)
+		if err != nil {
+			msg = "保存审批流失败"
+			return
+		}
+		ok = true
+	} else {
+		ok, err = CheckDeleteDataApproveFlow(flowInfo.DataApproveFlowId)
+		if err != nil {
+			msg = "保存审批流失败"
+			return
+		}
+		if !ok {
+			msg = "保存审批流失败, 存在还未审批的报告"
+			return
+		}
+		var updateCols []string
+		if flowInfo.FlowName != flow.FlowName {
+			flowInfo.FlowName = flow.FlowName
+			updateCols = append(updateCols, "flow_name")
+		}
+		flowInfo.CurrVersion += 1
+		flowInfo.ModifyTime = time.Now()
+		updateCols = append(updateCols, "modify_time", "curr_version")
+
+		biFlowNodeItems := make([]*DataApprove.DataApproveNode, 0)
+		for _, node := range flow.Nodes {
+			flowNode := new(DataApprove.DataApproveNode)
+			flowNode.ApproveType = node.ApproveType
+			flowNode.CurrVersion = flowInfo.CurrVersion
+			userBytes, er := json.Marshal(node.Users)
+			if er != nil {
+				err = er
+				msg = "保存审批流失败"
+				return
+			}
+			flowNode.Users = string(userBytes)
+			flowNode.CreatedTime = time.Now()
+			biFlowNodeItems = append(biFlowNodeItems, flowNode)
+		}
+
+		err = flowInfo.Update(updateCols, biFlowNodeItems)
+		if err != nil {
+			msg = "保存审批流失败"
+			return
+		}
+		ok = true
+	}
+	return
+}
+
+// GetDataApproveFlowDetail 获取审批流详情
+func GetDataApproveFlowDetail(dataType int) (detail *response.DataApproveFlowDetailResp, msg string, err error) {
+	flowInfo, err := DataApprove.GetDataApproveFlowByDataType(dataType)
+	if err != nil && !utils.IsErrNoRow(err) {
+		msg = "获取审批流详情失败"
+		return
+	}
+	flowNodes := make([]*DataApprove.DataApproveNode, 0)
+
+	// 如果有配置的话
+	if flowInfo.DataApproveFlowId > 0 {
+		flowNodes, err = DataApprove.GetDataApproveNodeByFlowIdAndVersionId(flowInfo.DataApproveFlowId, flowInfo.CurrVersion)
+		if err != nil {
+			msg = "获取审批流详情失败"
+			return
+		}
+	}
+
+	detail, err = FormatFlowAndNodesItem2Detail(flowInfo, flowNodes)
+	if err != nil {
+		msg = "获取审批流详情失败"
+		return
+	}
+	return
+}
+
+// CheckDeleteDataApproveFlow 检查是否可以删除审批流
+func CheckDeleteDataApproveFlow(flowId int) (ok bool, err error) {
+	flowInfo, err := DataApprove.GetDataApproveFlowById(flowId)
+	if err != nil {
+		return
+	}
+	// 检查是否存在还未审批的Bi看报
+	approveList, err := DataApprove.GetDataApproveByFlowIdAndVersionId(flowInfo.DataApproveFlowId, flowInfo.CurrVersion)
+	if err != nil {
+		return
+	}
+	for _, v := range approveList {
+		if v.State == DataApproveStateApproving {
+			return false, nil
+		}
+	}
+
+	ok = true
+	return
+}
+
+func FormatFlowAndNodesItem2Detail(flowItem *DataApprove.DataApproveFlow, nodeItems []*DataApprove.DataApproveNode) (detail *response.DataApproveFlowDetailResp, err error) {
+	if flowItem == nil {
+		return
+	}
+	detail = new(response.DataApproveFlowDetailResp)
+	detail.DataApproveFlowId = flowItem.DataApproveFlowId
+	detail.FlowName = flowItem.FlowName
+	detail.DataType = flowItem.DataType
+	detail.CreateTime = utils.TimeTransferString(utils.FormatDateTime, flowItem.CreateTime)
+	detail.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, flowItem.ModifyTime)
+	detail.Nodes = make([]*response.DataApproveNodeItem, 0)
+	for _, v := range nodeItems {
+		t, e := FormatDataApproveNode2Item(v)
+		if e != nil {
+			err = fmt.Errorf("format node err: %s", e.Error())
+			return
+		}
+		detail.Nodes = append(detail.Nodes, t)
+	}
+	return
+}

+ 89 - 0
services/data/data_approve/approve_message.go

@@ -0,0 +1,89 @@
+package data_approve
+
+import (
+	DataApprove "eta_gn/eta_api/models/data_manage/data_approve"
+	"eta_gn/eta_api/models/data_manage/data_approve/response"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+func GetDataApproveMessage(adminId, startSize, pageSize int) (list []*response.DataApproveMessageItem, total, unread int, msg string, err error) {
+	cond := fmt.Sprintf(` AND %s = ?`, DataApprove.DataApproveMessageCols.ReceiveUserId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, adminId)
+	order := fmt.Sprintf(`%s ASC, %s DESC`, DataApprove.DataApproveMessageCols.IsRead, DataApprove.DataApproveMessageCols.CreateTime)
+
+	messageOb := new(DataApprove.DataApproveMessage)
+	total, e := messageOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetCountByCondition, Err: %s", e.Error())
+		return
+	}
+	tmpList, e := messageOb.GetPageItemsByCondition(cond, pars, []string{}, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetPageItemsByCondition, Err: %s", e.Error())
+		return
+	}
+	for _, v := range tmpList {
+		t := FormatDataApproveMessage2Item(v)
+		list = append(list, t)
+	}
+
+	// 未读消息数
+	cond += fmt.Sprintf(` AND %s = ?`, DataApprove.DataApproveMessageCols.IsRead)
+	pars = append(pars, 0)
+	unreadTotal, e := messageOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetCountByCondition, Err: %s", e.Error())
+		return
+	}
+	unread = unreadTotal
+	return
+}
+
+func ReadBiMessage(msgId int, adminId int) (msg string, err error) {
+	messageOb := new(DataApprove.DataApproveMessage)
+	messageItem, e := messageOb.GetItemById(msgId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "消息不存在, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetItemById, Err: %s", e.Error())
+		return
+	}
+	messageItem.IsRead = 1
+	messageItem.ModifyTime = time.Now().Local()
+	cols := []string{"IsRead", "ModifyTime"}
+	if e = messageItem.Update(cols); e != nil {
+		msg = "操作失败"
+		err = fmt.Errorf("message.Update, Err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// FormatDataApproveMessage2Item 格式化报告审批消息
+func FormatDataApproveMessage2Item(origin *DataApprove.DataApproveMessage) (item *response.DataApproveMessageItem) {
+	item = new(response.DataApproveMessageItem)
+	if origin == nil {
+		return
+	}
+	item.Id = origin.Id
+	item.SendUserId = origin.SendUserId
+	item.ReceiveUserId = origin.ReceiveUserId
+	item.Content = origin.Content
+	item.Remark = origin.Remark
+	item.DataApproveId = origin.DataApproveId
+	item.ApproveState = origin.ApproveState
+	item.IsRead = origin.IsRead
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	return
+}

+ 31 - 0
services/data/data_approve/approve_node.go

@@ -0,0 +1,31 @@
+package data_approve
+
+import (
+	"encoding/json"
+	DataApprove "eta_gn/eta_api/models/data_manage/data_approve"
+	"eta_gn/eta_api/models/data_manage/data_approve/response"
+	"fmt"
+)
+
+// FormatDataApproveNode2Item 格式化报告审批节点信息
+func FormatDataApproveNode2Item(origin *DataApprove.DataApproveNode) (item *response.DataApproveNodeItem, err error) {
+	if origin == nil {
+		return
+	}
+	item = new(response.DataApproveNodeItem)
+	item.DataApproveNodeId = origin.DataApproveNodeId
+	item.DataApproveFlowId = origin.DataApproveFlowId
+	item.PrevNodeId = origin.PrevNodeId
+	item.NextNodeId = origin.NextNodeId
+	item.NodeType = origin.NodeType
+	item.ApproveType = origin.ApproveType
+	item.Users = make([]*response.DataApproveNodeUser, 0)
+	if origin.Users != "" {
+		e := json.Unmarshal([]byte(origin.Users), &item.Users)
+		if e != nil {
+			err = fmt.Errorf("node users unmarshal err: %s", e.Error())
+			return
+		}
+	}
+	return
+}

+ 37 - 0
services/data/data_approve/constant.go

@@ -0,0 +1,37 @@
+package data_approve
+
+// 看板状态
+const (
+	BiStateUnpublished = 1 // 未公开
+	// BiStatePublished   = 2 // 已发布
+	// BiStateWaitSubmit  = 3 // 待提交
+	BiStateWaitApprove = 4 // 待审批
+	BiStateRefused     = 5 // 已驳回
+	BiStatePass        = 6 // 已通过
+)
+
+const (
+	DataTypeEdb   = 1 // 指标审批
+	DataTypeChart = 2 // 图库审批
+)
+
+// 节点审批方式
+const (
+	NodeApproveTypeRoll = 1 // 依次审批
+	NodeApproveTypeAll  = 2 // 会签
+	NodeApproveTypeAny  = 3 // 或签
+)
+
+// 节点审批人类型
+const (
+	NodeUserTypeNormal = "user" // 用户
+	NodeUserTypeRole   = "role" // 角色
+)
+
+// 报告审批状态
+const (
+	DataApproveStateApproving = 1 // 待审批
+	DataApproveStatePass      = 2 // 已审批
+	DataApproveStateRefuse    = 3 // 已驳回
+	DataApproveStateCancel    = 4 // 已撤销
+)

+ 2 - 2
services/data/data_manage_permission/data_move.go

@@ -296,7 +296,7 @@ func GetMoveEdbChartList(source, subSource, userId int, keyword, classify string
 		}
 
 		// 获取所有的图表分类
-		firstClassifyList, tmpErr := data_manage.GetChartClassifyByParentId(0, 1)
+		firstClassifyList, tmpErr := data_manage.GetChartClassifyByParentId(0, 1, userId)
 		if tmpErr != nil {
 			err = tmpErr
 			return
@@ -307,7 +307,7 @@ func GetMoveEdbChartList(source, subSource, userId int, keyword, classify string
 			firstClassifyNameMap[v.ChartClassifyId] = v.ChartClassifyName
 			firstClassifyNameEnMap[v.ChartClassifyId] = v.ChartClassifyNameEn
 		}
-		secondClassList, tmpErr := data_manage.GetChartClassifyAll(1)
+		secondClassList, tmpErr := data_manage.GetChartClassifyAll(1, userId)
 		if tmpErr != nil {
 			err = tmpErr
 			return

+ 34 - 20
services/data/edb_classify.go

@@ -32,7 +32,12 @@ func GetClassifyTreeRecursive(list []*data_manage.EdbClassifyItems, parentId int
 	res := make([]*data_manage.EdbClassifyItems, 0)
 	for _, v := range list {
 		if v.ParentId == parentId {
-			v.Children = GetClassifyTreeRecursive(list, v.ClassifyId)
+			children := GetClassifyTreeRecursive(list, v.ClassifyId)
+			if v.Children == nil {
+				v.Children = children
+			} else {
+				v.Children = append(v.Children, children...)
+			}
 			res = append(res, v)
 		}
 	}
@@ -258,9 +263,9 @@ func AddEdbClassify(classifyName string, parentId, level int, classifyType uint8
 		var count int
 		switch lang {
 		case utils.EnLangVersion:
-			count, err = data_manage.GetEdbClassifyEnCount(classifyName, parentId, classifyType)
+			count, err = data_manage.GetEdbClassifyEnCount(classifyName, parentId, sysUserId, classifyType)
 		default:
-			count, err = data_manage.GetEdbClassifyCount(classifyName, parentId, classifyType)
+			count, err = data_manage.GetEdbClassifyCount(classifyName, parentId, sysUserId, classifyType)
 		}
 		if err != nil {
 			errMsg = `判断名称是否已存在失败`
@@ -332,21 +337,6 @@ func AddEdbClassify(classifyName string, parentId, level int, classifyType uint8
 		errMsg = "保存分类失败"
 		return
 	}
-	// 更改分类id完整路径path
-	classifyInfo.ClassifyIdPath = fmt.Sprint(classifyIdPath, classifyInfo.ClassifyId)
-	_ = classifyInfo.Update([]string{"ClassifyIdPath"})
-
-	// 继承分类权限
-	{
-		source := utils.EdbPermissionSourceBase
-		if classifyType == 1 {
-			source = utils.EdbPermissionSourcePredict
-		}
-		if classifyType == utils.EdbClassifyTypeCalculate {
-			source = utils.EdbPermissionSourceCalculate
-		}
-		go data_manage_permission.InheritParentClassify(source, int(classifyType), classifyInfo.ClassifyId, classifyInfo.ParentId, classifyInfo.ClassifyName)
-	}
 
 	// 更改分类id完整路径path
 	updateCols := []string{"ClassifyIdPath"}
@@ -363,6 +353,18 @@ func AddEdbClassify(classifyName string, parentId, level int, classifyType uint8
 		return
 	}
 
+	// 继承分类权限
+	{
+		source := utils.EdbPermissionSourceBase
+		if classifyType == 1 {
+			source = utils.EdbPermissionSourcePredict
+		}
+		if classifyType == utils.EdbClassifyTypeCalculate {
+			source = utils.EdbPermissionSourceCalculate
+		}
+		go data_manage_permission.InheritParentClassify(source, int(classifyType), classifyInfo.ClassifyId, classifyInfo.ParentId, classifyInfo.ClassifyName)
+	}
+
 	return
 }
 
@@ -418,7 +420,7 @@ func EditEdbClassify(classifyId int, classifyName, lang string, sysUser *system.
 		}
 
 		// 判断名称是否已存在
-		count, tmpErr := data_manage.GetEdbClassifyEnCount(classifyName, item.ParentId, item.ClassifyType)
+		count, tmpErr := data_manage.GetEdbClassifyEnCount(classifyName, item.ParentId, sysUser.AdminId, item.ClassifyType)
 		if tmpErr != nil {
 			err = tmpErr
 			errMsg = "判断名称是否已存在失败"
@@ -441,7 +443,7 @@ func EditEdbClassify(classifyId int, classifyName, lang string, sysUser *system.
 		}
 
 		// 判断名称是否已存在
-		count, tmpErr := data_manage.GetEdbClassifyCount(classifyName, item.ParentId, item.ClassifyType)
+		count, tmpErr := data_manage.GetEdbClassifyCount(classifyName, item.ParentId, sysUser.AdminId, item.ClassifyType)
 		if tmpErr != nil {
 			err = tmpErr
 			errMsg = "判断名称是否已存在失败"
@@ -1024,6 +1026,11 @@ func MoveEdbClassify(req data_manage.MoveEdbClassifyReq, sysUser *system.Admin,
 			err = errors.New("获取分类信息失败,Err:" + err.Error())
 			return
 		}
+		if edbClassifyInfo.SysUserId != sysUser.AdminId {
+			errMsg = "不是本人目录,您没有操作权限"
+			err = errors.New(errMsg)
+			return
+		}
 		if parentClassifyId > 0 && parentEdbClassifyInfo.Level == 6 {
 			errMsg = "最高只支持添加6级分类"
 			err = errors.New(errMsg)
@@ -1082,6 +1089,13 @@ func MoveEdbClassify(req data_manage.MoveEdbClassifyReq, sysUser *system.Admin,
 			err = errors.New("获取分类信息失败,Err:" + err.Error())
 			return
 		}
+
+		if edbInfo.SysUserId != sysUser.AdminId {
+			errMsg = "不是本人指标,您没有操作权限"
+			err = errors.New(errMsg)
+			return
+		}
+
 		if parentClassifyId == 0 {
 			errMsg = "移动失败,指标必须挂在分类下"
 			err = errors.New(errMsg)

+ 2 - 2
services/data/edb_info.go

@@ -702,7 +702,7 @@ func AddEdbInfo(secName, unit, frequency, noticeTime, mobile string, classifyId,
 // AddOrEditEdbInfoToEs 添加/修改ES中的指标
 func AddOrEditEdbInfoToEs(edbInfoId int) {
 	//添加es
-	itemInfo, _ := data_manage.GetEdbInfoByCondition("AND edb_info_id=?", []interface{}{edbInfoId})
+	itemInfo, _ := data_manage.GetEdbInfoEsByCondition("AND edb_info_id=?", []interface{}{edbInfoId})
 	obj := data_manage.EdbInfoShare{}
 	list, _ := obj.GetListByEdbInfoId(edbInfoId)
 	sharedList := make([]int, 0)
@@ -717,7 +717,7 @@ func AddOrEditEdbInfoToEs(edbInfoId int) {
 // AddOrEditAllEdbInfoToEs 修复ES中的所有指标
 func AddOrEditAllEdbInfoToEs() {
 	//添加es
-	total, itemInfoList, _ := data_manage.GetEdbInfoFilterList("", []interface{}{}, 0, 100000)
+	total, itemInfoList, _ := data_manage.GetEsEdbInfo("", []interface{}{}, 0, 100000)
 	obj := data_manage.EdbInfoShare{}
 	for k, itemInfo := range itemInfoList {
 		list, _ := obj.GetListByEdbInfoId(itemInfo.EdbInfoId)

+ 135 - 0
services/data/edb_info_share.go

@@ -0,0 +1,135 @@
+package data
+
+import (
+	"eta_gn/eta_api/models/data_manage"
+	"eta_gn/eta_api/utils"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// GetAllShareEdbListByFromUserId
+// @Description: 根据共享人id获取所有的指标列表
+// @author: Roc
+// @datetime 2024-12-03 10:01:49
+// @param sysUserId int
+// @return item []*data_manage.ShareEdbInfoQuery
+// @return err error
+func GetAllShareEdbListByFromUserId(sysUserId int) (item []*data_manage.ShareEdbInfoQuery, err error) {
+	obj := data_manage.EdbInfoShare{}
+	item, err = obj.GetAllSharedEdbInfoListByFromUserId(sysUserId)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// GetAllShareEdbListByReceivedUserId
+// @Description: 根据接收人id获取所有的指标列表
+// @author: Roc
+// @datetime 2024-12-03 10:01:49
+// @param sysUserId int
+// @return item []*data_manage.ShareEdbInfoQuery
+// @return err error
+func GetAllShareEdbListByReceivedUserId(sysUserId int) (item []*data_manage.ShareEdbInfoQuery, err error) {
+	obj := data_manage.EdbInfoShare{}
+	item, err = obj.GetAllSharedEdbInfoListByReceivedUserId(sysUserId)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// GetEdbClassifyItemListByShareEdbInfoQueryList
+// @Description: 根据共享的指标来获取分类和指标的树形结构
+// @author: Roc
+// @datetime 2024-12-03 11:12:26
+// @param items []*data_manage.ShareEdbInfoQuery
+// @return item data_manage.EdbClassifyItemList
+// @return err error
+func GetEdbClassifyItemListByShareEdbInfoQueryList(items []*data_manage.ShareEdbInfoQuery) (item data_manage.EdbClassifyItemList, err error) {
+	// 所有分类
+	edbClassifyItemListMap := make(map[int][]*data_manage.EdbClassifyItems)
+	classifyIdList := make([]int, 0)
+
+	for _, v := range items {
+		edbClassifyItem := &data_manage.EdbClassifyItems{
+			ClassifyId: v.ClassifyId,
+			EdbInfoId:  v.EdbInfoId,
+			//ParentId:   v.ClassifyId,
+			//ClassifyType:     v.ClassifyT,
+			ClassifyName:    v.EdbName,
+			ClassifyNameEn:  v.EdbNameEn,
+			Sort:            v.Sort,
+			UniqueCode:      v.UniqueCode,
+			Source:          v.Source,
+			SourceName:      v.SourceName,
+			SysUserId:       v.SysUserId,
+			SysUserRealName: v.SysUserRealName,
+			StartDate:       v.StartDate.Format(utils.FormatDate),
+			EdbCode:         v.EdbCode,
+			EdbType:         v.EdbType,
+			//Children:         nil,
+			Button:           data_manage.EdbClassifyItemsButton{},
+			IsJoinPermission: v.IsJoinPermission,
+			HaveOperaAuth:    false,
+			ClassifyIdPath:   "",
+		}
+		edbClassifyItemList, ok := edbClassifyItemListMap[v.ClassifyId]
+		if ok {
+			edbClassifyItemListMap[v.ClassifyId] = []*data_manage.EdbClassifyItems{edbClassifyItem}
+			continue
+		}
+		edbClassifyItemListMap[v.ClassifyId] = append(edbClassifyItemList, edbClassifyItem)
+		classifyIdList = append(classifyIdList, v.ClassifyId)
+	}
+
+	// 组成一个分类树形结构
+	{
+		// 根据分类id获取分类
+		classifyItemsList, tmpErr := data_manage.GetEdbClassifyItemsByIdList(classifyIdList)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		allClassifyIdList := make([]int, 0)
+		// 获取分类的完整路径id集合(子级、父级、顶级)
+		allClassifyIdStrList := make([]string, 0)
+		for _, v := range classifyItemsList {
+			allClassifyIdStrList = append(allClassifyIdStrList, v.ClassifyIdPath)
+		}
+		allClassifyIdStrList = strings.Split(strings.Join(allClassifyIdStrList, ","), ",")
+		for _, v := range allClassifyIdStrList {
+			classifyId, tmpErr := strconv.Atoi(v)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			allClassifyIdList = append(allClassifyIdList, classifyId)
+		}
+
+		classifyItemsList, err = data_manage.GetEdbClassifyItemsByIdList(allClassifyIdList)
+		if err != nil {
+			return
+		}
+
+		for _, v := range classifyItemsList {
+			if edbClassifyItemList, ok := edbClassifyItemListMap[v.ClassifyId]; ok {
+				if v.Children == nil {
+					v.Children = edbClassifyItemList
+				} else {
+					v.Children = append(v.Children, edbClassifyItemList...)
+				}
+			}
+		}
+
+		item = GetClassifyTreeRecursive(classifyItemsList, 0)
+		//根据sort值排序
+		sort.Sort(item)
+	}
+
+	return
+}

+ 44 - 0
services/data/edb_public.go

@@ -0,0 +1,44 @@
+package data
+
+import (
+	"eta_gn/eta_api/models/data_manage"
+	"eta_gn/eta_api/models/system"
+)
+
+// DeleteEdbPublicCheck
+// @Description: 移除指标公共检测
+// @author: Roc
+// @datetime 2024-12-05 10:23:01
+// @param classifyId int
+// @param edbInfoId int
+// @param sysUser *system.Admin
+// @return deleteStatus int
+// @return tipsMsg string
+// @return tableList []*data_manage.ExcelBaseInfo
+// @return err error
+// @return errMsg string
+func DeleteEdbPublicCheck(edbInfoId int, sysUser *system.Admin) (deleteStatus int, tipsMsg string, tableList []*data_manage.ExcelBaseInfo, err error, errMsg string) {
+	// TODO 操作权限校验
+	{
+
+	}
+
+	// 移除指标
+	if edbInfoId > 0 {
+
+		// TODO 需要判断该指标是否被其他人给收藏了
+
+		//if edbInfo == nil {
+		//	errMsg = "指标已删除,请刷新页面"
+		//	return
+		//}
+		//if chartCount > 0 {
+		//	deleteStatus = 3
+		//	tipsMsg = "当前指标已用作画图,不可删除"
+		//	return
+		//}
+		return
+	}
+
+	return
+}

+ 850 - 0
services/data/edb_public_classify.go

@@ -0,0 +1,850 @@
+package data
+
+import (
+	"errors"
+	"eta_gn/eta_api/models/data_manage"
+	"eta_gn/eta_api/models/system"
+	"eta_gn/eta_api/services/data/data_manage_permission"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"strconv"
+	"time"
+)
+
+// AddEdbPublicClassify
+// @Description: 添加公共指标分类
+// @author: Roc
+// @datetime 2024-12-04 18:00:22
+// @param classifyName string
+// @param parentId int
+// @param level int
+// @param classifyType uint8
+// @param sysUserId int
+// @param sysUserName string
+// @return classifyInfo *data_manage.EdbPublicClassify
+// @return err error
+// @return errMsg string
+func AddEdbPublicClassify(classifyName string, parentId, level int, classifyType uint8, sysUserId int, sysUserName string) (classifyInfo *data_manage.EdbPublicClassify, err error, errMsg string) {
+	edbPublicClassifyObj := data_manage.EdbPublicClassify{}
+	// 校验分类名称相同的数量
+	{
+		var count int
+		count, err = edbPublicClassifyObj.GetEdbClassifyCount(classifyName, parentId, classifyType)
+		if err != nil {
+			errMsg = `判断名称是否已存在失败`
+			return
+		}
+		if count > 0 {
+			errMsg = `分类名称已存在,请重新输入`
+			err = errors.New(errMsg)
+			return
+		}
+	}
+
+	// 层级校验
+	if level > utils.EdbClassifyMaxLevel {
+		errMsg = fmt.Sprintf("最高只支持添加%d级分类", level)
+		return
+	}
+
+	//获取该层级下最大的排序数
+	maxSort, err := GetEdbPublicClassifyMaxSort(parentId, classifyType)
+	if err != nil {
+		errMsg = "获取失败"
+		err = errors.New("查询排序信息失败,Err:" + err.Error())
+		return
+	}
+	//查询顶级rootId
+	rootId := 0
+	var classifyNamePath, classifyIdPath string
+	if parentId > 0 {
+		parentClassify, tErr := edbPublicClassifyObj.GetEdbClassifyById(parentId)
+		if tErr != nil {
+			if utils.IsErrNoRow(tErr) {
+				errMsg = "父级分类不存在"
+				err = errors.New(errMsg)
+				return
+			}
+			errMsg = "获取失败"
+			err = errors.New("获取分类信息失败,Err:" + tErr.Error())
+			return
+		}
+		rootId = parentClassify.RootId
+
+		classifyNamePath = fmt.Sprint(parentClassify.EdbPublicClassifyNamePath, "|", classifyName)
+		classifyIdPath = fmt.Sprint(parentClassify.EdbPublicClassifyIdPath, ",")
+	} else {
+		classifyNamePath = classifyName
+	}
+
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	classifyInfo = &data_manage.EdbPublicClassify{
+		//EdbPublicClassifyId:       0,
+		ClassifyType:              classifyType,
+		EdbPublicClassifyName:     classifyName,
+		ParentId:                  parentId,
+		HasData:                   0,
+		RootId:                    rootId,
+		CreateTime:                time.Now(),
+		ModifyTime:                time.Now(),
+		SysUserId:                 sysUserId,
+		SysUserRealName:           sysUserName,
+		Level:                     level + 1,
+		UniqueCode:                utils.MD5(utils.PUBLIC_CLASSIFY_PREFIX + "_" + timestamp),
+		Sort:                      maxSort + 1,
+		LastModifyUserId:          sysUserId,
+		LastModifyUserRealName:    sysUserName,
+		EdbPublicClassifyNamePath: classifyNamePath,
+		EdbPublicClassifyIdPath:   "",
+	}
+	err = classifyInfo.Add()
+	if err != nil {
+		errMsg = "保存分类失败"
+		return
+	}
+
+	// 更改分类id完整路径path
+	updateCols := []string{"EdbPublicClassifyIdPath"}
+	classifyInfo.EdbPublicClassifyIdPath = fmt.Sprint(classifyIdPath, classifyInfo.EdbPublicClassifyId)
+	if parentId == 0 { //一级目录的rootId等于自己本身
+		classifyInfo.RootId = classifyInfo.EdbPublicClassifyId
+		updateCols = append(updateCols, "RootId")
+
+	}
+	err = classifyInfo.Update(updateCols)
+	if err != nil {
+		errMsg = "更新分类失败"
+		return
+	}
+
+	return
+}
+
+// EditEdbPublicClassify
+// @Description: 编辑指标分类
+// @author: Roc
+// @datetime 2024-12-05 09:29:38
+// @param classifyId int
+// @param classifyName string
+// @param sysUser *system.Admin
+// @return err error
+// @return errMsg string
+func EditEdbPublicClassify(classifyId int, classifyName string, sysUser *system.Admin) (err error, errMsg string) {
+	edbPublicClassifyObj := data_manage.EdbPublicClassify{}
+	item, err := edbPublicClassifyObj.GetEdbClassifyById(classifyId)
+	if err != nil {
+		errMsg = `修改失败`
+		return
+	}
+
+	// TODO 操作权限校验
+	{
+	}
+
+	// 需要变更的字段
+	updateCols := make([]string, 0)
+
+	// 旧完整路径  , 新的完整路径
+	var oldClassifyNamePath, newClassifyNamePath string
+
+	// 名字相同,那么就直接返回
+	if item.EdbPublicClassifyName == classifyName {
+		return
+	}
+
+	// 判断名称是否已存在
+	count, tmpErr := edbPublicClassifyObj.GetEdbClassifyCount(classifyName, item.ParentId, item.ClassifyType)
+	if tmpErr != nil {
+		err = tmpErr
+		errMsg = "判断名称是否已存在失败"
+		return
+	}
+	if count > 0 {
+		errMsg = "分类名称已存在,请重新输入"
+		err = errors.New(errMsg)
+		return
+	}
+
+	// 旧完整路径
+	oldClassifyNamePath = item.EdbPublicClassifyNamePath
+
+	if item.ParentId > 0 {
+		parentItem, tmpErr := edbPublicClassifyObj.GetEdbClassifyById(item.ParentId)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		newClassifyNamePath = fmt.Sprint(parentItem.EdbPublicClassifyNamePath, "|", classifyName)
+	} else {
+		newClassifyNamePath = classifyName
+	}
+
+	// 更新自己的信息
+	item.EdbPublicClassifyName = classifyName
+	item.EdbPublicClassifyNamePath = newClassifyNamePath
+	item.LastModifyUserId = sysUser.AdminId
+	item.LastModifyUserRealName = sysUser.RealName
+	updateCols = append(updateCols, "EdbPublicClassifyName", "EdbPublicClassifyNamePath", "LastModifyUserId", "LastModifyUserRealName")
+
+	// 修改数据
+	if len(updateCols) > 0 {
+		err = item.UpdateEdbClassifyNameAndNamePath(updateCols, oldClassifyNamePath, newClassifyNamePath)
+		if err != nil {
+			errMsg = "保存失败"
+		}
+	}
+
+	return
+}
+
+// GetEdbPublicClassifyMaxSort
+// @Description: 获取最大排序值
+// @author: Roc
+// @datetime 2024-12-04 16:54:57
+// @param parentId int
+// @param classifyType uint8
+// @return maxSort int
+// @return err error
+func GetEdbPublicClassifyMaxSort(parentId int, classifyType uint8) (maxSort int, err error) {
+	edbPublicClassifyObj := data_manage.EdbPublicClassify{}
+	//获取该层级下最大的排序数
+	classifyMaxSort, err := edbPublicClassifyObj.GetEdbClassifyMaxSort(parentId, classifyType)
+	if err != nil {
+		return
+	}
+	maxSort = classifyMaxSort
+	edbMaxSort, err := data_manage.GetEdbInfoMaxSortByClassifyId(parentId)
+	if err != nil {
+		return
+	}
+	if maxSort < edbMaxSort {
+		maxSort = edbMaxSort
+	}
+
+	return
+}
+
+// DeleteEdbPublicClassifyCheck 删除检测
+func DeleteEdbPublicClassifyCheck(classifyId int, sysUser *system.Admin) (deleteStatus int, tipsMsg string, allClassifyIdList []int, tableList []*data_manage.ExcelBaseInfo, err error, errMsg string) {
+	// TODO 操作权限校验
+	{
+
+	}
+
+	edbPublicClassifyObj := data_manage.EdbPublicClassify{}
+	// 查找当前分类
+	item, tmpErr := edbPublicClassifyObj.GetEdbClassifyById(classifyId)
+	if tmpErr != nil {
+		errMsg = `查找分类失败`
+		err = tmpErr
+		return
+	}
+
+	// 查找分类下所有子分类
+	childClassifyIdList, tmpErr := item.GetAllChildClassifyIdList()
+	if tmpErr != nil {
+		errMsg = `查找下级分类失败`
+		err = tmpErr
+		return
+	}
+	allClassifyIdList = childClassifyIdList
+	allClassifyIdList = append(allClassifyIdList, item.EdbPublicClassifyId)
+
+	// 判断分类下,是否含有指标
+	{
+		//判断分类下,是否含有指标
+		count, tmpErr := edbPublicClassifyObj.GetEdbInfoCountByClassifyIdList(allClassifyIdList)
+		if tmpErr != nil {
+			errMsg = "删除失败"
+			err = errors.New("分类下是否含有指标失败,Err:" + tmpErr.Error())
+			return
+		}
+
+		if count > 0 {
+			deleteStatus = 1
+			tipsMsg = "目录关联指标不可删除"
+			return
+		}
+	}
+
+	// 子目录数量校验
+	if len(childClassifyIdList) > 0 {
+		deleteStatus = 2
+		tipsMsg = "确认删除当前目录及包含的子目录吗"
+		return
+	}
+
+	return
+}
+
+// DeleteEdbPublicClassify 删除分类/指标
+func DeleteEdbPublicClassify(classifyId int, sysUser *system.Admin, requestBody, requestUrl string) (nextItem *data_manage.EdbInfo, tableList []*data_manage.ExcelBaseInfo, err error, errMsg string) {
+	//删除分类校验
+	deleteStatus, tipsMsg, allClassifyIdList, _, err, errMsg := DeleteEdbPublicClassifyCheck(classifyId, sysUser)
+	// 0:可以;2:删除子目录;1:不可删除(有关联指标)
+	if deleteStatus == 1 {
+		if tipsMsg != `` {
+			errMsg = tipsMsg
+		}
+		if err == nil {
+			err = errors.New(errMsg)
+		}
+		return
+	}
+
+	edbPublicClassifyObj := data_manage.EdbPublicClassify{}
+	err = edbPublicClassifyObj.BatchesDel(allClassifyIdList)
+	if err != nil {
+		errMsg = "删除失败"
+		return
+	}
+
+	return
+}
+
+// MoveEdbClassify 移动指标分类
+func MoveEdbPublicClassify(req data_manage.MoveEdbClassifyReq, sysUser *system.Admin, classifyType uint8) (err error, errMsg string) {
+	// req.ClassifyId, req.ParentClassifyId, req.PrevClassifyId, req.NextClassifyId
+	classifyId := req.ClassifyId
+	parentClassifyId := req.ParentClassifyId
+	prevClassifyId := req.PrevClassifyId
+	nextClassifyId := req.NextClassifyId
+
+	edbInfoId := req.EdbInfoId
+	prevEdbInfoId := req.PrevEdbInfoId
+	nextEdbInfoId := req.NextEdbInfoId
+
+	//首先确定移动的对象是分类还是指标
+	//判断上一个节点是分类还是指标
+	//判断下一个节点是分类还是指标
+	//同时更新分类目录下的分类sort和指标sort
+	//更新当前移动的分类或者指标sort
+
+	var parentEdbClassifyInfo *data_manage.EdbClassify
+	if parentClassifyId > 0 {
+		parentEdbClassifyInfo, err = data_manage.GetEdbClassifyById(parentClassifyId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("获取上级分类信息失败,Err:" + err.Error())
+			return
+		}
+	}
+
+	//如果有传入 上一个兄弟节点分类id
+	var (
+		edbClassifyInfo *data_manage.EdbClassify
+		prevClassify    *data_manage.EdbClassify
+		nextClassify    *data_manage.EdbClassify
+
+		edbInfo     *data_manage.EdbInfo
+		prevEdbInfo *data_manage.EdbInfo
+		nextEdbInfo *data_manage.EdbInfo
+		prevSort    int
+		nextSort    int
+	)
+
+	// 移动对象为分类, 判断权限
+	if edbInfoId == 0 {
+		edbClassifyInfo, err = data_manage.GetEdbClassifyById(classifyId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				errMsg = "当前分类不存在"
+				err = errors.New("获取分类信息失败,Err:" + err.Error())
+				return
+			}
+			errMsg = "移动失败"
+			err = errors.New("获取分类信息失败,Err:" + err.Error())
+			return
+		}
+		if edbClassifyInfo.SysUserId != sysUser.AdminId {
+			errMsg = "不是本人目录,您没有操作权限"
+			err = errors.New(errMsg)
+			return
+		}
+		if parentClassifyId > 0 && parentEdbClassifyInfo.Level == 6 {
+			errMsg = "最高只支持添加6级分类"
+			err = errors.New(errMsg)
+			return
+		}
+		// 如果是移动目录, 那么校验一下父级目录下是否有重名目录
+		exists, e := data_manage.GetEdbClassifyByParentIdAndName(parentClassifyId, edbClassifyInfo.ClassifyName, classifyId, classifyType)
+		if e != nil && !utils.IsErrNoRow(e) {
+			errMsg = "移动失败"
+			err = fmt.Errorf("获取父级分类下的同名分类失败, Err: %s", e.Error())
+			return
+		}
+		if exists != nil && exists.ClassifyId > 0 {
+			errMsg = "移动失败,分类名称已存在"
+			return
+		}
+
+		// 权限校验
+		{
+			// 已授权分类id
+			permissionClassifyIdList, tmpErr := data_manage_permission.GetUserEdbClassifyPermissionList(sysUser.AdminId, classifyId)
+			if tmpErr != nil {
+				errMsg = "移动失败"
+				err = errors.New("获取已授权分类id数据失败,Err:" + tmpErr.Error())
+				return
+			}
+			// 数据权限
+			haveOperaAuth := data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(edbClassifyInfo.IsJoinPermission, edbClassifyInfo.ClassifyId, permissionClassifyIdList)
+
+			if edbClassifyInfo.ClassifyType == 0 { // 普通指标
+				button := GetEdbClassifyOpButton(sysUser, edbClassifyInfo.SysUserId, haveOperaAuth)
+				if !button.MoveButton {
+					errMsg = "无操作权限"
+					err = errors.New(errMsg)
+					return
+				}
+			} else if edbClassifyInfo.ClassifyType == 1 { // 预测指标
+				button := GetPredictEdbClassifyOpButton(sysUser, edbClassifyInfo.SysUserId, haveOperaAuth)
+				if !button.MoveButton {
+					errMsg = "无操作权限"
+					err = errors.New(errMsg)
+					return
+				}
+			}
+		}
+
+	} else {
+		edbInfo, err = data_manage.GetEdbInfoById(req.EdbInfoId)
+		if err != nil {
+			if utils.IsErrNoRow(err) {
+				errMsg = "当前指标不存在"
+				err = errors.New("获取分类信息失败,Err:" + err.Error())
+				return
+			}
+			errMsg = "移动失败"
+			err = errors.New("获取分类信息失败,Err:" + err.Error())
+			return
+		}
+
+		if edbInfo.SysUserId != sysUser.AdminId {
+			errMsg = "不是本人指标,您没有操作权限"
+			err = errors.New(errMsg)
+			return
+		}
+
+		if parentClassifyId == 0 {
+			errMsg = "移动失败,指标必须挂在分类下"
+			err = errors.New(errMsg)
+			return
+		}
+
+		var haveOperaAuth bool
+		// 权限校验
+		{
+			haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.EdbInfoId, edbInfo.ClassifyId, edbInfo.IsJoinPermission, sysUser.AdminId)
+			if err != nil {
+				errMsg = "移动失败"
+				err = errors.New("获取指标权限信息失败,Err:" + err.Error())
+				return
+			}
+		}
+
+		// 移动权限校验
+		button := GetEdbOpButton(sysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType, haveOperaAuth)
+		if !button.MoveButton {
+			errMsg = "无操作权限"
+			err = errors.New(errMsg)
+			return
+		}
+	}
+
+	if prevClassifyId > 0 {
+		prevClassify, err = data_manage.GetEdbClassifyById(prevClassifyId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
+			return
+		}
+		prevSort = prevClassify.Sort
+	} else if prevEdbInfoId > 0 {
+		prevEdbInfo, err = data_manage.GetEdbInfoById(prevEdbInfoId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
+			return
+		}
+		prevSort = prevEdbInfo.Sort
+	}
+
+	if nextClassifyId > 0 {
+		//下一个兄弟节点
+		nextClassify, err = data_manage.GetEdbClassifyById(nextClassifyId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
+			return
+		}
+		nextSort = nextClassify.Sort
+	} else if nextEdbInfoId > 0 {
+		//下一个兄弟节点
+		nextEdbInfo, err = data_manage.GetEdbInfoById(nextEdbInfoId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
+			return
+		}
+		nextSort = nextEdbInfo.Sort
+	}
+
+	err, errMsg = moveEdbOrClassify(parentEdbClassifyInfo, edbClassifyInfo, prevClassify, nextClassify, edbInfo, prevEdbInfo, nextEdbInfo, parentClassifyId, prevSort, nextSort, classifyType)
+	return
+}
+
+// moveEdbOrClassify 移动指标分类
+func moveEdbOrPublicClassify(parentEdbClassifyInfo, edbClassifyInfo, prevClassify, nextClassify *data_manage.EdbClassify, edbInfo, prevEdbInfo, nextEdbInfo *data_manage.EdbInfo, parentClassifyId int, prevSort, nextSort int, classifyType uint8) (err error, errMsg string) {
+
+	if edbClassifyInfo != nil {
+		// 移动分类
+		return moveEdbClassify(parentEdbClassifyInfo, edbClassifyInfo, prevClassify, nextClassify, prevEdbInfo, nextEdbInfo, parentClassifyId, prevSort, nextSort, classifyType)
+	} else {
+		// 移动指标
+		return moveEdb(prevClassify, nextClassify, edbInfo, prevEdbInfo, nextEdbInfo, parentClassifyId, prevSort, nextSort, classifyType)
+	}
+
+	return
+}
+
+// moveEdb
+// @Description: 移动指标
+// @author: Roc
+// @datetime 2024-11-26 16:07:37
+// @param prevClassify *data_manage.EdbClassify
+// @param nextClassify *data_manage.EdbClassify
+// @param edbInfo *data_manage.EdbInfo
+// @param prevEdbInfo *data_manage.EdbInfo
+// @param nextEdbInfo *data_manage.EdbInfo
+// @param parentClassifyId int
+// @param prevSort int
+// @param nextSort int
+// @param classifyType uint8
+// @return err error
+// @return errMsg string
+func movePublicEdb(prevClassify, nextClassify *data_manage.EdbClassify, edbInfo, prevEdbInfo, nextEdbInfo *data_manage.EdbInfo, parentClassifyId int, prevSort, nextSort int, classifyType uint8) (err error, errMsg string) {
+	updateCol := make([]string, 0)
+
+	if edbInfo == nil {
+		errMsg = "当前指标不存在"
+		err = errors.New(errMsg)
+		return
+	}
+	//如果改变了分类,那么移动该指标数据
+	if edbInfo.ClassifyId != parentClassifyId {
+		edbInfo.ClassifyId = parentClassifyId
+		edbInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "ClassifyId", "ModifyTime")
+	}
+	if prevSort > 0 {
+		//如果是移动在两个兄弟节点之间
+		if nextSort > 0 {
+			//下一个兄弟节点
+			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+			if prevSort == nextSort || prevSort == edbInfo.Sort {
+				//变更兄弟节点的排序
+				updateSortStr := `sort + 2`
+
+				//变更分类
+				if prevClassify != nil {
+					_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, prevClassify.ClassifyId, prevClassify.Sort, updateSortStr, classifyType)
+				} else {
+					_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, 0, prevSort, updateSortStr, classifyType)
+				}
+
+				//变更指标
+				if prevEdbInfo != nil {
+					//变更兄弟节点的排序
+					_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, prevEdbInfo.EdbInfoId, updateSortStr)
+				} else {
+					_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, 0, updateSortStr)
+				}
+			} else {
+				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+				if nextSort-prevSort == 1 {
+					//变更兄弟节点的排序
+					updateSortStr := `sort + 1`
+					//变更分类
+					if prevClassify != nil {
+						_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, prevClassify.ClassifyId, prevSort, updateSortStr, classifyType)
+					} else {
+						_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, 0, prevSort, updateSortStr, classifyType)
+					}
+
+					//变更指标
+					if prevEdbInfo != nil {
+						//变更兄弟节点的排序
+						_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, prevEdbInfo.EdbInfoId, updateSortStr)
+					} else {
+						_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, 0, updateSortStr)
+					}
+				}
+			}
+		}
+
+		edbInfo.Sort = prevSort + 1
+		edbInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	} else if prevClassify == nil && nextClassify == nil && prevEdbInfo == nil && nextEdbInfo == nil && parentClassifyId > 0 {
+		//处理只拖动到目录里,默认放到目录底部的情况
+		var maxSort int
+		maxSort, err = GetEdbClassifyMaxSort(parentClassifyId, classifyType)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("查询组内排序信息失败,Err:" + err.Error())
+			return
+		}
+		edbInfo.Sort = maxSort + 1 //那就是排在组内最后一位
+		edbInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	} else {
+		// 拖动到父级分类的第一位
+		firstClassify, tmpErr := data_manage.GetFirstEdbClassifyByParentId(parentClassifyId)
+		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
+			errMsg = "移动失败"
+			err = errors.New("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error())
+			return
+		}
+
+		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+		if firstClassify != nil && firstClassify.ClassifyId > 0 && firstClassify.Sort == 0 {
+			updateSortStr := ` sort + 1 `
+			_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, firstClassify.ClassifyId-1, 0, updateSortStr, classifyType)
+			//该分类下的所有指标也需要+1
+			_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, 0, 0, updateSortStr)
+		} else {
+			//如果该分类下存在指标,且第一个指标的排序等于0,那么需要调整排序
+			firstEdb, tErr := data_manage.GetFirstEdbInfoByClassifyId(parentClassifyId)
+			if tErr != nil && !utils.IsErrNoRow(tErr) {
+				errMsg = "移动失败"
+				err = errors.New("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tErr.Error())
+				return
+			}
+
+			//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+			if firstEdb != nil && firstEdb.ClassifyId > 0 && firstEdb.Sort == 0 {
+				updateSortStr := ` sort + 1 `
+				_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, 0, firstEdb.EdbInfoId-1, updateSortStr)
+				_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, 0, 0, updateSortStr, classifyType)
+			}
+		}
+
+		edbInfo.Sort = 0 //那就是排在第一位
+		edbInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	}
+
+	//更新
+	if len(updateCol) > 0 {
+		err = edbInfo.Update(updateCol)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("修改失败,Err:" + err.Error())
+			return
+		}
+	}
+
+	return
+}
+
+// moveEdbClassify
+// @Description: 移动指标分类
+// @author: Roc
+// @datetime 2024-11-26 16:07:44
+// @param parentEdbClassifyInfo *data_manage.EdbClassify
+// @param edbClassifyInfo *data_manage.EdbClassify
+// @param prevClassify *data_manage.EdbClassify
+// @param nextClassify *data_manage.EdbClassify
+// @param edbInfo *data_manage.EdbInfo
+// @param prevEdbInfo *data_manage.EdbInfo
+// @param nextEdbInfo *data_manage.EdbInfo
+// @param parentClassifyId int
+// @param prevSort int
+// @param nextSort int
+// @param classifyType uint8
+// @return err error
+// @return errMsg string
+func moveEdbPublicClassify(parentEdbClassifyInfo, edbClassifyInfo, prevClassify, nextClassify *data_manage.EdbClassify, prevEdbInfo, nextEdbInfo *data_manage.EdbInfo, parentClassifyId int, prevSort, nextSort int, classifyType uint8) (err error, errMsg string) {
+	updateCol := make([]string, 0)
+
+	// 移动对象为分类, 判断分类是否存在
+	oldParentId := edbClassifyInfo.ParentId
+	oldLevel := edbClassifyInfo.Level
+	var classifyIds []int
+	if oldParentId != parentClassifyId {
+		//更新子分类对应的level
+		childList, e, m := GetChildClassifyByClassifyId(edbClassifyInfo.ClassifyId)
+		if e != nil {
+			errMsg = "移动失败"
+			err = errors.New("查询子分类失败,Err:" + e.Error() + m)
+			return
+		}
+
+		if len(childList) > 0 {
+			for _, v := range childList {
+				if v.ClassifyId == edbClassifyInfo.ClassifyId {
+					continue
+				}
+				classifyIds = append(classifyIds, v.ClassifyId)
+			}
+		}
+	}
+	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
+	if edbClassifyInfo.ParentId != parentClassifyId && parentClassifyId != 0 {
+		if edbClassifyInfo.Level != parentEdbClassifyInfo.Level+1 { //禁止层级调整
+			errMsg = "移动失败"
+			err = errors.New("不支持目录层级变更")
+			return
+		}
+		edbClassifyInfo.ParentId = parentEdbClassifyInfo.ClassifyId
+		edbClassifyInfo.RootId = parentEdbClassifyInfo.RootId
+		edbClassifyInfo.Level = parentEdbClassifyInfo.Level + 1
+		edbClassifyInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "ParentId", "RootId", "Level", "ModifyTime")
+	} else if edbClassifyInfo.ParentId != parentClassifyId && parentClassifyId == 0 {
+		errMsg = "移动失败"
+		err = errors.New("不支持目录层级变更")
+		return
+	}
+
+	if prevSort > 0 {
+		//如果是移动在两个兄弟节点之间
+		if nextSort > 0 {
+			//下一个兄弟节点
+			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+			if prevSort == nextSort || prevSort == edbClassifyInfo.Sort {
+				//变更兄弟节点的排序
+				updateSortStr := `sort + 2`
+
+				//变更分类
+				if prevClassify != nil {
+					_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, prevClassify.ClassifyId, prevClassify.Sort, updateSortStr, classifyType)
+				} else {
+					_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, 0, prevSort, updateSortStr, classifyType)
+				}
+
+				//变更指标
+				if prevEdbInfo != nil {
+					//变更兄弟节点的排序
+					_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, prevEdbInfo.EdbInfoId, updateSortStr)
+				} else {
+					_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, 0, updateSortStr)
+				}
+			} else {
+				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+				if nextSort-prevSort == 1 {
+					//变更兄弟节点的排序
+					updateSortStr := `sort + 1`
+
+					//变更分类
+					if prevClassify != nil {
+						_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, prevClassify.ClassifyId, prevSort, updateSortStr, classifyType)
+					} else {
+						_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, 0, prevSort, updateSortStr, classifyType)
+					}
+
+					//变更指标
+					if prevEdbInfo != nil {
+						//变更兄弟节点的排序
+						_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, prevEdbInfo.EdbInfoId, updateSortStr)
+					} else {
+						_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, prevSort, 0, updateSortStr)
+					}
+
+				}
+			}
+		}
+
+		edbClassifyInfo.Sort = prevSort + 1
+		edbClassifyInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	} else if prevClassify == nil && nextClassify == nil && prevEdbInfo == nil && nextEdbInfo == nil && parentClassifyId > 0 {
+		//处理只拖动到目录里,默认放到目录底部的情况
+		var maxSort int
+		maxSort, err = GetEdbClassifyMaxSort(parentClassifyId, classifyType)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("查询组内排序信息失败,Err:" + err.Error())
+			return
+		}
+		edbClassifyInfo.Sort = maxSort + 1 //那就是排在组内最后一位
+		edbClassifyInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	} else {
+		// 拖动到父级分类的第一位
+		firstClassify, tmpErr := data_manage.GetFirstEdbClassifyByParentId(parentClassifyId)
+		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
+			errMsg = "移动失败"
+			err = errors.New("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error())
+			return
+		}
+
+		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+		if firstClassify != nil && firstClassify.ClassifyId > 0 && firstClassify.Sort == 0 {
+			updateSortStr := ` sort + 1 `
+			_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, firstClassify.ClassifyId-1, 0, updateSortStr, classifyType)
+			//该分类下的所有指标也需要+1
+			_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, 0, 0, updateSortStr)
+		} else {
+			//如果该分类下存在指标,且第一个指标的排序等于0,那么需要调整排序
+			firstEdb, tErr := data_manage.GetFirstEdbInfoByClassifyId(parentClassifyId)
+			if tErr != nil && !utils.IsErrNoRow(tErr) {
+				errMsg = "移动失败"
+				err = errors.New("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tErr.Error())
+				return
+			}
+
+			//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+			if firstEdb != nil && firstEdb.ClassifyId > 0 && firstEdb.Sort == 0 {
+				updateSortStr := ` sort + 1 `
+				_ = data_manage.UpdateEdbInfoSortByClassifyId(parentClassifyId, 0, firstEdb.EdbInfoId-1, updateSortStr)
+				_ = data_manage.UpdateEdbClassifySortByParentId(parentClassifyId, 0, 0, updateSortStr, classifyType)
+			}
+		}
+
+		edbClassifyInfo.Sort = 0 //那就是排在第一位
+		edbClassifyInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	}
+
+	oldClassifyIdPath := edbClassifyInfo.ClassifyIdPath
+	oldClassifyNamePath := edbClassifyInfo.ClassifyNamePath
+	newClassifyNamePath := fmt.Sprint(parentEdbClassifyInfo.ClassifyNamePath, `|`, edbClassifyInfo.ClassifyName)
+	newClassifyIdPath := fmt.Sprint(parentEdbClassifyInfo.ClassifyIdPath, `,`, edbClassifyInfo.ClassifyId)
+
+	//更新
+	if len(updateCol) > 0 {
+		edbClassifyInfo.ClassifyNamePath = newClassifyNamePath
+		edbClassifyInfo.ClassifyIdPath = newClassifyIdPath
+		updateCol = append(updateCol, "ClassifyNamePath", "ClassifyIdPath")
+
+		err = edbClassifyInfo.Update(updateCol)
+		if err != nil {
+			errMsg = "移动失败"
+			err = errors.New("修改失败,Err:" + err.Error())
+			return
+		}
+		//更新对应分类的root_id和层级
+		if oldParentId != parentClassifyId {
+			if len(classifyIds) > 0 {
+				levelStep := edbClassifyInfo.Level - oldLevel
+				err = data_manage.UpdateEdbClassifyChildByParentClassifyId(classifyIds, edbClassifyInfo.RootId, levelStep)
+				if err != nil {
+					errMsg = "移动失败"
+					err = errors.New("更新子分类失败,Err:" + err.Error())
+					return
+				}
+			}
+
+			// 更改了上级分类,那么需要同步去更改自己的分类全路径
+			tmpErr := data_manage.UpdateEdbClassifyNameAndNamePathByOldClassifyIdPath(oldClassifyIdPath, newClassifyIdPath, oldClassifyNamePath, newClassifyNamePath)
+			if tmpErr != nil {
+				utils.FileLog.Error(fmt.Sprintf("更新分类全路径失败,分类id:%d;失败原因Err:%s", edbClassifyInfo.ClassifyId, tmpErr.Error()))
+			}
+		}
+
+	}
+
+	return
+}

+ 1 - 1
services/edb_info_replace.go

@@ -84,7 +84,7 @@ func DealReplaceEdbCache() {
 func ReplaceEdbInExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo) (err error) {
 	defer func() {
 		if err != nil {
-			go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errmsg:"+err.Error(), 3)
+			go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errMsg:"+err.Error(), 3)
 		}
 	}()
 	//查询和指标相关的时间序列表格和混合表格

+ 726 - 0
services/elastic/edb_info.go

@@ -0,0 +1,726 @@
+package elastic
+
+import (
+	"context"
+	"encoding/json"
+	"eta_gn/eta_api/models/data_manage"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"github.com/olivere/elastic/v7"
+)
+
+// EsAddOrEditEdbInfoData 新增/修改es中的指标数据
+func EsAddOrEditEdbInfoData(indexName, docId string, item *data_manage.EdbInfoEs) (err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println("EsAddOrEditData Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+
+	resp, err := client.Index().Index(indexName).Id(docId).BodyJson(item).Do(context.Background())
+	if err != nil {
+		fmt.Println("新增失败:", err.Error())
+		return err
+	}
+	fmt.Println(resp)
+	if resp.Status == 0 {
+		fmt.Println("新增成功", resp.Result)
+		err = nil
+	} else {
+		fmt.Println("AddData", resp.Status, resp.Result)
+	}
+	return
+}
+
+// searchEdbInfoData 查询es中的指标数据
+func searchEdbInfoData(indexName string, mustMap, mustNotMap []interface{}, shouldMapList []map[string]interface{}, sortList []interface{}, from, size int) (total int64, list []*data_manage.EdbInfoList, err error) {
+	list = make([]*data_manage.EdbInfoList, 0)
+	defer func() {
+		if err != nil {
+			fmt.Println("searchEdbInfoData Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+
+	//queryString := elastic.NewQueryStringQuery(keywordStr)
+	//boolQueryJson, err := json.Marshal(queryString)
+	//if err != nil {
+	//	fmt.Println("boolQueryJson err:", err)
+	//} else {
+	//	fmt.Println("boolQueryJson ", string(boolQueryJson))
+	//}
+
+	highlight := elastic.NewHighlight()
+	highlight = highlight.Fields(elastic.NewHighlighterField("EdbCode"), elastic.NewHighlighterField("EdbName"))
+	highlight = highlight.PreTags("<font color='red'>").PostTags("</font>")
+
+	//query := elastic.RawStringQuery(`{"match_all":{}}`)
+
+	//关键字匹配
+	for _, shouldMap := range shouldMapList {
+		mustMap = append(mustMap, map[string]interface{}{
+			"bool": shouldMap,
+		})
+	}
+
+	queryMap := map[string]interface{}{
+		"query": map[string]interface{}{
+			"bool": map[string]interface{}{
+				"must":     mustMap,
+				"must_not": mustNotMap,
+				//"should":   shouldMap,
+			},
+		},
+	}
+
+	//根据条件数量统计
+	requestTotalHits := client.Count(indexName).BodyJson(queryMap)
+	total, err = requestTotalHits.Do(context.Background())
+	if err != nil {
+		return
+	}
+
+	queryMap["from"] = from
+	queryMap["size"] = size
+
+	// 如果有指定排序,那么就按照排序来
+	if len(sortList) > 0 {
+		queryMap["sort"] = sortList
+	}
+
+	jsonBytes, _ := json.Marshal(queryMap)
+	fmt.Println(string(jsonBytes))
+
+	//queryString := elastic.NewMatchQuery("EdbCode", keywordStr)
+	//request := client.Search(indexName).Highlight(highlight).From(from).Size(size).Query(queryString)
+
+	request := client.Search(indexName).Highlight(highlight).Source(queryMap) // sets the JSON request
+
+	//requestJson, err := json.Marshal(request)
+	//if err != nil {
+	//	fmt.Println("requestJson err:", err)
+	//}
+	//fmt.Println("requestJson ", string(requestJson))
+	searchMap := make(map[string]string)
+
+	searchResp, err := request.Do(context.Background())
+	if err != nil {
+		return
+	}
+	fmt.Println(searchResp)
+	fmt.Println(searchResp.Status)
+	if searchResp.Status != 0 {
+		return
+	}
+	//total = searchResp.TotalHits()
+	if searchResp.Hits != nil {
+		for _, v := range searchResp.Hits.Hits {
+			if _, ok := searchMap[v.Id]; !ok {
+				itemJson, tmpErr := v.Source.MarshalJSON()
+				if tmpErr != nil {
+					err = tmpErr
+					fmt.Println("movieJson err:", err)
+					return
+				}
+				edbInfoItem := new(data_manage.EdbInfoList)
+				tmpErr = json.Unmarshal(itemJson, &edbInfoItem)
+				if tmpErr != nil {
+					fmt.Println("json.Unmarshal movieJson err:", tmpErr)
+					err = tmpErr
+					return
+				}
+				if len(v.Highlight["EdbCode"]) > 0 {
+					edbInfoItem.EdbCode = v.Highlight["EdbCode"][0]
+				}
+				if len(v.Highlight["EdbName"]) > 0 {
+					edbInfoItem.EdbCode = v.Highlight["EdbName"][0]
+				}
+				list = append(list, edbInfoItem)
+				searchMap[v.Id] = v.Id
+			}
+		}
+	}
+
+	return
+}
+
+// SearchEdbInfoData
+// @Description: 查询es中的指标数据
+// @author: Roc
+// @datetime 2024-11-29 10:22:25
+// @param keywordStr string
+// @param from int
+// @param size int
+// @param filterSource int
+// @param source int
+// @param frequency string
+// @param noPermissionEdbInfoIdList []int
+// @param noPermissionEdbClassifyIdList []int
+// @param collectEdbInfoIdList []int
+// @param edbTypeList []int
+// @param edbInfoType int 指标类型,0:ETA指标库(基础指标+计算指标);1:预测指标
+// @param edbAuth int 指标权限范围,0-全部;1-我的;2-公共
+// @param sysUserId int
+// @return total int64
+// @return list []*data_manage.EdbInfoList
+// @return err error
+func SearchEdbInfoData(keywordStr string, from, size, filterSource, source int, frequency string, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, collectEdbInfoIdList, edbTypeList []int, edbInfoType, edbAuth, sysUserId int, sortMap map[string]string) (total int64, list []*data_manage.EdbInfoList, err error) {
+	indexName := utils.DATA_INDEX_NAME
+	list = make([]*data_manage.EdbInfoList, 0)
+	defer func() {
+		if err != nil {
+			fmt.Println("SearchEdbInfoData Err:", err.Error())
+		}
+	}()
+
+	highlight := elastic.NewHighlight()
+	highlight = highlight.Fields(elastic.NewHighlighterField("EdbCode"), elastic.NewHighlighterField("EdbName"))
+	highlight = highlight.PreTags("<font color='red'>").PostTags("</font>")
+
+	mustMap := make([]interface{}, 0)
+	mustNotMap := make([]interface{}, 0)
+
+	switch filterSource {
+	case 2:
+		mustMap = append(mustMap, map[string]interface{}{
+			"term": map[string]interface{}{
+				"Frequency.keyword": "月度",
+				//"Frequency.keyword": "月度",
+			},
+		})
+	case 3:
+	case 4:
+		mustMap = append(mustMap, map[string]interface{}{
+			"term": map[string]interface{}{
+				"EdbType": 1,
+			},
+		})
+	case 5:
+		mustMap = append(mustMap, map[string]interface{}{
+			"term": map[string]interface{}{
+				"Source": 6,
+			},
+		})
+	case 6:
+		mustMap = append(mustMap, map[string]interface{}{
+			"match": map[string]interface{}{
+				"Frequency.keyword": "年度",
+			},
+		})
+	}
+
+	//指标来源
+	if source > 0 {
+		mustMap = append(mustMap, map[string]interface{}{
+			"term": map[string]interface{}{
+				"Source": source,
+				//"Frequency.keyword": "月度",
+			},
+		})
+	}
+
+	if frequency != "" {
+		mustMap = append(mustMap, map[string]interface{}{
+			"term": map[string]interface{}{
+				"Frequency.keyword": frequency,
+				//"Frequency.keyword": "月度",
+			},
+		})
+	}
+
+	// noPermissionEdbInfoIdList 无权限指标id
+	if len(noPermissionEdbInfoIdList) > 0 {
+		mustNotMap = append(mustNotMap, map[string]interface{}{
+			"terms": map[string]interface{}{
+				"EdbInfoId": noPermissionEdbInfoIdList,
+				//"Frequency.keyword": "月度",
+			},
+		})
+	}
+
+	// noPermissionEdbInfoIdList 无权限指标id
+	if len(noPermissionEdbClassifyIdList) > 0 {
+		mustNotMap = append(mustNotMap, map[string]interface{}{
+			"terms": map[string]interface{}{
+				"ClassifyId": noPermissionEdbClassifyIdList,
+				//"Frequency.keyword": "月度",
+			},
+		})
+	}
+
+	// collectEdbInfoIdList 收藏的指标id
+	if len(collectEdbInfoIdList) > 0 {
+		mustMap = append(mustMap, map[string]interface{}{
+			"terms": map[string]interface{}{
+				"EdbInfoId": collectEdbInfoIdList,
+			},
+		})
+	}
+
+	// 指标类型:0-基础+计算;1-基础指标;2-计算指标;3-预测指标
+	if len(edbTypeList) > 0 {
+		mustMap = append(mustMap, map[string]interface{}{
+			"terms": map[string]interface{}{
+				"EdbType": edbTypeList,
+			},
+		})
+	}
+
+	if edbInfoType >= 0 {
+		mustMap = append(mustMap, map[string]interface{}{
+			"term": map[string]interface{}{
+				"EdbInfoType": edbInfoType,
+			},
+		})
+	}
+
+	shouldMapList := make([]map[string]interface{}, 0)
+
+	// 指标名称、编码匹配
+	if keywordStr != `` {
+		// 默认使用中文名字字段去匹配
+		keywordNameKey := `EdbName`
+		shouldMap := map[string]interface{}{
+			"should": []interface{}{
+				map[string]interface{}{
+					"match": map[string]interface{}{
+						"EdbCode": keywordStr,
+						//"Frequency.keyword": "月度",
+					},
+				},
+				map[string]interface{}{
+					"match": map[string]interface{}{
+						keywordNameKey: keywordStr,
+						//"Frequency.keyword": "月度",
+					},
+				},
+			},
+		}
+		shouldMapList = append(shouldMapList, shouldMap)
+	}
+
+	// 指标与用户的权限匹配
+	{
+		shouldTermList := make([]map[string]interface{}, 0)
+		//指标权限范围,0-全部;1-我的;2-公共
+		switch edbAuth {
+		case 1:
+			// 自己的指标
+			shouldTermList = append(shouldTermList, map[string]interface{}{
+				"term": map[string]interface{}{
+					"SysUserId": sysUserId,
+				},
+			})
+		case 2:
+			// 公开的指标
+			shouldTermList = append(shouldTermList, map[string]interface{}{
+				"term": map[string]interface{}{
+					"PublicStatus": utils.EdbPublicSuccess,
+				},
+			})
+		default:
+			// 自己的指标
+			shouldTermList = append(shouldTermList, map[string]interface{}{
+				"term": map[string]interface{}{
+					"SysUserId": sysUserId,
+				},
+			})
+			// 分享给我的指标
+			shouldTermList = append(shouldTermList, map[string]interface{}{
+				"terms": map[string]interface{}{
+					"SharedUserIdList": []int{sysUserId},
+				},
+			})
+			// 公开的指标
+			shouldTermList = append(shouldTermList, map[string]interface{}{
+				"term": map[string]interface{}{
+					"PublicStatus": utils.EdbPublicSuccess,
+				},
+			})
+
+		}
+
+		shouldMap := map[string]interface{}{
+			"should": shouldTermList,
+		}
+		shouldMapList = append(shouldMapList, shouldMap)
+	}
+
+	// 排序
+	sortList := make([]interface{}, 0)
+	// 如果没有关键字,那么就走指标id倒序
+
+	for orderKey, orderType := range sortMap {
+		sortEdbInfoId := map[string]interface{}{
+			orderKey: map[string]interface{}{
+				"order": orderType,
+			},
+		}
+		sortList = append(sortList, sortEdbInfoId)
+	}
+
+	return searchEdbInfoData(indexName, mustMap, mustNotMap, shouldMapList, sortList, from, size)
+}
+
+// searchEdbInfoData 查询es中的指标数量
+func searchEdbInfoDataTotal(indexName string, query elastic.Query) (total int64, err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println("searchEdbInfoDataV2 Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+
+	//根据条件数量统计
+	requestTotalHits := client.Count(indexName).Query(query)
+	total, err = requestTotalHits.Do(context.Background())
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// searchEdbInfoData 查询es中的指标数据
+func searchEdbInfoDataList(indexName string, query elastic.Query, sortList []*elastic.FieldSort, from, size int) (list []*data_manage.EdbInfoList, err error) {
+	list = make([]*data_manage.EdbInfoList, 0)
+	defer func() {
+		if err != nil {
+			fmt.Println("searchEdbInfoDataV2 Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+	// 高亮
+	highlight := elastic.NewHighlight()
+	highlight = highlight.Fields(elastic.NewHighlighterField("EdbCode"), elastic.NewHighlighterField("EdbName"))
+	highlight = highlight.PreTags("<font color='red'>").PostTags("</font>")
+
+	request := client.Search(indexName).Highlight(highlight).From(from).Size(size) // sets the JSON request
+
+	// 如果有指定排序,那么就按照排序来
+	if len(sortList) > 0 {
+		for _, v := range sortList {
+			request = request.SortBy(v)
+		}
+	}
+
+	searchMap := make(map[string]string)
+
+	searchResp, err := request.Query(query).Do(context.Background())
+	if err != nil {
+		return
+	}
+	//fmt.Println(searchResp)
+	//fmt.Println(searchResp.Status)
+	if searchResp.Status != 0 {
+		return
+	}
+	//total = searchResp.TotalHits()
+	if searchResp.Hits != nil {
+		for _, v := range searchResp.Hits.Hits {
+			if _, ok := searchMap[v.Id]; !ok {
+				itemJson, tmpErr := v.Source.MarshalJSON()
+				if tmpErr != nil {
+					err = tmpErr
+					fmt.Println("movieJson err:", err)
+					return
+				}
+				edbInfoItem := new(data_manage.EdbInfoList)
+				tmpErr = json.Unmarshal(itemJson, &edbInfoItem)
+				if tmpErr != nil {
+					fmt.Println("json.Unmarshal movieJson err:", tmpErr)
+					err = tmpErr
+					return
+				}
+				if len(v.Highlight["EdbCode"]) > 0 {
+					edbInfoItem.EdbCode = v.Highlight["EdbCode"][0]
+				}
+				if len(v.Highlight["EdbName"]) > 0 {
+					edbInfoItem.EdbCode = v.Highlight["EdbName"][0]
+				}
+				list = append(list, edbInfoItem)
+				searchMap[v.Id] = v.Id
+			}
+		}
+	}
+
+	return
+}
+
+// searchEdbInfoData 查询es中的指标数据
+func searchEdbInfoDataV2(indexName string, query elastic.Query, sortList []*elastic.FieldSort, from, size int) (total int64, list []*data_manage.EdbInfoList, err error) {
+	total, err = searchEdbInfoDataTotal(indexName, query)
+	if err != nil {
+		return
+	}
+
+	// 获取列表数据
+	list, err = searchEdbInfoDataList(indexName, query, sortList, from, size)
+	if err != nil {
+		return
+	}
+
+	return
+}
+
+// SearchEdbInfoDataByShared
+// @Description: 查询es中的指标数据
+// @author: Roc
+// @datetime 2024-11-29 10:22:25
+// @param keywordStr string
+// @param from int
+// @param size int
+// @param filterSource int
+// @param source int
+// @param frequency string
+// @param noPermissionEdbInfoIdList []int
+// @param noPermissionEdbClassifyIdList []int
+// @param collectEdbInfoIdList []int
+// @param edbTypeList []int
+// @param edbInfoType int 指标类型,0:ETA指标库(基础指标+计算指标);1:预测指标
+// @param edbAuth int 指标权限范围,0-全部;1-我的;2-公共
+// @param sysUserId int
+// @return total int64
+// @return list []*data_manage.EdbInfoList
+// @return err error
+func SearchEdbInfoDataByShared(keywordStr string, from, size, edbShare int, sourceList, classifyIdList, edbTypeList []int, edbInfoType, edbAuth, sysUserId int, sortMap map[string]string) (total int64, list []*data_manage.EdbInfoList, err error) {
+	indexName := utils.DATA_INDEX_NAME
+	list = make([]*data_manage.EdbInfoList, 0)
+	defer func() {
+		if err != nil {
+			fmt.Println("SearchEdbInfoData Err:", err.Error())
+		}
+	}()
+
+	query := elastic.NewBoolQuery()
+
+	//指标来源
+	if len(sourceList) > 0 {
+		termsList := make([]interface{}, 0)
+		for _, v := range sourceList {
+			termsList = append(termsList, v)
+		}
+		query = query.Must(elastic.NewTermsQuery("Source", termsList...))
+	}
+
+	// classifyIdList 指定分类下的指标
+	if len(classifyIdList) > 0 {
+		termsList := make([]interface{}, 0)
+		for _, v := range classifyIdList {
+			termsList = append(termsList, v)
+		}
+		query = query.Must(elastic.NewTermsQuery("ClassifyId", termsList...))
+	}
+
+	// 指标类型:0-基础+计算;1-基础指标;2-计算指标;3-预测指标
+	if len(edbTypeList) > 0 {
+		termsList := make([]interface{}, 0)
+		for _, v := range edbTypeList {
+			termsList = append(termsList, v)
+		}
+		query = query.Must(elastic.NewTermsQuery("EdbType", termsList...))
+	}
+
+	// 如果指定了分享状态,那么就添加分享状态的筛选
+	// 0:全部,1:未共享,2:已共享
+	switch edbShare {
+	case 1:
+		// 筛选 SharedUserIdList 为空的文档
+		query = query.MustNot(elastic.NewExistsQuery("SharedUserIdList"))
+	case 2:
+		// 筛选 SharedUserIdList 不为空的文档
+		query = query.Must(elastic.NewExistsQuery("SharedUserIdList"))
+	}
+
+	if edbInfoType >= 0 {
+		query = query.Must(elastic.NewTermQuery("EdbInfoType", edbInfoType))
+	}
+
+	// 指标名称、编码匹配
+	if keywordStr != `` {
+		// 默认使用中文名字字段去匹配
+		keywordNameKey := `EdbName`
+		query = query.Must(elastic.NewMultiMatchQuery(keywordStr, keywordNameKey, "EdbCode"))
+	}
+
+	// 指标与用户的权限匹配
+	{
+		//指标权限范围,0-全部;1-我的;2-公共
+		switch edbAuth {
+		case 1:
+			// 自己的指标
+			query = query.Must(elastic.NewTermQuery(`SysUserId`, sysUserId))
+		case 2:
+			// 公开的指标
+			query = query.Must(elastic.NewTermQuery(`PublicStatus`, utils.EdbPublicSuccess))
+		default:
+			tmpShouldQuery := elastic.NewBoolQuery()
+			// 自己的指标
+			tmpShouldQuery = tmpShouldQuery.Should(elastic.NewTermQuery(`SysUserId`, sysUserId))
+			// 分享给我的指标
+			tmpShouldQuery = tmpShouldQuery.Should(elastic.NewTermsQuery(`SharedUserIdList`, sysUserId))
+			//公开的指标
+			tmpShouldQuery = tmpShouldQuery.Should(elastic.NewTermQuery(`PublicStatus`, utils.EdbPublicSuccess))
+			//shouldQuery = shouldQuery.Should(tmpShouldQuery)
+			query = query.Must(tmpShouldQuery)
+		}
+	}
+
+	// 排序
+	sortList := make([]*elastic.FieldSort, 0)
+	// 如果没有关键字,那么就走指标id倒序
+
+	for orderKey, orderType := range sortMap {
+		switch orderType {
+		case "asc":
+			sortList = append(sortList, elastic.NewFieldSort(orderKey).Asc())
+		case "desc":
+			sortList = append(sortList, elastic.NewFieldSort(orderKey).Desc())
+
+		}
+
+	}
+
+	return searchEdbInfoDataV2(indexName, query, sortList, from, size)
+}
+
+// SearchEdbInfoDataByPublic
+// @Description: 查询es中的指标数据
+// @author: Roc
+// @datetime 2024-12-05 13:33:36
+// @param keywordStr string
+// @param from int
+// @param size int
+// @param edbPublicList []int
+// @param sourceList []int
+// @param classifyIdList []int
+// @param edbTypeList []int
+// @param edbInfoType int
+// @param edbAuth int
+// @param sysUserId int
+// @param sortMap map[string]string
+// @return total int64
+// @return list []*data_manage.EdbInfoList
+// @return err error
+func SearchEdbInfoDataByPublic(keywordStr string, from, size int, edbPublicList, sourceList, classifyIdList, edbTypeList []int, edbInfoType, edbAuth, sysUserId int, sortMap map[string]string) (total int64, list []*data_manage.EdbInfoList, err error) {
+	indexName := utils.DATA_INDEX_NAME
+	list = make([]*data_manage.EdbInfoList, 0)
+	defer func() {
+		if err != nil {
+			fmt.Println("SearchEdbInfoData Err:", err.Error())
+		}
+	}()
+
+	query := elastic.NewBoolQuery()
+
+	//指标来源
+	if len(sourceList) > 0 {
+		termsList := make([]interface{}, 0)
+		for _, v := range sourceList {
+			termsList = append(termsList, v)
+		}
+		query = query.Must(elastic.NewTermsQuery("Source", termsList...))
+	}
+
+	// classifyIdList 指定分类下的指标
+	if len(classifyIdList) > 0 {
+		termsList := make([]interface{}, 0)
+		for _, v := range classifyIdList {
+			termsList = append(termsList, v)
+		}
+		query = query.Must(elastic.NewTermsQuery("ClassifyId", termsList...))
+	}
+
+	// 指标类型:0-基础+计算;1-基础指标;2-计算指标;3-预测指标
+	if len(edbTypeList) > 0 {
+		termsList := make([]interface{}, 0)
+		for _, v := range edbTypeList {
+			termsList = append(termsList, v)
+		}
+		query = query.Must(elastic.NewTermsQuery("EdbType", termsList...))
+	}
+
+	// 如果指定了指标公开状态,那么就添加指标公开状态的筛选
+	// 公开状态;0:未公开;1:审批中;2:已驳回;3:已公开
+	if len(edbPublicList) > 0 {
+		termsList := make([]interface{}, 0)
+		for _, v := range edbPublicList {
+			termsList = append(termsList, v)
+		}
+		query = query.Must(elastic.NewTermsQuery("PublicStatus", termsList...))
+	}
+
+	if edbInfoType >= 0 {
+		query = query.Must(elastic.NewTermQuery("EdbInfoType", edbInfoType))
+	}
+
+	// 指标名称、编码匹配
+	if keywordStr != `` {
+		// 默认使用中文名字字段去匹配
+		keywordNameKey := `EdbName`
+		query = query.Must(elastic.NewMultiMatchQuery(keywordStr, keywordNameKey, "EdbCode"))
+	}
+
+	// 指标与用户的权限匹配
+	{
+		//指标权限范围,0-全部;1-我的;2-公共
+		switch edbAuth {
+		case 1:
+			// 自己的指标
+			query = query.Must(elastic.NewTermQuery(`SysUserId`, sysUserId))
+		case 2:
+			// 公开的指标
+			query = query.Must(elastic.NewTermQuery(`PublicStatus`, utils.EdbPublicSuccess))
+		default:
+			tmpShouldQuery := elastic.NewBoolQuery()
+			// 自己的指标
+			tmpShouldQuery = tmpShouldQuery.Should(elastic.NewTermQuery(`SysUserId`, sysUserId))
+			// 分享给我的指标
+			tmpShouldQuery = tmpShouldQuery.Should(elastic.NewTermsQuery(`SharedUserIdList`, sysUserId))
+			//公开的指标
+			tmpShouldQuery = tmpShouldQuery.Should(elastic.NewTermQuery(`PublicStatus`, utils.EdbPublicSuccess))
+			//shouldQuery = shouldQuery.Should(tmpShouldQuery)
+			query = query.Must(tmpShouldQuery)
+		}
+	}
+
+	// 排序
+	sortList := make([]*elastic.FieldSort, 0)
+	// 如果没有关键字,那么就走指标id倒序
+
+	for orderKey, orderType := range sortMap {
+		switch orderType {
+		case "asc":
+			sortList = append(sortList, elastic.NewFieldSort(orderKey).Asc())
+		case "desc":
+			sortList = append(sortList, elastic.NewFieldSort(orderKey).Desc())
+
+		}
+
+	}
+
+	return searchEdbInfoDataV2(indexName, query, sortList, from, size)
+}
+
+// EsDeleteEdbInfoData 删除es中的指标数据
+func EsDeleteEdbInfoData(indexName, docId string) (err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println("EsDeleteEdbInfoData Err:", err.Error())
+		}
+	}()
+	client := utils.EsClient
+
+	resp, err := client.Delete().Index(indexName).Id(docId).Do(context.Background())
+	fmt.Println(resp)
+	if err != nil {
+		return
+	}
+	if resp.Status == 0 {
+		fmt.Println("删除成功")
+	} else {
+		fmt.Println("AddData", resp.Status, resp.Result)
+	}
+	return
+}

+ 0 - 381
services/elastic/elastic.go

@@ -85,387 +85,6 @@ func MappingModify(indexName, mappingJson string) {
 	return
 }
 
-// EsAddOrEditEdbInfoData 新增/修改es中的指标数据
-func EsAddOrEditEdbInfoData(indexName, docId string, item *data_manage.EdbInfoList) (err error) {
-	defer func() {
-		if err != nil {
-			fmt.Println("EsAddOrEditData Err:", err.Error())
-		}
-	}()
-	client := utils.EsClient
-
-	resp, err := client.Index().Index(indexName).Id(docId).BodyJson(item).Do(context.Background())
-	if err != nil {
-		fmt.Println("新增失败:", err.Error())
-		return err
-	}
-	fmt.Println(resp)
-	if resp.Status == 0 {
-		fmt.Println("新增成功", resp.Result)
-		err = nil
-	} else {
-		fmt.Println("AddData", resp.Status, resp.Result)
-	}
-	return
-}
-
-// SearchEdbInfoData
-// @Description: 查询es中的指标数据
-// @author: Roc
-// @datetime 2024-11-29 10:22:25
-// @param keywordStr string
-// @param from int
-// @param size int
-// @param filterSource int
-// @param source int
-// @param frequency string
-// @param noPermissionEdbInfoIdList []int
-// @param noPermissionEdbClassifyIdList []int
-// @param collectEdbInfoIdList []int
-// @param edbTypeList []int
-// @param edbInfoType int 指标类型,0:ETA指标库(基础指标+计算指标);1:预测指标
-// @param edbAuth int 指标权限范围,0-全部;1-我的;2-公共
-// @param sysUserId int
-// @return total int64
-// @return list []*data_manage.EdbInfoList
-// @return err error
-func SearchEdbInfoData(keywordStr string, from, size, filterSource, source int, frequency string, noPermissionEdbInfoIdList, noPermissionEdbClassifyIdList, collectEdbInfoIdList, edbTypeList []int, edbInfoType, edbAuth, sysUserId int) (total int64, list []*data_manage.EdbInfoList, err error) {
-	indexName := utils.DATA_INDEX_NAME
-	list = make([]*data_manage.EdbInfoList, 0)
-	defer func() {
-		if err != nil {
-			fmt.Println("SearchEdbInfoData Err:", err.Error())
-		}
-	}()
-
-	highlight := elastic.NewHighlight()
-	highlight = highlight.Fields(elastic.NewHighlighterField("EdbCode"), elastic.NewHighlighterField("EdbName"))
-	highlight = highlight.PreTags("<font color='red'>").PostTags("</font>")
-
-	mustMap := make([]interface{}, 0)
-	mustNotMap := make([]interface{}, 0)
-
-	switch filterSource {
-	case 2:
-		mustMap = append(mustMap, map[string]interface{}{
-			"term": map[string]interface{}{
-				"Frequency.keyword": "月度",
-				//"Frequency.keyword": "月度",
-			},
-		})
-	case 3:
-	case 4:
-		mustMap = append(mustMap, map[string]interface{}{
-			"term": map[string]interface{}{
-				"EdbType": 1,
-			},
-		})
-	case 5:
-		mustMap = append(mustMap, map[string]interface{}{
-			"term": map[string]interface{}{
-				"Source": 6,
-			},
-		})
-	case 6:
-		mustMap = append(mustMap, map[string]interface{}{
-			"match": map[string]interface{}{
-				"Frequency.keyword": "年度",
-			},
-		})
-	}
-
-	//指标来源
-	if source > 0 {
-		mustMap = append(mustMap, map[string]interface{}{
-			"term": map[string]interface{}{
-				"Source": source,
-				//"Frequency.keyword": "月度",
-			},
-		})
-	}
-
-	if frequency != "" {
-		mustMap = append(mustMap, map[string]interface{}{
-			"term": map[string]interface{}{
-				"Frequency.keyword": frequency,
-				//"Frequency.keyword": "月度",
-			},
-		})
-	}
-
-	// noPermissionEdbInfoIdList 无权限指标id
-	if len(noPermissionEdbInfoIdList) > 0 {
-		mustNotMap = append(mustNotMap, map[string]interface{}{
-			"terms": map[string]interface{}{
-				"EdbInfoId": noPermissionEdbInfoIdList,
-				//"Frequency.keyword": "月度",
-			},
-		})
-	}
-
-	// noPermissionEdbInfoIdList 无权限指标id
-	if len(noPermissionEdbClassifyIdList) > 0 {
-		mustNotMap = append(mustNotMap, map[string]interface{}{
-			"terms": map[string]interface{}{
-				"ClassifyId": noPermissionEdbClassifyIdList,
-				//"Frequency.keyword": "月度",
-			},
-		})
-	}
-
-	// collectEdbInfoIdList 收藏的指标id
-	if len(collectEdbInfoIdList) > 0 {
-		mustMap = append(mustMap, map[string]interface{}{
-			"terms": map[string]interface{}{
-				"EdbInfoId": collectEdbInfoIdList,
-			},
-		})
-	}
-
-	// 指标类型:0-基础+计算;1-基础指标;2-计算指标;3-预测指标
-	if len(edbTypeList) > 0 {
-		mustMap = append(mustMap, map[string]interface{}{
-			"terms": map[string]interface{}{
-				"EdbType": edbTypeList,
-			},
-		})
-	}
-
-	if edbInfoType >= 0 {
-		mustMap = append(mustMap, map[string]interface{}{
-			"term": map[string]interface{}{
-				"EdbInfoType": edbInfoType,
-			},
-		})
-	}
-
-	shouldMapList := make([]map[string]interface{}, 0)
-
-	// 指标名称、编码匹配
-	if keywordStr != `` {
-		// 默认使用中文名字字段去匹配
-		keywordNameKey := `EdbName`
-		shouldMap := map[string]interface{}{
-			"should": []interface{}{
-				map[string]interface{}{
-					"match": map[string]interface{}{
-						"EdbCode": keywordStr,
-						//"Frequency.keyword": "月度",
-					},
-				},
-				map[string]interface{}{
-					"match": map[string]interface{}{
-						keywordNameKey: keywordStr,
-						//"Frequency.keyword": "月度",
-					},
-				},
-			},
-		}
-		shouldMapList = append(shouldMapList, shouldMap)
-	}
-
-	// 指标与用户的权限匹配
-	{
-		shouldTermList := make([]map[string]interface{}, 0)
-		//指标权限范围,0-全部;1-我的;2-公共
-		switch edbAuth {
-		case 1:
-			// 自己的指标
-			shouldTermList = append(shouldTermList, map[string]interface{}{
-				"term": map[string]interface{}{
-					"SysUserId": sysUserId,
-				},
-			})
-		case 2:
-			// 公开的指标
-			shouldTermList = append(shouldTermList, map[string]interface{}{
-				"term": map[string]interface{}{
-					"PublicStatus": 3,
-				},
-			})
-		default:
-			// 自己的指标
-			shouldTermList = append(shouldTermList, map[string]interface{}{
-				"term": map[string]interface{}{
-					"SysUserId": sysUserId,
-				},
-			})
-			// 分享给我的指标
-			shouldTermList = append(shouldTermList, map[string]interface{}{
-				"terms": map[string]interface{}{
-					"SharedUserIdList": []int{sysUserId},
-				},
-			})
-			// 公开的指标
-			//shouldTermList = append(shouldTermList,map[string]interface{}{
-			//	"term": map[string]interface{}{
-			//		"PublicStatus": 2,
-			//	},
-			//})
-
-		}
-		// 公开的指标
-		//shouldTermList = append(shouldTermList,map[string]interface{}{
-		//	"term": map[string]interface{}{
-		//		"PublicStatus": 2,
-		//	},
-		//})
-
-		shouldMap := map[string]interface{}{
-			"should": shouldTermList,
-		}
-		shouldMapList = append(shouldMapList, shouldMap)
-	}
-
-	// 排序
-	sortList := make([]interface{}, 0)
-	// 如果没有关键字,那么就走指标id倒序
-	if keywordStr == `` {
-		sortEdbInfoId := map[string]interface{}{
-			"EdbInfoId": map[string]interface{}{
-				"order": "desc",
-			},
-		}
-		sortList = append(sortList, sortEdbInfoId)
-	}
-
-	return searchEdbInfoData(indexName, mustMap, mustNotMap, shouldMapList, sortList, from, size)
-}
-
-// searchEdbInfoData 查询es中的指标数据
-func searchEdbInfoData(indexName string, mustMap, mustNotMap []interface{}, shouldMapList []map[string]interface{}, sortList []interface{}, from, size int) (total int64, list []*data_manage.EdbInfoList, err error) {
-	list = make([]*data_manage.EdbInfoList, 0)
-	defer func() {
-		if err != nil {
-			fmt.Println("EsAddOrEditData Err:", err.Error())
-		}
-	}()
-	client := utils.EsClient
-
-	//queryString := elastic.NewQueryStringQuery(keywordStr)
-	//boolQueryJson, err := json.Marshal(queryString)
-	//if err != nil {
-	//	fmt.Println("boolQueryJson err:", err)
-	//} else {
-	//	fmt.Println("boolQueryJson ", string(boolQueryJson))
-	//}
-
-	highlight := elastic.NewHighlight()
-	highlight = highlight.Fields(elastic.NewHighlighterField("EdbCode"), elastic.NewHighlighterField("EdbName"))
-	highlight = highlight.PreTags("<font color='red'>").PostTags("</font>")
-
-	//query := elastic.RawStringQuery(`{"match_all":{}}`)
-
-	//关键字匹配
-	for _, shouldMap := range shouldMapList {
-		mustMap = append(mustMap, map[string]interface{}{
-			"bool": shouldMap,
-		})
-	}
-
-	queryMap := map[string]interface{}{
-		"query": map[string]interface{}{
-			"bool": map[string]interface{}{
-				"must":     mustMap,
-				"must_not": mustNotMap,
-				//"should":   shouldMap,
-			},
-		},
-	}
-
-	//根据条件数量统计
-	requestTotalHits := client.Count(indexName).BodyJson(queryMap)
-	total, err = requestTotalHits.Do(context.Background())
-	if err != nil {
-		return
-	}
-
-	queryMap["from"] = from
-	queryMap["size"] = size
-
-	// 如果有指定排序,那么就按照排序来
-	if len(sortList) > 0 {
-		queryMap["sort"] = sortList
-	}
-
-	jsonBytes, _ := json.Marshal(queryMap)
-	fmt.Println(string(jsonBytes))
-
-	//queryString := elastic.NewMatchQuery("EdbCode", keywordStr)
-	//request := client.Search(indexName).Highlight(highlight).From(from).Size(size).Query(queryString)
-
-	request := client.Search(indexName).Highlight(highlight).Source(queryMap) // sets the JSON request
-
-	//requestJson, err := json.Marshal(request)
-	//if err != nil {
-	//	fmt.Println("requestJson err:", err)
-	//}
-	//fmt.Println("requestJson ", string(requestJson))
-	searchMap := make(map[string]string)
-
-	searchResp, err := request.Do(context.Background())
-	if err != nil {
-		return
-	}
-	fmt.Println(searchResp)
-	fmt.Println(searchResp.Status)
-	if searchResp.Status != 0 {
-		return
-	}
-	//total = searchResp.TotalHits()
-	if searchResp.Hits != nil {
-		for _, v := range searchResp.Hits.Hits {
-			if _, ok := searchMap[v.Id]; !ok {
-				itemJson, tmpErr := v.Source.MarshalJSON()
-				if tmpErr != nil {
-					err = tmpErr
-					fmt.Println("movieJson err:", err)
-					return
-				}
-				edbInfoItem := new(data_manage.EdbInfoList)
-				tmpErr = json.Unmarshal(itemJson, &edbInfoItem)
-				if tmpErr != nil {
-					fmt.Println("json.Unmarshal movieJson err:", tmpErr)
-					err = tmpErr
-					return
-				}
-				if len(v.Highlight["EdbCode"]) > 0 {
-					edbInfoItem.EdbCode = v.Highlight["EdbCode"][0]
-				}
-				if len(v.Highlight["EdbName"]) > 0 {
-					edbInfoItem.EdbCode = v.Highlight["EdbName"][0]
-				}
-				list = append(list, edbInfoItem)
-				searchMap[v.Id] = v.Id
-			}
-		}
-	}
-
-	return
-}
-
-// EsDeleteEdbInfoData 删除es中的指标数据
-func EsDeleteEdbInfoData(indexName, docId string) (err error) {
-	defer func() {
-		if err != nil {
-			fmt.Println("EsDeleteEdbInfoData Err:", err.Error())
-		}
-	}()
-	client := utils.EsClient
-
-	resp, err := client.Delete().Index(indexName).Id(docId).Do(context.Background())
-	fmt.Println(resp)
-	if err != nil {
-		return
-	}
-	if resp.Status == 0 {
-		fmt.Println("删除成功")
-	} else {
-		fmt.Println("AddData", resp.Status, resp.Result)
-	}
-	return
-}
-
 // EsAddOrEditReport 新增编辑es报告
 func EsAddOrEditReport(indexName, docId string, item *models.ElasticReportDetail) (err error) {
 	defer func() {

+ 11 - 3
utils/constants.go

@@ -179,9 +179,10 @@ const (
 )
 
 const (
-	DATA_PREFIX       = "hz_data"
-	CHART_PREFIX      = "hz_chart"
-	EXCEL_DATA_PREFIX = "hz_excel_data"
+	DATA_PREFIX            = "hz_data"
+	CHART_PREFIX           = "hz_chart"
+	EXCEL_DATA_PREFIX      = "hz_excel_data"
+	PUBLIC_CLASSIFY_PREFIX = "hz_data_public_classify"
 )
 
 const (
@@ -455,6 +456,13 @@ const (
 	EdbPermissionSourceCalculate = 7 // 指标权限来源-计算指标
 )
 
+const (
+	EdbPublicDefault = 0 // 指标公开状态-默认未提交
+	EdbPublicCommit  = 1 // 指标公开状态-已提交
+	EdbPublicReject  = 2 // 指标公开状态-已驳回
+	EdbPublicSuccess = 3 // 指标公开状态-成功
+)
+
 // BaseEdbRefreshStartDate 指标的基础刷新开始日期
 const BaseEdbRefreshStartDate = `1899-01-01`
 

+ 17 - 2
utils/elastic.go

@@ -2,16 +2,31 @@ package utils
 
 import (
 	"github.com/olivere/elastic/v7"
+	"log"
+	"os"
 )
 
 // EsClient es客户端
 var EsClient *elastic.Client
 
 func initEs() {
-	client, err := elastic.NewClient(
+	var logInfo *log.Logger
+	if RunMode == `debug` {
+		logInfo = log.New(os.Stderr, "", log.LstdFlags)
+	}
+
+	clientOptionFuncList := []elastic.ClientOptionFunc{
 		elastic.SetURL(ES_URL),
 		elastic.SetBasicAuth(ES_USERNAME, ES_PASSWORD),
-		elastic.SetSniff(false))
+		elastic.SetSniff(false),
+	}
+	if logInfo != nil {
+		clientOptionFuncList = append(clientOptionFuncList, elastic.SetTraceLog(logInfo))
+	}
+
+	client, err := elastic.NewClient(
+		clientOptionFuncList...,
+	)
 	EsClient = client
 	if err != nil {
 		panic("ElasticSearch连接失败,err:" + err.Error())