Browse Source

Merge branch 'master' into feature/eta1.6.2_trade_analysis_top

xyxie 1 year ago
parent
commit
c7bc4adaa0
100 changed files with 17239 additions and 1799 deletions
  1. 34 30
      controllers/banner.go
  2. 27 21
      controllers/base_auth.go
  3. 4 1
      controllers/base_common.go
  4. 4 2
      controllers/business_conf.go
  5. 268 0
      controllers/chart_permission.go
  6. 212 81
      controllers/classify.go
  7. 28 2
      controllers/cloud_disk.go
  8. 8 1
      controllers/company_permission.go
  9. 87 18
      controllers/data_manage/chart_classify.go
  10. 637 294
      controllers/data_manage/chart_info.go
  11. 2 2
      controllers/data_manage/correlation/correlation_chart_classify.go
  12. 132 2
      controllers/data_manage/correlation/correlation_chart_info.go
  13. 137 3
      controllers/data_manage/cross_variety/chart_info.go
  14. 2 2
      controllers/data_manage/cross_variety/classify.go
  15. 394 0
      controllers/data_manage/data_manage_permission/data_manage_permission.go
  16. 396 0
      controllers/data_manage/data_manage_permission/data_move.go
  17. 250 0
      controllers/data_manage/data_manage_permission/message.go
  18. 168 41
      controllers/data_manage/edb_classify.go
  19. 477 306
      controllers/data_manage/edb_info.go
  20. 98 14
      controllers/data_manage/edb_info_calculate.go
  21. 20 2
      controllers/data_manage/excel/custom_analysis.go
  22. 174 3
      controllers/data_manage/excel/excel_classify.go
  23. 88 23
      controllers/data_manage/excel/excel_info.go
  24. 54 12
      controllers/data_manage/excel/mixed_table.go
  25. 3 3
      controllers/data_manage/future_good/future_good_chart_classify.go
  26. 84 5
      controllers/data_manage/future_good/future_good_chart_info.go
  27. 81 4
      controllers/data_manage/future_good/future_good_profit_chart_info.go
  28. 2 2
      controllers/data_manage/line_equation/line_chart_classify.go
  29. 133 2
      controllers/data_manage/line_equation/line_chart_info.go
  30. 133 2
      controllers/data_manage/line_feature/chart_info.go
  31. 2 2
      controllers/data_manage/line_feature/classify.go
  32. 213 15
      controllers/data_manage/my_chart.go
  33. 335 270
      controllers/data_manage/predict_edb_classify.go
  34. 268 43
      controllers/data_manage/predict_edb_info.go
  35. 1 1
      controllers/data_stat/edb_source_stat.go
  36. 166 25
      controllers/english_report/en_permission.go
  37. 193 67
      controllers/english_report/english_classify.go
  38. 19 1
      controllers/english_report/report.go
  39. 86 0
      controllers/message.go
  40. 8 8
      controllers/ppt_v2.go
  41. 109 49
      controllers/report.go
  42. 239 57
      controllers/report_chapter_type.go
  43. 176 0
      controllers/resource.go
  44. 1141 0
      controllers/speech_recognition/speech_recognition.go
  45. 534 0
      controllers/speech_recognition/speech_recognition_menu.go
  46. 384 0
      controllers/speech_recognition/speech_recognition_tag.go
  47. 535 0
      controllers/speech_recognition/speech_recognition_tag_menu.go
  48. 2 2
      controllers/sys_user.go
  49. 2 2
      controllers/user_login.go
  50. 14 5
      go.mod
  51. 37 8
      go.sum
  52. 14 1
      models/business_conf.go
  53. 195 27
      models/chart_permission.go
  54. 130 43
      models/classify.go
  55. 9 9
      models/company/company_permission.go
  56. 37 0
      models/data_manage/chart_classify.go
  57. 7 7
      models/data_manage/chart_edb_mapping.go
  58. 65 4
      models/data_manage/chart_info.go
  59. 976 0
      models/data_manage/data_manage_permission/chart.go
  60. 489 0
      models/data_manage/data_manage_permission/classify_no_auth_record.go
  61. 989 0
      models/data_manage/data_manage_permission/edb.go
  62. 973 0
      models/data_manage/data_manage_permission/excel.go
  63. 152 0
      models/data_manage/data_manage_permission/message.go
  64. 103 0
      models/data_manage/data_manage_permission/move.go
  65. 85 0
      models/data_manage/data_manage_permission/move_record.go
  66. 316 0
      models/data_manage/data_manage_permission/no_auth_record.go
  67. 89 0
      models/data_manage/data_manage_permission/req_and_resp.go
  68. 75 37
      models/data_manage/edb_classify.go
  69. 23 0
      models/data_manage/edb_config.go
  70. 95 32
      models/data_manage/edb_info.go
  71. 7 5
      models/data_manage/edb_info_calculate.go
  72. 21 0
      models/data_manage/edb_terminal.go
  73. 56 0
      models/data_manage/excel/excel_classify.go
  74. 132 34
      models/data_manage/excel/excel_info.go
  75. 10 7
      models/data_manage/excel/request/excel_info.go
  76. 28 19
      models/data_manage/excel/response/excel_info.go
  77. 1 0
      models/data_manage/excel/response/sheet.go
  78. 3 1
      models/data_manage/my_chart.go
  79. 63 2
      models/data_manage/mysteel_chemical_index.go
  80. 7 2
      models/data_manage/response/predit_edb_info.go
  81. 46 0
      models/db.go
  82. 12 1
      models/en_classify_permission.go
  83. 75 7
      models/en_permission.go
  84. 58 0
      models/english_classify.go
  85. 55 37
      models/english_report.go
  86. 13 6
      models/permission.go
  87. 100 36
      models/report_chapter_type.go
  88. 10 2
      models/report_chapter_type_permission.go
  89. 561 0
      models/speech_recognition/speech_recognition.go
  90. 159 0
      models/speech_recognition/speech_recognition_api_log.go
  91. 211 0
      models/speech_recognition/speech_recognition_content.go
  92. 256 0
      models/speech_recognition/speech_recognition_menu.go
  93. 225 0
      models/speech_recognition/speech_recognition_tag.go
  94. 148 0
      models/speech_recognition/speech_recognition_tag_mapping.go
  95. 250 0
      models/speech_recognition/speech_recognition_tag_menu.go
  96. 51 0
      models/target.go
  97. 551 47
      routers/commentsRouter.go
  98. 23 0
      routers/router.go
  99. 478 0
      services/chart_permission.go
  100. 206 0
      services/chart_permission_sync.go

+ 34 - 30
controllers/banner.go

@@ -4,6 +4,8 @@ import (
 	"eta/eta_api/models"
 	"eta/eta_api/services"
 	"eta/eta_api/utils"
+	"github.com/h2non/filetype"
+	"io/ioutil"
 	"os"
 	"path"
 	"time"
@@ -22,15 +24,42 @@ type BannerController struct {
 func (this *BannerController) Upload() {
 	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
+	}
+
 	f, h, err := this.GetFile("file")
 	if err != nil {
 		br.Msg = "获取资源信息失败"
 		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
 		return
 	}
+	defer f.Close() //关闭上传文件
+
+	// 不依赖于文件扩展名检查文件格式
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "读取文件失败, Err: " + e.Error()
+		return
+	}
+	pass := filetype.IsImage(fileData)
+	if !pass {
+		br.Msg = "文件格式有误"
+		br.ErrMsg = "文件格式有误"
+		return
+	}
+
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
@@ -43,22 +72,18 @@ func (this *BannerController) Upload() {
 	randStr := utils.GetRandStringNoSpecialChar(28)
 	fileName := randStr + ext
 	fpath := uploadDir + "/" + fileName
-	defer f.Close() //关闭上传文件
 	err = this.SaveToFile("file", fpath)
 	if err != nil {
 		br.Msg = "文件上传失败"
 		br.ErrMsg = "文件上传失败,Err:" + err.Error()
 		return
 	}
-	resourceUrl := ``
-
-	//resourceUrl, err = services.UploadImgToMinIoTest(fileName, fpath)
-	//if err != nil {
-	//	br.Msg = "文件上传失败"
-	//	br.ErrMsg = "文件上传失败,Err:" + err.Error()
-	//	return
-	//}
+	defer func() {
+		os.Remove(fpath)
+	}()
 
+	// 上传文件
+	resourceUrl := ``
 	ossClient := services.NewOssClient()
 	if ossClient == nil {
 		br.Msg = "上传失败"
@@ -72,27 +97,6 @@ func (this *BannerController) Upload() {
 		return
 	}
 
-	////上传到阿里云 和 minio
-	//if utils.ObjectStorageClient == "minio" {
-	//	resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
-	//	if err != nil {
-	//		br.Msg = "文件上传失败"
-	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
-	//		return
-	//	}
-	//} else {
-	//	resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
-	//	if err != nil {
-	//		br.Msg = "文件上传失败"
-	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
-	//		return
-	//	}
-	//}
-
-	defer func() {
-		os.Remove(fpath)
-	}()
-
 	item := new(models.Resource)
 	item.ResourceUrl = resourceUrl
 	item.ResourceType = 1

+ 27 - 21
controllers/base_auth.go

@@ -54,10 +54,10 @@ type BaseAuthController struct {
 }
 
 func (c *BaseAuthController) Prepare() {
-	fmt.Println("enter prepare")
+	//fmt.Println("enter prepare")
 	method := c.Ctx.Input.Method()
 	uri := c.Ctx.Input.URI()
-	fmt.Println("Url:", uri)
+	//fmt.Println("Url:", uri)
 	if method != "HEAD" {
 		if method == "POST" || method == "GET" {
 			authorization := c.Ctx.Input.Header("authorization")
@@ -93,26 +93,20 @@ func (c *BaseAuthController) Prepare() {
 				c.StopRun()
 				return
 			}
-			authorizationArr := strings.Split(authorization, "$")
-			if len(authorizationArr) <= 1 {
-				c.JSON(models.BaseResponse{Ret: 408, Msg: "请重新授权!", ErrMsg: "请重新授权:Token is empty or account is empty"}, false, false)
-				c.StopRun()
-				return
-			}
-			tokenStr := authorizationArr[0]
+			//authorizationArr := strings.Split(authorization, "$")
+			//if len(authorizationArr) <= 1 {
+			//	c.JSON(models.BaseResponse{Ret: 408, Msg: "请重新授权!", ErrMsg: "请重新授权:Token is empty or account is empty"}, false, false)
+			//	c.StopRun()
+			//	return
+			//}
+			tokenStr := authorization
 			tokenArr := strings.Split(tokenStr, "=")
 			token := tokenArr[1]
 
-			accountStr := authorizationArr[1]
-			accountArr := strings.Split(accountStr, "=")
-			account := accountArr[1]
-			//校验token是否合法
-			// JWT校验Token和Account
-			if !utils.CheckToken(account, token) {
-				c.JSON(models.BaseResponse{Ret: 408, Msg: "鉴权失败,请重新登录!", ErrMsg: "登录失效,请重新登陆!,CheckToken Fail"}, false, false)
-				c.StopRun()
-				return
-			}
+			//accountStr := authorizationArr[1]
+			//accountArr := strings.Split(accountStr, "=")
+			//account := accountArr[1]
+
 			session, err := system.GetSysSessionByToken(token)
 			if err != nil {
 				if err.Error() == utils.ErrNoRow() {
@@ -129,6 +123,14 @@ func (c *BaseAuthController) Prepare() {
 				c.StopRun()
 				return
 			}
+			//校验token是否合法
+			// JWT校验Token和Account
+			account := utils.MD5(session.UserName)
+			if !utils.CheckToken(account, token) {
+				c.JSON(models.BaseResponse{Ret: 408, Msg: "鉴权失败,请重新登录!", ErrMsg: "登录失效,请重新登陆!,CheckToken Fail"}, false, false)
+				c.StopRun()
+				return
+			}
 			if time.Now().After(session.ExpiredTime) {
 				c.JSON(models.BaseResponse{Ret: 408, Msg: "请重新登录!", ErrMsg: "获取用户信息异常,Eerr:" + err.Error()}, false, false)
 				c.StopRun()
@@ -204,7 +206,7 @@ func (c *BaseAuthController) Prepare() {
 			uri = strings.Replace(uri, "/adminapi", "", 1)
 			uris := strings.Split(uri, "?")
 			uri = uris[0]
-			fmt.Println("uri:", uri)
+			//fmt.Println("uri:", uri)
 			apis := strings.Split(api, "&")
 			apiMap := make(map[string]bool, 0)
 			for _, s := range apis {
@@ -306,6 +308,10 @@ func (c *BaseAuthController) JSON(data interface{}, hasIndent bool, coding bool)
 	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
 	desEncrypt := utils.DesBase64Encrypt([]byte(utils.DesKey), utils.DesKeySalt)
 	c.Ctx.Output.Header("Dk", string(desEncrypt)) // des3加解密key
+	// 设置Cookie为HTTPOnly
+	c.Ctx.SetCookie("", "", -1, "/", "", false, true, "")
+	//fmt.Println(c.Ctx.ResponseWriter.Header().Get("Set-Cookie"))
+
 	var content []byte
 	var err error
 	if hasIndent {
@@ -392,7 +398,7 @@ func (c *BaseAuthController) logUri(respContent []byte, requestBody, ip string)
 	authorization := ""
 	method := c.Ctx.Input.Method()
 	uri := c.Ctx.Input.URI()
-	fmt.Println("Url:", uri)
+	//fmt.Println("Url:", uri)
 	if method != "HEAD" {
 		if method == "POST" || method == "GET" {
 			authorization = c.Ctx.Input.Header("authorization")

+ 4 - 1
controllers/base_common.go

@@ -87,6 +87,9 @@ func (c *BaseCommonController) JSON(data interface{}, hasIndent bool, coding boo
 	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
 	desEncrypt := utils.DesBase64Encrypt([]byte(utils.DesKey), utils.DesKeySalt)
 	c.Ctx.Output.Header("Dk", string(desEncrypt)) // des3加解密key
+	// 设置Cookie为HTTPOnly
+	c.Ctx.SetCookie("", "", -1, "/", "", false, true, "")
+
 	var content []byte
 	var err error
 	if hasIndent {
@@ -120,7 +123,7 @@ func (c *BaseCommonController) logUri(respContent []byte, requestBody, ip string
 	authorization := ""
 	method := c.Ctx.Input.Method()
 	uri := c.Ctx.Input.URI()
-	fmt.Println("Url:", uri)
+	//fmt.Println("Url:", uri)
 	if method != "HEAD" {
 		if method == "POST" || method == "GET" {
 			authorization = c.Ctx.Input.Header("authorization")

+ 4 - 2
controllers/business_conf.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_api/services"
 	"eta/eta_api/utils"
 	"fmt"
+	"github.com/shopspring/decimal"
 	"html"
 	"strconv"
 	"strings"
@@ -103,10 +104,11 @@ func (this *BusinessConfController) Save() {
 				approveType = str
 			}
 		case 2: // 数值
-			num, ok := v.(float64)
-			if !ok {
+			vDeci, err := decimal.NewFromString(fmt.Sprint(v))
+			if err != nil {
 				continue
 			}
+			num, _ := vDeci.Float64()
 			if conf.Necessary == 1 && num <= 0 {
 				br.Msg = conf.Remark + "不可为空"
 				return

+ 268 - 0
controllers/chart_permission.go

@@ -0,0 +1,268 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_api/models"
+	"eta/eta_api/services"
+	"eta/eta_api/utils"
+)
+
+// ChartPermissionController 品种列表
+type ChartPermissionController struct {
+	BaseAuthController
+}
+
+// List
+// @Title 品种列表
+// @Description 品种列表
+// @Param   Keyword  query  string  false  "关键词"
+// @Success 200 Ret=200 操作成功
+// @router /list [get]
+func (this *ChartPermissionController) List() {
+	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
+	}
+	cond := ` and product_id=1`
+	pars := make([]interface{}, 0)
+	list, e := services.GetChartPermissionList(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取品种列表失败, Err: " + e.Error()
+		return
+	}
+
+	// 品种树
+	resp := make([]*models.ChartPermissionItem, 0)
+	childMap := make(map[int][]*models.ChartPermissionItem)
+
+	for _, v := range list {
+		t := new(models.ChartPermissionItem)
+		t.PermissionId = v.ChartPermissionId
+		t.PermissionName = v.PermissionName
+		t.ParentId = v.ParentId
+		t.IsPublic = v.IsPublic
+		t.Enabled = v.Enabled
+		t.Sort = v.Sort
+		t.CreateTime = v.CreatedTime.Format(utils.FormatDateTime)
+		t.Child = make([]*models.ChartPermissionItem, 0)
+		if v.ParentId == 0 {
+			resp = append(resp, t)
+			continue
+		}
+		if v.ParentId > 0 {
+			if childMap[v.ParentId] == nil {
+				childMap[v.ParentId] = make([]*models.ChartPermissionItem, 0)
+			}
+			childMap[v.ParentId] = append(childMap[v.ParentId], t)
+		}
+	}
+	for _, r := range resp {
+		r.Child = childMap[r.PermissionId]
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// Add
+// @Title 新增品种列表
+// @Description 新增品种列表
+// @Param  request body models.PermissionAddReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /add [post]
+func (this *ChartPermissionController) Add() {
+	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 models.PermissionAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.PermissionName == "" {
+		br.Msg = "请输入品种名称"
+		return
+	}
+	e, msg := services.AddChartPermission(req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "新增品种失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Edit
+// @Title 编辑品种
+// @Description 编辑品种
+// @Param	request	body models.PermissionEditReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /edit [post]
+func (this *ChartPermissionController) Edit() {
+	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 models.PermissionEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.PermissionId <= 0 {
+		br.Msg = "请选择要编辑的品种"
+		return
+	}
+
+	if req.PermissionName == "" {
+		br.Msg = "请输入品种名称"
+		return
+	}
+
+	e, msg := services.EditChartPermission(req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "编辑品种失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Move
+// @Title 移动品种
+// @Description 移动品种
+// @Param	request	body models.PermissionMoveReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /move [post]
+func (this *ChartPermissionController) Move() {
+	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 models.PermissionMoveReq
+	// todo 限制修改一级品种
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+
+	if req.PermissionId == 0 {
+		br.Msg = "请选择要移动的品种"
+		return
+	}
+	e, msg := services.MoveChartPermission(req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "移动品种失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// SetEnabled
+// @Title 启用/禁用品种
+// @Description 启用/禁用品种
+// @Param	request	body models.PermissionEnabledReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /enabled/set [post]
+func (this *ChartPermissionController) SetEnabled() {
+	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 models.PermissionEnabledReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.PermissionId <= 0 {
+		br.Msg = "请选择要编辑的品种"
+		return
+	}
+	if req.Enabled != 0 && req.Enabled != 1 {
+		br.Msg = "请选择正确的启用禁用状态"
+		return
+	}
+
+	e, msg := services.SetEnabledChartPermission(req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "编辑品种失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 212 - 81
controllers/classify.go

@@ -4,11 +4,9 @@ import (
 	"encoding/json"
 	"eta/eta_api/models"
 	"eta/eta_api/models/report_approve"
-	"eta/eta_api/models/system"
 	"eta/eta_api/services"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"time"
 )
 
@@ -37,7 +35,7 @@ func (this *ClassifyController) Add() {
 	}
 
 	// 获取系统菜单, 如果没有对应的字段的特殊处理项, 则忽略必填
-	menus, e := system.GetSysMenuItemsByCondition(` AND hidden = 0`, make([]interface{}, 0), []string{}, ``)
+	/*menus, e := system.GetSysMenuItemsByCondition(` AND hidden = 0`, make([]interface{}, 0), []string{}, ``)
 	if e != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = "获取菜单列表失败, Err: " + e.Error()
@@ -48,13 +46,13 @@ func (this *ClassifyController) Add() {
 		if m.ButtonCode != "" {
 			menuMap[m.ButtonCode] = true
 		}
-	}
+	}*/
 
 	if req.ClassifyName == "" {
 		br.Msg = "分类名称不可为空"
 		return
 	}
-	if menuMap[system.MenuSpecialHandleClassifyShowType] && req.ParentId != 0 && req.ShowType == 0 {
+	/*if menuMap[system.MenuSpecialHandleClassifyShowType] && req.ParentId != 0 && req.ShowType == 0 {
 		br.Msg = "展示类型不可为空"
 		return
 	}
@@ -65,7 +63,7 @@ func (this *ClassifyController) Add() {
 	if menuMap[system.MenuSpecialHandleClassifyReportImgs] && (req.ShowType == 1 || req.ShowType == 3) && req.YbRightBanner == "" && req.ParentId == 0 { //当一级报告分类为列表、品种时,增加“报告合集配图”的配置项
 		br.Msg = "报告合集配图不可为空"
 		return
-	}
+	}*/
 
 	item, err := models.GetClassifyByName(req.ClassifyName, req.ParentId)
 	if err != nil && err.Error() != utils.ErrNoRow() {
@@ -77,13 +75,25 @@ func (this *ClassifyController) Add() {
 		br.Msg = "分类名称:" + req.ClassifyName + "已存在"
 		return
 	}
+
 	nowTime := time.Now().Local()
 	classify := new(models.Classify)
+
+	maxSort, e := classify.GetMaxSort()
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "查询品种排序失败, Err: " + e.Error()
+		return
+	}
 	classify.ClassifyName = req.ClassifyName
 	classify.ParentId = req.ParentId
 	classify.CreateTime = nowTime
 	classify.ModifyTime = nowTime
-	classify.Abstract = req.Abstract
+	classify.Sort = maxSort + 1
+	classify.Enabled = 1
+	classify.ShowType = 1 //默认列表格式
+	classify.IsShow = 1
+	/*classify.Abstract = req.Abstract
 	classify.Descript = req.Descript
 	classify.Abstract = req.Abstract
 	classify.Descript = req.Descript
@@ -98,7 +108,7 @@ func (this *ClassifyController) Add() {
 	classify.ShowType = req.ShowType
 	classify.HasTeleconference = req.HasTeleconference
 	classify.VipTitle = req.VipTitle
-	classify.Sort = req.Sort
+
 	classify.IsShow = req.IsShow
 	classify.YbFiccSort = req.YbFiccSort
 	classify.YbFiccIcon = req.YbFiccIcon
@@ -156,7 +166,7 @@ func (this *ClassifyController) Add() {
 				return
 			}
 		}
-	}
+	}*/
 	err = models.AddClassify(classify)
 	if err != nil {
 		br.Msg = "新增失败"
@@ -165,7 +175,7 @@ func (this *ClassifyController) Add() {
 	}
 
 	// 一级分类-新增子目录
-	if classify.ParentId == 0 && len(req.MenuList) > 0 {
+	/*if classify.ParentId == 0 && len(req.MenuList) > 0 {
 		menus := make([]*models.ClassifyMenu, 0)
 		for i := range req.MenuList {
 			menus = append(menus, &models.ClassifyMenu{
@@ -190,6 +200,18 @@ func (this *ClassifyController) Add() {
 			br.ErrMsg = "新增子目录关联失败, Err:" + e.Error()
 			return
 		}
+	}*/
+	//获取报告分类权限列表
+	if classify.ParentId > 0 { //二级分类才能修改权限
+		err = models.EditChartPermissionSearchKeyWordMappingMulti(req.ClassifyName, req.ChartPermissionIdList)
+		if err != nil {
+			br.Msg = "修改分类权限失败"
+			br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
+			return
+		}
+		go func() {
+			_ = services.EditClassifyChartPermissionSync(req.ClassifyName)
+		}()
 	}
 
 	// 新增关联了电话会的二级分类时, 同步FICC活动分类
@@ -386,7 +408,7 @@ func (this *ClassifyController) Edit() {
 	}
 
 	// 获取系统菜单, 如果没有对应的字段的特殊处理项, 则忽略必填
-	menus, e := system.GetSysMenuItemsByCondition(` AND hidden = 0`, make([]interface{}, 0), []string{}, ``)
+	/*menus, e := system.GetSysMenuItemsByCondition(` AND hidden = 0`, make([]interface{}, 0), []string{}, ``)
 	if e != nil {
 		br.Msg = "保存失败"
 		br.ErrMsg = "获取菜单列表失败, Err: " + e.Error()
@@ -397,7 +419,7 @@ func (this *ClassifyController) Edit() {
 		if m.ButtonCode != "" {
 			menuMap[m.ButtonCode] = true
 		}
-	}
+	}*/
 
 	if req.ClassifyId <= 0 {
 		br.Msg = "参数错误"
@@ -407,7 +429,7 @@ func (this *ClassifyController) Edit() {
 		br.Msg = "分类名称不可为空"
 		return
 	}
-	if menuMap[system.MenuSpecialHandleClassifyShowType] && req.ParentId != 0 && req.ShowType == 0 {
+	/*if menuMap[system.MenuSpecialHandleClassifyShowType] && req.ParentId != 0 && req.ShowType == 0 {
 		br.Msg = "展示类型不可为空"
 		return
 	}
@@ -418,7 +440,7 @@ func (this *ClassifyController) Edit() {
 	if menuMap[system.MenuSpecialHandleClassifyReportImgs] && (req.ShowType == 1 || req.ShowType == 3) && req.YbRightBanner == "" && req.ParentId == 0 { //当一级报告分类为列表、品种时,增加“报告合集配图”的配置项
 		br.Msg = "报告合集配图不可为空"
 		return
-	}
+	}*/
 
 	item, err := models.GetClassifyById(req.ClassifyId)
 	if err != nil {
@@ -446,59 +468,78 @@ func (this *ClassifyController) Edit() {
 		br.Msg = "分类名称:" + req.ClassifyName + "已存在"
 		return
 	}
-
 	item.ClassifyName = req.ClassifyName
-	item.Abstract = req.Abstract
 	item.ParentId = req.ParentId
-	item.Descript = req.Descript
-	item.ReportAuthor = req.ReportAuthor
-	item.AuthorDescript = req.AuthorDescript
-	item.ColumnImgUrl = req.ColumnImgUrl
-	item.HeadImgUrl = req.HeadImgUrl
-	item.AvatarImgUrl = req.AvatarImgUrl
-	item.ReportImgUrl = req.ReportImgUrl
-	item.HomeImgUrl = req.HomeImgUrl
-	item.ClassifyLabel = req.ClassifyLabel
-	item.ShowType = req.ShowType
-	item.HasTeleconference = req.HasTeleconference
-	item.VipTitle = req.VipTitle
-	item.Sort = req.Sort
-	item.IsShow = req.IsShow
-	item.YbFiccSort = req.YbFiccSort
-	item.YbFiccIcon = req.YbFiccIcon
-	item.YbFiccPcIcon = req.YbFiccPcIcon
-	item.YbIconUrl = req.YbIconUrl
-	item.YbBgUrl = req.YbBgUrl
-	item.YbListImg = req.YbListImg
-	item.YbShareBgImg = req.YbShareBgImg
-	item.YbRightBanner = req.YbRightBanner
-	item.RelateTel = req.RelateTel
-	item.RelateVideo = req.RelateVideo
 	item.ModifyTime = time.Now().Local()
 	cols := make([]string, 0)
-	cols = append(cols, "ClassifyName", "Abstract", "ParentId", "Descript", "ReportAuthor", "AuthorDescript", "ColumnImgUrl",
-		"HeadImgUrl", "AvatarImgUrl", "ReportImgUrl", "HomeImgUrl", "ClassifyLabel", "ShowType", "HasTeleconference", "VipTitle", "Sort",
-		"IsShow", "YbFiccSort", "YbFiccIcon", "YbFiccPcIcon", "YbIconUrl", "YbBgUrl", "YbListImg", "YbShareBgImg", "YbRightBanner",
-		"RelateTel", "RelateVideo", "ModifyTime")
+	cols = append(cols, "ClassifyName", "ParentId", "ModifyTime")
 	if e := item.UpdateClassify(cols); e != nil {
 		br.Msg = "修改失败"
 		br.ErrMsg = "修改失败,Err:" + e.Error()
 		return
 	}
-	// 一级分类关联设置会强制修改二级分类的所有关联设置
-	if item.ParentId == 0 {
-		if e = models.UpdateChildClassifyRelateSetting(item.Id, req.RelateTel, req.RelateVideo); e != nil {
-			br.Msg = "更新二级分类关联设置失败"
-			br.ErrMsg = "更新二级分类关联设置失败, Err: " + e.Error()
+
+	/*
+		item.Abstract = req.Abstract
+		item.Descript = req.Descript
+		item.ReportAuthor = req.ReportAuthor
+		item.AuthorDescript = req.AuthorDescript
+		item.ColumnImgUrl = req.ColumnImgUrl
+		item.HeadImgUrl = req.HeadImgUrl
+		item.AvatarImgUrl = req.AvatarImgUrl
+		item.ReportImgUrl = req.ReportImgUrl
+		item.HomeImgUrl = req.HomeImgUrl
+		item.ClassifyLabel = req.ClassifyLabel
+		item.ShowType = req.ShowType
+		item.HasTeleconference = req.HasTeleconference
+		item.VipTitle = req.VipTitle
+		//	item.Sort = req.Sort
+		item.IsShow = req.IsShow
+		item.YbFiccSort = req.YbFiccSort
+		item.YbFiccIcon = req.YbFiccIcon
+		item.YbFiccPcIcon = req.YbFiccPcIcon
+		item.YbIconUrl = req.YbIconUrl
+		item.YbBgUrl = req.YbBgUrl
+		item.YbListImg = req.YbListImg
+		item.YbShareBgImg = req.YbShareBgImg
+		item.YbRightBanner = req.YbRightBanner
+		item.RelateTel = req.RelateTel
+		item.RelateVideo = req.RelateVideo
+		item.ModifyTime = time.Now().Local()
+		cols := make([]string, 0)
+		cols = append(cols, "ClassifyName", "Abstract", "ParentId", "Descript", "ReportAuthor", "AuthorDescript", "ColumnImgUrl",
+			"HeadImgUrl", "AvatarImgUrl", "ReportImgUrl", "HomeImgUrl", "ClassifyLabel", "ShowType", "HasTeleconference", "VipTitle", "Sort",
+			"IsShow", "YbFiccSort", "YbFiccIcon", "YbFiccPcIcon", "YbIconUrl", "YbBgUrl", "YbListImg", "YbShareBgImg", "YbRightBanner",
+			"RelateTel", "RelateVideo", "ModifyTime")
+		if e := item.UpdateClassify(cols); e != nil {
+			br.Msg = "修改失败"
+			br.ErrMsg = "修改失败,Err:" + e.Error()
 			return
 		}
-	}
-
+		// 一级分类关联设置会强制修改二级分类的所有关联设置
+		if item.ParentId == 0 {
+			if e = models.UpdateChildClassifyRelateSetting(item.Id, req.RelateTel, req.RelateVideo); e != nil {
+				br.Msg = "更新二级分类关联设置失败"
+				br.ErrMsg = "更新二级分类关联设置失败, Err: " + e.Error()
+				return
+			}
+		}
+	*/
 	// 为二级分类时, 更新父级分类是否含电话会字段
 	if req.ParentId > 0 {
+		//二级分类才能修改权限
+		err = models.EditChartPermissionSearchKeyWordMappingMulti(item.ClassifyName, req.ChartPermissionIdList)
+		if err != nil {
+			br.Msg = "修改分类权限失败"
+			br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
+			return
+		}
 		go func() {
-			_ = services.UpdateParentClassifyHasTel(req.ClassifyId, req.ParentId, req.HasTeleconference)
+			_ = services.EditClassifyChartPermissionSync(item.ClassifyName)
 		}()
+		/*go func() {
+			_ = services.UpdateParentClassifyHasTel(req.ClassifyId, req.ParentId, req.HasTeleconference)
+		}()*/
 	}
 
 	// 更新报告分类名称/父级分类后
@@ -507,7 +548,7 @@ func (this *ClassifyController) Edit() {
 	}()
 
 	// 获取编辑前子目录列表
-	classifyId := item.Id
+	/*classifyId := item.Id
 	var menuCond string
 	var menuPars []interface{}
 	menuCond += ` AND classify_id = ?`
@@ -567,7 +608,7 @@ func (this *ClassifyController) Edit() {
 			br.ErrMsg = "新增子目录关联失败, Err:" + e.Error()
 			return
 		}
-	}
+	}*/
 
 	// 关联电话会选项被更改时, 同步FICC活动分类
 	//if originRelateTel != req.RelateTel {
@@ -675,8 +716,6 @@ func (this *ClassifyController) FindByIdClassify() {
 
 // @Title 获取分类列表
 // @Description 获取分类列表
-// @Param   PageSize   query   int  true       "每页数据条数"
-// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
 // @Param   KeyWord   query   string  true       "检索关键词"
 // @Param   CompanyType   query   string  false       "产品类型,枚举值:'ficc','权益';不传默认返回全部"
 // @Param   HideDayWeek   query   int  false       "是否隐藏晨周报"
@@ -688,32 +727,22 @@ func (this *ClassifyController) ListClassify() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	pageSize, _ := this.GetInt("PageSize")
-	currentIndex, _ := this.GetInt("CurrentIndex")
+
 	keyWord := this.GetString("KeyWord")
 	companyType := this.GetString("CompanyType")
 	hideDayWeek, _ := this.GetInt("HideDayWeek")
+
+	reqEnabled, _ := this.GetInt("Enabled", -1)
 	// 商家不隐藏晨周报
 	if utils.BusinessCode != utils.BusinessCodeRelease {
 		hideDayWeek = 0
 	}
-
-	var startSize int
-	if pageSize <= 0 {
-		pageSize = utils.PageSize20
-	}
-	if currentIndex <= 0 {
-		currentIndex = 1
+	enabled := -1
+	if reqEnabled == 1 {
+		enabled = reqEnabled
 	}
 
-	startSize = utils.StartIndex(currentIndex, pageSize)
-	list, err := models.GetClassifyList(startSize, pageSize, keyWord, companyType, hideDayWeek)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-	total, err := models.GetClassifyListCount(keyWord, companyType, hideDayWeek)
+	list, err := models.GetClassifyList(keyWord, companyType, hideDayWeek, enabled)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
@@ -727,8 +756,7 @@ func (this *ClassifyController) ListClassify() {
 	parentIdLen := len(parentIds)
 	if parentIdLen == 0 {
 		resp := &models.ClassifyListResp{
-			List:   list,
-			Paging: paging.GetPaging(currentIndex, pageSize, 0),
+			List: list,
 		}
 		br.Data = resp
 		br.Ret = 200
@@ -757,7 +785,7 @@ func (this *ClassifyController) ListClassify() {
 	}
 
 	// 获取子分类
-	children, e := models.GetClassifyChildByParentIds(parentIds, keyWord)
+	children, e := models.GetClassifyChildByParentIds(parentIds, keyWord, enabled)
 	if e != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取子分类失败"
@@ -787,16 +815,29 @@ func (this *ClassifyController) ListClassify() {
 		}
 	}
 
+	// 查询分类绑定的权限
+	permissionList, _ := models.GetAllPermissionMapping()
+	classifyPermissionMap := make(map[string][]int, 0)
+	if len(permissionList) > 0 {
+		for _, v := range permissionList {
+			classifyPermissionMap[v.KeyWord] = append(classifyPermissionMap[v.KeyWord], v.ChartPermissionId)
+		}
+	}
 	// 二级分类
 	childrenMap := make(map[int][]*models.ClassifyItem, 0)
 	for i := range children {
+
 		if childrenMap[children[i].ParentId] == nil {
 			childrenMap[children[i].ParentId] = make([]*models.ClassifyItem, 0)
 		}
-		childrenMap[children[i].ParentId] = append(childrenMap[children[i].ParentId], &models.ClassifyItem{
+		tmp := &models.ClassifyItem{
 			Classify:       *children[i],
 			ClassifyMenuId: relateMap[children[i].Id],
-		})
+		}
+		if permissionIds, ok := classifyPermissionMap[children[i].ClassifyName]; ok {
+			tmp.ChartPermissionIdList = permissionIds
+		}
+		childrenMap[children[i].ParentId] = append(childrenMap[children[i].ParentId], tmp)
 	}
 
 	// 一级分类
@@ -805,10 +846,8 @@ func (this *ClassifyController) ListClassify() {
 		list[i].Child = childrenMap[list[i].Id]
 	}
 
-	page := paging.GetPaging(currentIndex, pageSize, total)
 	resp := new(models.ClassifyListResp)
 	resp.List = list
-	resp.Paging = page
 	br.Data = resp
 	br.Ret = 200
 	br.Success = true
@@ -900,7 +939,9 @@ func (this *ClassifyController) EditClassifyPermission() {
 		br.ErrMsg = "修改分类权限失败,Err:" + err.Error()
 		return
 	}
-
+	go func() {
+		_ = services.EditClassifyChartPermissionSync(classifyInfo.ClassifyName)
+	}()
 	// 是关联电话会二级分类修改了权限, 同步关联报告电话会的分类
 	//if classifyInfo.ParentId > 0 && classifyInfo.RelateTel == 1 {
 	//	go func() {
@@ -955,3 +996,93 @@ func (this *ClassifyController) TelListClassify() {
 	br.Success = true
 	br.Msg = "获取成功"
 }
+
+// Move
+// @Title 移动分类接口
+// @Description 移动分类
+// @Param	request	body models.ClassifyMoveReq true "type json string"
+// @Success 200 新增成功
+// @router /move [post]
+func (this *ClassifyController) Move() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.ClassifyMoveReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	e, msg := services.MoveReportClassify(req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "移动分类失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// SetEnabled
+// @Title 启用/禁用分类接口
+// @Description 启用/禁用分类
+// @Param	request	body models.ClassifyMoveReq true "type json string"
+// @Success 200 新增成功
+// @router /enabled/set [post]
+func (this *ClassifyController) SetEnabled() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.ClassifySetEnabledReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	if req.Enabled != 0 && req.Enabled != 1 {
+		br.Msg = "请选择正确的启用禁用状态"
+		return
+	}
+	item, err := models.GetClassifyById(req.ClassifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "分类不存在"
+			return
+		}
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item == nil {
+		br.Msg = "分类不存在"
+		return
+	}
+	ob := new(models.Classify)
+	//设置分类启用、禁用状态
+	err = ob.SetEnabled(req.ClassifyId, req.Enabled)
+	if err != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 28 - 2
controllers/cloud_disk.go

@@ -8,7 +8,9 @@ import (
 	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/utils"
 	"fmt"
+	"github.com/h2non/filetype"
 	"github.com/rdlucklib/rdluck_tools/http"
+	"io/ioutil"
 	"os"
 	"path"
 	"strconv"
@@ -517,9 +519,20 @@ func (this *CloudDiskController) CheckResourceRepeat() {
 func (this *CloudDiskController) ResourceUpload() {
 	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
+	}
+
 	menuId, _ := this.GetInt("MenuId", 0)
 	if menuId <= 0 {
 		br.Msg = "不允许上传文件至根目录"
@@ -543,10 +556,22 @@ func (this *CloudDiskController) ResourceUpload() {
 	defer func() {
 		_ = f.Close()
 	}()
-
 	extIndex := strings.LastIndex(originName, ".")
 	fileName := originName[:extIndex]
-	ext := path.Ext(h.Filename)
+
+	// 不依赖于文件扩展名检查文件格式
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "读取文件失败, Err: " + e.Error()
+		return
+	}
+	// 允许上传图片/音视频/文档/压缩包
+	if !filetype.IsImage(fileData) && !filetype.IsVideo(fileData) && !filetype.IsAudio(fileData) && !filetype.IsDocument(fileData) && !filetype.IsArchive(fileData) {
+		br.Msg = "不允许上传该格式文件"
+		br.ErrMsg = "文件格式有误"
+		return
+	}
 
 	// 重名校验
 	existItem := new(models.CloudDiskResource)
@@ -569,6 +594,7 @@ func (this *CloudDiskController) ResourceUpload() {
 		br.ErrMsg = "存储目录创建失败, Err:" + e.Error()
 		return
 	}
+	ext := path.Ext(h.Filename)
 	ossFileName := utils.GetRandStringNoSpecialChar(28) + ext
 	filePath := uploadDir + "/" + ossFileName
 	if e = this.SaveToFile("file", filePath); e != nil {

+ 8 - 1
controllers/company_permission.go

@@ -52,7 +52,7 @@ func (this *CompanyPermissionController) List() {
 
 	// FICC
 	if productId == utils.COMPANY_PRODUCT_FICC_ID || companyType == utils.COMPANY_PRODUCT_FICC_NAME {
-		for _, v := range utils.PermissionFiccClassifyArr {
+		/*for _, v := range utils.PermissionFiccClassifyArr {
 			checkList := make([]int, 0)
 			p := new(company.PermissionSetList)
 			p.ClassifyName = v
@@ -68,7 +68,14 @@ func (this *CompanyPermissionController) List() {
 			}
 			p.CheckList = checkList
 			resp.List = append(resp.List, p)
+		}*/
+		list, err := services.GetChartPermissionEnabledList()
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取权限信息失败,Err:" + err.Error()
+			return
 		}
+		resp.List = list
 		br.Ret = 200
 		br.Success = true
 		br.Msg = "获取成功"

+ 87 - 18
controllers/data_manage/chart_classify.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
 	"fmt"
 	"strconv"
@@ -95,7 +96,7 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 			return
 		}
 		// 移除没有权限的图表
-		allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
+		allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap, this.SysUser.AdminId)
 		resp.AllNodes = allNodes
 
 		br.Ret = 200
@@ -114,7 +115,7 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 				err := json.Unmarshal(redisData, &resp)
 				if err == nil && resp != nil {
 					// 移除没有权限的图表
-					allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
+					allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap, this.SysUser.AdminId)
 					resp.AllNodes = allNodes
 
 					br.Ret = 200
@@ -190,7 +191,7 @@ func (this *ChartClassifyController) ChartClassifyListV2() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap, this.SysUser.AdminId)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -274,10 +275,18 @@ func (this *ChartClassifyController) ChartClassifyItems() {
 		return
 	}
 
+	// 已授权分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserChartClassifyPermissionList(this.SysUser.AdminId, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+		return
+	}
+
 	nodeAll := make([]*data_manage.ChartClassifyItems, 0)
 	for k := range rootList {
 		rootNode := rootList[k]
-		data.ChartClassifyItemsMakeTree(this.SysUser, classifyAll, rootNode)
+		data.ChartClassifyItemsMakeTree(this.SysUser, classifyAll, rootNode, permissionClassifyIdList)
 		nodeAll = append(nodeAll, rootNode)
 	}
 
@@ -369,12 +378,19 @@ func (this *ChartClassifyController) AddChartClassify() {
 	classify.Sort = maxSort + 1
 	classify.Source = utils.CHART_SOURCE_DEFAULT
 
-	_, err = data_manage.AddChartClassify(classify)
+	classifyId, err := data_manage.AddChartClassify(classify)
 	if err != nil {
 		br.Msg = "保存分类失败"
 		br.ErrMsg = "保存分类失败,Err:" + err.Error()
 		return
 	}
+	classify.ChartClassifyId = int(classifyId)
+
+	// 继承分类权限
+	{
+		go data_manage_permission.InheritParentClassify(5, utils.CHART_SOURCE_DEFAULT, classify.ChartClassifyId, classify.ParentId, classify.ChartClassifyName)
+	}
+
 	br.Ret = 200
 	br.Msg = "保存成功"
 	br.Success = true
@@ -416,10 +432,18 @@ func (this *ChartClassifyController) EditChartClassify() {
 		br.Msg = "获取分类信息失败,Err:" + err.Error()
 		return
 	}
+	// 已授权分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserChartClassifyPermissionList(this.SysUser.AdminId, item.ChartClassifyId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+		return
+	}
+	haveOperaAuth := data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(item.IsJoinPermission, item.ChartClassifyId, permissionClassifyIdList)
 
 	// 权限校验
 	{
-		button := data.GetChartClassifyOpButton(this.SysUser, item.SysUserId)
+		button := data.GetChartClassifyOpButton(this.SysUser, item.SysUserId, haveOperaAuth)
 		if !button.OpButton {
 			br.Msg = "无操作权限"
 			br.IsSendEmail = false
@@ -488,9 +512,17 @@ func (this *ChartClassifyController) DeleteChartClassifyCheck() {
 			br.Msg = "获取分类信息失败,Err:" + err.Error()
 			return
 		}
+		// 已授权分类id
+		permissionClassifyIdList, err := data_manage_permission.GetUserChartClassifyPermissionList(this.SysUser.AdminId, item.ChartClassifyId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
 		// 权限校验
 		{
-			button := data.GetChartClassifyOpButton(this.SysUser, item.SysUserId)
+			haveOperaAuth := data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(item.IsJoinPermission, item.ChartClassifyId, permissionClassifyIdList)
+			button := data.GetChartClassifyOpButton(this.SysUser, item.SysUserId, haveOperaAuth)
 			if !button.OpButton {
 				br.Msg = "无操作权限"
 				br.IsSendEmail = false
@@ -580,9 +612,18 @@ func (this *ChartClassifyController) DeleteChartClassify() {
 			br.Msg = "获取分类信息失败,Err:" + err.Error()
 			return
 		}
+		// 已授权分类id
+		permissionClassifyIdList, err := data_manage_permission.GetUserChartClassifyPermissionList(this.SysUser.AdminId, item.ChartClassifyId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
 		// 权限校验
 		{
-			button := data.GetChartClassifyOpButton(this.SysUser, item.SysUserId)
+			haveOperaAuth := data_manage_permission.CheckChartClassifyPermissionByPermissionIdList(item.IsJoinPermission, item.ChartClassifyId, permissionClassifyIdList)
+			button := data.GetChartClassifyOpButton(this.SysUser, item.SysUserId, haveOperaAuth)
 			if !button.OpButton {
 				br.Msg = "无操作权限"
 				br.IsSendEmail = false
@@ -630,14 +671,34 @@ func (this *ChartClassifyController) DeleteChartClassify() {
 			br.Msg = "图表已删除,请刷新页面"
 			return
 		}
-		//图表操作权限
-		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
-		if !ok {
-			br.Msg = "没有该图表的操作权限"
-			br.ErrMsg = "没有该图表的操作权限"
+
+		chartClassifyItem, err := data_manage.GetChartClassifyById(chartInfo.ChartClassifyId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取图表分类详情数据失败,Err:" + err.Error()
 			return
 		}
 
+		// 已授权图表、分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
+		// 权限校验
+		{
+			haveOperaAuth := data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, chartClassifyItem.IsJoinPermission, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			//图表操作权限
+			ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, haveOperaAuth)
+			if !ok {
+				br.Msg = "没有该图表的操作权限"
+				br.ErrMsg = "没有该图表的操作权限"
+				return
+			}
+		}
+
 		// 获取引用该图表的MyCharts, 用于ES删除
 		var myCond string
 		var myPars []interface{}
@@ -798,10 +859,18 @@ func (this *ChartClassifyController) ChartClassifyMove() {
 		br.Msg = "移动失败,分类名称已存在"
 		return
 	}
-
+	// 已授权分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserChartClassifyPermissionList(this.SysUser.AdminId, chartClassifyInfo.ChartClassifyId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+		return
+	}
 	// 权限校验
 	{
-		button := data.GetChartClassifyOpButton(this.SysUser, chartClassifyInfo.SysUserId)
+		haveOperaAuth := data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(chartClassifyInfo.IsJoinPermission, chartClassifyInfo.ChartClassifyId, permissionClassifyIdList)
+
+		button := data.GetChartClassifyOpButton(this.SysUser, chartClassifyInfo.SysUserId, haveOperaAuth)
 		if !button.OpButton {
 			br.Msg = "无操作权限"
 			br.IsSendEmail = false
@@ -988,7 +1057,7 @@ func (this *ChartClassifyController) ChartClassifyChartListV2() {
 			return
 		}
 		// 移除没有权限的图表
-		allNodes := data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap)
+		allNodes := data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap, this.SysUser.AdminId)
 		resp.AllNodes = allNodes
 
 		br.Ret = 200
@@ -1006,10 +1075,10 @@ func (this *ChartClassifyController) ChartClassifyChartListV2() {
 		return
 	}
 	// 移除没有权限的图表
-	allNodes := data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(allChartInfo, noPermissionChartIdMap, this.SysUser.AdminId)
 
 	for k, item := range allNodes {
-		item.Button = data.GetChartOpButton(this.SysUser, item.SysUserId)
+		item.Button = data.GetChartOpButton(this.SysUser, item.SysUserId, item.HaveOperaAuth)
 		item.Button.AddButton = false
 		item.Button.OpButton = false
 		item.Button.DeleteButton = false

+ 637 - 294
controllers/data_manage/chart_info.go

@@ -9,6 +9,7 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/services"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
 	"fmt"
@@ -601,6 +602,22 @@ func (this *ChartInfoController) ChartInfoMove() {
 		return
 	}
 
+	// 数据权限校验
+	{
+		haveOperaAuth, err := data_manage_permission.CheckChartPermissionByChartInfoId(chartInfo.ChartInfoId, chartInfo.ChartClassifyId, chartInfo.IsJoinPermission, sysUser.AdminId)
+		if err != nil {
+			br.Msg = "移动失败"
+			br.ErrMsg = "获取图表权限失败,Err:" + err.Error()
+			return
+		}
+		if !haveOperaAuth {
+			br.Msg = "无操作权限"
+			br.ErrMsg = "无操作权限"
+			br.IsSendEmail = false
+			return
+		}
+	}
+
 	//如果改变了分类,那么移动该图表数据
 	if chartInfo.ChartClassifyId != req.ChartClassifyId {
 		//查询需要修改的分类下是否存在同一个图表名称
@@ -772,6 +789,8 @@ func (this *ChartInfoController) ChartInfoDetail() {
 
 	var err error
 	chartInfo := new(data_manage.ChartInfoView)
+	chartInfo.HaveOperaAuth = true
+
 	if chartInfoId > 0 {
 		chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 		if err != nil {
@@ -796,8 +815,30 @@ func (this *ChartInfoController) ChartInfoDetail() {
 		}
 		chartInfo.ChartThemeStyle = chartTheme.Config
 		chartInfo.ChartThemeId = chartTheme.ChartThemeId
+
+		// 图表数据权限
+		{
+			// 图表分类
+			chartClassify, err := data_manage.GetChartClassifyById(chartInfo.ChartClassifyId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表分类信息失败,Err:" + err.Error()
+				return
+			}
+
+			// 已授权分类id
+			permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+				return
+			}
+			chartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, chartClassify.IsJoinPermission, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+		}
 	}
 
+	resp := new(data_manage.ChartInfoDetailResp)
+
 	mappingList := make([]*data_manage.ChartEdbInfoMapping, 0)
 	if chartInfoId > 0 {
 		mappingList, err = data_manage.GetChartEdbMappingList(chartInfoId)
@@ -854,72 +895,79 @@ func (this *ChartInfoController) ChartInfoDetail() {
 	// 开始/结束日期
 	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
 
-	// 获取图表中的指标数据
-	edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
-	if err != nil {
-		br.Msg = "获取失败"
-		if errMsg != `` {
-			br.Msg = errMsg
+	if chartInfo.HaveOperaAuth {
+		// 获取图表中的指标数据
+		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
+		if err != nil {
+			br.Msg = "获取失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+			return
 		}
-		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
-		return
-	}
-	// 单位
-	if chartType == utils.CHART_TYPE_BAR && len(yDataList) > 0 {
-		chartInfo.Unit = yDataList[0].Unit
-		chartInfo.UnitEn = yDataList[0].UnitEn
-	}
-	warnEdbList := make([]string, 0)
-	for _, v := range edbList {
-		if v.IsNullData {
-			warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
+		// 单位
+		if chartType == utils.CHART_TYPE_BAR && len(yDataList) > 0 {
+			chartInfo.Unit = yDataList[0].Unit
+			chartInfo.UnitEn = yDataList[0].UnitEn
 		}
-	}
-	if len(warnEdbList) > 0 {
-		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
-	}
-	if chartInfoId > 0 && chartInfo != nil {
-		//判断是否加入我的图库
-		{
-			var myChartCondition string
-			var myChartPars []interface{}
-			myChartCondition += ` AND a.admin_id=? `
-			myChartPars = append(myChartPars, sysUser.AdminId)
-			myChartCondition += ` AND a.chart_info_id=? `
-			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
-
-			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				br.Msg = "获取失败"
-				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
-				return
-			}
-			if myChartList != nil && len(myChartList) > 0 {
-				chartInfo.IsAdd = true
-				chartInfo.MyChartId = myChartList[0].MyChartId
-				chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+		warnEdbList := make([]string, 0)
+		for _, v := range edbList {
+			if v.IsNullData {
+				warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
 			}
 		}
-		if chartInfo.ChartType == 2 {
-			if chartInfo.SeasonStartDate != "" {
-				chartInfo.StartDate = chartInfo.SeasonStartDate
-				chartInfo.EndDate = chartInfo.SeasonEndDate
-				if chartInfo.DateType == 3 {
-					chartInfo.DateType = 5
+		if len(warnEdbList) > 0 {
+			chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
+		}
+		if chartInfoId > 0 && chartInfo != nil {
+			//判断是否加入我的图库
+			{
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, sysUser.AdminId)
+				myChartCondition += ` AND a.chart_info_id=? `
+				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
+
+				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+					return
+				}
+				if myChartList != nil && len(myChartList) > 0 {
+					chartInfo.IsAdd = true
+					chartInfo.MyChartId = myChartList[0].MyChartId
+					chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+				}
+			}
+			if chartInfo.ChartType == 2 {
+				if chartInfo.SeasonStartDate != "" {
+					chartInfo.StartDate = chartInfo.SeasonStartDate
+					chartInfo.EndDate = chartInfo.SeasonEndDate
+					if chartInfo.DateType == 3 {
+						chartInfo.DateType = 5
+					}
 				}
 			}
 		}
-	}
 
-	// 图表的指标来源
-	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
-	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
-	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+		// 图表的指标来源
+		sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+		chartInfo.ChartSource = strings.Join(sourceNameList, ",")
+		chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+		//判断是否需要展示英文标识
+		chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
+
+		resp.EdbInfoList = edbList
+		resp.XEdbIdValue = xEdbIdValue
+		resp.YDataList = yDataList
+		resp.DataResp = dataResp
+	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
-	//判断是否需要展示英文标识
-	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, chartInfo.HaveOperaAuth)
 	chartInfo.Button = data_manage.ChartViewButton{
 		IsEdit:    chartInfo.IsEdit,
 		IsEnChart: chartInfo.IsEnChart,
@@ -928,13 +976,8 @@ func (this *ChartInfoController) ChartInfoDetail() {
 		IsSetName: chartInfo.IsSetName,
 	}
 
-	resp := new(data_manage.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
-	resp.EdbInfoList = edbList
-	resp.XEdbIdValue = xEdbIdValue
-	resp.YDataList = yDataList
 	resp.BarChartInfo = barConfig
-	resp.DataResp = dataResp
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -1104,7 +1147,7 @@ func (this *ChartInfoController) PreviewChartInfoDetail() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
 	chartInfo.Button = data_manage.ChartViewButton{
@@ -1172,6 +1215,28 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 		return
 	}
 
+	resp := new(data_manage.ChartInfoDetailResp)
+
+	// 图表数据权限
+	{
+		// 图表分类
+		chartClassify, err := data_manage.GetChartClassifyById(chartInfo.ChartClassifyId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取图表分类信息失败,Err:" + err.Error()
+			return
+		}
+
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+		chartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, chartClassify.IsJoinPermission, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+	}
+
 	// 获取主题样式
 	chartTheme, err := data.GetChartThemeConfig(chartInfo.ChartThemeId, chartInfo.Source, chartInfo.ChartType)
 	if err != nil {
@@ -1262,58 +1327,110 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 		extraConfigStr = chartInfo.BarConfig
 	}
 
-	// 获取图表中的指标数据
-	edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
-	if err != nil {
-		br.Msg = "获取失败"
-		if errMsg != `` {
-			br.Msg = errMsg
+	if chartInfo.HaveOperaAuth {
+		// 获取图表中的指标数据
+		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
+		if err != nil {
+			br.Msg = "获取失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+			return
 		}
-		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
-		return
-	}
-	// 单位
-	if chartType == utils.CHART_TYPE_BAR && len(yDataList) > 0 {
-		chartInfo.Unit = yDataList[0].Unit
-		chartInfo.UnitEn = yDataList[0].UnitEn
-	}
-	warnEdbList := make([]string, 0)
-	for _, v := range edbList {
-		if v.IsNullData {
-			warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
+		// 单位
+		if chartType == utils.CHART_TYPE_BAR && len(yDataList) > 0 {
+			chartInfo.Unit = yDataList[0].Unit
+			chartInfo.UnitEn = yDataList[0].UnitEn
 		}
-	}
-	if len(warnEdbList) > 0 {
-		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
-	}
-	if chartInfoId > 0 && chartInfo != nil {
-		//判断是否加入我的图库
+		warnEdbList := make([]string, 0)
+		for _, v := range edbList {
+			if v.IsNullData {
+				warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
+			}
+		}
+		if len(warnEdbList) > 0 {
+			chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
+		}
+		if chartInfoId > 0 && chartInfo != nil {
+			//判断是否加入我的图库
+			{
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, sysUser.AdminId)
+				myChartCondition += ` AND a.chart_info_id=? `
+				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
+
+				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+					return
+				}
+				if myChartList != nil && len(myChartList) > 0 {
+					chartInfo.IsAdd = true
+					chartInfo.MyChartId = myChartList[0].MyChartId
+					chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+				}
+			}
+		}
+		//判断是否需要展示英文标识
+		chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
+
+		// 图表的指标来源
+		sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+
+		chartInfo.ChartSource = strings.Join(sourceNameList, ",")
+		chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+
+		// 指标权限
 		{
-			var myChartCondition string
-			var myChartPars []interface{}
-			myChartCondition += ` AND a.admin_id=? `
-			myChartPars = append(myChartPars, sysUser.AdminId)
-			myChartCondition += ` AND a.chart_info_id=? `
-			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
-
-			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
+
+			classifyMap := make(map[int]*data_manage.EdbClassify)
+
+			// 分类
+			{
+				classifyIdList := make([]int, 0)
+				for _, v := range edbList {
+					classifyIdList = append(classifyIdList, v.ClassifyId)
+				}
+				classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+				if tmpErr != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+					return
+				}
+				for _, v := range classifyList {
+					classifyMap[v.ClassifyId] = v
+				}
+			}
+			// 获取所有有权限的指标和分类
+			permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+			if err != nil {
 				br.Msg = "获取失败"
-				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+				br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
 				return
 			}
-			if myChartList != nil && len(myChartList) > 0 {
-				chartInfo.IsAdd = true
-				chartInfo.MyChartId = myChartList[0].MyChartId
-				chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+
+			for _, item := range edbList {
+				// 数据权限
+				if currClassify, ok := classifyMap[item.ClassifyId]; ok {
+					item.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(item.IsJoinPermission, currClassify.IsJoinPermission, item.EdbInfoId, item.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+				}
 			}
 		}
+
+		resp.EdbInfoList = edbList
+		resp.XEdbIdValue = xEdbIdValue
+		resp.YDataList = yDataList
+		resp.DataResp = dataResp
+	} else {
+		resp.EdbInfoList = mappingList
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
-	//判断是否需要展示英文标识
-	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, chartInfo.HaveOperaAuth)
 	chartInfo.Button = data_manage.ChartViewButton{
 		IsEdit:    chartInfo.IsEdit,
 		IsEnChart: chartInfo.IsEnChart,
@@ -1322,18 +1439,8 @@ func (this *ChartInfoController) ChartInfoDetailV2() {
 		IsSetName: chartInfo.IsSetName,
 	}
 
-	// 图表的指标来源
-	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
-	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
-	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
-
-	resp := new(data_manage.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
-	resp.EdbInfoList = edbList
-	resp.XEdbIdValue = xEdbIdValue
-	resp.YDataList = yDataList
 	resp.BarChartInfo = barConfig
-	resp.DataResp = dataResp
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -1635,7 +1742,7 @@ func (this *ChartInfoController) ChartInfoSearch() {
 		return
 	}
 	keyWord := this.GetString("KeyWord")
-	searchList := make([]*data_manage.ChartInfo, 0)
+	searchList := make([]data_manage.ChartInfoMore, 0)
 	//var err error
 	//if KeyWord == "" {
 	//	searchList, err = data_manage.ChartInfoSearchByKeyWord(KeyWord)
@@ -1676,15 +1783,55 @@ func (this *ChartInfoController) ChartInfoSearch() {
 		}
 		for _, nv := range newSearchList {
 			if _, ok := existMap[nv.ChartInfoId]; !ok {
-				searchList = append(searchList, nv)
+				searchList = append(searchList, data_manage.ChartInfoMore{
+					ChartInfo: *nv,
+				})
 			}
 			existMap[nv.ChartInfoId] = nv.ChartName
 		}
 	}
 
 	if searchList == nil {
-		searchList = make([]*data_manage.ChartInfo, 0)
+		searchList = make([]data_manage.ChartInfoMore, 0)
+	}
+
+	// 数据权限
+	if len(searchList) > 0 {
+		// 涉及分类id
+		classifyIdList := make([]int, 0)
+		for _, v := range searchList {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+		}
+
+		// 图表分类
+		chartClassifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取图表分类失败,Err:" + err.Error()
+			return
+		}
+
+		chartClassifyMap := make(map[int]*data_manage.ChartClassify)
+		for _, v := range chartClassifyList {
+			chartClassifyMap[v.ChartClassifyId] = v
+		}
+
+		// 已授权图表和分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "已授权图表和分类id失败,Err:" + err.Error()
+			return
+		}
+
+		// 权限判断
+		for k, v := range searchList {
+			if currClassify, ok := chartClassifyMap[v.ChartClassifyId]; ok {
+				searchList[k].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.ChartInfoId, v.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+		}
 	}
+
 	//新增搜索词记录
 	{
 		searchKeyword := new(data_manage.SearchKeyword)
@@ -1759,8 +1906,11 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 		}
 	}
 
+	// 是否走ES
+	isEs := false
 	if keyword != "" {
 		searchList, total, err = data.EsSearchChartInfo(keyword, showSysId, []int{utils.CHART_SOURCE_DEFAULT}, noPermissionChartIdList, startSize, pageSize)
+		isEs = true
 	} else {
 		total, searchList, err = data_manage.ChartInfoSearchByEmptyKeyWord(showSysId, []int{utils.CHART_SOURCE_DEFAULT}, noPermissionChartIdList, startSize, pageSize)
 		if err != nil && err.Error() != utils.ErrNoRow() {
@@ -1772,10 +1922,18 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 
 	finalList := make([]*data_manage.ChartInfoMore, 0)
 	if len(searchList) > 0 {
+		// 涉及分类id
+		classifyIdList := make([]int, 0)
+		// 图表id
+		chartInfoIdList := make([]int, 0)
+
 		chartInfoIds := ""
 		chartEdbMap := make(map[int][]*data_manage.ChartEdbInfoMapping)
+
 		for _, v := range searchList {
 			chartInfoIds += strconv.Itoa(v.ChartInfoId) + ","
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+			chartInfoIdList = append(chartInfoIdList, v.ChartInfoId)
 		}
 		if chartInfoIds != "" {
 			chartInfoIds = strings.Trim(chartInfoIds, ",")
@@ -1790,6 +1948,51 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 				chartEdbMap[v.ChartInfoId] = append(chartEdbMap[v.ChartInfoId], v)
 			}
 		}
+		// 当前列表中的分类map
+		chartClassifyMap := make(map[int]*data_manage.ChartClassify)
+
+		// 图表分类
+		{
+			chartClassifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表分类失败,Err:" + err.Error()
+				return
+			}
+			for _, v := range chartClassifyList {
+				chartClassifyMap[v.ChartClassifyId] = v
+			}
+		}
+		// 图表
+		if isEs {
+			// 当前列表中的图表map
+			chartInfoMap := make(map[int]*data_manage.ChartInfo)
+			tmpChartList, err := data_manage.GetChartInfoByIdList(chartInfoIdList)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取所有有权限的图表失败,Err:" + err.Error()
+				return
+			}
+			for _, tmpChartInfo := range tmpChartList {
+				chartInfoMap[tmpChartInfo.ChartInfoId] = tmpChartInfo
+			}
+			for _, v := range searchList {
+				// 图表权限
+				chartViewInfo, ok := chartInfoMap[v.ChartInfoId]
+				if !ok {
+					continue
+				}
+				v.IsJoinPermission = chartViewInfo.IsJoinPermission
+			}
+		}
+
+		// 已授权图表和分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "已授权图表和分类id失败,Err:" + err.Error()
+			return
+		}
 
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
@@ -1798,6 +2001,12 @@ func (this *ChartInfoController) ChartInfoSearchByEs() {
 			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
 			}
+
+			// 图表权限
+			if currClassify, ok := chartClassifyMap[v.ChartClassifyId]; ok {
+				tmp.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.ChartInfoId, v.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+
 			finalList = append(finalList, tmp)
 		}
 	}
@@ -2012,41 +2221,170 @@ func (this *ChartInfoController) ChartInfoDetailFromUniqueCode() {
 func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCache bool, sysUser *system.Admin) (resp *data_manage.ChartInfoDetailFromUniqueCodeResp, isOk bool, msg, errMsg string) {
 	resp = new(data_manage.ChartInfoDetailFromUniqueCodeResp)
 
+	msg = `获取失败`
 	adminId := sysUser.AdminId
 
+	// 图表数据权限
+	// 图表分类
+	chartClassify, err := data_manage.GetChartClassifyById(chartInfo.ChartClassifyId)
+	if err != nil {
+		errMsg = "获取图表分类信息失败,Err:" + err.Error()
+		return
+	}
+
+	// 已授权分类id
+	permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(adminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
+	if err != nil {
+		errMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+		return
+	}
+
+	// 指标数据map
+	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+	defer func() {
+		if isOk {
+
+			// 图表权限校验
+			{
+				resp.ChartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, chartClassify.IsJoinPermission, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+
+				//图表操作权限
+				chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, resp.ChartInfo.HaveOperaAuth)
+				chartInfo.Button = data_manage.ChartViewButton{
+					IsEdit:    chartInfo.IsEdit,
+					IsEnChart: chartInfo.IsEnChart,
+					IsAdd:     chartInfo.IsAdd,
+					IsCopy:    true,
+					IsSetName: chartInfo.IsSetName,
+				}
+
+				//if !resp.ChartInfo.HaveOperaAuth {
+				//	for _, v := range resp.EdbInfoList {
+				//		v.DataList = nil
+				//	}
+				//	resp.DataResp = nil
+				//	resp.XEdbIdValue = []int{}
+				//	resp.YDataList = []data_manage.YData{}
+				//}
+			}
+
+			// 指标权限
+			{
+				classifyMap := make(map[int]*data_manage.EdbClassify)
+				// 分类
+				{
+					classifyIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						classifyIdList = append(classifyIdList, v.ClassifyId)
+					}
+					classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+					if tmpErr != nil {
+						errMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range classifyList {
+						classifyMap[v.ClassifyId] = v
+					}
+				}
+
+				// 指标
+				if len(edbClassifyPermissionMap) < 0 {
+					edbInfoIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+					edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+					if tmpErr != nil {
+						errMsg = "获取指标列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range edbInfoList {
+						edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+							ClassifyId:       v.ClassifyId,
+							IsJoinPermission: v.IsJoinPermission,
+							EdbInfoId:        v.EdbInfoId,
+						}
+					}
+				}
+
+				// 获取所有有权限的指标和分类
+				permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+				if err != nil {
+					errMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+					return
+				}
+
+				for _, v := range resp.EdbInfoList {
+					// 数据权限
+					edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+						v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					}
+				}
+			}
+		}
+	}()
+
 	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
 	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
 	if utils.Re == nil && isCache {
 		if utils.Re == nil && utils.Rc.IsExist(key) {
-			if data, err1 := utils.Rc.RedisBytes(key); err1 == nil {
-				err := json.Unmarshal(data, &resp)
-				if err == nil && resp != nil {
-					// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
-					var myCond string
-					var myPars []interface{}
-					myCond += ` AND a.admin_id=? `
-					myPars = append(myPars, adminId)
-					myCond += ` AND a.chart_info_id=? `
-					myPars = append(myPars, chartInfo.ChartInfoId)
-					myList, err := data_manage.GetMyChartByCondition(myCond, myPars)
+			if redisData, err1 := utils.Rc.RedisBytes(key); err1 == nil {
+				err := json.Unmarshal(redisData, &resp)
+				if err != nil || resp == nil {
+					return
+				}
+				// 这里跟当前用户相关的信息重新查询写入resp, 不使用缓存中的
+				var myCond string
+				var myPars []interface{}
+				myCond += ` AND a.admin_id=? `
+				myPars = append(myPars, adminId)
+				myCond += ` AND a.chart_info_id=? `
+				myPars = append(myPars, chartInfo.ChartInfoId)
+				myList, err := data_manage.GetMyChartByCondition(myCond, myPars)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					msg = "获取失败"
+					errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+					return
+				}
+				resp.ChartInfo.IsAdd = false
+				resp.ChartInfo.MyChartId = 0
+				resp.ChartInfo.MyChartClassifyId = ""
+				if myList != nil && len(myList) > 0 {
+					resp.ChartInfo.IsAdd = true
+					resp.ChartInfo.MyChartId = myList[0].MyChartId
+					resp.ChartInfo.MyChartClassifyId = myList[0].MyChartClassifyId
+				}
+
+				//判断是否加入我的图库
+				{
+					var myChartCondition string
+					var myChartPars []interface{}
+					myChartCondition += ` AND a.admin_id=? `
+					myChartPars = append(myChartPars, adminId)
+					myChartCondition += ` AND a.chart_info_id=? `
+					myChartPars = append(myChartPars, chartInfo.ChartInfoId)
+
+					myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
 					if err != nil && err.Error() != utils.ErrNoRow() {
 						msg = "获取失败"
 						errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
 						return
 					}
-					resp.ChartInfo.IsAdd = false
-					resp.ChartInfo.MyChartId = 0
-					resp.ChartInfo.MyChartClassifyId = ""
-					if myList != nil && len(myList) > 0 {
-						resp.ChartInfo.IsAdd = true
-						resp.ChartInfo.MyChartId = myList[0].MyChartId
-						resp.ChartInfo.MyChartClassifyId = myList[0].MyChartClassifyId
+					if myChartList != nil && len(myChartList) > 0 {
+						chartInfo.IsAdd = true
+						chartInfo.MyChartId = myChartList[0].MyChartId
+						chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
 					}
-
-					isOk = true
-					fmt.Println("source redis")
-					return
 				}
+
+				isOk = true
+				fmt.Println("source redis")
+				return
 			}
 		}
 	}
@@ -2150,46 +2488,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 		ChartClassify     []*ChartClassifyView
 	*/
 
-	chartClassify, _ := data_manage.GetChartClassifyViewById(chartInfo.ChartClassifyId)
-	if chartClassify != nil {
+	chartViewClassify, _ := data_manage.GetChartClassifyViewById(chartInfo.ChartClassifyId)
+	if chartViewClassify != nil {
 		chartClassifyParent, _ := data_manage.GetChartClassifyViewById(chartClassify.ParentId)
 		chartInfo.ChartClassify = append(chartInfo.ChartClassify, chartClassifyParent)
 	}
-	chartInfo.ChartClassify = append(chartInfo.ChartClassify, chartClassify)
+	chartInfo.ChartClassify = append(chartInfo.ChartClassify, chartViewClassify)
 	resp.EdbInfoList = edbList
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
-	//判断是否加入我的图库
-	{
-		var myChartCondition string
-		var myChartPars []interface{}
-		myChartCondition += ` AND a.admin_id=? `
-		myChartPars = append(myChartPars, adminId)
-		myChartCondition += ` AND a.chart_info_id=? `
-		myChartPars = append(myChartPars, chartInfo.ChartInfoId)
-
-		myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-		if err != nil && err.Error() != utils.ErrNoRow() {
-			msg = "获取失败"
-			errMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
-			return
-		}
-		if myChartList != nil && len(myChartList) > 0 {
-			chartInfo.IsAdd = true
-			chartInfo.MyChartId = myChartList[0].MyChartId
-			chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
-		}
-	}
-
-	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
-	chartInfo.Button = data_manage.ChartViewButton{
-		IsEdit:    chartInfo.IsEdit,
-		IsEnChart: chartInfo.IsEnChart,
-		IsAdd:     chartInfo.IsAdd,
-		IsCopy:    true,
-		IsSetName: chartInfo.IsSetName,
-	}
 
 	// 图表的指标来源
 	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
@@ -2210,6 +2517,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	}
 	isOk = true
 
+	// 遍历到校验map
+	for _, v := range edbList {
+		edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+			ClassifyId:       v.ClassifyId,
+			IsJoinPermission: v.IsJoinPermission,
+			EdbInfoId:        v.EdbInfoId,
+		}
+	}
+
 	return
 }
 
@@ -2748,7 +3064,7 @@ func (this *ChartInfoController) PreviewBarChartInfo() {
 	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
 	chartInfo.Button = data_manage.ChartViewButton{
@@ -2838,7 +3154,7 @@ func (this *ChartInfoController) PreviewSectionScatterChartInfo() {
 	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, utils.CHART_SOURCE_DEFAULT, chartType)
 	chartInfo.Button = data_manage.ChartViewButton{
@@ -3247,7 +3563,7 @@ func (this *ChartInfoController) PreviewRadarChartInfo() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, utils.CHART_SOURCE_DEFAULT, chartType)
 	chartInfo.Button = data_manage.ChartViewButton{
@@ -3327,8 +3643,12 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 	convertUnit := this.GetString("ConvertUnit")
 	convertEnUnit := this.GetString("ConvertEnUnit")
 
+	resp := new(data_manage.ChartInfoDetailResp)
 	var err error
 	chartInfo := new(data_manage.ChartInfoView)
+	chartInfo.HaveOperaAuth = true
+
+	// 通过id获取详情
 	if chartInfoId > 0 {
 		chartInfo, err = data_manage.GetChartInfoViewById(chartInfoId)
 		if err != nil {
@@ -3353,154 +3673,177 @@ func (this *ChartInfoController) ChartInfoConvertDetail() {
 		}
 		chartInfo.ChartThemeStyle = chartTheme.Config
 		chartInfo.ChartThemeId = chartTheme.ChartThemeId
-	}
 
-	mappingList := make([]*data_manage.ChartEdbInfoMapping, 0)
-	if chartInfoId > 0 {
-		mappingList, err = data_manage.GetChartEdbMappingList(chartInfoId)
-		if err != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
-			return
-		}
-	} else {
-		if edbInfoId != "" {
-			mappingList, err = data_manage.GetChartEdbMappingListByEdbInfoId(edbInfoId)
+		// 图表数据权限
+		{
+			// 图表分类
+			chartClassify, err := data_manage.GetChartClassifyById(chartInfo.ChartClassifyId)
 			if err != nil {
 				br.Msg = "获取失败"
-				br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+				br.ErrMsg = "获取图表分类信息失败,Err:" + err.Error()
 				return
 			}
-			if isConvert == 1 && len(mappingList) > 0 {
-				for i, _ := range mappingList {
-					mappingList[i].IsConvert = 1
-					mappingList[i].ConvertType = convertType
-					mappingList[i].ConvertValue = convertValue
-					mappingList[i].ConvertUnit = convertUnit
-					mappingList[i].ConvertEnUnit = convertEnUnit
-				}
+
+			// 已授权分类id
+			permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, chartInfo.ChartInfoId, chartInfo.ChartClassifyId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+				return
 			}
+			chartInfo.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartInfo.IsJoinPermission, chartClassify.IsJoinPermission, chartInfo.ChartInfoId, chartInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
 		}
-	}
 
-	// 图表额外数据参数
-	extraConfigStr := chartInfo.ExtraConfig
-	// 柱方图的一些配置
-	var barConfig data_manage.BarChartInfoReq
-	if chartInfo != nil && chartInfo.ChartType == 7 {
-		if chartInfo.BarConfig == `` {
-			br.Msg = "柱方图未配置"
-			br.ErrMsg = "柱方图未配置"
-			return
+		//图表操作权限
+		chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, chartInfo.HaveOperaAuth)
+		chartInfo.Button = data_manage.ChartViewButton{
+			IsEdit:    chartInfo.IsEdit,
+			IsEnChart: chartInfo.IsEnChart,
+			IsAdd:     chartInfo.IsAdd,
+			IsCopy:    true,
+			IsSetName: chartInfo.IsSetName,
 		}
-		err := json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
-		if err != nil {
-			br.Msg = "柱方图配置异常"
-			br.ErrMsg = "柱方图配置异常"
-			return
-		}
-		extraConfigStr = chartInfo.BarConfig
 	}
-	yearMax := 0
-	if dateType == utils.DateTypeNYears {
-		for _, v := range mappingList {
-			if v.LatestDate != "" {
-				lastDateT, tErr := time.Parse(utils.FormatDate, v.LatestDate)
-				if tErr != nil {
+
+	// 有数据权限的话,获取图表的数据
+	if chartInfo.HaveOperaAuth {
+		mappingList := make([]*data_manage.ChartEdbInfoMapping, 0)
+		if chartInfoId > 0 {
+			mappingList, err = data_manage.GetChartEdbMappingList(chartInfoId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			if edbInfoId != "" {
+				mappingList, err = data_manage.GetChartEdbMappingListByEdbInfoId(edbInfoId)
+				if err != nil {
 					br.Msg = "获取失败"
-					br.ErrMsg = "获取图表日期信息失败,Err:" + tErr.Error()
+					br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
 					return
 				}
-				if lastDateT.Year() > yearMax {
-					yearMax = lastDateT.Year()
+				if isConvert == 1 && len(mappingList) > 0 {
+					for i, _ := range mappingList {
+						mappingList[i].IsConvert = 1
+						mappingList[i].ConvertType = convertType
+						mappingList[i].ConvertValue = convertValue
+						mappingList[i].ConvertUnit = convertUnit
+						mappingList[i].ConvertEnUnit = convertEnUnit
+					}
 				}
 			}
 		}
-	}
-	// 开始/结束日期
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
 
-	// 获取图表中的指标数据
-	edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartConvertEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
-	if err != nil {
-		br.Msg = "获取失败"
-		if errMsg != `` {
-			br.Msg = errMsg
-		}
-		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
-		return
-	}
-	// 单位
-	if chartType == utils.CHART_TYPE_BAR && len(yDataList) > 0 {
-		chartInfo.Unit = yDataList[0].Unit
-		chartInfo.UnitEn = yDataList[0].UnitEn
-	}
-	warnEdbList := make([]string, 0)
-	for _, v := range edbList {
-		if v.IsNullData {
-			warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
-		}
-	}
-	if len(warnEdbList) > 0 {
-		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
-	}
-	if chartInfoId > 0 && chartInfo != nil {
-		//判断是否加入我的图库
-		{
-			var myChartCondition string
-			var myChartPars []interface{}
-			myChartCondition += ` AND a.admin_id=? `
-			myChartPars = append(myChartPars, sysUser.AdminId)
-			myChartCondition += ` AND a.chart_info_id=? `
-			myChartPars = append(myChartPars, chartInfo.ChartInfoId)
-
-			myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				br.Msg = "获取失败"
-				br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+		// 图表额外数据参数
+		extraConfigStr := chartInfo.ExtraConfig
+		// 柱方图的一些配置
+		var barConfig data_manage.BarChartInfoReq
+		if chartInfo != nil && chartInfo.ChartType == 7 {
+			if chartInfo.BarConfig == `` {
+				br.Msg = "柱方图未配置"
+				br.ErrMsg = "柱方图未配置"
 				return
 			}
-			if myChartList != nil && len(myChartList) > 0 {
-				chartInfo.IsAdd = true
-				chartInfo.MyChartId = myChartList[0].MyChartId
-				chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+			err := json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
+			if err != nil {
+				br.Msg = "柱方图配置异常"
+				br.ErrMsg = "柱方图配置异常"
+				return
+			}
+			extraConfigStr = chartInfo.BarConfig
+		}
+		yearMax := 0
+		if dateType == utils.DateTypeNYears {
+			for _, v := range mappingList {
+				if v.LatestDate != "" {
+					lastDateT, tErr := time.Parse(utils.FormatDate, v.LatestDate)
+					if tErr != nil {
+						br.Msg = "获取失败"
+						br.ErrMsg = "获取图表日期信息失败,Err:" + tErr.Error()
+						return
+					}
+					if lastDateT.Year() > yearMax {
+						yearMax = lastDateT.Year()
+					}
+				}
 			}
 		}
-		if chartInfo.ChartType == 2 {
-			if chartInfo.SeasonStartDate != "" {
-				chartInfo.StartDate = chartInfo.SeasonStartDate
-				chartInfo.EndDate = chartInfo.SeasonEndDate
-				if chartInfo.DateType == 3 {
-					chartInfo.DateType = 5
+		// 开始/结束日期
+		startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)
+
+		// 获取图表中的指标数据
+		edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartConvertEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig)
+		if err != nil {
+			br.Msg = "获取失败"
+			if errMsg != `` {
+				br.Msg = errMsg
+			}
+			br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+			return
+		}
+		// 单位
+		if chartType == utils.CHART_TYPE_BAR && len(yDataList) > 0 {
+			chartInfo.Unit = yDataList[0].Unit
+			chartInfo.UnitEn = yDataList[0].UnitEn
+		}
+		warnEdbList := make([]string, 0)
+		for _, v := range edbList {
+			if v.IsNullData {
+				warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
+			}
+		}
+		if len(warnEdbList) > 0 {
+			chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
+		}
+		if chartInfoId > 0 && chartInfo != nil {
+			//判断是否加入我的图库
+			{
+				var myChartCondition string
+				var myChartPars []interface{}
+				myChartCondition += ` AND a.admin_id=? `
+				myChartPars = append(myChartPars, sysUser.AdminId)
+				myChartCondition += ` AND a.chart_info_id=? `
+				myChartPars = append(myChartPars, chartInfo.ChartInfoId)
+
+				myChartList, err := data_manage.GetMyChartByCondition(myChartCondition, myChartPars)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取我的图表信息失败,GetMyChartByCondition,Err:" + err.Error()
+					return
+				}
+				if myChartList != nil && len(myChartList) > 0 {
+					chartInfo.IsAdd = true
+					chartInfo.MyChartId = myChartList[0].MyChartId
+					chartInfo.MyChartClassifyId = myChartList[0].MyChartClassifyId
+				}
+			}
+			if chartInfo.ChartType == 2 {
+				if chartInfo.SeasonStartDate != "" {
+					chartInfo.StartDate = chartInfo.SeasonStartDate
+					chartInfo.EndDate = chartInfo.SeasonEndDate
+					if chartInfo.DateType == 3 {
+						chartInfo.DateType = 5
+					}
 				}
 			}
 		}
-	}
 
-	// 图表的指标来源
-	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
-	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
-	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+		// 图表的指标来源
+		sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+		chartInfo.ChartSource = strings.Join(sourceNameList, ",")
+		chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+		//判断是否需要展示英文标识
+		chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
 
-	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
-	//判断是否需要展示英文标识
-	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, chartInfo.Source, chartInfo.ChartType)
-	chartInfo.Button = data_manage.ChartViewButton{
-		IsEdit:    chartInfo.IsEdit,
-		IsEnChart: chartInfo.IsEnChart,
-		IsAdd:     chartInfo.IsAdd,
-		IsCopy:    true,
-		IsSetName: chartInfo.IsSetName,
+		resp.EdbInfoList = edbList
+		resp.XEdbIdValue = xEdbIdValue
+		resp.YDataList = yDataList
+		resp.DataResp = dataResp
+		resp.BarChartInfo = barConfig
 	}
 
-	resp := new(data_manage.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
-	resp.EdbInfoList = edbList
-	resp.XEdbIdValue = xEdbIdValue
-	resp.YDataList = yDataList
-	resp.BarChartInfo = barConfig
-	resp.DataResp = dataResp
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"

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

@@ -104,7 +104,7 @@ func (this *CorrelationChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap, this.SysUser.AdminId)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -475,7 +475,7 @@ func (this *CorrelationChartClassifyController) DeleteChartClassify() {
 			return
 		}
 		//图表操作权限
-		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 		if !ok {
 			br.Msg = "没有该图表的操作权限"
 			br.ErrMsg = "没有该图表的操作权限"

+ 132 - 2
controllers/data_manage/correlation/correlation_chart_info.go

@@ -9,6 +9,7 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
 	correlationServ "eta/eta_api/services/data/correlation"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -777,7 +778,7 @@ func (this *CorrelationChartInfoController) Detail() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList[0:1], chartInfo.Source, chartInfo.ChartType)
 	chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -800,6 +801,57 @@ func (this *CorrelationChartInfoController) Detail() {
 		IsSetName: chartInfo.IsSetName,
 	}
 
+	// 指标权限
+	{
+		edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		// 分类
+		{
+			classifyIdList := make([]int, 0)
+			for _, v := range edbList {
+				classifyIdList = append(classifyIdList, v.ClassifyId)
+			}
+			classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if tmpErr != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+				return
+			}
+			for _, v := range classifyList {
+				classifyMap[v.ClassifyId] = v
+			}
+		}
+
+		// 遍历到校验map
+		for _, v := range edbList {
+			edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+				ClassifyId:       v.ClassifyId,
+				IsJoinPermission: v.IsJoinPermission,
+				EdbInfoId:        v.EdbInfoId,
+			}
+		}
+
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range edbList {
+			// 数据权限
+			edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+			if !ok {
+				continue
+			}
+
+			if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+				v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+		}
+	}
+
 	resp := new(data_manage.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
 	resp.EdbInfoList = edbList
@@ -1127,6 +1179,73 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 
 	adminId := sysUser.AdminId
 
+	// 指标数据map
+	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+	defer func() {
+		if isOk {
+			resp.ChartInfo.HaveOperaAuth = true
+
+			// 指标权限
+			{
+				classifyMap := make(map[int]*data_manage.EdbClassify)
+				// 分类
+				{
+					classifyIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						classifyIdList = append(classifyIdList, v.ClassifyId)
+					}
+					classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+					if tmpErr != nil {
+						errMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range classifyList {
+						classifyMap[v.ClassifyId] = v
+					}
+				}
+
+				// 指标
+				if len(edbClassifyPermissionMap) < 0 {
+					edbInfoIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+					edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+					if tmpErr != nil {
+						errMsg = "获取指标列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range edbInfoList {
+						edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+							ClassifyId:       v.ClassifyId,
+							IsJoinPermission: v.IsJoinPermission,
+							EdbInfoId:        v.EdbInfoId,
+						}
+					}
+				}
+
+				// 获取所有有权限的指标和分类
+				permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+				if err != nil {
+					errMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+					return
+				}
+
+				for _, v := range resp.EdbInfoList {
+					// 数据权限
+					edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+						v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					}
+				}
+			}
+		}
+	}()
+
 	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
 	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
 	if utils.Re == nil && isCache {
@@ -1272,7 +1391,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList[0:1], chartInfo.Source, chartInfo.ChartType)
 	chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -1303,6 +1422,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	resp.DataResp = dataResp
 	resp.Status = true
 
+	// 遍历到校验map
+	for _, v := range edbList {
+		edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+			ClassifyId:       v.ClassifyId,
+			IsJoinPermission: v.IsJoinPermission,
+			EdbInfoId:        v.EdbInfoId,
+		}
+	}
+
 	// 将数据加入缓存
 	if utils.Re == nil {
 		d, _ := json.Marshal(resp)
@@ -1523,6 +1651,8 @@ func (this *CorrelationChartInfoController) SearchByEs() {
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
 			tmp.ChartInfo = *v
+			// 图表数据权限
+			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)

+ 137 - 3
controllers/data_manage/cross_variety/chart_info.go

@@ -11,6 +11,7 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
 	"eta/eta_api/services/data/cross_variety"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -578,7 +579,7 @@ func (c *ChartInfoController) Detail() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	////判断是否需要展示英文标识
 	//chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList[0:1], chartInfo.Source, chartInfo.ChartType)
 	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -592,6 +593,58 @@ func (c *ChartInfoController) Detail() {
 		IsSetName: chartInfo.IsSetName,
 	}
 
+	chartInfo.HaveOperaAuth = true
+	// 指标权限
+	{
+		edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		// 分类
+		{
+			classifyIdList := make([]int, 0)
+			for _, v := range edbList {
+				classifyIdList = append(classifyIdList, v.ClassifyId)
+			}
+			classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if tmpErr != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+				return
+			}
+			for _, v := range classifyList {
+				classifyMap[v.ClassifyId] = v
+			}
+		}
+
+		// 遍历到校验map
+		for _, v := range edbList {
+			edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+				ClassifyId:       v.ClassifyId,
+				IsJoinPermission: v.IsJoinPermission,
+				EdbInfoId:        v.EdbInfoId,
+			}
+		}
+
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range edbList {
+			// 数据权限
+			edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+			if !ok {
+				continue
+			}
+
+			if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+				v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+		}
+	}
+
 	resp := new(data_manage.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
 	resp.DataResp = dataResp
@@ -1221,7 +1274,7 @@ func (c *ChartInfoController) DeleteChart() {
 		return
 	}
 	//图表操作权限
-	ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	if !ok {
 		br.Msg = "没有该图表的操作权限"
 		br.ErrMsg = "没有该图表的操作权限"
@@ -1365,6 +1418,9 @@ func (c *ChartInfoController) SearchByEs() {
 	startSize = paging.StartIndex(currentIndex, pageSize)
 
 	keyword := c.GetString("Keyword")
+	if keyword == `` { // 兼容jp前端
+		keyword = c.GetString("KeyWord")
+	}
 
 	//只看我的
 	isShowMe, _ := c.GetBool("IsShowMe")
@@ -1429,6 +1485,8 @@ func (c *ChartInfoController) SearchByEs() {
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
 			tmp.ChartInfo = *v
+			// 图表数据权限
+			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if _, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, v.Source, v.ChartType)
@@ -1461,6 +1519,73 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 
 	adminId := sysUser.AdminId
 
+	// 指标数据map
+	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+	defer func() {
+		if isOk {
+			resp.ChartInfo.HaveOperaAuth = true
+
+			// 指标权限
+			{
+				classifyMap := make(map[int]*data_manage.EdbClassify)
+				// 分类
+				{
+					classifyIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						classifyIdList = append(classifyIdList, v.ClassifyId)
+					}
+					classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+					if tmpErr != nil {
+						errMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range classifyList {
+						classifyMap[v.ClassifyId] = v
+					}
+				}
+
+				// 指标
+				if len(edbClassifyPermissionMap) < 0 {
+					edbInfoIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+					edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+					if tmpErr != nil {
+						errMsg = "获取指标列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range edbInfoList {
+						edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+							ClassifyId:       v.ClassifyId,
+							IsJoinPermission: v.IsJoinPermission,
+							EdbInfoId:        v.EdbInfoId,
+						}
+					}
+				}
+
+				// 获取所有有权限的指标和分类
+				permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+				if err != nil {
+					errMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+					return
+				}
+
+				for _, v := range resp.EdbInfoList {
+					// 数据权限
+					edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+						v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					}
+				}
+			}
+		}
+	}()
+
 	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
 	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
 	if utils.Re == nil && isCache {
@@ -1553,7 +1678,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	//chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList[0:1], chartInfo.Source, chartInfo.ChartType)
 	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -1578,6 +1703,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	resp.EdbInfoList = edbList
 	resp.Status = true
 
+	// 遍历到校验map
+	for _, v := range edbList {
+		edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+			ClassifyId:       v.ClassifyId,
+			IsJoinPermission: v.IsJoinPermission,
+			EdbInfoId:        v.EdbInfoId,
+		}
+	}
+
 	// 将数据加入缓存
 	if utils.Re == nil {
 		d, _ := json.Marshal(resp)

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

@@ -95,7 +95,7 @@ func (c *ClassifyController) List() {
 	}
 
 	// 移除没有权限的图表
-	allNodes = data.HandleNoPermissionChart(allNodes, noPermissionChartIdMap)
+	allNodes = data.HandleNoPermissionChart(allNodes, noPermissionChartIdMap, c.SysUser.AdminId)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -315,7 +315,7 @@ func (c *ClassifyController) DeleteChartClassify() {
 			return
 		}
 		//图表操作权限
-		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 		if !ok {
 			br.Msg = "没有该图表的操作权限"
 			br.ErrMsg = "没有该图表的操作权限"

+ 394 - 0
controllers/data_manage/data_manage_permission/data_manage_permission.go

@@ -0,0 +1,394 @@
+package data_manage_permission
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	data_manage_permission2 "eta/eta_api/models/data_manage/data_manage_permission"
+	"eta/eta_api/services/data/data_manage_permission"
+	"eta/eta_api/utils"
+)
+
+// 资产的含义:指标/图表/表格
+
+// DataMangePermissionController 数据权限管理
+type DataMangePermissionController struct {
+	controllers.BaseAuthController
+}
+
+// SetEdbChartPermission
+// @Title 指标/图表/表格权限设置接口
+// @Description 指标/图表/表格权限设置接口
+// @Param	request	body data_manage.SetEdbChartPermissionReq true "type json string"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/permission/set [post]
+func (c *DataMangePermissionController) SetEdbChartPermission() {
+	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_permission2.SetEdbChartPermissionReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.Source <= 0 || req.Source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	if req.Source == 6 && (req.SubSource <= utils.EXCEL_DEFAULT || req.SubSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	if !req.IsSelectAll && len(req.DataIdList) <= 0 {
+		br.Msg = "请勾选数据项"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data_manage_permission.SetEdbChartPermission(req.Source, req.SubSource, req.UserId, req.UserList, req.IsSelectAll, req.DataIdList, req.NoDataIdList, req.Keyword, req.ClassifyId, sysUser.AdminId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "设置失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "设置失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.IsAddLog = true
+	br.Success = true
+	br.Msg = "设置成功"
+}
+
+// SetPermissionEdbChartClassifyIsPermission
+// @Title 指标/图表/表格分类是否涉密设置接口
+// @Description 指标/图表/表格分类是否涉密设置接口
+// @Param	request	body data_manage.MoveEdbChartReq true "type json string"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/classify/permission/is_permission/set [post]
+func (c *DataMangePermissionController) SetPermissionEdbChartClassifyIsPermission() {
+	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_permission2.SetDataIsPermissionReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.Source <= 0 || req.Source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	if req.Source == 6 && (req.SubSource <= utils.EXCEL_DEFAULT || req.SubSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data_manage_permission.SetDataClassifyIsPermission(req.Source, req.SubSource, req.ClassifyIdList, sysUser.AdminId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "设置失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "设置失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.IsAddLog = true
+	br.Success = true
+	br.Msg = "设置成功"
+}
+
+// SetEdbChartClassifyPermission
+// @Title 指标/图表/表格分类权限设置接口
+// @Description 指标/图表/表格分类权限设置接口
+// @Param	request	body data_manage.SetEdbChartClassifyPermissionReq true "type json string"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/classify/permission/set [post]
+func (c *DataMangePermissionController) SetEdbChartClassifyPermission() {
+	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_permission2.SetEdbChartClassifyPermissionReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.Source <= 0 || req.Source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	if req.Source == 6 && (req.SubSource <= utils.EXCEL_DEFAULT || req.SubSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	if len(req.UserList) <= 0 {
+		br.Msg = "请选择用户"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data_manage_permission.SetEdbChartClassifyPermission(req.Source, req.SubSource, req.UserList, req.ClassifyIdList, sysUser.AdminId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "设置失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "设置失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.IsAddLog = true
+	br.Success = true
+	br.Msg = "设置成功"
+}
+
+// GetEdbChartPermission
+// @Title 指标/图表/表格权限设置接口
+// @Description 指标/图表/表格权限设置接口
+// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格"
+// @Param   SubSource   query   int  false       "子来源 :目前作用于ETA表格,2024-3-26 14:12:09"
+// @Param   DataId   query   int  false       "资产id"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/permission/show_by_data [get]
+func (c *DataMangePermissionController) GetEdbChartPermission() {
+	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
+	}
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 || source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	subSource, _ := c.GetInt("SubSource")
+	if source == 6 && (subSource <= utils.EXCEL_DEFAULT || subSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	dataId, _ := c.GetInt("DataId")
+	// 用户判断
+	if dataId <= 0 {
+		br.Msg = "请选择数据"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取已经配置了的资产id列表
+	idList, err := data_manage_permission.GetUserIdListPermissionByDataId(source, subSource, dataId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = idList
+}
+
+// GetEdbChartClassifyPermission
+// @Title 获取指标/图表/表格分类权限设置接口
+// @Description 获取指标/图表/表格分类权限设置接口
+// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格"
+// @Param   SubSource   query   int  false       "子来源 :目前作用于ETA表格,2024-3-26 14:12:09"
+// @Param   UserId   query   int  false       "用户id"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/classify/permission/show_by_user [get]
+func (c *DataMangePermissionController) GetEdbChartClassifyPermission() {
+	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
+	}
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 || source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	subSource, _ := c.GetInt("SubSource")
+	if source == 6 && (subSource <= utils.EXCEL_DEFAULT || subSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	userId, _ := c.GetInt("UserId")
+
+	// 来源判断
+	if source <= 0 || source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	if source == 6 && (subSource <= utils.EXCEL_DEFAULT || subSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 用户判断
+	if userId <= 0 {
+		br.Msg = "请选择用户"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取已经配置了的分类id列表
+	idList, err := data_manage_permission.GetEdbChartClassifyIdListPermissionByUserId(source, subSource, userId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = idList
+}
+
+// GetEdbChartNoPermission
+// @Title 根据资产id获取其分类没有权限的用户id列表接口
+// @Description 根据资产id获取其分类没有权限的用户id列表接口
+// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格"
+// @Param   SubSource   query   int  false       "子来源 :目前作用于ETA表格,2024-3-26 14:12:09"
+// @Param   DataId   query   int  false       "资产id"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/no_classify_permission/show_by_data [get]
+func (c *DataMangePermissionController) GetEdbChartNoPermission() {
+	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
+	}
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 || source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	subSource, _ := c.GetInt("SubSource")
+	if source == 6 && (subSource <= utils.EXCEL_DEFAULT || subSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	dataId, _ := c.GetInt("DataId")
+
+	// 用户判断
+	if dataId <= 0 {
+		br.Msg = "请选择数据"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 获取已经配置了的资产id列表
+	idList, err := data_manage_permission.GetUserIdListNoPermissionByDataId(source, subSource, dataId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = idList
+}

+ 396 - 0
controllers/data_manage/data_manage_permission/data_move.go

@@ -0,0 +1,396 @@
+package data_manage_permission
+
+import (
+	"encoding/json"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	data_manage_permissionModel "eta/eta_api/models/data_manage/data_manage_permission"
+	"eta/eta_api/services/data/data_manage_permission"
+	"eta/eta_api/utils"
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+// EdbChartClassifyList
+// @Title 获取指标/图表分类列表数据接口
+// @Description 获取指标/图表分类列表数据接口
+// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格"
+// @Param   SubSource   query   int  false       "子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/classify [get]
+func (c *DataMangePermissionController) EdbChartClassifyList() {
+	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
+	}
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 || source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	subSource, _ := c.GetInt("SubSource")
+	if source == 6 && (subSource <= utils.EXCEL_DEFAULT || subSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	list, err := data_manage_permission.GetEdbChartClassifyList(source, subSource)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// SecretEdbChartClassifyList
+// @Title 获取涉密的指标/图表分类列表数据接口
+// @Description 获取指标/图表分类列表数据接口
+// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格"
+// @Param   SubSource   query   int  false       "子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/classify/secret [get]
+func (c *DataMangePermissionController) SecretEdbChartClassifyList() {
+	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
+	}
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 || source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	subSource, _ := c.GetInt("SubSource")
+	if source == 6 && (subSource <= utils.EXCEL_DEFAULT || subSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	resp, err := data_manage_permission.GetEdbChartClassifyList(source, subSource)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	resp.List = removeNodesWithNoJoinPermissionAndEmptyChildRecursively(resp.List)
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+func removeNodesWithNoJoinPermissionAndEmptyChildRecursively(nodes []*data_manage.EdbChartClassify) []*data_manage.EdbChartClassify {
+	var newListNode []*data_manage.EdbChartClassify
+
+	for _, node := range nodes {
+		if node.Child != nil {
+			node.Child = removeNodesWithNoJoinPermissionAndEmptyChildRecursively(node.Child)
+		}
+
+		if node.IsJoinPermission != 0 || (node.Child != nil && len(node.Child) > 0) {
+			newListNode = append(newListNode, node)
+		}
+	}
+
+	return newListNode
+}
+
+// MoveEdbChartList
+// @Title 获取指标/图表创建人列表数据接口
+// @Description 获取指标/图表创建人列表数据接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格"
+// @Param   SubSource   query   int  false       "子来源 :目前作用于ETA表格,2024-3-26 14:12:09"
+// @Param   Keyword   query   string  false       "关键字,code或者名称"
+// @Param   Classify   query   string  false       "分类id"
+// @Param   UserId   query   int  false       "创建人id"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/list [get]
+func (c *DataMangePermissionController) MoveEdbChartList() {
+	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
+	}
+
+	source, _ := c.GetInt("Source")
+	if source <= 0 || source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	subSource, _ := c.GetInt("SubSource")
+	if source == 6 && (subSource <= utils.EXCEL_DEFAULT || subSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	userId, _ := c.GetInt("UserId")
+	keyword := c.GetString("Keyword")
+	classify := c.GetString("Classify")
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+	resp := data_manage.MoveEdbChartListResp{}
+	var total int
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	defaultList := make([]data_manage.MoveEdbChartList, 0)
+	resp.List = defaultList
+	resp.Paging = page
+	// 没有传入条件,那就默认自动返回
+	//if userId <= 0 && keyword == `` && classify == `` {
+	//	br.Ret = 200
+	//	br.Success = true
+	//	br.Msg = "获取成功"
+	//	br.Data = resp
+	//	return
+	//}
+
+	list, total, err := data_manage_permission.GetMoveEdbChartList(source, subSource, userId, keyword, classify, startSize, pageSize)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if list == nil {
+		list = defaultList
+	}
+
+	page = paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.IsAddLog = false
+	br.Data = resp
+}
+
+// MoveEdbChartUser
+// @Title 指标/图表创建人变更接口
+// @Description 指标/图表创建人变更接口
+// @Param	request	body data_manage_permissionModel.MoveEdbChartReq true "type json string"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/change_user [post]
+func (c *DataMangePermissionController) MoveEdbChartUser() {
+	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_permissionModel.MoveEdbChartReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.Source <= 0 || req.Source > 6 {
+		br.Msg = "错误的来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	if req.Source == 6 && (req.SubSource <= utils.EXCEL_DEFAULT || req.SubSource > utils.CUSTOM_ANALYSIS_TABLE) {
+		br.Msg = "错误的子来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	if !req.IsSelectAll && len(req.DataIdList) <= 0 {
+		br.Msg = "请勾选数据项"
+		br.IsSendEmail = false
+		return
+	}
+	if req.NewUserId <= 0 {
+		br.Msg = "请选择新的创建人"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data_manage_permission.MoveEdbChart(req.Source, req.SubSource, req.UserId, req.NewUserId, req.IsSelectAll, req.DataIdList, req.NoDataIdList, req.Keyword, req.ClassifyId, sysUser.AdminId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "移动失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "移动失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.IsAddLog = true
+	br.Success = true
+	br.Msg = "修改成功"
+}
+
+// MoveAllEdbChartUser
+// @Title 通过原创建人转移指标/图表创建人接口
+// @Description 通过原创建人转移指标/图表创建人接口
+// @Param request body data_manage_permission.MoveAllEdbChartReq true "type json string"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/all/change_user [post]
+func (c *DataMangePermissionController) MoveAllEdbChartUser() {
+	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_permissionModel.MoveAllEdbChartReq
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if len(req.Source) <= 0 {
+		br.Msg = "请选择来源"
+		br.IsSendEmail = false
+		return
+	}
+
+	if len(req.OldUserId) <= 0 {
+		br.Msg = "请选择旧的创建人"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.NewUserId <= 0 {
+		br.Msg = "请选择新的创建人"
+		br.IsSendEmail = false
+		return
+	}
+
+	err, errMsg := data_manage_permission.MoveAllEdbChart(req.Source, req.OldUserId, req.NewUserId, sysUser.AdminId)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "移动失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "移动失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.IsAddLog = true
+	br.Success = true
+	br.Msg = "移动成功"
+}
+
+// MoveEdbChartCount
+// @Title 获取指标/图表创建人汇总数据接口
+// @Description 获取指标/图表创建人汇总数据接口
+// @Param   UserId   query   int  false       "创建人id"
+// @Param   CountType   query   int  false       "来源 :1:设置资产权限;2:设置数据权限"
+// @Success 200 {object} data_manage.ChartListResp
+// @router /edb_chart/count [get]
+func (c *DataMangePermissionController) MoveEdbChartCount() {
+	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
+	}
+
+	userId, _ := c.GetInt("UserId")
+	countType, _ := c.GetInt("CountType", 1)
+
+	// 没有传入条件,那就默认自动返回
+	if userId <= 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		//br.Data = resp
+		return
+	}
+
+	resp, err := data_manage_permission.GetMoveEdbChartCount(userId, countType)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 250 - 0
controllers/data_manage/data_manage_permission/message.go

@@ -0,0 +1,250 @@
+package data_manage_permission
+
+import (
+	"encoding/json"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage/data_manage_permission"
+	data_manage_permissionServ "eta/eta_api/services/data/data_manage_permission"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+// MessageList
+// @Title 资产消息列表
+// @Description 资产消息列表
+// @Param   PageSize			query	int		true	"每页数据条数"
+// @Param   CurrentIndex		query	int		true	"当前页页码"
+// @Success 200 {object} data_manage_permission.DataPermissionMessageListResp
+// @router /message/list [get]
+func (c *DataMangePermissionController) MessageList() {
+	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")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+
+	resp := new(data_manage_permission.DataPermissionMessageListResp)
+	resp.List = make([]*data_manage_permission.DataPermissionMessageItem, 0)
+	cond := fmt.Sprintf(` AND %s = ?`, data_manage_permission.DataPermissionMessageCols.ReceiveUserId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, sysUser.AdminId)
+	order := fmt.Sprintf(`%s ASC, %s DESC`, data_manage_permission.DataPermissionMessageCols.IsRead, data_manage_permission.DataPermissionMessageCols.CreateTime)
+
+	messageOb := new(data_manage_permission.DataPermissionMessage)
+	total, e := messageOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取资产消息列表总数失败, Err: " + e.Error()
+		return
+	}
+	list, e := messageOb.GetPageItemsByCondition(cond, pars, []string{}, order, startSize, pageSize)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取资产消息列表失败, Err: " + e.Error()
+		return
+	}
+	for _, v := range list {
+		t := data_manage_permission.FormatDataPermissionMessage2Item(v)
+		resp.List = append(resp.List, t)
+	}
+
+	// 未读消息数
+	cond += fmt.Sprintf(` AND %s = ?`, data_manage_permission.DataPermissionMessageCols.IsRead)
+	pars = append(pars, 0)
+	unreadTotal, e := messageOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取资产消息列表总数失败, Err: " + e.Error()
+		return
+	}
+	resp.UnreadTotal = unreadTotal
+
+	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 data_manage_permission.DataPermissionMessageReadReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /message/read [post]
+func (c *DataMangePermissionController) MessageRead() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req data_manage_permission.DataPermissionMessageReadReq
+	if e := json.Unmarshal(c.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
+	}
+
+	messageOb := new(data_manage_permission.DataPermissionMessage)
+	messageItem, e := messageOb.GetItemById(req.MessageId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "消息不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取审批消息失败, Err: " + e.Error()
+		return
+	}
+
+	// 不等于0的时候,说明已经操作过了,就不重复操作了
+	if messageItem.IsRead != 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "操作成功"
+		return
+	}
+
+	if messageItem.ReceiveUserId != int32(sysUser.AdminId) {
+		br.Msg = "标记已读失败,不是本人消息"
+		br.ErrMsg = "标记已读失败,不是本人消息 "
+		br.IsSendEmail = false
+		return
+	}
+	messageItem.IsRead = 1
+	messageItem.ModifyTime = time.Now().Local()
+	cols := []string{"IsRead", "ModifyTime"}
+	if e = messageItem.Update(cols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新消息已读失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// MessageDetail
+// @Title 资产消息详情
+// @Description 资产消息详情
+// @Param   MessageId			query	int		true	"消息ID"
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格"
+// @Param   SubSource   query   int  false       "子来源 :目前作用于ETA表格,2024-3-26 14:12:09"
+// @Success 200 {object} data_manage_permission.MessageDetailListResp
+// @router /message/detail [get]
+func (c *DataMangePermissionController) MessageDetail() {
+	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
+	}
+	messageId, _ := c.GetInt("MessageId", 0)
+	if messageId <= 0 {
+		br.Msg = "请选择消息"
+		br.ErrMsg = "请选择消息"
+		br.IsSendEmail = false
+		return
+	}
+	source, _ := c.GetInt("Source")
+	// 子来源(目前作用于ETA表格,2024-3-26 14:12:09)
+	subSource, _ := c.GetInt("SubSource")
+
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+	resp := data_manage_permission.MessageDetailListResp{}
+	var total int
+	page := paging.GetPaging(currentIndex, pageSize, total)
+
+	messageOb := new(data_manage_permission.DataPermissionMessage)
+	messageItem, e := messageOb.GetItemById(messageId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "消息不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取审批消息失败, Err: " + e.Error()
+		return
+	}
+
+	total, list, err := data_manage_permissionServ.GetMessageDetail(messageItem, source, subSource, startSize, pageSize)
+	if err != nil {
+		//br.Success = true
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	page = paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	resp.List = list
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.IsAddLog = false
+	br.Data = resp
+}

+ 168 - 41
controllers/data_manage/edb_classify.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
 	"sort"
 )
@@ -39,6 +40,19 @@ func (this *EdbClassifyController) ListV2() {
 		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(this.SysUser.AdminId, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+		return
+	}
 
 	// 获取当前账号的不可见指标
 	obj := data_manage.EdbInfoNoPermissionAdmin{}
@@ -59,19 +73,36 @@ func (this *EdbClassifyController) ListV2() {
 		return
 	}
 	edbInfoMap := make(map[int][]*data_manage.EdbClassifyItems)
-	for _, v := range allEdbInfo {
-		// 如果指标不可见,那么就不返回该指标
-		if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
-			continue
+	if len(allEdbInfo) > 0 {
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.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(this.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)
 		}
-		button := data.GetEdbOpButton(this.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE)
-		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 {
-		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
 		v.Button = button
 
@@ -85,7 +116,10 @@ func (this *EdbClassifyController) ListV2() {
 	}
 	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
 	for _, v := range rootList {
-		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 		v.Button = button
 
 		if existItems, ok := rootChildMap[v.ClassifyId]; ok {
@@ -620,6 +654,13 @@ func (this *EdbClassifyController) ItemsV2() {
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
+	// 已授权分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(this.SysUser.AdminId, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+		return
+	}
 	//allEdbInfo, err := data_manage.GetEdbInfoAll(0)
 	//if err != nil && err.Error() != utils.ErrNoRow() {
 	//	br.Msg = "获取失败"
@@ -635,7 +676,10 @@ func (this *EdbClassifyController) ItemsV2() {
 	//}
 	rootChildMap := make(map[int][]*data_manage.EdbClassifyItems)
 	for _, v := range classifyAll {
-		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
 		v.Button = button
 
@@ -649,7 +693,10 @@ func (this *EdbClassifyController) ItemsV2() {
 	}
 	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
 	for _, v := range rootList {
-		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 		v.Button = button
 
 		if existItems, ok := rootChildMap[v.ClassifyId]; ok {
@@ -711,6 +758,13 @@ func (this *EdbClassifyController) ClassifyEdbInfoList() {
 		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(this.SysUser.AdminId)
@@ -732,16 +786,27 @@ func (this *EdbClassifyController) ClassifyEdbInfoList() {
 	}
 
 	list := make([]*data_manage.EdbClassifyItems, 0)
-	for _, v := range allEdbInfo {
-		// 如果指标不可见,那么就不返回该指标
-		if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
-			continue
+
+	if len(allEdbInfo) > 0 {
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+			return
 		}
-		button := data.GetEdbOpButton(this.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE)
-		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
-		v.Button = button
+		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(this.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE, v.HaveOperaAuth)
+			button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+			v.Button = button
 
-		list = append(list, v)
+			list = append(list, v)
+		}
 	}
 
 	resp := new(data_manage.ClassifyEdbInfoListResp)
@@ -781,16 +846,30 @@ func (this *EdbClassifyController) ItemsV3() {
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
+	// 已授权分类id
+	permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(this.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 {
-		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(this.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 {
-		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 		v.Button = button
 		if v.Level == 3 {
 			rootTwoChildMap[v.ParentId] = append(rootTwoChildMap[v.ParentId], v)
@@ -799,18 +878,27 @@ func (this *EdbClassifyController) ItemsV3() {
 
 	nodeAll := make([]*data_manage.EdbClassifyItems, 0)
 	for _, v := range rootList {
-		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+		// 按钮权限
+		button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 		v.Button = button
 
 		if existItems, ok := rootTwoMap[v.ClassifyId]; ok {
 			v.Children = existItems
 			for _, item := range existItems {
-				button := data.GetEdbClassifyOpButton(this.SysUser, item.SysUserId)
+				// 数据权限
+				v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+				// 按钮权限
+				button := data.GetEdbClassifyOpButton(this.SysUser, item.SysUserId, v.HaveOperaAuth)
 				item.Button = button
 
 				if existItems, ok := rootTwoChildMap[item.ClassifyId]; ok {
 					for _, existItem := range existItems {
-						button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+						// 数据权限
+						v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+						// 按钮权限
+						button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 						button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
 						existItem.Button = button
 					}
@@ -839,11 +927,10 @@ func (this *EdbClassifyController) ItemsV3() {
 			}
 		}
 	}
-	// 是否允许添加一级分类
 
 	// 是否允许添加一级分类
 	canOpClassify := true
-	button := data.GetEdbClassifyOpButton(this.SysUser, 0)
+	button := data.GetEdbClassifyOpButton(this.SysUser, 0, true)
 	if !button.AddButton {
 		canOpClassify = false
 	}
@@ -909,22 +996,51 @@ func (this *EdbClassifyController) SimpleList() {
 			return
 		}
 
-		for _, v := range allEdbInfo {
-			// 如果指标不可见,那么就不返回该指标
-			if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
-				continue
+		if len(allEdbInfo) > 0 {
+			// 查询当前分类信息
+			currClassify, err := data_manage.GetEdbClassifyById(parentId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取当前分类信息失败,Err:" + err.Error()
+				return
+			}
+			// 获取所有有权限的指标和分类
+			permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.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, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+				button := data.GetEdbOpButton(this.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)
 			}
-			button := data.GetEdbOpButton(this.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE)
-			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(this.SysUser.AdminId, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
 		for _, v := range rootList {
-			button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+			// 数据权限
+			v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+			// 按钮权限
+			button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 			v.Button = button
 			v.Children = make([]*data_manage.EdbClassifyItems, 0)
 			nodeAll = append(nodeAll, v)
@@ -952,7 +1068,7 @@ func (this *EdbClassifyController) SimpleList() {
 
 	// 是否允许添加一级分类
 	canOpClassify := true
-	button := data.GetEdbClassifyOpButton(this.SysUser, 0)
+	button := data.GetEdbClassifyOpButton(this.SysUser, 0, true)
 	if !button.AddButton {
 		canOpClassify = false
 	}
@@ -989,8 +1105,19 @@ func (this *EdbClassifyController) ClassifyTree() {
 	var sortList data_manage.EdbClassifyItemList
 
 	if len(allList) > 0 {
+		// 已授权分类id
+		permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(this.SysUser.AdminId, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
 		for k, v := range allList {
-			button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId)
+			// 数据权限
+			v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+			// 按钮权限
+			button := data.GetEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 			allList[k].Button = button
 		}
 		nodeAll = data.GetClassifyTreeRecursive(allList, 0)
@@ -1014,7 +1141,7 @@ func (this *EdbClassifyController) ClassifyTree() {
 
 	// 是否允许添加一级分类
 	canOpClassify := true
-	button := data.GetEdbClassifyOpButton(this.SysUser, 0)
+	button := data.GetEdbClassifyOpButton(this.SysUser, 0, true)
 	if !button.AddButton {
 		canOpClassify = false
 	}

+ 477 - 306
controllers/data_manage/edb_info.go

@@ -12,6 +12,7 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/alarm_msg"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	excel2 "eta/eta_api/services/data/excel"
 	"eta/eta_api/services/data_stat"
 	"eta/eta_api/services/elastic"
@@ -2056,64 +2057,100 @@ func (this *EdbInfoController) EdbInfoList() {
 
 	//获取英文频度
 	edbInfoItem.FrequencyEn = data.GetFrequencyEn(edbInfoItem.Frequency)
-	//获取指标数据
-	var dataCondition string
-	var dataPars []interface{}
 
-	dataCondition += ` AND edb_info_id=? `
-	dataPars = append(dataPars, edbInfoItem.EdbInfoId)
+	//查询目录
+	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfoItem.ClassifyId)
+	if err != nil {
+		br.Msg = err.Error()
+		br.ErrMsg = errMsg
+		return
+	}
 
-	if edbInfoItem.SubSource == utils.DATA_SUB_SOURCE_DATE {
-		if edbInfoItem.Source == utils.DATA_SOURCE_WIND {
-			dataCount, err := data_manage.GetEdbWsdDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
-			if err != nil && err.Error() != utils.ErrNoRow() {
-				br.Msg = "获取指标信息失败"
-				br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
-				return
+	// 权限校验
+	{
+		var currClassify *data_manage.EdbClassifyIdItems
+		for _, v := range classifyList {
+			if edbInfoItem.ClassifyId == v.ClassifyId {
+				currClassify = v
+				break
 			}
-			page = paging.GetPaging(currentIndex, pageSize, dataCount)
-			dataList, err := data_manage.GetEdbWsdDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
+		}
+		if currClassify != nil {
+			edbInfoItem.HaveOperaAuth, err = data_manage_permission.CheckEdbPermission(edbInfoItem.IsJoinPermission, currClassify.IsJoinPermission, this.SysUser.AdminId, edbInfoItem.EdbInfoId, edbInfoItem.ClassifyId)
 			if err != nil {
-				br.Msg = "获取指标信息失败"
-				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+				br.Msg = err.Error()
+				br.ErrMsg = "校验指标权限失败,err:" + err.Error()
 				return
 			}
-			edbInfoItem.DataList = dataList
-		} else if edbInfoItem.Source == utils.DATA_SOURCE_THS {
-			dataCount, err := data_manage.GetTHsDsDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
+		}
+	}
+
+	// 按钮校验
+	button := data.GetEdbOpButton(this.SysUser, edbInfoItem.SysUserId, edbInfoItem.EdbType, edbInfoItem.EdbInfoType, edbInfoItem.HaveOperaAuth)
+	button.AddButton = false
+	edbInfoItem.Button = button
+	edbInfoItem.DataList = make([]*data_manage.EdbData, 0)
+
+	// 如果有数据权限,那么就去获取指标数据
+	if edbInfoItem.HaveOperaAuth {
+		var dataCondition string
+		var dataPars []interface{}
+
+		dataCondition += ` AND edb_info_id=? `
+		dataPars = append(dataPars, edbInfoItem.EdbInfoId)
+
+		if edbInfoItem.SubSource == utils.DATA_SUB_SOURCE_DATE {
+			if edbInfoItem.Source == utils.DATA_SOURCE_WIND {
+				dataCount, err := data_manage.GetEdbWsdDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取指标信息失败"
+					br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+					return
+				}
+				page = paging.GetPaging(currentIndex, pageSize, dataCount)
+				dataList, err := data_manage.GetEdbWsdDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
+				if err != nil {
+					br.Msg = "获取指标信息失败"
+					br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+					return
+				}
+				edbInfoItem.DataList = dataList
+			} else if edbInfoItem.Source == utils.DATA_SOURCE_THS {
+				dataCount, err := data_manage.GetTHsDsDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取指标信息失败"
+					br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
+					return
+				}
+				page = paging.GetPaging(currentIndex, pageSize, dataCount)
+				dataList, err := data_manage.GetThsDsDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
+				if err != nil {
+					br.Msg = "获取指标信息失败"
+					br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
+					return
+				}
+				edbInfoItem.DataList = dataList
+			} else {
+				br.Msg = "指标数据源id错误"
+				br.ErrMsg = "指标数据源id错误"
+				return
+			}
+		} else {
+			dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource)
 			if err != nil && err.Error() != utils.ErrNoRow() {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
 				return
 			}
 			page = paging.GetPaging(currentIndex, pageSize, dataCount)
-			dataList, err := data_manage.GetThsDsDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, pageSize, startSize)
+			dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource, pageSize, startSize)
 			if err != nil {
 				br.Msg = "获取指标信息失败"
 				br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
 				return
 			}
 			edbInfoItem.DataList = dataList
-		} else {
-			br.Msg = "指标数据源id错误"
-			br.ErrMsg = "指标数据源id错误"
-			return
-		}
-	} else {
-		dataCount, err := data_manage.GetEdbDataCountByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource)
-		if err != nil && err.Error() != utils.ErrNoRow() {
-			br.Msg = "获取指标信息失败"
-			br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
-			return
 		}
-		page = paging.GetPaging(currentIndex, pageSize, dataCount)
-		dataList, err := data_manage.GetEdbDataListByCondition(dataCondition, dataPars, edbInfoItem.Source, edbInfoItem.SubSource, pageSize, startSize)
-		if err != nil {
-			br.Msg = "获取指标信息失败"
-			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
-			return
-		}
-		edbInfoItem.DataList = dataList
 	}
 
 	// 获取指标插入配置
@@ -2131,20 +2168,8 @@ func (this *EdbInfoController) EdbInfoList() {
 		}
 	}
 
-	// 按钮校验
-	button := data.GetEdbOpButton(this.SysUser, edbInfoItem.SysUserId, edbInfoItem.EdbType, edbInfoItem.EdbInfoType)
-	button.AddButton = false
-	edbInfoItem.Button = button
-
 	//是否展示英文标识
 	edbInfoItem.IsEnEdb = data.CheckIsEnEdb(edbInfoItem.EdbNameEn, edbInfoItem.Unit, edbInfoItem.UnitEn)
-	//查询目录
-	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfoItem.ClassifyId)
-	if err != nil {
-		br.Msg = err.Error()
-		br.ErrMsg = errMsg
-		return
-	}
 
 	resp.Paging = page
 	resp.Item = edbInfoItem
@@ -2377,8 +2402,19 @@ func (this *EdbInfoController) EdbInfoEdit() {
 		return
 	}
 
+	var haveOperaAuth bool
+	// 权限校验
+	{
+		haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.EdbInfoId, edbInfo.ClassifyId, edbInfo.IsJoinPermission, this.SysUser.AdminId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+	}
+
 	// 编辑权限校验
-	button := data.GetEdbOpButton(this.SysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType)
+	button := data.GetEdbOpButton(this.SysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType, haveOperaAuth)
 	if !button.OpButton {
 		br.Msg = "无权限操作"
 		br.IsSendEmail = false
@@ -2713,8 +2749,19 @@ func (this *EdbInfoController) EdbInfoMove() {
 		return
 	}
 
+	var haveOperaAuth bool
+	// 权限校验
+	{
+		haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.IsJoinPermission, edbInfo.EdbInfoId, edbInfo.ClassifyId, this.SysUser.AdminId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+	}
+
 	// 移动权限校验
-	button := data.GetEdbOpButton(this.SysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType)
+	button := data.GetEdbOpButton(this.SysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType, haveOperaAuth)
 	if !button.MoveButton {
 		br.Msg = "无权限操作"
 		br.IsSendEmail = false
@@ -2862,6 +2909,24 @@ func (this *EdbInfoController) EdbInfoDetail() {
 		br.ErrMsg = errMsg
 		return
 	}
+
+	// 权限校验
+	{
+		classifyMap := make(map[int]*data_manage.EdbClassifyIdItems)
+		for _, v := range classifyList {
+			classifyMap[v.ClassifyId] = v
+		}
+		if currClassify, ok := classifyMap[edbInfo.ClassifyId]; ok {
+			haveOperaAuth, err := data_manage_permission.CheckEdbPermission(edbInfo.IsJoinPermission, currClassify.IsJoinPermission, this.SysUser.AdminId, edbInfo.EdbInfoId, edbInfo.ClassifyId)
+			if err != nil {
+				br.Msg = err.Error()
+				br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+				return
+			}
+			resp.HaveOperaAuth = haveOperaAuth
+		}
+	}
+
 	resp.EdbInfo = edbInfo
 	resp.ClassifyList = classifyList
 
@@ -3071,6 +3136,8 @@ func (this *EdbInfoController) EdbInfoFilterByEs() {
 		}
 	}
 
+	// 是否走ES
+	isEs := false
 	if keyWord != "" {
 		var keyWordArr []string
 		keyWordArr = append(keyWordArr, keyWord)
@@ -3085,6 +3152,7 @@ func (this *EdbInfoController) EdbInfoFilterByEs() {
 			// 允许添加预测指标的搜索
 			total, edbInfoList, err = elastic.SearchAddPredictEdbInfoData(utils.DATA_INDEX_NAME, keyWord, noPermissionEdbInfoIdList, startSize, pageSize)
 		}
+		isEs = true
 	} else {
 		var condition string
 		var pars []interface{}
@@ -3134,8 +3202,72 @@ func (this *EdbInfoController) EdbInfoFilterByEs() {
 
 	edbInfoListLen := len(edbInfoList)
 
+	classifyIdList := make([]int, 0)
 	for i := 0; i < edbInfoListLen; i++ {
 		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的话,需要重新查一下指标的信息,主要是为了把是否授权字段找出来
+		if isEs {
+			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++ {
@@ -3365,6 +3497,11 @@ func (this *ChartInfoController) EdbInfoData() {
 		br.Ret = 408
 		return
 	}
+
+	fullEdb := new(data_manage.EdbInfoFullClassify)
+	resp := new(data_manage.EdbInfoDataFullClassifyResp)
+	dataList := make([]*data_manage.EdbDataList, 0)
+
 	edbInfoId, _ := this.GetInt("EdbInfoId")
 	if edbInfoId <= 0 {
 		br.Msg = "参数错误"
@@ -3394,21 +3531,8 @@ func (this *ChartInfoController) EdbInfoData() {
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-	maxYear := 0
-	if edbInfo.LatestDate != "" {
-		latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
-		maxYear = latestDateT.Year()
-	}
-	dataList := make([]*data_manage.EdbDataList, 0)
-	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
-	dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfoId, startDate, endDate)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-	fullEdb := new(data_manage.EdbInfoFullClassify)
-	resp := new(data_manage.EdbInfoDataFullClassifyResp)
+
+	// 分类
 	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfo.ClassifyId)
 	if err != nil {
 		br.Msg = err.Error()
@@ -3417,8 +3541,42 @@ func (this *ChartInfoController) EdbInfoData() {
 	}
 	fullEdb.EdbInfo = edbInfo
 	fullEdb.ClassifyList = classifyList
+
+	var currClassifyItem *data_manage.EdbClassifyIdItems
+	for _, v := range classifyList {
+		if v.ClassifyId == edbInfo.ClassifyId {
+			currClassifyItem = v
+		}
+	}
+	if currClassifyItem != nil {
+		haveOperaAuth, err := data_manage_permission.CheckEdbPermission(edbInfo.IsJoinPermission, currClassifyItem.IsJoinPermission, sysUser.AdminId, edbInfo.EdbInfoId, edbInfo.ClassifyId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+		fullEdb.HaveOperaAuth = haveOperaAuth
+	}
 	resp.EdbInfo = fullEdb
-	resp.DataList = dataList
+
+	resp.DataList = make([]*data_manage.EdbDataList, 0)
+	// 数据获取
+	if fullEdb.HaveOperaAuth { // 有权限才获取数据
+		maxYear := 0
+		if edbInfo.LatestDate != "" {
+			latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
+			maxYear = latestDateT.Year()
+		}
+		startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
+		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfoId, startDate, endDate)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+
+		resp.DataList = dataList
+	}
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -3691,11 +3849,44 @@ func (this *EdbInfoController) RelationChartList() {
 		myChartMap[v.ChartInfoId] = v
 	}
 	listLen := len(list)
-	for i := 0; i < listLen; i++ {
-		if existItem, ok := myChartMap[list[i].ChartInfoId]; ok {
-			list[i].IsAdd = true
-			list[i].MyChartId = existItem.MyChartId
-			list[i].MyChartClassifyId = existItem.MyChartClassifyId
+
+	if listLen > 0 {
+		// 分类id
+		classifyIdList := make([]int, 0)
+		// 当前列表中的分类map
+		classifyMap := make(map[int]*data_manage.ChartClassify)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+		}
+		classifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range classifyList {
+			classifyMap[v.ChartClassifyId] = v
+		}
+
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range list {
+			if existItem, ok := myChartMap[v.ChartInfoId]; ok {
+				v.IsAdd = true
+				v.MyChartId = existItem.MyChartId
+				v.MyChartClassifyId = existItem.MyChartClassifyId
+			}
+			// 权限
+			if currClassify, ok := classifyMap[v.ChartClassifyId]; ok {
+				v.HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.ChartInfoId, v.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
 		}
 	}
 
@@ -3823,55 +4014,96 @@ func (this *EdbInfoController) RelationEdbList() {
 	}
 
 	edbList := make([]*data_manage.ChartEdbInfoMapping, 0)
-	for _, v := range list {
-		item := new(data_manage.ChartEdbInfoMapping)
-		item.EdbInfoId = v.EdbInfoId
-		item.SourceName = v.SourceName
-		item.Source = v.Source
-		item.EdbCode = v.EdbCode
-		item.EdbName = v.EdbName
-		item.EdbNameEn = v.EdbNameEn
-		item.Frequency = v.Frequency
-		item.FrequencyEn = data.GetFrequencyEn(v.Frequency)
-		if v.Unit != `无` {
-			item.Unit = v.Unit
-		}
-		item.UnitEn = v.UnitEn
-		item.StartDate = v.StartDate
-		item.EndDate = v.EndDate
-		item.ModifyTime = v.ModifyTime
-		item.IsAxis = 1
-		item.LeadValue = 0
-		item.LeadUnit = ""
-		item.ChartEdbMappingId = 0
-		item.ChartInfoId = 0
-		item.IsOrder = false
-		item.EdbInfoType = v.EdbInfoType
-		item.EdbInfoCategoryType = v.EdbInfoType
-		item.ChartStyle = ""
-		item.ChartColor = ""
-		item.ChartWidth = 0
-		item.MaxData = v.MaxValue
-		item.MinData = v.MinValue
-		item.LatestValue = v.LatestValue
-		item.LatestDate = v.LatestDate
-		item.UniqueCode = v.UniqueCode
-		item.ClassifyId = v.ClassifyId
-
-		dataList := make([]*data_manage.EdbDataList, 0)
-		if v.EdbInfoType == 0 {
-			dataList, err = data_manage.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, "", "")
-		} else {
-			_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, "", "", false)
+
+	if len(list) > 0 {
+
+		// 当前的分类
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		{
+			classifyIdList := make([]int, 0)
+			for _, v := range list {
+				classifyIdList = append(classifyIdList, v.ClassifyId)
+			}
+			classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if err != nil {
+				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.Msg = "获取失败,Err:" + err.Error()
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
 			return
 		}
 
-		item.DataList = dataList
-		edbList = append(edbList, item)
+		for _, v := range list {
+			item := new(data_manage.ChartEdbInfoMapping)
+			item.EdbInfoId = v.EdbInfoId
+			item.SourceName = v.SourceName
+			item.Source = v.Source
+			item.EdbCode = v.EdbCode
+			item.EdbName = v.EdbName
+			item.EdbNameEn = v.EdbNameEn
+			item.Frequency = v.Frequency
+			item.FrequencyEn = data.GetFrequencyEn(v.Frequency)
+			if v.Unit != `无` {
+				item.Unit = v.Unit
+			}
+			item.UnitEn = v.UnitEn
+			item.StartDate = v.StartDate
+			item.EndDate = v.EndDate
+			item.ModifyTime = v.ModifyTime
+			item.IsAxis = 1
+			item.LeadValue = 0
+			item.LeadUnit = ""
+			item.ChartEdbMappingId = 0
+			item.ChartInfoId = 0
+			item.IsOrder = false
+			item.EdbInfoType = v.EdbInfoType
+			item.EdbInfoCategoryType = v.EdbInfoType
+			item.ChartStyle = ""
+			item.ChartColor = ""
+			item.ChartWidth = 0
+			item.MaxData = v.MaxValue
+			item.MinData = v.MinValue
+			item.LatestValue = v.LatestValue
+			item.LatestDate = v.LatestDate
+			item.UniqueCode = v.UniqueCode
+			item.ClassifyId = v.ClassifyId
+
+			dataList := make([]*data_manage.EdbDataList, 0)
+			// 指标权限
+			if currClassify, ok := classifyMap[v.ClassifyId]; ok {
+				item.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+
+			// 有权限则获取数据
+			if item.HaveOperaAuth {
+				if v.EdbInfoType == 0 {
+					dataList, err = data_manage.GetEdbDataList(v.Source, v.SubSource, v.EdbInfoId, "", "")
+				} else {
+					_, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(v.EdbInfoId, "", "", false)
+				}
+				if err != nil {
+					br.Msg = "获取失败"
+					br.Msg = "获取失败,Err:" + err.Error()
+					return
+				}
+			}
+
+			item.DataList = dataList
+			edbList = append(edbList, item)
+		}
 	}
 
 	page = paging.GetPaging(currentIndex, pageSize, dataCount)
@@ -3883,192 +4115,6 @@ func (this *EdbInfoController) RelationEdbList() {
 	br.Data = resp
 }
 
-// MoveEdbChartList
-// @Title 获取指标/图表创建人列表数据接口
-// @Description 获取指标/图表创建人列表数据接口
-// @Param   PageSize   query   int  true       "每页数据条数"
-// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
-// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库"
-// @Param   Keyword   query   string  false       "关键字,code或者名称"
-// @Param   Classify   query   string  false       "分类id"
-// @Param   UserId   query   int  false       "创建人id"
-// @Success 200 {object} data_manage.ChartListResp
-// @router /edb_chart/list [get]
-func (this *EdbInfoController) MoveEdbChartList() {
-	br := new(models.BaseResponse).Init()
-	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
-	}()
-	sysUser := this.SysUser
-	if sysUser == nil {
-		br.Msg = "请登录"
-		br.ErrMsg = "请登录,SysUser Is Empty"
-		br.Ret = 408
-		return
-	}
-
-	source, _ := this.GetInt("Source")
-	if source <= 0 || source > 5 {
-		br.Msg = "错误的来源"
-		br.IsSendEmail = false
-		return
-	}
-
-	userId, _ := this.GetInt("UserId")
-	keyword := this.GetString("Keyword")
-	classify := this.GetString("Classify")
-	pageSize, _ := this.GetInt("PageSize")
-	currentIndex, _ := this.GetInt("CurrentIndex")
-
-	var startSize int
-	if pageSize <= 0 {
-		pageSize = utils.PageSize20
-	}
-	if currentIndex <= 0 {
-		currentIndex = 1
-	}
-	startSize = paging.StartIndex(currentIndex, pageSize)
-	resp := data_manage.MoveEdbChartListResp{}
-	var total int
-	page := paging.GetPaging(currentIndex, pageSize, total)
-	defaultList := make([]data_manage.MoveEdbChartList, 0)
-	resp.List = defaultList
-	resp.Paging = page
-	// 没有传入条件,那就默认自动返回
-	if userId <= 0 && keyword == `` && classify == `` {
-		br.Ret = 200
-		br.Success = true
-		br.Msg = "获取成功"
-		br.Data = resp
-		return
-	}
-
-	list, total, err := data.GetMoveEdbChartList(source, userId, keyword, classify, startSize, pageSize)
-	if err != nil {
-		//br.Success = true
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-	if list == nil {
-		list = defaultList
-	}
-
-	page = paging.GetPaging(currentIndex, pageSize, total)
-	resp.Paging = page
-	resp.List = list
-	br.Ret = 200
-	br.Success = true
-	br.Msg = "获取成功"
-	br.Data = resp
-}
-
-// MoveEdbChartUser
-// @Title 指标/图表创建人变更接口
-// @Description 指标/图表创建人变更接口
-// @Param   PageSize   query   int  true       "每页数据条数"
-// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
-// @Param   EdbInfoId   query   int  true       "指标id"
-// @Param   IsShowMe   query   bool  true       "是否只看我的,true、false"
-// @Success 200 {object} data_manage.ChartListResp
-// @router /edb_chart/change_user [post]
-func (this *EdbInfoController) MoveEdbChartUser() {
-	br := new(models.BaseResponse).Init()
-	defer func() {
-		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 data_manage.MoveEdbChartReq
-	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
-	if err != nil {
-		br.Msg = "参数解析异常!"
-		br.ErrMsg = "参数解析失败,Err:" + err.Error()
-		return
-	}
-
-	if req.Source <= 0 || req.Source > 5 {
-		br.Msg = "错误的来源"
-		br.IsSendEmail = false
-		return
-	}
-
-	if len(req.DataIdList) <= 0 {
-		br.Msg = "请勾选数据项"
-		br.IsSendEmail = false
-		return
-	}
-	if req.NewUserId <= 0 {
-		br.Msg = "请选择新的创建人"
-		br.IsSendEmail = false
-		return
-	}
-
-	err, errMsg := data.MoveEdbChart(req.Source, req.NewUserId, req.DataIdList)
-	if err != nil {
-		//br.Success = true
-		br.Msg = "获取失败"
-		if errMsg != `` {
-			br.Msg = errMsg
-		}
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-	br.Ret = 200
-	br.IsAddLog = true
-	br.Success = true
-	br.Msg = "修改成功"
-}
-
-// EdbChartClassifyList
-// @Title 获取指标/图表分类列表数据接口
-// @Description 获取指标/图表分类列表数据接口
-// @Param   Source   query   int  false       "来源 :1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库"
-// @Success 200 {object} data_manage.ChartListResp
-// @router /edb_chart/classify [get]
-func (this *EdbInfoController) EdbChartClassifyList() {
-	br := new(models.BaseResponse).Init()
-	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
-	}()
-	sysUser := this.SysUser
-	if sysUser == nil {
-		br.Msg = "请登录"
-		br.ErrMsg = "请登录,SysUser Is Empty"
-		br.Ret = 408
-		return
-	}
-
-	source, _ := this.GetInt("Source")
-	if source <= 0 || source > 5 {
-		br.Msg = "错误的来源"
-		br.IsSendEmail = false
-		return
-	}
-
-	list, err := data.GetEdbChartClassifyList(source)
-	if err != nil {
-		//br.Success = true
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-
-	br.Ret = 200
-	br.Success = true
-	br.Msg = "获取成功"
-	br.Data = list
-}
-
 // EdbInfoDataTb
 // @Title 获取指标数据同比值
 // @Description 获取指标数据
@@ -4368,7 +4414,7 @@ func (this *EdbInfoController) TraceEdbInfo() {
 		return
 	}
 
-	resp, err := data.TraceEdbInfoByEdbInfoId(edbInfo.EdbInfoId)
+	resp, err := data.TraceEdbInfoByEdbInfoId(edbInfo.EdbInfoId, this.SysUser.AdminId)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.Msg = "获取失败,Err:" + err.Error()
@@ -4443,6 +4489,8 @@ func (this *EdbInfoController) AllEdbInfoByEs() {
 		}
 	}
 
+	// 是否走ES
+	isEs := false
 	if keyWord != "" {
 		var keyWordArr []string
 		keyWordArr = append(keyWordArr, keyWord)
@@ -4452,6 +4500,7 @@ func (this *EdbInfoController) AllEdbInfoByEs() {
 
 		// 普通的搜索
 		total, edbInfoList, err = elastic.SearchEdbInfoData(utils.DATA_INDEX_NAME, keyWord, startSize, pageSize, filterSource, source, -1, frequency, noPermissionEdbInfoIdList)
+		isEs = true
 	} else {
 		var condition string
 		var pars []interface{}
@@ -4501,8 +4550,73 @@ func (this *EdbInfoController) AllEdbInfoByEs() {
 
 	edbInfoListLen := len(edbInfoList)
 
+	classifyIdList := make([]int, 0)
 	for i := 0; i < edbInfoListLen; i++ {
 		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的话,需要重新查一下指标的信息,主要是为了把是否授权字段找出来
+		if isEs {
+			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++ {
@@ -5025,9 +5139,45 @@ func (this *EdbInfoController) EdbChartList() {
 	if len(list) == 0 {
 		list = make([]*data_manage.EdbInfoList, 0)
 	} else {
+		classifyIdList := make([]int, 0)
 		for _, v := range list {
-			v.Button = data.GetEdbOpButton(sysUser, v.SysUserId, v.EdbType, v.EdbInfoType)
+			classifyIdList = append(classifyIdList, v.ClassifyId)
+		}
+
+		// 指标权限
+		{
+			// 当前的分类
+			classifyMap := make(map[int]*data_manage.EdbClassify)
+			classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if err != nil {
+				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
+			}
+
+			for _, v := range list {
+				if currClassify, ok := classifyMap[v.ClassifyId]; ok {
+					v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+
+					v.Button = data.GetEdbOpButton(sysUser, v.SysUserId, v.EdbType, v.EdbInfoType, v.HaveOperaAuth)
+				}
+			}
 		}
+
 		page = paging.GetPaging(currentIndex, pageSize, int(dataCount))
 	}
 
@@ -5083,8 +5233,20 @@ func (this *EdbInfoController) Modify() {
 		br.ErrMsg = "获取指标信息失败, Err:" + err.Error()
 		return
 	}
+
+	var haveOperaAuth bool
+	// 权限校验
+	{
+		haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.EdbInfoId, edbInfo.ClassifyId, edbInfo.IsJoinPermission, this.SysUser.AdminId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+	}
+
 	// 编辑权限校验
-	button := data.GetEdbOpButton(this.SysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType)
+	button := data.GetEdbOpButton(this.SysUser, edbInfo.SysUserId, edbInfo.EdbType, edbInfo.EdbInfoType, haveOperaAuth)
 	if !button.OpButton {
 		br.Msg = "无权限操作"
 		return
@@ -5372,6 +5534,13 @@ func (this *EdbInfoController) EdbInfoBatchAdd() {
 			return
 		}
 
+		terminalCode, serverUrl, _, e := data.GetEdbTerminalCodeBySource(v.Source, v.EdbCode, v.StockCode)
+		if e != nil {
+			br.Msg = "获取可以使用的终端地址失败"
+			br.ErrMsg = "获取可以使用的终端地址失败,Err:" + e.Error()
+			return
+		}
+
 		edbInfoItem := new(data_manage.EdbInfo)
 		edbInfoItem.Source = v.Source
 		switch v.Source {
@@ -5392,6 +5561,8 @@ func (this *EdbInfoController) EdbInfoBatchAdd() {
 		edbInfoItem.SysUserRealName = sysUser.RealName
 		edbInfoItem.IndicatorCode = v.EdbCode
 		edbInfoItem.StockCode = v.StockCode
+		edbInfoItem.TerminalCode = terminalCode
+		edbInfoItem.ServerUrl = serverUrl
 
 		// 指标入库
 		edbInfo, err, errMsg, isSendEmail := data.EdbInfoWsdAdd(edbInfoItem)

+ 98 - 14
controllers/data_manage/edb_info_calculate.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_api/models"
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -236,11 +237,28 @@ func (this *ChartInfoController) CalculateDetail() {
 		br.ErrMsg = errMsg
 		return
 	}
+
 	fullEdb.EdbInfo = edbInfo
 	fullEdb.ClassifyList = classifyList
 
+	var currClassifyItem *data_manage.EdbClassifyIdItems
+	for _, v := range classifyList {
+		if v.ClassifyId == edbInfo.ClassifyId {
+			currClassifyItem = v
+		}
+	}
+	if currClassifyItem != nil {
+		haveOperaAuth, err := data_manage_permission.CheckEdbPermission(edbInfo.IsJoinPermission, currClassifyItem.IsJoinPermission, sysUser.AdminId, edbInfo.EdbInfoId, edbInfo.ClassifyId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+		fullEdb.HaveOperaAuth = haveOperaAuth
+	}
+
 	// 拟合残差计算相关系数
-	if edbInfo.Source == utils.DATA_SOURCE_CALCULATE_NHCC {
+	if fullEdb.HaveOperaAuth && edbInfo.Source == utils.DATA_SOURCE_CALCULATE_NHCC {
 		var aEdbInfo, bEdbInfo *data_manage.EdbInfoCalculateDetail
 		for _, v := range calculateList {
 			if v.FromTag == "A" {
@@ -2197,15 +2215,50 @@ func (this *ChartInfoController) CalculateMultiChoice() {
 
 	resp := new(data_manage.CalculateMultiChoiceResp)
 
-	for _, info := range list {
-		searchItem := data_manage.EdbInfoBase{
-			Frequency:  info.Frequency,
-			Unit:       info.Unit,
-			EdbName:    info.EdbName,
-			EdbInfoId:  info.EdbInfoId,
-			ClassifyId: info.ClassifyId,
+	if len(list) > 0 {
+		// 当前列表中的分类map
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		{
+			classifyIdList := make([]int, 0)
+			for _, info := range list {
+				classifyIdList = append(classifyIdList, info.ClassifyId)
+			}
+			classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if err != nil {
+				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
+		}
+		for _, info := range list {
+			var haveOperaAuth bool
+			if currClassify, ok := classifyMap[info.ClassifyId]; ok {
+				haveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(info.IsJoinPermission, currClassify.IsJoinPermission, info.EdbInfoId, info.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+			searchItem := data_manage.EdbInfoBase{
+				Frequency:     info.Frequency,
+				Unit:          info.Unit,
+				EdbName:       info.EdbName,
+				EdbInfoId:     info.EdbInfoId,
+				ClassifyId:    info.ClassifyId,
+				HaveOperaAuth: haveOperaAuth,
+			}
+			searchItemList = append(searchItemList, searchItem)
 		}
-		searchItemList = append(searchItemList, searchItem)
 	}
 
 	resp.SearchItem = searchItemList
@@ -2300,18 +2353,44 @@ func (this *ChartInfoController) CalculateMultiSearch() {
 	page := paging.GetPaging(currentIndex, pageSize, total)
 	resp := new(data_manage.CalculateMultiEdbSearchResp)
 
-	edbList, e := data_manage.GetEdbInfoListByCondition(condition, pars, startSize, pageSize)
+	edbList, e := data_manage.GetEdbInfoListByCondition(condition, pars, startSize, pageSize, "")
 	if e != nil {
 		br.Msg = "获取指标列表失败"
 		br.ErrMsg = "获取指标列表失败,Err:" + e.Error()
 		return
 	}
 
-	for _, v := range edbList {
-		edbIdArr = append(edbIdArr, v.EdbInfoId)
-	}
+	if len(edbList) > 0 {
+		classifyIdList := make([]int, 0)
+		for _, v := range edbList {
+			edbIdArr = append(edbIdArr, v.EdbInfoId)
+			classifyIdList = append(classifyIdList, v.ClassifyId)
+		}
+
+		// 当前列表中的分类map
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		{
+			classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if err != nil {
+				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
+		}
 
-	if len(edbIdArr) > 0 {
 		list, err := data_manage.GetEdbInfoByIdList(edbIdArr)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取指标列表失败"
@@ -2319,6 +2398,10 @@ func (this *ChartInfoController) CalculateMultiSearch() {
 			return
 		}
 		for _, info := range list {
+			var haveOperaAuth bool
+			if currClassify, ok := classifyMap[info.ClassifyId]; ok {
+				haveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(info.IsJoinPermission, currClassify.IsJoinPermission, info.EdbInfoId, info.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
 			searchItem := data_manage.CalculateMultiEdbSearchItem{
 				Frequency:       info.Frequency,
 				Unit:            info.Unit,
@@ -2329,6 +2412,7 @@ func (this *ChartInfoController) CalculateMultiSearch() {
 				SysUserId:       info.SysUserId,
 				EndDate:         info.EndDate,
 				EndValue:        info.EndValue,
+				HaveOperaAuth:   haveOperaAuth,
 			}
 			searchItemList = append(searchItemList, searchItem)
 		}

+ 20 - 2
controllers/data_manage/excel/custom_analysis.go

@@ -8,6 +8,7 @@ import (
 	"eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/models/data_manage/excel/response"
 	"eta/eta_api/services"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/services/data/excel"
 	"eta/eta_api/utils"
 	"strconv"
@@ -66,6 +67,14 @@ func (c *CustomAnalysisController) ExcelByName() {
 		return
 	}
 
+	// 数据权限
+	haveOperaAuth, err := data_manage_permission.CheckExcelPermissionByExcelInfoId(excelDetail.ExcelInfoId, excelDetail.ExcelClassifyId, excelDetail.IsJoinPermission, c.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取ETA表格失败"
+		br.ErrMsg = "获取ETA表格权限失败,Err:" + err.Error()
+		return
+	}
+
 	resp.IsFind = true
 	resp.ExcelInfo = response.FindExcelInfo{
 		ExcelInfoId:     excelDetail.ExcelInfoId,
@@ -81,7 +90,8 @@ func (c *CustomAnalysisController) ExcelByName() {
 		Sort:            excelDetail.Sort,
 		ModifyTime:      excelDetail.ModifyTime,
 		CreateTime:      excelDetail.CreateTime,
-		Button:          excel.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source),
+		Button:          excel.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source, haveOperaAuth),
+		HaveOperaAuth:   true,
 	}
 
 	if excelDetail != nil {
@@ -402,6 +412,13 @@ func (c *CustomAnalysisController) BaseExcelDetail() {
 		return
 	}
 
+	// 数据权限
+	haveOperaAuth, err := data_manage_permission.CheckExcelPermissionByExcelInfoId(excelDetail.ExcelInfoId, excelDetail.ExcelClassifyId, excelDetail.IsJoinPermission, c.SysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取ETA表格失败"
+		br.ErrMsg = "获取ETA表格权限失败,Err:" + err.Error()
+		return
+	}
 
 	resp.IsFind = true
 	resp.ExcelInfo = response.FindExcelInfo{
@@ -418,7 +435,8 @@ func (c *CustomAnalysisController) BaseExcelDetail() {
 		Sort:            excelDetail.Sort,
 		ModifyTime:      excelDetail.ModifyTime,
 		CreateTime:      excelDetail.CreateTime,
-		Button:          excel.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source),
+		Button:          excel.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source, haveOperaAuth),
+		HaveOperaAuth:   true,
 	}
 	if markStatus.Status == 0 {
 		resp.ExcelInfo.CanEdit = true

+ 174 - 3
controllers/data_manage/excel/excel_classify.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage/excel"
 	"eta/eta_api/models/data_manage/excel/request"
 	response2 "eta/eta_api/models/data_manage/excel/response"
+	"eta/eta_api/services/data/data_manage_permission"
 	excel2 "eta/eta_api/services/data/excel"
 	"eta/eta_api/utils"
 	"fmt"
@@ -40,6 +41,12 @@ func (this *ExcelClassifyController) List() {
 	}
 	//只看我的
 	isShowMe, _ := this.GetBool("IsShowMe")
+	// 自定义分析只看自己的
+	if source == utils.CUSTOM_ANALYSIS_TABLE {
+		br = AnalysisClassifyList(this)
+		return
+	}
+
 	showUserId := 0
 	if isShowMe {
 		showUserId = this.SysUser.AdminId
@@ -51,6 +58,11 @@ func (this *ExcelClassifyController) List() {
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
+	// 分类map
+	classifyMap := make(map[int]*excel.ExcelClassifyItems)
+	for _, v := range classifyList {
+		classifyMap[v.ExcelClassifyId] = v
+	}
 
 	// 获取二级分类
 	// 获取三级分类
@@ -62,12 +74,28 @@ func (this *ExcelClassifyController) List() {
 		return
 	}
 
+	// 获取所有有权限的指标和分类
+	permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserExcelAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+		return
+	}
+
 	ExcelInfoMap := make(map[int][]*excel.ExcelClassifyItems)
 	for _, v := range allExcelInfo {
+		// 数据权限
+		if classifyInfo, ok := classifyMap[v.ExcelClassifyId]; ok {
+			v.HaveOperaAuth = data_manage_permission.CheckExcelPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.ExcelInfoId, v.ExcelClassifyId, permissionEdbIdList, permissionClassifyIdList)
+		}
+
 		ExcelInfoMap[v.ExcelClassifyId] = append(ExcelInfoMap[v.ExcelClassifyId], v)
 	}
-	classifyMap := make(map[int][]*excel.ExcelClassifyItems)
+
+	classifyListMap := make(map[int][]*excel.ExcelClassifyItems)
 	for _, v := range classifyList {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckExcelClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ExcelClassifyId, permissionClassifyIdList)
 		if existItems, ok := ExcelInfoMap[v.ExcelClassifyId]; ok {
 			v.Children = existItems
 		}
@@ -75,12 +103,108 @@ func (this *ExcelClassifyController) List() {
 
 	for _, v := range classifyList {
 		if v.ParentId > 0 {
-			classifyMap[v.ParentId] = append(classifyMap[v.ParentId], v)
+			classifyListMap[v.ParentId] = append(classifyListMap[v.ParentId], v)
 		}
 	}
 	//组装三级分类
 	for key, classify := range classifyList {
-		subList, ok := classifyMap[classify.ExcelClassifyId]
+		subList, ok := classifyListMap[classify.ExcelClassifyId]
+		if ok {
+			classifyList[key].Children = append(classifyList[key].Children, subList...)
+			sort.Slice(classifyList[key].Children, func(i, j int) bool {
+				return excel.ExcelClassifyItemBySort(classifyList[key].Children[i], classifyList[key].Children[j])
+			})
+		}
+	}
+
+	nodeAll := make([]*excel.ExcelClassifyItems, 0)
+	for _, v := range classifyList {
+		if v.ParentId == 0 {
+			sort.Slice(v.Children, func(i, j int) bool { return excel.ExcelClassifyItemBySort(v.Children[i], v.Children[j]) })
+			nodeAll = append(nodeAll, v)
+		}
+	}
+
+	resp := response2.ExcelClassifyListResp{
+		AllNodes: nodeAll,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+func AnalysisClassifyList(this *ExcelClassifyController) (br *models.BaseResponse) {
+	br = new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	source, _ := this.GetInt("Source")
+	if source <= 0 {
+		source = utils.EXCEL_DEFAULT
+	}
+	//只看我的
+	showUserId := this.SysUser.AdminId
+
+	classifyList, err := excel.GetExcelClassifyBySource(source)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	// 分类map
+	classifyMap := make(map[int]*excel.ExcelClassifyItems)
+	for _, v := range classifyList {
+		classifyMap[v.ExcelClassifyId] = v
+	}
+
+	// 获取二级分类
+	// 获取三级分类
+	// 根据来源获取所有excel表格(无内容)
+	allExcelInfo, err := excel.GetNoContentExcelInfoAll(source, showUserId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取表格信息失败,Err:" + err.Error()
+		return
+	}
+
+	// 获取所有有权限的指标和分类
+	permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserExcelAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+		return
+	}
+
+	ExcelInfoMap := make(map[int][]*excel.ExcelClassifyItems)
+	for _, v := range allExcelInfo {
+		// 数据权限
+		if classifyInfo, ok := classifyMap[v.ExcelClassifyId]; ok {
+			v.HaveOperaAuth = data_manage_permission.CheckExcelPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.ExcelInfoId, v.ExcelClassifyId, permissionEdbIdList, permissionClassifyIdList)
+		}
+
+		ExcelInfoMap[v.ExcelClassifyId] = append(ExcelInfoMap[v.ExcelClassifyId], v)
+	}
+
+	classifyListMap := make(map[int][]*excel.ExcelClassifyItems)
+	for _, v := range classifyList {
+		// 数据权限
+		v.HaveOperaAuth = data_manage_permission.CheckExcelClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ExcelClassifyId, permissionClassifyIdList)
+		if existItems, ok := ExcelInfoMap[v.ExcelClassifyId]; ok {
+			v.Children = existItems
+		}
+	}
+
+	for _, v := range classifyList {
+		if v.ParentId > 0 {
+			classifyListMap[v.ParentId] = append(classifyListMap[v.ParentId], v)
+		}
+	}
+	//组装三级分类
+	for key, classify := range classifyList {
+		subList, ok := classifyListMap[classify.ExcelClassifyId]
 		if ok {
 			classifyList[key].Children = append(classifyList[key].Children, subList...)
 			sort.Slice(classifyList[key].Children, func(i, j int) bool {
@@ -96,6 +220,10 @@ func (this *ExcelClassifyController) List() {
 			nodeAll = append(nodeAll, v)
 		}
 	}
+
+	// 自定义分析只看自己的分类
+	nodeAll = removeNodesWithAnalysisClassify(nodeAll, this.SysUser.AdminId)
+
 	resp := response2.ExcelClassifyListResp{
 		AllNodes: nodeAll,
 	}
@@ -103,6 +231,45 @@ func (this *ExcelClassifyController) List() {
 	br.Success = true
 	br.Msg = "获取成功"
 	br.Data = resp
+
+	return
+}
+
+// removeNodesWithAnalysisClassify
+// @Description:  自定义分析只看自己的分类,所以需要移除分类
+// @author: Roc
+// @datetime 2024-04-09 13:46:51
+// @param nodes []*excel.ExcelClassifyItems
+// @param adminId int
+// @return []*excel.ExcelClassifyItems
+func removeNodesWithAnalysisClassify(nodes []*excel.ExcelClassifyItems, adminId int) []*excel.ExcelClassifyItems {
+	var newListNode []*excel.ExcelClassifyItems
+
+	for _, node := range nodes {
+		if node.Children != nil {
+			node.Children = removeNodesWithAnalysisClassify(node.Children, adminId)
+		}
+
+		// 如果是ETA表格,那么就保留
+		if node.ExcelInfoId > 0 {
+			newListNode = append(newListNode, node)
+			continue
+		}
+
+		// 如果是公共分类,且名下的ETA表格不为空,那么就保留
+		if node.SysUserId == 0 && node.Children != nil && len(node.Children) > 0 {
+			newListNode = append(newListNode, node)
+			continue
+		}
+
+		// 如果是自己的分类,那么就保留
+		if node.SysUserId == adminId {
+			newListNode = append(newListNode, node)
+			continue
+		}
+	}
+
+	return newListNode
 }
 
 // ExcelClassifyItems
@@ -251,6 +418,10 @@ func (this *ExcelClassifyController) AddExcelClassify() {
 		br.ErrMsg = "保存分类失败,Err:" + err.Error()
 		return
 	}
+	// 继承分类权限
+	{
+		go data_manage_permission.InheritParentClassify(6, source, classify.ExcelClassifyId, classify.ParentId, classify.ExcelClassifyName)
+	}
 	br.Ret = 200
 	br.Msg = "保存成功"
 	br.Success = true

+ 88 - 23
controllers/data_manage/excel/excel_info.go

@@ -11,11 +11,13 @@ import (
 	"eta/eta_api/models/data_manage/excel/response"
 	"eta/eta_api/services"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	excel2 "eta/eta_api/services/data/excel"
 	"eta/eta_api/services/excel"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/shopspring/decimal"
 	"github.com/yidane/formula"
 	"io"
 	"os"
@@ -396,9 +398,47 @@ func (c *ExcelInfoController) List() {
 		return
 	}
 
-	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
+	lenList := len(list)
+	if list == nil || lenList <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
 		list = make([]*excel3.MyExcelInfoList, 0)
 	}
+
+	if lenList > 0 {
+		classifyIdList := make([]int, 0)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ExcelClassifyId)
+		}
+		classifyMap := make(map[int]*excel3.ExcelClassify)
+
+		// 分类信息
+		{
+			classifyList, err := excel3.GetClassifyByIdList(classifyIdList)
+			if err != nil {
+				br.Msg = "获取表格列表信息失败"
+				br.ErrMsg = "获取表格分类列表数据失败,Err:" + err.Error()
+				return
+			}
+			for _, v := range classifyList {
+				classifyMap[v.ExcelClassifyId] = v
+			}
+		}
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserExcelAndClassifyPermissionList(c.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range list {
+			// 数据权限
+			if classifyInfo, ok := classifyMap[v.ExcelClassifyId]; ok {
+				v.HaveOperaAuth = data_manage_permission.CheckExcelPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.ExcelInfoId, v.ExcelClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+		}
+
+	}
+
 	// 总数据量
 	dataCount, err := excel3.GetExcelListCountByCondition(condition, pars)
 	if err != nil && err.Error() != utils.ErrNoRow() {
@@ -447,7 +487,7 @@ func (c *ExcelInfoController) Detail() {
 	}
 
 	// 获取数据详情
-	excelDetail, errMsg, err := excel2.GetExcelDetailInfoByExcelInfoId(excelInfoId)
+	excelDetail, errMsg, err := excel2.GetExcelDetailInfoByExcelInfoId(excelInfoId, c.SysUser.AdminId)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = err.Error()
@@ -468,7 +508,7 @@ func (c *ExcelInfoController) Detail() {
 	}
 
 	// excel表格按钮权限
-	excelDetail.Button = excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source)
+	excelDetail.Button = excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source, excelDetail.HaveOperaAuth)
 
 	br.Ret = 200
 	br.Success = true
@@ -600,7 +640,14 @@ func (c *ExcelInfoController) Edit() {
 
 	// 操作权限校验
 	{
-		button := excel2.GetExcelInfoOpButton(sysUser, excelInfo.SysUserId, excelInfo.Source)
+		// 数据权限
+		haveOperaAuth, err := data_manage_permission.CheckExcelPermissionByExcelInfoId(excelInfo.ExcelInfoId, excelInfo.ExcelClassifyId, excelInfo.IsJoinPermission, c.SysUser.AdminId)
+		if err != nil {
+			br.Msg = "获取ETA表格失败"
+			br.ErrMsg = "获取ETA表格权限失败,Err:" + err.Error()
+			return
+		}
+		button := excel2.GetExcelInfoOpButton(sysUser, excelInfo.SysUserId, excelInfo.Source, haveOperaAuth)
 		if !button.OpButton {
 			br.Msg = "无操作权限"
 			br.Msg = "无操作权限"
@@ -1181,6 +1228,7 @@ func (c *ExcelInfoController) AddDraft() {
 // @Title 获取excel表格的table数据
 // @Description 获取excel表格的table数据接口
 // @Param   UniqueCode   query   string  true       "表格code"
+// @Param   FromScene   query   int  true       "场景来源,1:智能研报,2:研报列表;3:英文研报;4:中文PPT;5:英文PPT"
 // @Success 200 {object} response.ExcelTableDetailResp
 // @router /excel_info/table_data [get]
 func (c *ExcelInfoController) GetExcelTableData() {
@@ -1197,6 +1245,7 @@ func (c *ExcelInfoController) GetExcelTableData() {
 		return
 	}
 	uniqueCode := c.GetString("UniqueCode")
+	fromScene, _ := c.GetInt("FromScene", 0)
 
 	var err error
 	if uniqueCode == `` {
@@ -1281,11 +1330,28 @@ func (c *ExcelInfoController) GetExcelTableData() {
 
 	tableData = excel.HandleTableCell(tableData)
 
+	config := response.ExcelTableDetailConfigResp{
+		FontSize: 9,
+	}
+
+	// 获取配置的字体大小
+	confName := models.FromSceneMap[fromScene]
+	if confName != `` {
+		busConf, err := models.GetBusinessConfByKey(confName)
+		if err == nil {
+			sizeDeci, err := decimal.NewFromString(busConf.ConfVal)
+			if err == nil {
+				config.FontSize = int(sizeDeci.IntPart())
+			}
+		}
+	}
+
 	resp := response.ExcelTableDetailResp{
 		UniqueCode: excelInfo.UniqueCode,
 		ExcelImage: excelInfo.ExcelImage,
 		ExcelName:  excelInfo.ExcelName,
 		TableInfo:  tableData,
+		Config:     config,
 	}
 	br.Ret = 200
 	br.Success = true
@@ -1857,7 +1923,7 @@ func (c *ExcelInfoController) Refresh() {
 	}
 
 	// 获取数据详情
-	excelDetail, errMsg, err := excel2.GetExcelDetailInfoByExcelInfoId(excelInfoId)
+	excelDetail, errMsg, err := excel2.GetExcelDetailInfoByExcelInfoId(excelInfoId, c.SysUser.AdminId)
 	if err != nil {
 		br.Msg = errMsg
 		br.ErrMsg = err.Error()
@@ -1866,9 +1932,8 @@ func (c *ExcelInfoController) Refresh() {
 
 	// 操作权限校验
 	{
-		button := excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source)
+		button := excel2.GetExcelInfoOpButton(sysUser, excelDetail.SysUserId, excelDetail.Source, excelDetail.HaveOperaAuth)
 		if !button.RefreshButton {
-			br.Msg = "无操作权限"
 			br.Msg = "无操作权限"
 			br.IsSendEmail = false
 			return
@@ -2276,13 +2341,13 @@ func decompressZip(src string) error {
 // @Param	request	body request.MarkEditSandbox true "type json string"
 // @Success 200 标记成功 ;202 标记成功
 // @router /excel_info/mark [post]
-func (this *ExcelInfoController) MarkEditStatus() {
+func (c *ExcelInfoController) MarkEditStatus() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
+		c.Data["json"] = br
+		c.ServeJSON()
 	}()
-	sysUser := this.SysUser
+	sysUser := c.SysUser
 	if sysUser == nil {
 		br.Msg = "请登录"
 		br.ErrMsg = "请登录,SysUser Is Empty"
@@ -2290,7 +2355,7 @@ func (this *ExcelInfoController) MarkEditStatus() {
 		return
 	}
 	var req request.MarkEditExcel
-	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
 	if err != nil {
 		br.Msg = "参数解析异常!"
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
@@ -2330,16 +2395,16 @@ func (this *ExcelInfoController) MarkEditStatus() {
 // @Param	request	body excel3.BatchRefreshExcelReq true "type json string"
 // @Success Ret=200 刷新成功
 // @router /excel_info/table/batch_refresh [post]
-func (this *ExcelInfoController) BatchRefresh() {
+func (c *ExcelInfoController) BatchRefresh() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
 		if br.ErrMsg == "" {
 			br.IsSendEmail = false
 		}
-		this.Data["json"] = br
-		this.ServeJSON()
+		c.Data["json"] = br
+		c.ServeJSON()
 	}()
-	sysUser := this.SysUser
+	sysUser := c.SysUser
 	if sysUser == nil {
 		br.Msg = "请登录"
 		br.ErrMsg = "请登录,SysUser Is Empty"
@@ -2347,7 +2412,7 @@ func (this *ExcelInfoController) BatchRefresh() {
 		return
 	}
 	var req excel3.BatchRefreshExcelReq
-	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
 	if err != nil {
 		br.Msg = "参数解析异常!"
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()
@@ -2361,7 +2426,7 @@ func (this *ExcelInfoController) BatchRefresh() {
 	}
 
 	// 获取表格关联的指标IDs
-	edbIds, e := excel2.GetEdbIdsFromExcelCodes(req.ExcelCodes)
+	edbIds, e := excel2.GetEdbIdsFromExcelCodes(req.ExcelCodes, sysUser.AdminId)
 	if e != nil {
 		br.Msg = "刷新失败"
 		br.ErrMsg = "获取表格关联的指标IDs失败, Err: " + e.Error()
@@ -2396,13 +2461,13 @@ func (this *ExcelInfoController) BatchRefresh() {
 // @Param	request	body excel3.BatchRefreshExcelReq true "type json string"
 // @Success Ret=200 刷新成功
 // @router /excel_info/table/batch_refresh/result [post]
-func (this *ExcelInfoController) GetBatchChartRefreshResult() {
+func (c *ExcelInfoController) GetBatchChartRefreshResult() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
+		c.Data["json"] = br
+		c.ServeJSON()
 	}()
-	sysUser := this.SysUser
+	sysUser := c.SysUser
 	if sysUser == nil {
 		br.Msg = "请登录"
 		br.ErrMsg = "请登录,SysUser Is Empty"
@@ -2410,7 +2475,7 @@ func (this *ExcelInfoController) GetBatchChartRefreshResult() {
 		return
 	}
 	var req excel3.BatchRefreshExcelReq
-	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
 	if err != nil {
 		br.Msg = "参数解析异常!"
 		br.ErrMsg = "参数解析失败,Err:" + err.Error()

+ 54 - 12
controllers/data_manage/excel/mixed_table.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/data_manage/excel/request"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	excel2 "eta/eta_api/services/data/excel"
 	"eta/eta_api/utils"
 	"fmt"
@@ -424,20 +425,61 @@ func (c *ExcelInfoController) GetBaseEdbInfo() {
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
 	}
+
 	list := make([]*data_manage.BaseEdbNameItem, 0)
-	for _, v := range edbInfoList {
-		tmp := new(data_manage.BaseEdbNameItem)
-
-		tmp.EdbInfoId = v.EdbInfoId
-		tmp.EdbInfoType = v.EdbInfoType
-		tmp.EdbCode = v.EdbCode
-		tmp.EdbName = v.EdbName
-		tmp.Source = v.Source
-		tmp.SourceName = v.SourceName
-		tmp.Frequency = v.Frequency
-		tmp.Unit = v.Unit
-		list = append(list, tmp)
+
+	if len(edbInfoList) > 0 {
+		classifyIdList := make([]int, 0)
+		for _, v := range edbInfoList {
+			classifyIdList = append(classifyIdList, v.ClassifyId)
+		}
+		// 指标权限
+		{
+			// 当前的分类
+			classifyMap := make(map[int]*data_manage.EdbClassify)
+			classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if err != nil {
+				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(c.SysUser.AdminId, 0, 0)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+				return
+			}
+
+			for _, v := range edbInfoList {
+				tmp := new(data_manage.BaseEdbNameItem)
+
+				// 指标权限
+				if currClassify, ok := classifyMap[v.ClassifyId]; ok {
+					tmp.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+				}
+
+				tmp.EdbInfoId = v.EdbInfoId
+				tmp.EdbInfoType = v.EdbInfoType
+				tmp.EdbCode = v.EdbCode
+				tmp.EdbName = v.EdbName
+				tmp.Source = v.Source
+				tmp.SourceName = v.SourceName
+				tmp.Frequency = v.Frequency
+				tmp.Unit = v.Unit
+				list = append(list, tmp)
+			}
+		}
+
 	}
+
 	resp := data_manage.BaseEdbInfoResp{
 		List: list,
 	}

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

@@ -56,7 +56,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 			return
 		}
 		// 移除没有权限的图表
-		allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap)
+		allNodes := data.HandleNoPermissionChart(resp.AllNodes, noPermissionChartIdMap, this.SysUser.AdminId)
 		resp.AllNodes = allNodes
 
 		br.Ret = 200
@@ -97,7 +97,7 @@ func (this *FutureGoodChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap, this.SysUser.AdminId)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -450,7 +450,7 @@ func (this *FutureGoodChartClassifyController) DeleteChartClassify() {
 			return
 		}
 		//图表操作权限
-		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 		if !ok {
 			br.Msg = "没有该图表的操作权限"
 			br.ErrMsg = "没有该图表的操作权限"

+ 84 - 5
controllers/data_manage/future_good/future_good_chart_info.go

@@ -10,6 +10,7 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/services"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	future_goodServ "eta/eta_api/services/data/future_good"
 	etaTrialService "eta/eta_api/services/eta_trial"
 	"eta/eta_api/utils"
@@ -653,7 +654,7 @@ func (this *FutureGoodChartInfoController) ChartInfoEdit() {
 	}
 
 	//图表操作权限
-	ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId)
+	ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId, true)
 	if !ok {
 		br.Msg = "没有该图表的操作权限"
 		br.ErrMsg = "没有该图表的操作权限"
@@ -1397,7 +1398,7 @@ func getFutureGoodChartInfo(chartInfo *data_manage.ChartInfoView, chartType, dat
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	chartInfo.Button.IsEdit = chartInfo.IsEdit
 	chartInfo.Button.IsCopy = true
 	//判断是否需要展示英文标识
@@ -1495,6 +1496,72 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	resp = new(data_manage.ChartInfoDetailFromUniqueCodeResp)
 
 	adminId := sysUser.AdminId
+	// 指标数据map
+	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+	defer func() {
+		if isOk {
+			resp.ChartInfo.HaveOperaAuth = true
+
+			// 指标权限
+			{
+				classifyMap := make(map[int]*data_manage.EdbClassify)
+				// 分类
+				{
+					classifyIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						classifyIdList = append(classifyIdList, v.ClassifyId)
+					}
+					classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+					if tmpErr != nil {
+						errMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range classifyList {
+						classifyMap[v.ClassifyId] = v
+					}
+				}
+
+				// 指标
+				if len(edbClassifyPermissionMap) < 0 {
+					edbInfoIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+					edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+					if tmpErr != nil {
+						errMsg = "获取指标列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range edbInfoList {
+						edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+							ClassifyId:       v.ClassifyId,
+							IsJoinPermission: v.IsJoinPermission,
+							EdbInfoId:        v.EdbInfoId,
+						}
+					}
+				}
+
+				// 获取所有有权限的指标和分类
+				permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+				if err != nil {
+					errMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+					return
+				}
+
+				for _, v := range resp.EdbInfoList {
+					// 数据权限
+					edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+						v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					}
+				}
+			}
+		}
+	}()
 
 	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
 	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
@@ -1646,7 +1713,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	chartInfo.Button.IsEdit = chartInfo.IsEdit
 	chartInfo.Button.IsCopy = true
 	//判断是否需要展示英文标识
@@ -1659,6 +1726,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
 
 	resp.ChartInfo = chartInfo
+
 	resp.EdbInfoList = edbList
 	resp.XEdbIdValue = xEdbIdValue
 	resp.YDataList = yDataList
@@ -1666,6 +1734,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	resp.BarChartInfo = barConfig
 	resp.Status = true
 
+	// 遍历到校验map
+	for _, v := range edbList {
+		edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+			ClassifyId:       v.ClassifyId,
+			IsJoinPermission: v.IsJoinPermission,
+			EdbInfoId:        v.EdbInfoId,
+		}
+	}
+
 	// 将数据加入缓存
 	if utils.Re == nil {
 		data, _ := json.Marshal(resp)
@@ -2099,7 +2176,7 @@ func (this *FutureGoodChartInfoController) BaseChartInfoDetailFromUniqueCode() {
 		}
 
 		//图表操作权限
-		chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+		chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 		chartInfo.Button.IsEdit = chartInfo.IsEdit
 		chartInfo.Button.IsCopy = true
 		//判断是否需要展示英文标识
@@ -2225,6 +2302,8 @@ func (this *FutureGoodChartInfoController) ChartInfoSearchByEs() {
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
 			tmp.ChartInfo = *v
+			// 图表数据权限
+			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if edbTmpList, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, edbTmpList, v.Source, v.ChartType)
@@ -2905,7 +2984,7 @@ func (this *FutureGoodChartInfoController) PreviewBarChartInfo() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	chartInfo.Button.IsEdit = chartInfo.IsEdit
 	chartInfo.Button.IsCopy = true
 	//判断是否需要展示英文标识

+ 81 - 4
controllers/data_manage/future_good/future_good_profit_chart_info.go

@@ -9,6 +9,7 @@ import (
 	"eta/eta_api/models/data_manage/future_good/response"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	future_goodServ "eta/eta_api/services/data/future_good"
 	"eta/eta_api/utils"
 	"fmt"
@@ -412,7 +413,7 @@ func (this *FutureGoodChartInfoController) ProfitChartInfoEdit() {
 	}
 
 	//图表操作权限
-	ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId)
+	ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId, true)
 	if !ok {
 		br.Msg = "没有该图表的操作权限"
 		br.ErrMsg = "没有该图表的操作权限"
@@ -957,7 +958,7 @@ func (this *FutureGoodChartInfoController) PreviewProfitChartInfo() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	chartInfo.Button.IsEdit = chartInfo.IsEdit
 	chartInfo.Button.IsCopy = true
 	//判断是否需要展示英文标识
@@ -1073,7 +1074,7 @@ func getFutureGoodProfitChartInfo(chartInfo *data_manage.ChartInfoView, sysUser
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	chartInfo.Button.IsEdit = chartInfo.IsEdit
 	chartInfo.Button.IsCopy = true
 	//判断是否需要展示英文标识
@@ -1108,6 +1109,73 @@ func GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo *data_manage.Cha
 
 	adminId := sysUser.AdminId
 
+	// 指标数据map
+	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+	defer func() {
+		if isOk {
+			resp.ChartInfo.HaveOperaAuth = true
+
+			// 指标权限
+			{
+				classifyMap := make(map[int]*data_manage.EdbClassify)
+				// 分类
+				{
+					classifyIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						classifyIdList = append(classifyIdList, v.ClassifyId)
+					}
+					classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+					if tmpErr != nil {
+						errMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range classifyList {
+						classifyMap[v.ClassifyId] = v
+					}
+				}
+
+				// 指标
+				if len(edbClassifyPermissionMap) < 0 {
+					edbInfoIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+					edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+					if tmpErr != nil {
+						errMsg = "获取指标列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range edbInfoList {
+						edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+							ClassifyId:       v.ClassifyId,
+							IsJoinPermission: v.IsJoinPermission,
+							EdbInfoId:        v.EdbInfoId,
+						}
+					}
+				}
+
+				// 获取所有有权限的指标和分类
+				permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+				if err != nil {
+					errMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+					return
+				}
+
+				for _, v := range resp.EdbInfoList {
+					// 数据权限
+					edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+						v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					}
+				}
+			}
+		}
+	}()
+
 	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
 	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
 	if utils.Re == nil && isCache {
@@ -1248,7 +1316,7 @@ func GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo *data_manage.Cha
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	chartInfo.Button.IsEdit = chartInfo.IsEdit
 	chartInfo.Button.IsCopy = true
 	//判断是否需要展示英文标识
@@ -1271,6 +1339,15 @@ func GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo *data_manage.Cha
 	}
 	resp.Status = true
 
+	// 遍历到校验map
+	for _, v := range edbList {
+		edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+			ClassifyId:       v.ClassifyId,
+			IsJoinPermission: v.IsJoinPermission,
+			EdbInfoId:        v.EdbInfoId,
+		}
+	}
+
 	// 将数据加入缓存
 	if utils.Re == nil {
 		data, _ := json.Marshal(resp)

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

@@ -101,7 +101,7 @@ func (this *LineEquationChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap, this.SysUser.AdminId)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -457,7 +457,7 @@ func (this *LineEquationChartClassifyController) DeleteChartClassify() {
 			return
 		}
 		//图表操作权限
-		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 		if !ok {
 			br.Msg = "没有该图表的操作权限"
 			br.ErrMsg = "没有该图表的操作权限"

+ 133 - 2
controllers/data_manage/line_equation/line_chart_info.go

@@ -9,6 +9,7 @@ import (
 	"eta/eta_api/models/data_manage/line_equation/response"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/services/data/line_equation"
 	"eta/eta_api/utils"
 	"fmt"
@@ -829,7 +830,7 @@ func (this *LineEquationChartInfoController) Detail() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, chartInfo.Source, chartInfo.ChartType)
 	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -844,6 +845,58 @@ func (this *LineEquationChartInfoController) Detail() {
 		IsSetName: chartInfo.IsSetName,
 	}
 
+	chartInfo.HaveOperaAuth = true
+	// 指标权限
+	{
+		edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		// 分类
+		{
+			classifyIdList := make([]int, 0)
+			for _, v := range edbList {
+				classifyIdList = append(classifyIdList, v.ClassifyId)
+			}
+			classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if tmpErr != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+				return
+			}
+			for _, v := range classifyList {
+				classifyMap[v.ClassifyId] = v
+			}
+		}
+
+		// 遍历到校验map
+		for _, v := range edbList {
+			edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+				ClassifyId:       v.ClassifyId,
+				IsJoinPermission: v.IsJoinPermission,
+				EdbInfoId:        v.EdbInfoId,
+			}
+		}
+
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range edbList {
+			// 数据权限
+			edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+			if !ok {
+				continue
+			}
+
+			if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+				v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+		}
+	}
+
 	resp := new(data_manage.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
 	resp.EdbInfoList = edbList
@@ -1150,6 +1203,73 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 
 	adminId := sysUser.AdminId
 
+	// 指标数据map
+	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+	defer func() {
+		if isOk {
+			resp.ChartInfo.HaveOperaAuth = true
+
+			// 指标权限
+			{
+				classifyMap := make(map[int]*data_manage.EdbClassify)
+				// 分类
+				{
+					classifyIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						classifyIdList = append(classifyIdList, v.ClassifyId)
+					}
+					classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+					if tmpErr != nil {
+						errMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range classifyList {
+						classifyMap[v.ClassifyId] = v
+					}
+				}
+
+				// 指标
+				if len(edbClassifyPermissionMap) < 0 {
+					edbInfoIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+					edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+					if tmpErr != nil {
+						errMsg = "获取指标列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range edbInfoList {
+						edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+							ClassifyId:       v.ClassifyId,
+							IsJoinPermission: v.IsJoinPermission,
+							EdbInfoId:        v.EdbInfoId,
+						}
+					}
+				}
+
+				// 获取所有有权限的指标和分类
+				permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+				if err != nil {
+					errMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+					return
+				}
+
+				for _, v := range resp.EdbInfoList {
+					// 数据权限
+					edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+						v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					}
+				}
+			}
+		}
+	}()
+
 	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
 	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
 	if utils.Re == nil && isCache {
@@ -1263,7 +1383,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, chartInfo.Source, chartInfo.ChartType)
 	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -1288,6 +1408,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	resp.DataResp = resultResp
 	resp.Status = true
 
+	// 遍历到校验map
+	for _, v := range edbList {
+		edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+			ClassifyId:       v.ClassifyId,
+			IsJoinPermission: v.IsJoinPermission,
+			EdbInfoId:        v.EdbInfoId,
+		}
+	}
+
 	// 将数据加入缓存
 	if utils.Re == nil {
 		d, _ := json.Marshal(resp)
@@ -1508,6 +1637,8 @@ func (this *LineEquationChartInfoController) SearchByEs() {
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
 			tmp.ChartInfo = *v
+			// 图表数据权限
+			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if _, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, v.Source, v.ChartType)

+ 133 - 2
controllers/data_manage/line_feature/chart_info.go

@@ -10,6 +10,7 @@ import (
 	"eta/eta_api/models/data_manage/line_feature/response"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	lineFeatureServ "eta/eta_api/services/data/line_feature"
 	"eta/eta_api/utils"
 	"fmt"
@@ -1920,7 +1921,7 @@ func (this *LineFeaturesChartInfoController) Detail() {
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, chartInfo.Source, chartInfo.ChartType)
 	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -1935,6 +1936,58 @@ func (this *LineFeaturesChartInfoController) Detail() {
 		IsSetName: chartInfo.IsSetName,
 	}
 
+	chartInfo.HaveOperaAuth = true
+	// 指标权限
+	{
+		edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		// 分类
+		{
+			classifyIdList := make([]int, 0)
+			for _, v := range edbList {
+				classifyIdList = append(classifyIdList, v.ClassifyId)
+			}
+			classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if tmpErr != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+				return
+			}
+			for _, v := range classifyList {
+				classifyMap[v.ClassifyId] = v
+			}
+		}
+
+		// 遍历到校验map
+		for _, v := range edbList {
+			edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+				ClassifyId:       v.ClassifyId,
+				IsJoinPermission: v.IsJoinPermission,
+				EdbInfoId:        v.EdbInfoId,
+			}
+		}
+
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range edbList {
+			// 数据权限
+			edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+			if !ok {
+				continue
+			}
+
+			if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+				v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+			}
+		}
+	}
+
 	resp := new(data_manage.ChartInfoDetailResp)
 	resp.ChartInfo = chartInfo
 	resp.EdbInfoList = edbList
@@ -2247,6 +2300,73 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 
 	adminId := sysUser.AdminId
 
+	// 指标数据map
+	edbClassifyPermissionMap := make(map[int]data_manage_permission.EdbClassifyPermission)
+	defer func() {
+		if isOk {
+			resp.ChartInfo.HaveOperaAuth = true
+
+			// 指标权限
+			{
+				classifyMap := make(map[int]*data_manage.EdbClassify)
+				// 分类
+				{
+					classifyIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						classifyIdList = append(classifyIdList, v.ClassifyId)
+					}
+					classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
+					if tmpErr != nil {
+						errMsg = "获取分类列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range classifyList {
+						classifyMap[v.ClassifyId] = v
+					}
+				}
+
+				// 指标
+				if len(edbClassifyPermissionMap) < 0 {
+					edbInfoIdList := make([]int, 0)
+					for _, v := range resp.EdbInfoList {
+						edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
+					}
+					edbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdList)
+					if tmpErr != nil {
+						errMsg = "获取指标列表失败,Err:" + tmpErr.Error()
+						return
+					}
+					for _, v := range edbInfoList {
+						edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+							ClassifyId:       v.ClassifyId,
+							IsJoinPermission: v.IsJoinPermission,
+							EdbInfoId:        v.EdbInfoId,
+						}
+					}
+				}
+
+				// 获取所有有权限的指标和分类
+				permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUser.AdminId, 0, 0)
+				if err != nil {
+					errMsg = "获取所有有权限的指标和分类失败,Err:" + err.Error()
+					return
+				}
+
+				for _, v := range resp.EdbInfoList {
+					// 数据权限
+					edbItem, ok := edbClassifyPermissionMap[v.EdbInfoId]
+					if !ok {
+						continue
+					}
+
+					if currClassify, ok := classifyMap[edbItem.ClassifyId]; ok {
+						v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(edbItem.IsJoinPermission, currClassify.IsJoinPermission, edbItem.EdbInfoId, edbItem.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					}
+				}
+			}
+		}
+	}()
+
 	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
 	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
 	if utils.Re == nil && isCache {
@@ -2395,7 +2515,7 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	}
 
 	//图表操作权限
-	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 	//判断是否需要展示英文标识
 	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, chartInfo.Source, chartInfo.ChartType)
 	//chartInfo.UnitEn = edbInfoMappingA.UnitEn
@@ -2420,6 +2540,15 @@ func GetChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCa
 	resp.DataResp = resultResp
 	resp.Status = true
 
+	// 遍历到校验map
+	for _, v := range edbList {
+		edbClassifyPermissionMap[v.EdbInfoId] = data_manage_permission.EdbClassifyPermission{
+			ClassifyId:       v.ClassifyId,
+			IsJoinPermission: v.IsJoinPermission,
+			EdbInfoId:        v.EdbInfoId,
+		}
+	}
+
 	// 将数据加入缓存
 	if utils.Re == nil {
 		d, _ := json.Marshal(resp)
@@ -2640,6 +2769,8 @@ func (this *LineFeaturesChartInfoController) SearchByEs() {
 		for _, v := range searchList {
 			tmp := new(data_manage.ChartInfoMore)
 			tmp.ChartInfo = *v
+			// 图表数据权限
+			tmp.HaveOperaAuth = true
 			//判断是否需要展示英文标识
 			if _, ok := chartEdbMap[v.ChartInfoId]; ok {
 				tmp.IsEnChart = data.CheckIsEnChart(v.ChartNameEn, []*data_manage.ChartEdbInfoMapping{}, v.Source, v.ChartType)

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

@@ -101,7 +101,7 @@ func (this *LineFeaturesChartClassifyController) ChartClassifyList() {
 	}
 
 	// 移除没有权限的图表
-	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap)
+	allNodes := data.HandleNoPermissionChart(rootList, noPermissionChartIdMap, this.SysUser.AdminId)
 	resp.AllNodes = allNodes
 
 	br.Ret = 200
@@ -457,7 +457,7 @@ func (this *LineFeaturesChartClassifyController) DeleteChartClassify() {
 			return
 		}
 		//图表操作权限
-		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+		ok := data.CheckOpChartPermission(sysUser, chartInfo.SysUserId, true)
 		if !ok {
 			br.Msg = "没有该图表的操作权限"
 			br.ErrMsg = "没有该图表的操作权限"

+ 213 - 15
controllers/data_manage/my_chart.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
@@ -132,6 +133,39 @@ func (this *MyChartController) ChartList() {
 	listLen := len(list)
 	chartEdbMap := make(map[int][]*data_manage.ChartEdbInfoMapping)
 	if listLen > 0 {
+		// 分类id
+		classifyIdList := make([]int, 0)
+		// 当前列表中的分类map
+		classifyMap := make(map[int]*data_manage.ChartClassify)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+		}
+		classifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range classifyList {
+			classifyMap[v.ChartClassifyId] = v
+		}
+
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
+		// 权限
+		for k, chartViewInfo := range list {
+			if currClassify, ok := classifyMap[chartViewInfo.ChartClassifyId]; ok {
+				list[k].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartViewInfo.IsJoinPermission, currClassify.IsJoinPermission, chartViewInfo.ChartInfoId, chartViewInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+		}
+
 		chartInfoIds := ""
 		for _, v := range list {
 			chartInfoIds += strconv.Itoa(v.ChartInfoId) + ","
@@ -1283,15 +1317,51 @@ func (this *MyChartController) MyChartList() {
 	}
 
 	listLen := len(list)
-	for i := 0; i < listLen; i++ {
-		//判断是否需要展示英文标识
-		if edbTmpList, ok := chartEdbMap[list[i].ChartInfoId]; ok {
-			list[i].IsEnChart = data.CheckIsEnChart(list[i].ChartNameEn, edbTmpList, list[i].Source, list[i].ChartType)
+	if listLen > 0 {
+		// 分类id
+		classifyIdList := make([]int, 0)
+		// 当前列表中的分类map
+		classifyMap := make(map[int]*data_manage.ChartClassify)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
 		}
-		if _, ok := myChartMap[list[i].ChartInfoId]; ok {
-			list[i].IsAdd = true
+		classifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range classifyList {
+			classifyMap[v.ChartClassifyId] = v
 		}
+
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
+		// 权限
+		for i, chartViewInfo := range list {
+			//判断是否需要展示英文标识
+			if edbTmpList, ok := chartEdbMap[list[i].ChartInfoId]; ok {
+				list[i].IsEnChart = data.CheckIsEnChart(list[i].ChartNameEn, edbTmpList, list[i].Source, list[i].ChartType)
+			}
+			if _, ok := myChartMap[list[i].ChartInfoId]; ok {
+				list[i].IsAdd = true
+			}
+
+			// 数据权限
+			if currClassify, ok := classifyMap[chartViewInfo.ChartClassifyId]; ok {
+				list[i].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartViewInfo.IsJoinPermission, currClassify.IsJoinPermission, chartViewInfo.ChartInfoId, chartViewInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+		}
+
 	}
+
 	resp := new(data_manage.MyChartListResp)
 	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
 		items := make([]*data_manage.MyChartList, 0)
@@ -1502,10 +1572,44 @@ func (this *MyChartController) ChartRecommendList() {
 		myChartMap[v.ChartInfoId] = v.ChartInfoId
 	}
 	listLen := len(list)
-	for i := 0; i < listLen; i++ {
-		if _, ok := myChartMap[list[i].ChartInfoId]; ok {
-			list[i].IsAdd = true
+
+	if listLen > 0 {
+		// 分类id
+		classifyIdList := make([]int, 0)
+		// 当前列表中的分类map
+		classifyMap := make(map[int]*data_manage.ChartClassify)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+		}
+		classifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range classifyList {
+			classifyMap[v.ChartClassifyId] = v
+		}
+
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+		// 权限
+		for k, chartViewInfo := range list {
+			if currClassify, ok := classifyMap[chartViewInfo.ChartClassifyId]; ok {
+				list[k].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartViewInfo.IsJoinPermission, currClassify.IsJoinPermission, chartViewInfo.ChartInfoId, chartViewInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+
+			if _, ok := myChartMap[list[k].ChartInfoId]; ok {
+				list[k].IsAdd = true
+			}
 		}
+
 	}
 
 	resp := new(data_manage.ChartRecommendListResp)
@@ -1565,9 +1669,43 @@ func (this *MyChartController) MyChartSearch() {
 		return
 	}
 	listLen := len(list)
-	for i := 0; i < listLen; i++ {
-		list[i].IsAdd = true
+
+	if listLen > 0 {
+		// 分类id
+		classifyIdList := make([]int, 0)
+		// 当前列表中的分类map
+		classifyMap := make(map[int]*data_manage.ChartClassify)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+		}
+		classifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range classifyList {
+			classifyMap[v.ChartClassifyId] = v
+		}
+
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+		// 权限
+		for k, chartViewInfo := range list {
+			if currClassify, ok := classifyMap[chartViewInfo.ChartClassifyId]; ok {
+				list[k].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartViewInfo.IsJoinPermission, currClassify.IsJoinPermission, chartViewInfo.ChartInfoId, chartViewInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+			list[k].IsAdd = true
+		}
+
 	}
+
 	resp := new(data_manage.MyChartSearchListResp)
 	if list == nil {
 		list = make([]*data_manage.MyChartList, 0)
@@ -1636,11 +1774,71 @@ func (this *MyChartController) MyChartSearchByEs() {
 		br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
 		return
 	}
-	if len(list) <= 0 {
+
+	lenList := len(list)
+	if lenList <= 0 {
 		list = make([]*data_manage.MyChartList, 0)
-	}
-	for _, v := range list {
-		v.IsAdd = true
+	} else {
+		// 分类id
+		classifyIdList := make([]int, 0)
+		// 图表id
+		chartInfoIdList := make([]int, 0)
+
+		// 当前列表中的分类map
+		chartClassifyMap := make(map[int]*data_manage.ChartClassify)
+		// 当前列表中的图表map
+		chartInfoMap := make(map[int]*data_manage.ChartInfo)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ChartClassifyId)
+			chartInfoIdList = append(chartInfoIdList, v.ChartInfoId)
+		}
+
+		// 分类
+		{
+			classifyList, err := data_manage.GetChartClassifyByIdList(classifyIdList)
+			if err != nil {
+				if err != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取分类列表失败,Err:" + err.Error()
+					return
+				}
+			}
+			for _, tmpClassifyInfo := range classifyList {
+				chartClassifyMap[tmpClassifyInfo.ChartClassifyId] = tmpClassifyInfo
+			}
+		}
+
+		// 图表
+		{
+			tmpChartList, err := data_manage.GetChartInfoByIdList(chartInfoIdList)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取所有有权限的图表失败,Err:" + err.Error()
+				return
+			}
+			for _, tmpChartInfo := range tmpChartList {
+				chartInfoMap[tmpChartInfo.ChartInfoId] = tmpChartInfo
+			}
+		}
+
+		// 已授权分类id
+		permissionChartIdList, permissionClassifyIdList, err := data_manage_permission.GetUserChartAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+		// 权限
+		for k, tmpChartViewInfo := range list {
+			list[k].IsAdd = true
+			chartViewInfo, ok := chartInfoMap[tmpChartViewInfo.ChartInfoId]
+			if !ok {
+				continue
+			}
+			if currClassify, ok := chartClassifyMap[chartViewInfo.ChartClassifyId]; ok {
+				list[k].HaveOperaAuth = data_manage_permission.CheckChartPermissionByPermissionIdList(chartViewInfo.IsJoinPermission, currClassify.IsJoinPermission, chartViewInfo.ChartInfoId, chartViewInfo.ChartClassifyId, permissionChartIdList, permissionClassifyIdList)
+			}
+		}
 	}
 
 	page := paging.GetPaging(currentIndex, pageSize, int(total))

+ 335 - 270
controllers/data_manage/predict_edb_classify.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/system"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/utils"
 	"sort"
 )
@@ -22,109 +23,109 @@ type PredictEdbClassifyController struct {
 // @Param   IsOnlyMe   query   bool  false       "是否只看我的"
 // @Success 200 {object} data_manage.EdbClassifyListResp
 // @router /predict_classify/list [get]
-func (this *PredictEdbClassifyController) List() {
-	br := new(models.BaseResponse).Init()
-	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
-	}()
-
-	isOnlyMe, _ := this.GetBool("IsOnlyMe")
-
-	rootList, err := data_manage.GetEdbClassifyByParentId(0, 1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + err.Error()
-		return
-	}
-	// 获取当前账号的不可见指标
-	obj := data_manage.EdbInfoNoPermissionAdmin{}
-	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		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.GetPredictEdbInfoAll(1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + err.Error()
-		return
-	}
-	edbInfoMap := make(map[int][]*data_manage.EdbClassifyItems)
-	for _, v := range allEdbInfo {
-		// 如果指标不可见,那么就不返回该指标
-		if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
-			continue
-		}
-		button := data.GetPredictEdbOpButton(this.SysUser, v.SysUserId)
-		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
-		button.OpButton = false
-		button.DeleteButton = false
-		v.Button = button
-		if isOnlyMe {
-			if v.SysUserId == this.SysUser.AdminId {
-				edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
-			}
-		} else {
-			edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
-		}
-	}
-	rootChildMap := make(map[int][]*data_manage.EdbClassifyItems)
-	for _, v := range rootList {
-		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
-		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 {
-		nodeAll = append(nodeAll, v)
-	}
-
-	// 是否允许添加分类
-	canOpClassify := true
-
-	// 如果不是 超管 或者 ficc管理员 或者 ficc研究员,那么就没有权限
-	//if !utils.InArrayByStr([]string{utils.ROLE_TYPE_CODE_ADMIN, utils.ROLE_TYPE_CODE_FICC_ADMIN, utils.ROLE_TYPE_CODE_RESEARCHR, utils.ROLE_TYPE_CODE_FICC_RESEARCHR}, this.SysUser.RoleTypeCode) {
-	//	canOpClassify = false
-	//}
-
-	language := `CN`
-	// 指标显示的语言
-	{
-		configDetail, _ := system.GetConfigDetailByCode(this.SysUser.AdminId, system.PredictEdbLanguageVar)
-		if configDetail != nil {
-			language = configDetail.ConfigValue
-		} else {
-			configDetail, _ = system.GetDefaultConfigDetailByCode(system.PredictEdbLanguageVar)
-			if configDetail != nil {
-				language = configDetail.ConfigValue
-			}
-		}
-	}
-
-	resp := data_manage.EdbClassifyListResp{
-		AllNodes:      nodeAll,
-		CanOpClassify: canOpClassify,
-		Language:      language,
-	}
-	br.Ret = 200
-	br.Success = true
-	br.Msg = "获取成功"
-	br.Data = resp
-}
+//func (this *PredictEdbClassifyController) List() {
+//	br := new(models.BaseResponse).Init()
+//	defer func() {
+//		this.Data["json"] = br
+//		this.ServeJSON()
+//	}()
+//
+//	isOnlyMe, _ := this.GetBool("IsOnlyMe")
+//
+//	rootList, err := data_manage.GetEdbClassifyByParentId(0, 1)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		br.Msg = "获取失败"
+//		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+//		return
+//	}
+//	// 获取当前账号的不可见指标
+//	obj := data_manage.EdbInfoNoPermissionAdmin{}
+//	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		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.GetPredictEdbInfoAll(1)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		br.Msg = "获取失败"
+//		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+//		return
+//	}
+//	edbInfoMap := make(map[int][]*data_manage.EdbClassifyItems)
+//	for _, v := range allEdbInfo {
+//		// 如果指标不可见,那么就不返回该指标
+//		if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
+//			continue
+//		}
+//		button := data.GetPredictEdbOpButton(this.SysUser, v.SysUserId)
+//		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+//		button.OpButton = false
+//		button.DeleteButton = false
+//		v.Button = button
+//		if isOnlyMe {
+//			if v.SysUserId == this.SysUser.AdminId {
+//				edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+//			}
+//		} else {
+//			edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+//		}
+//	}
+//	rootChildMap := make(map[int][]*data_manage.EdbClassifyItems)
+//	for _, v := range rootList {
+//		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
+//		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 {
+//		nodeAll = append(nodeAll, v)
+//	}
+//
+//	// 是否允许添加分类
+//	canOpClassify := true
+//
+//	// 如果不是 超管 或者 ficc管理员 或者 ficc研究员,那么就没有权限
+//	//if !utils.InArrayByStr([]string{utils.ROLE_TYPE_CODE_ADMIN, utils.ROLE_TYPE_CODE_FICC_ADMIN, utils.ROLE_TYPE_CODE_RESEARCHR, utils.ROLE_TYPE_CODE_FICC_RESEARCHR}, this.SysUser.RoleTypeCode) {
+//	//	canOpClassify = false
+//	//}
+//
+//	language := `CN`
+//	// 指标显示的语言
+//	{
+//		configDetail, _ := system.GetConfigDetailByCode(this.SysUser.AdminId, system.PredictEdbLanguageVar)
+//		if configDetail != nil {
+//			language = configDetail.ConfigValue
+//		} else {
+//			configDetail, _ = system.GetDefaultConfigDetailByCode(system.PredictEdbLanguageVar)
+//			if configDetail != nil {
+//				language = configDetail.ConfigValue
+//			}
+//		}
+//	}
+//
+//	resp := data_manage.EdbClassifyListResp{
+//		AllNodes:      nodeAll,
+//		CanOpClassify: canOpClassify,
+//		Language:      language,
+//	}
+//	br.Ret = 200
+//	br.Success = true
+//	br.Msg = "获取成功"
+//	br.Data = resp
+//}
 
 // Items
 // @Title 获取所有预测指标分类接口-不包含指标
@@ -181,7 +182,28 @@ func (this *PredictEdbClassifyController) Add() {
 		return
 	}
 
-	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0)
+	haveOperaAuth := true
+
+	if req.ParentId > 0 {
+		parentClassify, err := data_manage.GetEdbClassifyById(req.ParentId)
+		if err != nil {
+			br.Msg = "获取父级分类失败"
+			br.ErrMsg = "获取父级分类失败,Err:" + err.Error()
+			return
+		}
+
+		// 已授权分类id
+		permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(this.SysUser.AdminId, parentClassify.ClassifyId)
+		if err != nil {
+			br.Msg = "添加失败"
+			br.ErrMsg = "获取父级分类失败,Err:" + err.Error()
+			return
+		}
+		// 数据权限
+		haveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(parentClassify.IsJoinPermission, parentClassify.ClassifyId, permissionClassifyIdList)
+	}
+
+	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0, haveOperaAuth)
 	if !button.AddButton {
 		br.Msg = "不允许添加分类"
 		br.IsSendEmail = false
@@ -505,156 +527,156 @@ func (this *PredictEdbClassifyController) Move() {
 // @Param   IsOnlyMe   query   bool  false       "是否只看我的"
 // @Success 200 {object} data_manage.EdbClassifyListResp
 // @router /predict_classify/list/v2 [get]
-func (this *PredictEdbClassifyController) ListV2() {
-	br := new(models.BaseResponse).Init()
-	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
-	}()
-
-	isOnlyMe, _ := this.GetBool("IsOnlyMe")
-
-	rootList, err := data_manage.GetEdbClassifyByParentId(0, 1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + err.Error()
-		return
-	}
-	// 获取当前账号的不可见指标
-	obj := data_manage.EdbInfoNoPermissionAdmin{}
-	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		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.GetPredictEdbInfoAll(1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + err.Error()
-		return
-	}
-	edbInfoMap := make(map[int][]*data_manage.EdbClassifyItems)
-	for _, v := range allEdbInfo {
-		// 如果指标不可见,那么就不返回该指标
-		if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
-			continue
-		}
-		button := data.GetPredictEdbOpButton(this.SysUser, v.SysUserId)
-		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
-		button.OpButton = false
-		button.DeleteButton = false
-		v.Button = button
-		if isOnlyMe {
-			if v.SysUserId == this.SysUser.AdminId {
-				edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
-			}
-		} else {
-			edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
-		}
-	}
-	rootTwoList, err := data_manage.GetEdbClassifyByParentIdTwo(1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + err.Error()
-		return
-	}
-	classifyAll, err := data_manage.GetEdbClassifyAllV2(1)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取数据失败,Err:" + err.Error()
-		return
-	}
-	rootTwoMap := make(map[int][]*data_manage.EdbClassifyItems)
-	for _, v := range rootTwoList {
-		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
-		v.Button = button
-		rootTwoMap[v.ParentId] = append(rootTwoMap[v.ParentId], v)
-	}
-	rootTwoChildMap := make(map[int][]*data_manage.EdbClassifyItems)
-	for _, v := range classifyAll {
-		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
-		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 {
-		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
-		v.Button = button
-
-		if existItems, ok := rootTwoMap[v.ClassifyId]; ok {
-			v.Children = existItems
-			for _, item := range existItems {
-				item.Button = button
-
-				if existItems, ok := rootTwoChildMap[item.ClassifyId]; ok {
-					item.Children = existItems
-					for _, existItem := range existItems {
-						if _, ok := noPermissionEdbInfoIdMap[existItem.EdbInfoId]; ok {
-							continue
-						}
-						button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
-						button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
-						existItem.Button = button
-						if isOnlyMe {
-							if existItem.SysUserId == this.SysUser.AdminId {
-								edbInfoMap[existItem.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
-							}
-						} else {
-							edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
-						}
-					}
-				} else {
-					items := make([]*data_manage.EdbClassifyItems, 0)
-					item.Children = items
-				}
-			}
-		} else {
-			items := make([]*data_manage.EdbClassifyItems, 0)
-			v.Children = items
-		}
-		nodeAll = append(nodeAll, v)
-	}
-
-	// 是否允许添加一级分类
-	canOpClassify := true
-	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0)
-	if !button.AddButton {
-		canOpClassify = false
-	}
-
-	language := `CN`
-	// 指标显示的语言
-	{
-		configDetail, _ := system.GetConfigDetailByCode(this.SysUser.AdminId, system.PredictEdbLanguageVar)
-		if configDetail != nil {
-			language = configDetail.ConfigValue
-		} else {
-			configDetail, _ = system.GetDefaultConfigDetailByCode(system.PredictEdbLanguageVar)
-			if configDetail != nil {
-				language = configDetail.ConfigValue
-			}
-		}
-	}
-
-	resp := data_manage.EdbClassifyListResp{
-		AllNodes:      nodeAll,
-		CanOpClassify: canOpClassify,
-		Language:      language,
-	}
-	br.Ret = 200
-	br.Success = true
-	br.Msg = "获取成功"
-	br.Data = resp
-}
+//func (this *PredictEdbClassifyController) ListV2() {
+//	br := new(models.BaseResponse).Init()
+//	defer func() {
+//		this.Data["json"] = br
+//		this.ServeJSON()
+//	}()
+//
+//	isOnlyMe, _ := this.GetBool("IsOnlyMe")
+//
+//	rootList, err := data_manage.GetEdbClassifyByParentId(0, 1)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		br.Msg = "获取失败"
+//		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+//		return
+//	}
+//	// 获取当前账号的不可见指标
+//	obj := data_manage.EdbInfoNoPermissionAdmin{}
+//	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		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.GetPredictEdbInfoAll(1)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		br.Msg = "获取失败"
+//		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+//		return
+//	}
+//	edbInfoMap := make(map[int][]*data_manage.EdbClassifyItems)
+//	for _, v := range allEdbInfo {
+//		// 如果指标不可见,那么就不返回该指标
+//		if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
+//			continue
+//		}
+//		button := data.GetPredictEdbOpButton(this.SysUser, v.SysUserId)
+//		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+//		button.OpButton = false
+//		button.DeleteButton = false
+//		v.Button = button
+//		if isOnlyMe {
+//			if v.SysUserId == this.SysUser.AdminId {
+//				edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+//			}
+//		} else {
+//			edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+//		}
+//	}
+//	rootTwoList, err := data_manage.GetEdbClassifyByParentIdTwo(1)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		br.Msg = "获取失败"
+//		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+//		return
+//	}
+//	classifyAll, err := data_manage.GetEdbClassifyAllV2(1)
+//	if err != nil && err.Error() != utils.ErrNoRow() {
+//		br.Msg = "获取失败"
+//		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+//		return
+//	}
+//	rootTwoMap := make(map[int][]*data_manage.EdbClassifyItems)
+//	for _, v := range rootTwoList {
+//		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
+//		v.Button = button
+//		rootTwoMap[v.ParentId] = append(rootTwoMap[v.ParentId], v)
+//	}
+//	rootTwoChildMap := make(map[int][]*data_manage.EdbClassifyItems)
+//	for _, v := range classifyAll {
+//		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
+//		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 {
+//		button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
+//		v.Button = button
+//
+//		if existItems, ok := rootTwoMap[v.ClassifyId]; ok {
+//			v.Children = existItems
+//			for _, item := range existItems {
+//				item.Button = button
+//
+//				if existItems, ok := rootTwoChildMap[item.ClassifyId]; ok {
+//					item.Children = existItems
+//					for _, existItem := range existItems {
+//						if _, ok := noPermissionEdbInfoIdMap[existItem.EdbInfoId]; ok {
+//							continue
+//						}
+//						button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
+//						button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+//						existItem.Button = button
+//						if isOnlyMe {
+//							if existItem.SysUserId == this.SysUser.AdminId {
+//								edbInfoMap[existItem.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+//							}
+//						} else {
+//							edbInfoMap[v.ClassifyId] = append(edbInfoMap[v.ClassifyId], v)
+//						}
+//					}
+//				} else {
+//					items := make([]*data_manage.EdbClassifyItems, 0)
+//					item.Children = items
+//				}
+//			}
+//		} else {
+//			items := make([]*data_manage.EdbClassifyItems, 0)
+//			v.Children = items
+//		}
+//		nodeAll = append(nodeAll, v)
+//	}
+//
+//	// 是否允许添加一级分类
+//	canOpClassify := true
+//	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0)
+//	if !button.AddButton {
+//		canOpClassify = false
+//	}
+//
+//	language := `CN`
+//	// 指标显示的语言
+//	{
+//		configDetail, _ := system.GetConfigDetailByCode(this.SysUser.AdminId, system.PredictEdbLanguageVar)
+//		if configDetail != nil {
+//			language = configDetail.ConfigValue
+//		} else {
+//			configDetail, _ = system.GetDefaultConfigDetailByCode(system.PredictEdbLanguageVar)
+//			if configDetail != nil {
+//				language = configDetail.ConfigValue
+//			}
+//		}
+//	}
+//
+//	resp := data_manage.EdbClassifyListResp{
+//		AllNodes:      nodeAll,
+//		CanOpClassify: canOpClassify,
+//		Language:      language,
+//	}
+//	br.Ret = 200
+//	br.Success = true
+//	br.Msg = "获取成功"
+//	br.Data = resp
+//}
 
 // SimpleList
 // @Title 单层分类列表
@@ -708,24 +730,56 @@ func (this *PredictEdbClassifyController) SimpleList() {
 			return
 		}
 
-		for _, v := range allEdbInfo {
-			// 如果指标不可见,那么就不返回该指标
-			if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
-				continue
+		if len(allEdbInfo) > 0 {
+			// 查询当前分类信息
+			currClassify, err := data_manage.GetEdbClassifyById(parentId)
+			if err != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取当前分类信息失败,Err:" + err.Error()
+				return
+			}
+			// 获取所有有权限的指标和分类
+			permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.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, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+				// 按钮权限
+				button := data.GetPredictEdbOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
+				button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
+				button.OpButton = false
+				button.DeleteButton = false
+				v.Button = button
+				v.ParentId = parentId
+				v.Children = make([]*data_manage.EdbClassifyItems, 0)
+				nodeAll = append(nodeAll, v)
 			}
-			button := data.GetPredictEdbOpButton(this.SysUser, v.SysUserId)
-			button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
-			button.OpButton = false
-			button.DeleteButton = 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(this.SysUser.AdminId, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
 		for _, v := range rootList {
-			button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
+			// 数据权限
+			v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+			// 按钮权限
+			button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 			v.Button = button
 			v.Children = make([]*data_manage.EdbClassifyItems, 0)
 			nodeAll = append(nodeAll, v)
@@ -739,7 +793,7 @@ func (this *PredictEdbClassifyController) SimpleList() {
 
 	// 是否允许添加一级分类
 	canOpClassify := true
-	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0)
+	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0, true)
 	if !button.AddButton {
 		canOpClassify = false
 	}
@@ -790,8 +844,19 @@ func (this *PredictEdbClassifyController) ClassifyTree() {
 	var sortList data_manage.EdbClassifyItemList
 
 	if len(allList) > 0 {
+		// 已授权分类id
+		permissionClassifyIdList, err := data_manage_permission.GetUserEdbClassifyPermissionList(this.SysUser.AdminId, 0)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取已授权分类id数据失败,Err:" + err.Error()
+			return
+		}
+
 		for k, v := range allList {
-			button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId)
+			// 数据权限
+			v.HaveOperaAuth = data_manage_permission.CheckEdbClassifyPermissionByPermissionIdList(v.IsJoinPermission, v.ClassifyId, permissionClassifyIdList)
+			// 按钮权限
+			button := data.GetPredictEdbClassifyOpButton(this.SysUser, v.SysUserId, v.HaveOperaAuth)
 			allList[k].Button = button
 		}
 		nodeAll = data.GetClassifyTreeRecursive(allList, 0)
@@ -801,7 +866,7 @@ func (this *PredictEdbClassifyController) ClassifyTree() {
 	}
 	// 是否允许添加一级分类
 	canOpClassify := true
-	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0)
+	button := data.GetPredictEdbClassifyOpButton(this.SysUser, 0, true)
 	if !button.AddButton {
 		canOpClassify = false
 	}

+ 268 - 43
controllers/data_manage/predict_edb_info.go

@@ -8,6 +8,7 @@ import (
 	"eta/eta_api/models/data_manage/request"
 	"eta/eta_api/models/data_manage/response"
 	"eta/eta_api/services/data"
+	"eta/eta_api/services/data/data_manage_permission"
 	"eta/eta_api/services/elastic"
 	"eta/eta_api/utils"
 	"fmt"
@@ -127,6 +128,44 @@ func (this *PredictEdbInfoController) EdbChartList() {
 	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
 		list = make([]*data_manage.EdbInfoList, 0)
 	} else {
+		classifyIdList := make([]int, 0)
+		for _, v := range list {
+			classifyIdList = append(classifyIdList, v.ClassifyId)
+		}
+
+		// 指标权限
+		{
+			// 当前的分类
+			classifyMap := make(map[int]*data_manage.EdbClassify)
+			classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+			if err != nil {
+				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
+			}
+
+			for _, v := range list {
+				if currClassify, ok := classifyMap[v.ClassifyId]; ok {
+					v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
+					v.Button = data.GetEdbOpButton(sysUser, v.SysUserId, v.EdbType, v.EdbInfoType, v.HaveOperaAuth)
+				}
+			}
+		}
+
 		page = paging.GetPaging(currentIndex, pageSize, int(dataCount))
 	}
 
@@ -408,6 +447,23 @@ func (this *PredictEdbInfoController) List() {
 		return
 	}
 
+	// 权限校验
+	{
+		classifyMap := make(map[int]*data_manage.EdbClassifyIdItems)
+		for _, v := range classifyList {
+			classifyMap[v.ClassifyId] = v
+		}
+		if currClassify, ok := classifyMap[edbInfoItem.ClassifyId]; ok {
+			haveOperaAuth, err := data_manage_permission.CheckEdbPermission(edbInfoItem.IsJoinPermission, currClassify.IsJoinPermission, this.SysUser.AdminId, edbInfoItem.EdbInfoId, edbInfoItem.ClassifyId)
+			if err != nil {
+				br.Msg = err.Error()
+				br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+				return
+			}
+			edbInfoItem.HaveOperaAuth = haveOperaAuth
+		}
+	}
+
 	resp.Paging = page
 	resp.Item = edbInfoItem
 	resp.ClassifyList = classifyList
@@ -698,8 +754,20 @@ func (this *PredictEdbInfoController) Edit() {
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
 	}
+
+	var haveOperaAuth bool
+	// 数据权限校验
+	{
+		haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.EdbInfoId, edbInfo.ClassifyId, edbInfo.IsJoinPermission, this.SysUser.AdminId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+	}
+
 	// 编辑权限校验
-	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId)
+	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId, haveOperaAuth)
 	if !button.OpButton {
 		br.Msg = "无权限操作"
 		br.IsSendEmail = false
@@ -984,6 +1052,25 @@ func (this *PredictEdbInfoController) Detail() {
 		return
 	}
 
+	edbInfoFull := new(response.EdbInfoFull)
+	edbInfoFull.EdbInfo = edbInfo
+	// 权限校验
+	{
+		classifyMap := make(map[int]*data_manage.EdbClassifyIdItems)
+		for _, v := range classifyList {
+			classifyMap[v.ClassifyId] = v
+		}
+		if currClassify, ok := classifyMap[edbInfo.ClassifyId]; ok {
+			haveOperaAuth, err := data_manage_permission.CheckEdbPermission(edbInfo.IsJoinPermission, currClassify.IsJoinPermission, this.SysUser.AdminId, edbInfo.EdbInfoId, edbInfo.ClassifyId)
+			if err != nil {
+				br.Msg = err.Error()
+				br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+				return
+			}
+			edbInfoFull.HaveOperaAuth = haveOperaAuth
+		}
+	}
+
 	// 拟合残差计算相关系数
 	var correlationStr string
 	if edbInfo.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC {
@@ -1028,7 +1115,7 @@ func (this *PredictEdbInfoController) Detail() {
 	}
 
 	resp := response.PredictEdbInfo{
-		EdbInfo:        *edbInfo,
+		EdbInfoFull:    edbInfoFull,
 		RuleType:       ruleType,
 		FixedValue:     fixedValue,
 		CalculateList:  calculateList,
@@ -1109,6 +1196,8 @@ func (this *PredictEdbInfoController) FilterByEs() {
 		}
 	}
 
+	// 是否走ES
+	isEs := false
 	if keyWord != "" {
 		var keyWordArr []string
 		keyWordArr = append(keyWordArr, keyWord)
@@ -1120,6 +1209,7 @@ func (this *PredictEdbInfoController) FilterByEs() {
 		} else {
 			total, edbInfoList, err = elastic.SearchEdbInfoData(utils.DATA_INDEX_NAME, keyWord, startSize, pageSize, filterSource, source, 1, frequency, noPermissionEdbInfoIdList)
 		}
+		isEs = true
 	} else {
 		var condition string
 		var pars []interface{}
@@ -1168,8 +1258,73 @@ func (this *PredictEdbInfoController) FilterByEs() {
 
 	edbInfoListLen := len(edbInfoList)
 
+	classifyIdList := make([]int, 0)
 	for i := 0; i < edbInfoListLen; i++ {
 		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的话,需要重新查一下指标的信息,主要是为了把是否授权字段找出来
+		if isEs {
+			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++ {
+			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)
+			}
+		}
+
 	}
 
 	for i := 0; i < edbInfoListLen; i++ {
@@ -1306,6 +1461,7 @@ func (this *PredictEdbInfoController) DataList() {
 	if dateType == 5 {
 		isTimeBetween = true
 	}
+	fullEdb := new(response.EdbInfoFull)
 
 	// 获取预测指标信息
 	edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
@@ -1314,6 +1470,29 @@ func (this *PredictEdbInfoController) DataList() {
 		br.ErrMsg = "获取预测指标信息失败,Err:" + err.Error()
 		return
 	}
+	fullEdb.EdbInfo = edbInfo
+	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfo.ClassifyId)
+	if err != nil {
+		br.Msg = err.Error()
+		br.ErrMsg = errMsg
+		return
+	}
+	var currClassifyItem *data_manage.EdbClassifyIdItems
+	for _, v := range classifyList {
+		if v.ClassifyId == edbInfo.ClassifyId {
+			currClassifyItem = v
+			break
+		}
+	}
+	if currClassifyItem != nil {
+		fullEdb.HaveOperaAuth, err = data_manage_permission.CheckEdbPermission(edbInfo.IsJoinPermission, currClassifyItem.IsJoinPermission, sysUser.AdminId, edbInfo.EdbInfoId, edbInfo.ClassifyId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+	}
+
 	maxYear := 0
 	if edbInfo.LatestDate != "" {
 		latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
@@ -1330,44 +1509,43 @@ func (this *PredictEdbInfoController) DataList() {
 		endDate = ""
 	}
 	// 按钮校验
-	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId)
+	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId, fullEdb.HaveOperaAuth)
 	button.AddButton = false
 
-	dataList, _, _, err, _ := data.GetPredictDataListByPredictEdbInfo(edbInfo, startDate, endDate, isTimeBetween)
-	//lenDataList := len(dataList)
-	//if lenDataList > 0 {
-	//	tmpValue := dataList[lenDataList-1]
-	//
-	//	// 如果最大值 小于 预测值,那么将预测值作为最大值数据返回
-	//	if edbInfo.MaxValue < tmpValue.Value {
-	//		edbInfo.MaxValue = tmpValue.Value
-	//	}
-	//
-	//	// 如果最小值 大于 预测值,那么将预测值作为最小值数据返回
-	//	if edbInfo.MinValue > tmpValue.Value {
-	//		edbInfo.MinValue = tmpValue.Value
-	//	}
-	//}
-
-	// 季节性图、公历、农历处理
-	resultDataList, err := data.GetChartDataList(dataList, chartType, calendar, edbInfo.LatestDate, startDate)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfo.ClassifyId)
-	if err != nil {
-		br.Msg = err.Error()
-		br.ErrMsg = errMsg
-		return
-	}
 	resp := response.PredictEdbInfoDataResp{
-		EdbInfo:      edbInfo,
-		DataList:     resultDataList,
+		EdbInfo:      fullEdb,
 		Button:       button,
 		ClassifyList: classifyList,
 	}
+
+	if fullEdb.HaveOperaAuth {
+		dataList, _, _, err, _ := data.GetPredictDataListByPredictEdbInfo(edbInfo, startDate, endDate, isTimeBetween)
+		//lenDataList := len(dataList)
+		//if lenDataList > 0 {
+		//	tmpValue := dataList[lenDataList-1]
+		//
+		//	// 如果最大值 小于 预测值,那么将预测值作为最大值数据返回
+		//	if edbInfo.MaxValue < tmpValue.Value {
+		//		edbInfo.MaxValue = tmpValue.Value
+		//	}
+		//
+		//	// 如果最小值 大于 预测值,那么将预测值作为最小值数据返回
+		//	if edbInfo.MinValue > tmpValue.Value {
+		//		edbInfo.MinValue = tmpValue.Value
+		//	}
+		//}
+
+		// 季节性图、公历、农历处理
+		resultDataList, err := data.GetChartDataList(dataList, chartType, calendar, edbInfo.LatestDate, startDate)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+
+		resp.DataList = resultDataList
+	}
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -1736,8 +1914,20 @@ func (this *PredictEdbInfoController) Modify() {
 		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
 		return
 	}
+
+	var haveOperaAuth bool
+	// 数据权限校验
+	{
+		haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.EdbInfoId, edbInfo.ClassifyId, edbInfo.IsJoinPermission, this.SysUser.AdminId)
+		if err != nil {
+			br.Msg = err.Error()
+			br.ErrMsg = "校验指标权限失败,err:" + err.Error()
+			return
+		}
+	}
+
 	// 编辑权限校验
-	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId)
+	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId, haveOperaAuth)
 	if !button.OpButton {
 		br.Msg = "无权限操作"
 		br.IsSendEmail = false
@@ -1880,17 +2070,52 @@ func (this *PredictEdbInfoController) ClassifyEdbInfoItems() {
 	}
 
 	list := make([]*data_manage.EdbClassifyItems, 0)
-	for _, v := range allEdbInfo {
-		// 如果指标不可见,那么就不返回该指标
-		if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
-			continue
+
+	edbInfoNum := len(allEdbInfo)
+	if edbInfoNum > 0 {
+		classifyIdList := make([]int, 0)
+		for _, v := range allEdbInfo {
+			classifyIdList = append(classifyIdList, v.ClassifyId)
+		}
+
+		classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取分类数据失败,Err:" + err.Error()
+			return
 		}
 
-		button := data.GetEdbOpButton(this.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE)
-		button.AddButton = false //不管有没有权限,指标都是没有添加按钮的
-		v.Button = button
+		// 分类map
+		classifyMap := make(map[int]*data_manage.EdbClassify)
+		for _, v := range classifyList {
+			classifyMap[v.ClassifyId] = v
+		}
 
-		list = append(list, v)
+		// 获取所有有权限的指标和分类
+		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.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(this.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)

+ 1 - 1
controllers/data_stat/edb_source_stat.go

@@ -592,7 +592,7 @@ func (this *EdbSourceStatController) EdbUpdateStat() {
 		baseCond := " and index_code in (" + utils.GetOrmInReplace(len(edbCodeList)) + ")"
 		var basePars []interface{}
 		basePars = append(basePars, edbCodeList)
-		indexList, tErr := data_manage.GetMysteelChemicalIndexList(baseCond, basePars, 0, 1000)
+		indexList, tErr := data_manage.GetMysteelChemicalIndexList(baseCond, basePars, 0, 1000, "")
 		if tErr != nil {
 			br.Msg = "获取初始指标信息失败"
 			br.ErrMsg = "获取初始指标信息失败,Err:" + tErr.Error()

+ 166 - 25
controllers/english_report/en_permission.go

@@ -2,10 +2,11 @@ package english_report
 
 import (
 	"encoding/json"
-	"fmt"
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
+	"eta/eta_api/services"
 	"eta/eta_api/utils"
+	"fmt"
 	"strings"
 	"time"
 )
@@ -44,17 +45,22 @@ func (this *EnPermissionController) Add() {
 		br.ErrMsg = "参数解析失败,Err:" + e.Error()
 		return
 	}
-	req.EnPermissionName = strings.TrimSpace(req.EnPermissionName)
-	if req.EnPermissionName == "" {
+	req.PermissionName = strings.TrimSpace(req.PermissionName)
+	if req.PermissionName == "" {
 		br.Msg = "请输入品种名称"
 		return
 	}
 
+	if req.Enabled != 1 && req.Enabled != 0 {
+		br.Msg = "请设置正确的状态"
+		return
+	}
+
 	// 重名校验
 	existOB := new(models.EnPermission)
 	existCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, models.EnPermissionColumns.EnPermissionName, models.EnPermissionColumns.ParentId)
 	existPars := make([]interface{}, 0)
-	existPars = append(existPars, req.EnPermissionName, req.ParentId)
+	existPars = append(existPars, req.PermissionName, req.ParentId)
 	exist, e := existOB.GetItemByCondition(existCond, existPars)
 	if e != nil && e.Error() != utils.ErrNoRow() {
 		br.Msg = "操作失败"
@@ -65,12 +71,19 @@ func (this *EnPermissionController) Add() {
 		br.Msg = "品种名称已存在"
 		return
 	}
-
-	// 新增
+	// 获取最大的排序值
 	item := new(models.EnPermission)
-	item.EnPermissionName = req.EnPermissionName
+	maxSort, e := item.GetMaxSort()
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "查询品种排序失败, Err: " + e.Error()
+		return
+	}
+	// 新增
+	item.EnPermissionName = req.PermissionName
 	item.ParentId = req.ParentId
-	item.Sort = req.Sort
+	item.Sort = maxSort + 1
+	item.Enabled = req.Enabled
 	item.CreateTime = time.Now().Local()
 	item.ModifyTime = time.Now().Local()
 	if e = item.Create(); e != nil {
@@ -114,12 +127,12 @@ func (this *EnPermissionController) Edit() {
 		br.ErrMsg = "参数解析失败,Err:" + e.Error()
 		return
 	}
-	if req.EnPermissionId <= 0 {
+	if req.PermissionId <= 0 {
 		br.Msg = "参数有误"
 		return
 	}
-	req.EnPermissionName = strings.TrimSpace(req.EnPermissionName)
-	if req.EnPermissionName == "" {
+	req.PermissionName = strings.TrimSpace(req.PermissionName)
+	if req.PermissionName == "" {
 		br.Msg = "请输入品种名称"
 		return
 	}
@@ -128,7 +141,7 @@ func (this *EnPermissionController) Edit() {
 	ob := new(models.EnPermission)
 	existCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s <> ?`, models.EnPermissionColumns.EnPermissionName, models.EnPermissionColumns.ParentId, models.EnPermissionColumns.EnPermissionId)
 	existPars := make([]interface{}, 0)
-	existPars = append(existPars, req.EnPermissionName, req.ParentId, req.EnPermissionId)
+	existPars = append(existPars, req.PermissionName, req.ParentId, req.PermissionId)
 	exist, e := ob.GetItemByCondition(existCond, existPars)
 	if e != nil && e.Error() != utils.ErrNoRow() {
 		br.Msg = "操作失败"
@@ -140,7 +153,7 @@ func (this *EnPermissionController) Edit() {
 		return
 	}
 
-	item, e := ob.GetItemById(req.EnPermissionId)
+	item, e := ob.GetItemById(req.PermissionId)
 	if e != nil {
 		if e.Error() == utils.ErrNoRow() {
 			br.Msg = "品种不存在, 请刷新页面"
@@ -151,11 +164,10 @@ func (this *EnPermissionController) Edit() {
 		return
 	}
 	originPid := item.ParentId
-	item.EnPermissionName = req.EnPermissionName
+	item.EnPermissionName = req.PermissionName
 	item.ParentId = req.ParentId
-	item.Sort = req.Sort
 	item.ModifyTime = time.Now().Local()
-	if e = item.Update([]string{"EnPermissionName", "ParentId", "Sort", "ModifyTime"}); e != nil {
+	if e = item.Update([]string{"EnPermissionName", "ParentId", "ModifyTime"}); e != nil {
 		br.Msg = "操作失败"
 		br.ErrMsg = "更新品种权限失败, Err: " + e.Error()
 		return
@@ -212,8 +224,8 @@ func (this *EnPermissionController) ParentList() {
 	resp := make([]*models.EnPermissionItem, 0)
 	for _, v := range list {
 		t := new(models.EnPermissionItem)
-		t.EnPermissionId = v.EnPermissionId
-		t.EnPermissionName = v.EnPermissionName
+		t.PermissionId = v.EnPermissionId
+		t.PermissionName = v.EnPermissionName
 		t.CnPermissionName = v.CnPermissionName
 		t.ParentId = v.ParentId
 		t.Sort = v.Sort
@@ -255,6 +267,8 @@ func (this *EnPermissionController) List() {
 	keyword := this.GetString("Keyword", "")
 	keyword = strings.TrimSpace(keyword)
 
+	enabled, _ := this.GetInt("Enabled", -1)
+
 	// 禁用指定报告、指定路演无权限的品种
 	reportId, _ := this.GetInt("ReportId", 0)
 	videoId, _ := this.GetInt("VideoId", 0)
@@ -297,9 +311,10 @@ func (this *EnPermissionController) List() {
 	childMap := make(map[int][]*models.EnPermissionItem)
 	for _, v := range list {
 		t := new(models.EnPermissionItem)
-		t.EnPermissionId = v.EnPermissionId
-		t.EnPermissionName = v.EnPermissionName
+		t.PermissionId = v.EnPermissionId
+		t.PermissionName = v.EnPermissionName
 		t.CnPermissionName = v.CnPermissionName
+		t.Enabled = v.Enabled
 		t.ParentId = v.ParentId
 		t.Sort = v.Sort
 		t.CreateTime = v.CreateTime.Format(utils.FormatDateTime)
@@ -309,20 +324,24 @@ func (this *EnPermissionController) List() {
 			continue
 		}
 		if v.ParentId > 0 {
+			if v.Enabled == 0 && enabled == 1 {
+				continue
+			}
 			if childMap[v.ParentId] == nil {
 				childMap[v.ParentId] = make([]*models.EnPermissionItem, 0)
 			}
 			// 无权限则隐藏
-			if (reportId > 0 || videoId > 0) && !utils.InArrayByInt(limitIds, t.EnPermissionId) {
+			if (reportId > 0 || videoId > 0) && !utils.InArrayByInt(limitIds, t.PermissionId) {
 				continue
 			}
 			childMap[v.ParentId] = append(childMap[v.ParentId], t)
 		}
 	}
 	for _, r := range resp {
-		r.Child = childMap[r.EnPermissionId]
+		r.Child = childMap[r.PermissionId]
 	}
 
+	// todo 过滤禁用品种的一级分类,如果一级分类没有二级分类
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -357,13 +376,13 @@ func (this *EnPermissionController) Remove() {
 		br.ErrMsg = "参数解析失败,Err:" + e.Error()
 		return
 	}
-	if req.EnPermissionId <= 0 {
+	if req.PermissionId <= 0 {
 		br.Msg = "参数有误"
 		return
 	}
 
 	ob := new(models.EnPermission)
-	item, e := ob.GetItemById(req.EnPermissionId)
+	item, e := ob.GetItemById(req.PermissionId)
 	if e != nil {
 		if e.Error() == utils.ErrNoRow() {
 			br.Msg = "品种不存在, 请刷新页面"
@@ -377,7 +396,7 @@ func (this *EnPermissionController) Remove() {
 	// 校验是否有子品种
 	childCond := fmt.Sprintf(` AND %s = ?`, models.EnPermissionColumns.ParentId)
 	childPars := make([]interface{}, 0)
-	childPars = append(childPars, req.EnPermissionId)
+	childPars = append(childPars, req.PermissionId)
 	num, e := ob.GetCountByCondition(childCond, childPars)
 	if e != nil {
 		br.Msg = "操作失败"
@@ -418,3 +437,125 @@ func (this *EnPermissionController) Remove() {
 	br.Success = true
 	br.Msg = "操作成功"
 }
+
+// Move
+// @Title 移动品种权限
+// @Description 移动品种权限
+// @Param	request	body models.EnPermissionMoveReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /move [post]
+func (this *EnPermissionController) Move() {
+	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 models.EnPermissionMoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.PermissionId <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+
+	e, msg := services.MoveEnPermission(req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "移动品种失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// SetEnabled
+// @Title 启用/禁用品种
+// @Description 启用/禁用品种
+// @Param	request	body models.EnPermissionEnabledReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /enabled/set [post]
+func (this *EnPermissionController) SetEnabled() {
+	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 models.EnPermissionEnabledReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.PermissionId <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+
+	// 重名校验
+	ob := new(models.EnPermission)
+
+	item, e := ob.GetItemById(req.PermissionId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "品种不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取品种权限失败, Err: " + e.Error()
+		return
+	}
+	item.Enabled = req.Enabled
+	item.ModifyTime = time.Now().Local()
+	if e = item.Update([]string{"Enabled", "ModifyTime"}); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新品种权限失败, Err: " + e.Error()
+		return
+	}
+
+	// 如果是一级品种被启用,则所有二级设置成启用, 如果一级品种被禁用,则所有二级设置成禁用
+	if item.ParentId == 0 {
+		if e = item.SetEnabled(item.EnPermissionId, req.Enabled); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "更新英文分类权限失败, Err: " + e.Error()
+			return
+		}
+	} else if item.ParentId > 0 && req.Enabled == 1 {
+		// 如果二级品种被启用,则他的上级品种设置成启用
+		if e = item.SetEnabledByPermissionId(item.ParentId, req.Enabled); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "更新英文分类权限失败, Err: " + e.Error()
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+	br.Data = item.EnPermissionId
+}

+ 193 - 67
controllers/english_report/english_classify.go

@@ -8,7 +8,6 @@ import (
 	"eta/eta_api/services"
 	"eta/eta_api/utils"
 	"fmt"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"sort"
 	"time"
 )
@@ -33,46 +32,24 @@ func (this *EnglishReportController) ListClassify() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	pageSize, _ := this.GetInt("PageSize")
-	currentIndex, _ := this.GetInt("CurrentIndex")
-	keyWord := this.GetString("KeyWord")
 
-	var startSize int
-	if pageSize <= 0 {
-		pageSize = utils.PageSize20
-	}
-	if currentIndex <= 0 {
-		currentIndex = 1
+	keyWord := this.GetString("KeyWord")
+	reqEnabled, _ := this.GetInt("Enabled", -1)
+	enabled := -1
+	if reqEnabled == 1 {
+		enabled = reqEnabled
 	}
-
-	startSize = utils.StartIndex(currentIndex, pageSize)
-
-	page := paging.GetPaging(currentIndex, pageSize, 0)
 	resp := new(models.EnglishClassifyListResp)
 
 	// 处理一级分类分页的情况
-	rootList, err := models.GetEnglishClassifyRootId(startSize, pageSize, keyWord)
+	rootList, err := models.GetEnglishClassifyRootId(keyWord, enabled)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-	var ids []int
-	var rootIds []int
-	rootMap := make(map[int]struct{}, 0)
-	for _, v := range rootList {
-		rootIds = append(rootIds, v.Id)
-		rootMap[v.Id] = struct{}{}
-	}
-	total, err := models.GetEnglishClassifyListCount(keyWord)
-	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,Err:" + err.Error()
-		return
-	}
-	if total == 0 {
+	if len(rootList) == 0 {
 		resp.List = make([]*models.EnglishClassifyList, 0)
-		resp.Paging = page
 
 		br.Data = resp
 		br.Ret = 200
@@ -80,10 +57,16 @@ func (this *EnglishReportController) ListClassify() {
 		br.Msg = "获取成功"
 		return
 	}
-	page = paging.GetPaging(currentIndex, pageSize, total)
+	var ids []int
+	var rootIds []int
+	rootMap := make(map[int]struct{}, 0)
+	for _, v := range rootList {
+		rootIds = append(rootIds, v.Id)
+		rootMap[v.Id] = struct{}{}
+	}
 
 	//获取相关的分类ID
-	idList, err := models.GetEnglishClassifyListByRootId(rootIds, keyWord)
+	idList, err := models.GetEnglishClassifyListByRootId(rootIds, keyWord, enabled)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
@@ -177,7 +160,6 @@ func (this *EnglishReportController) ListClassify() {
 	sort.Sort(sortList)
 
 	resp.List = sortList
-	resp.Paging = page
 
 	br.Data = resp
 	br.Ret = 200
@@ -191,17 +173,25 @@ func (this *EnglishReportController) ListClassify() {
 // @Param   ParentId   query   int  true       "父级Id 添加父级时为0"
 // @Param   Sort   query   string  false       "排序"
 // @Success 200 新增成功
-// @router /classify/add [get]
+// @router /classify/add [post]
 func (this *EnglishReportController) AddClassify() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	classifyName := this.GetString("ClassifyName")
-	parentId, _ := this.GetInt("ParentId")
-	sort, _ := this.GetInt("Sort")
-
+	//classifyName := this.GetString("ClassifyName")
+	//parentId, _ := this.GetInt("ParentId")
+	var req models.EnClassifyAddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	classifyName := req.ClassifyName
+	parentId := req.ParentId
+	ob := new(models.EnglishClassify)
 	// 查新父级分类是否存在
 	rootId := 0
 	if parentId > 0 {
@@ -221,15 +211,23 @@ func (this *EnglishReportController) AddClassify() {
 			rootId = parentClassify.RootId
 		}
 	}
+	maxSort, e := ob.GetMaxSort()
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "查询品种排序失败, Err: " + e.Error()
+		return
+	}
 
+	nowTime := time.Now().Local()
 	item := &models.EnglishClassify{
 		ClassifyName: classifyName,
-		Sort:         sort,
+		Sort:         maxSort + 1,
 		ParentId:     parentId,
 		RootId:       rootId,
-		CreateTime:   time.Now(),
-		ModifyTime:   time.Now(),
+		CreateTime:   nowTime,
+		ModifyTime:   nowTime,
 		IsShow:       1,
+		Enabled:      1,
 	}
 	counts, err := models.GetEnglishClassifyCountsByName(classifyName, parentId)
 	if err != nil {
@@ -249,8 +247,8 @@ func (this *EnglishReportController) AddClassify() {
 		br.ErrMsg = "保存失败,Err:" + err.Error()
 		return
 	}
+	item.Id = int(newId)
 	if parentId == 0 { //一级目录的rootId等于自己本身
-		item.Id = int(newId)
 		item.RootId = int(newId)
 		err = item.UpdateEnglishClassify([]string{"RootId"})
 		if err != nil {
@@ -260,11 +258,28 @@ func (this *EnglishReportController) AddClassify() {
 		}
 	}
 
+	if item.ParentId != item.RootId && item.ParentId > 0 { //三级分类才能绑定品种权限
+		permissions := make([]*models.EnClassifyPermission, 0)
+		for _, p := range req.EnPermissions {
+			v := new(models.EnClassifyPermission)
+			v.EnPermissionId = p
+			v.EnClassifyId = item.Id
+			v.CreateTime = nowTime
+			permissions = append(permissions, v)
+		}
+		if e = models.CreateEnClassifyPermissions(permissions); e != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = "更新分类品种权限失败, Err: " + e.Error()
+			return
+		}
+	}
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "新增成功"
 }
 
+// EditClassify
 // @Title 编辑分类
 // @Description 编辑分类接口
 // @Param   ClassifyId   int  true       "分类Id"
@@ -272,17 +287,25 @@ func (this *EnglishReportController) AddClassify() {
 // @Param   ParentId   query   int  true       "父级Id 添加父级时为0"
 // @Param   Sort   query   string  false       "排序"
 // @Success 200 保存成功
-// @router /classify/edit [get]
+// @router /classify/edit [post]
 func (this *EnglishReportController) EditClassify() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	classifyId, _ := this.GetInt("ClassifyId")
-	classifyName := this.GetString("ClassifyName")
-	parentId, _ := this.GetInt("ParentId")
-	sort, _ := this.GetInt("Sort")
+
+	var req models.EnClassifyEditReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	classifyId := req.ClassifyId
+	classifyName := req.ClassifyName
+	parentId := req.ParentId
+	//ob := new(models.EnglishClassify)
 
 	if parentId == classifyId {
 		br.Msg = "上级分类不能选择自己"
@@ -359,14 +382,24 @@ func (this *EnglishReportController) EditClassify() {
 	if parentId == 0 { //一级分类的顶级分类为自己的ID
 		rootId = oldItem.Id
 	}
+
+	/*maxSort, e := ob.GetMaxSortByParentId(parentId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "查询品种排序失败, Err: " + e.Error()
+		return
+	}*/
+
+	nowTime := time.Now().Local()
+
 	item := &models.EnglishClassify{
 		Id:           oldItem.Id,
 		ClassifyName: classifyName,
-		Sort:         sort,
-		ParentId:     parentId,
-		RootId:       rootId,
-		ModifyTime:   time.Now(),
-		IsShow:       1,
+		//	Sort:         maxSort + 1,
+		ParentId:   parentId,
+		RootId:     rootId,
+		ModifyTime: nowTime,
+		IsShow:     1,
 	}
 	{
 		// 更新研报里的分类名称
@@ -389,6 +422,23 @@ func (this *EnglishReportController) EditClassify() {
 		br.ErrMsg = "保存失败,Err:" + err.Error()
 		return
 	}
+	// 更新权限
+	if item.ParentId != item.RootId && item.ParentId > 0 { //三级分类才能编辑品种
+		permissions := make([]*models.EnClassifyPermission, 0)
+		for _, p := range req.EnPermissions {
+			v := new(models.EnClassifyPermission)
+			v.EnPermissionId = p
+			v.EnClassifyId = req.ClassifyId
+			v.CreateTime = nowTime
+			permissions = append(permissions, v)
+		}
+		if e = models.ClearAndCreateEnClassifyPermissions(req.ClassifyId, permissions); e != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = "更新分类品种权限失败, Err: " + e.Error()
+			return
+		}
+	}
+
 	err = models.UpdateEnglishReportClassifyByFirstSecondClassifyId(classifyId, parentId)
 	if err != nil {
 		br.Msg = "保存失败"
@@ -511,19 +561,8 @@ func (this *EnglishReportController) FistListClassify() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
-	pageSize, _ := this.GetInt("PageSize")
-	currentIndex, _ := this.GetInt("CurrentIndex")
-
-	var startSize int
-	if pageSize <= 0 {
-		pageSize = utils.PageSize20
-	}
-	if currentIndex <= 0 {
-		currentIndex = 1
-	}
 
-	startSize = utils.StartIndex(currentIndex, pageSize)
-	rootList, err := models.GetEnglishFirstClassifyList(startSize, pageSize)
+	rootList, err := models.GetEnglishFirstClassifyList()
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()
@@ -535,12 +574,10 @@ func (this *EnglishReportController) FistListClassify() {
 		br.ErrMsg = "获取失败,Err:" + err.Error()
 		return
 	}
-	page := paging.GetPaging(currentIndex, pageSize, total)
 	resp := new(models.EnglishClassifyListResp)
 
 	if total == 0 {
 		resp.List = make([]*models.EnglishClassifyList, 0)
-		resp.Paging = page
 
 		br.Data = resp
 		br.Ret = 200
@@ -583,7 +620,6 @@ func (this *EnglishReportController) FistListClassify() {
 	sort.Sort(sortList)
 
 	resp.List = sortList
-	resp.Paging = page
 
 	br.Data = resp
 	br.Ret = 200
@@ -644,3 +680,93 @@ func (this *EnglishClassifyController) PermissionEdit() {
 	br.Success = true
 	br.Msg = "操作成功"
 }
+
+// MoveClassify
+// @Title 移动分类接口
+// @Description 移动分类
+// @Param	request	body models.EnglishClassifyMoveReq true "type json string"
+// @Success 200 新增成功
+// @router /classify/move [post]
+func (this *EnglishReportController) MoveClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.EnglishClassifyMoveReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	e, msg := services.MoveEnglishReportClassify(req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "移动分类失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// SetEnabled
+// @Title 启用/禁用分类接口
+// @Description 启用/禁用分类
+// @Param	request	body models.ClassifyMoveReq true "type json string"
+// @Success 200 新增成功
+// @router /classify/enabled/set [post]
+func (this *EnglishReportController) SetEnabled() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.EnglishClassifySetEnabledReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	if req.Enabled != 0 && req.Enabled != 1 {
+		br.Msg = "请选择正确的启用禁用状态"
+		return
+	}
+	item, err := models.GetEnglishReportClassifyById(req.ClassifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "分类不存在"
+			return
+		}
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item == nil {
+		br.Msg = "分类不存在"
+		return
+	}
+	ob := new(models.EnglishClassify)
+	//设置分类启用、禁用状态
+	err = ob.SetEnabled(req.ClassifyId, req.Enabled)
+	if err != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 19 - 1
controllers/english_report/report.go

@@ -65,6 +65,12 @@ func (this *EnglishReportController) Add() {
 
 	var contentSub string
 	if req.Content != "" {
+		e := utils.ContentXssCheck(req.Content)
+		if e != nil {
+			br.Msg = "存在非法标签"
+			br.ErrMsg = "存在非法标签, Err: " + e.Error()
+			return
+		}
 		content, e := services.FilterReportContentBr(req.Content)
 		if e != nil {
 			br.Msg = "内容去除前后空格失败"
@@ -182,6 +188,12 @@ func (this *EnglishReportController) Edit() {
 	}
 	var contentSub string
 	if req.Content != "" {
+		e := utils.ContentXssCheck(req.Content)
+		if e != nil {
+			br.Msg = "存在非法标签"
+			br.ErrMsg = "存在非法标签, Err: " + e.Error()
+			return
+		}
 		content, e := services.FilterReportContentBr(req.Content)
 		if e != nil {
 			br.Msg = "内容去除前后空格失败"
@@ -956,7 +968,7 @@ func (this *EnglishReportController) Delete() {
 	go func() {
 		_ = services.ResetPPTReport(req.ReportIds, true)
 	}()
-	
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "删除成功"
@@ -1013,6 +1025,12 @@ func (this *EnglishReportController) SaveReportContent() {
 			content = this.GetString("Content")
 		}
 		if content != "" {
+			e := utils.ContentXssCheck(req.Content)
+			if e != nil {
+				br.Msg = "存在非法标签"
+				br.ErrMsg = "存在非法标签, Err: " + e.Error()
+				return
+			}
 			contentClean, e := services.FilterReportContentBr(req.Content)
 			if e != nil {
 				br.Msg = "内容去除前后空格失败"

+ 86 - 0
controllers/message.go

@@ -0,0 +1,86 @@
+package controllers
+
+import (
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage/data_manage_permission"
+	"eta/eta_api/models/report_approve"
+	"fmt"
+)
+
+// MessageController
+// @Description: 消息控制器
+type MessageController struct {
+	BaseAuthController
+}
+
+// UnReadMessageNum
+// @Title 获取未读取的消息数量
+// @Description 获取未读取的消息数量
+// @Success 200 {object} data_manage_permission.MessageDetailListResp
+// @router /unread/num [get]
+func (c *MessageController) UnReadMessageNum() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var unReadReportNum, unReadDataPermissionNum int
+
+	// 获取报告审批消息
+	{
+		cond := fmt.Sprintf(` AND %s = ?`, report_approve.ReportApproveMessageCols.ReceiveUserId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, sysUser.AdminId)
+
+		messageOb := new(report_approve.ReportApproveMessage)
+
+		// 未读消息数
+		cond += fmt.Sprintf(` AND %s = ?`, report_approve.ReportApproveMessageCols.IsRead)
+		pars = append(pars, 0)
+		unreadTotal, e := messageOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取审批消息列表总数失败, Err: " + e.Error()
+			return
+		}
+		unReadReportNum = unreadTotal
+	}
+
+	// 获取资产消息
+	{
+		cond := fmt.Sprintf(` AND %s = ?`, data_manage_permission.DataPermissionMessageCols.ReceiveUserId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, sysUser.AdminId)
+
+		messageOb := new(data_manage_permission.DataPermissionMessage)
+		// 未读消息数
+		cond += fmt.Sprintf(` AND %s = ?`, data_manage_permission.DataPermissionMessageCols.IsRead)
+		pars = append(pars, 0)
+		unreadTotal, e := messageOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取资产消息列表总数失败, Err: " + e.Error()
+			return
+		}
+		unReadDataPermissionNum = unreadTotal
+	}
+
+	// 汇总数
+	num := unReadReportNum + unReadDataPermissionNum
+
+	br.Data = num
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 8 - 8
controllers/ppt_v2.go

@@ -641,14 +641,14 @@ func (this *PptV2Controller) SaveLog() {
 			return
 		}
 	}
-	//pptInfo.TemplateType = req.FirstPage.TemplateType
-	//pptInfo.BackgroundImg = req.FirstPage.ImgUrl
-	//pptInfo.Title = req.FirstPage.Title
-	//pptInfo.ReportType = req.FirstPage.ReportType
-	//pptInfo.PptDate = req.FirstPage.PptDate
-	//pptInfo.Content = req.Content
-	//pptInfo.ModifyTime = time.Now()
-	//err = pptInfo.Update([]string{"TemplateType", "BackgroundImg", "Title", "ReportType", "PptDate", "Content", "ModifyTime"})
+	pptItem.TemplateType = req.FirstPage.TemplateType
+	pptItem.BackgroundImg = req.FirstPage.ImgUrl
+	pptItem.Title = req.FirstPage.Title
+	pptItem.ReportType = req.FirstPage.ReportType
+	pptItem.PptDate = req.FirstPage.PptDate
+	pptItem.Content = req.Content
+	pptItem.ModifyTime = time.Now()
+	err = pptItem.Update([]string{"TemplateType", "BackgroundImg", "Title", "ReportType", "PptDate", "Content", "ModifyTime"})
 
 	//日志记录
 	logInfo := &models.PptV2SaveLog{

+ 109 - 49
controllers/report.go

@@ -10,9 +10,11 @@ import (
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/beego/beego/v2/server/web"
+	"github.com/h2non/filetype"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"github.com/tealeg/xlsx"
 	"html"
+	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -523,6 +525,12 @@ func (this *ReportController) Add() {
 	}
 	var contentSub string
 	if req.Content != "" {
+		e := utils.ContentXssCheck(req.Content)
+		if e != nil {
+			br.Msg = "存在非法标签"
+			br.ErrMsg = "存在非法标签, Err: " + e.Error()
+			return
+		}
 		content, e := services.FilterReportContentBr(req.Content)
 		if e != nil {
 			br.Msg = "内容去除前后空格失败"
@@ -584,22 +592,24 @@ func (this *ReportController) Add() {
 	}
 
 	//处理权限
-	if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
-		go func() {
-			permissionItems, e := models.GetPermission(req.ClassifyNameSecond)
+	//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
+	go func() {
+		permissionItems, e := models.GetPermission(req.ClassifyNameSecond)
+		if e != nil {
+			alarm_msg.SendAlarmMsg("获取权限失败,Err:"+e.Error(), 3)
+			return
+		}
+		for _, v := range permissionItems {
+			e = models.AddChartPermissionChapterMapping(v.ChartPermissionId, newReportId)
 			if e != nil {
-				alarm_msg.SendAlarmMsg("获取权限失败,Err:"+e.Error(), 3)
+				alarm_msg.SendAlarmMsg("新增权限失败,Err:"+e.Error(), 3)
 				return
 			}
-			for _, v := range permissionItems {
-				e = models.AddChartPermissionChapterMapping(v.ChartPermissionId, newReportId)
-				if e != nil {
-					alarm_msg.SendAlarmMsg("新增权限失败,Err:"+e.Error(), 3)
-					return
-				}
-			}
-		}()
-	}
+		}
+		// 同步crm权限
+		_ = services.EditReportPermissionSync(newReportId, req.ClassifyNameSecond)
+	}()
+	//}
 
 	recordItem := &models.ReportStateRecord{
 		ReportId:   int(newReportId),
@@ -655,6 +665,12 @@ func (this *ReportController) Edit() {
 	}
 	var contentSub string
 	if req.Content != "" {
+		e := utils.ContentXssCheck(req.Content)
+		if e != nil {
+			br.Msg = "存在非法标签"
+			br.ErrMsg = "存在非法标签, Err: " + e.Error()
+			return
+		}
 		content, e := services.FilterReportContentBr(req.Content)
 		if e != nil {
 			br.Msg = "内容去除前后空格失败"
@@ -741,27 +757,29 @@ func (this *ReportController) Edit() {
 	}
 
 	//处理权限
-	if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
-		go func() {
-			e := models.RemoveChartPermissionChapterMapping(req.ReportId)
-			if e != nil {
-				alarm_msg.SendAlarmMsg("修改删除报告权限失败,Err:"+e.Error(), 3)
-				return
-			}
-			permissionItems, e := models.GetPermission(req.ClassifyNameSecond)
+	//if utils.BusinessCode == utils.BusinessCodeRelease || utils.BusinessCode == utils.BusinessCodeSandbox {
+	go func() {
+		e := models.RemoveChartPermissionChapterMapping(req.ReportId)
+		if e != nil {
+			alarm_msg.SendAlarmMsg("修改删除报告权限失败,Err:"+e.Error(), 3)
+			return
+		}
+		permissionItems, e := models.GetPermission(req.ClassifyNameSecond)
+		if e != nil {
+			alarm_msg.SendAlarmMsg("获取权限失败,Err:"+e.Error(), 3)
+			return
+		}
+		for _, v := range permissionItems {
+			e = models.AddChartPermissionChapterMapping(v.ChartPermissionId, req.ReportId)
 			if e != nil {
-				alarm_msg.SendAlarmMsg("获取权限失败,Err:"+e.Error(), 3)
+				alarm_msg.SendAlarmMsg("新增权限失败,Err:"+e.Error(), 3)
 				return
 			}
-			for _, v := range permissionItems {
-				e = models.AddChartPermissionChapterMapping(v.ChartPermissionId, req.ReportId)
-				if e != nil {
-					alarm_msg.SendAlarmMsg("新增权限失败,Err:"+e.Error(), 3)
-					return
-				}
-			}
-		}()
-	}
+		}
+		// 同步crm权限
+		_ = services.EditReportPermissionSync(req.ReportId, req.ClassifyNameSecond)
+	}()
+	//}
 
 	reportCode := utils.MD5(strconv.Itoa(int(req.ReportId)))
 	resp := new(models.EditResp)
@@ -907,6 +925,20 @@ func (this *ReportController) Upload() {
 		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
 		return
 	}
+
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "读取文件失败, Err: " + e.Error()
+		return
+	}
+	pass := filetype.IsImage(fileData)
+	if !pass {
+		br.Msg = "文件格式有误"
+		br.ErrMsg = "文件格式有误"
+		return
+	}
+
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
@@ -1187,6 +1219,12 @@ func (this *ReportController) SaveReportContent() {
 			content = this.GetString("Content")
 		}
 		if content != "" {
+			e := utils.ContentXssCheck(req.Content)
+			if e != nil {
+				br.Msg = "存在非法标签"
+				br.ErrMsg = "存在非法标签, Err: " + e.Error()
+				return
+			}
 			contentClean, e := services.FilterReportContentBr(req.Content)
 			if e != nil {
 				br.Msg = "内容去除前后空格失败"
@@ -1238,6 +1276,20 @@ func (this *ReportUploadCommonController) UploadImg() {
 	if err != nil {
 		return
 	}
+	defer f.Close() //关闭上传文件
+
+	// 不依赖于文件扩展名检查文件格式
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		err = fmt.Errorf("读取文件失败, Err: %s", e.Error())
+		return
+	}
+	pass := filetype.IsImage(fileData)
+	if !pass {
+		err = fmt.Errorf("文件格式有误")
+		return
+	}
+
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
@@ -1248,24 +1300,16 @@ func (this *ReportUploadCommonController) UploadImg() {
 	randStr := utils.GetRandStringNoSpecialChar(28)
 	fileName := randStr + ext
 	fpath := uploadDir + "/" + fileName
-	defer f.Close() //关闭上传文件
 	err = this.SaveToFile("file", fpath)
 	if err != nil {
 		return
 	}
+	defer func() {
+		os.Remove(fpath)
+	}()
+
+	// 上传至对象存储
 	resourceUrl := ``
-	//上传到阿里云 和 minio
-	//if utils.ObjectStorageClient == "minio" {
-	//	resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
-	//	if err != nil {
-	//		return
-	//	}
-	//} else {
-	//	resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
-	//	if err != nil {
-	//		return
-	//	}
-	//}
 	ossClient := services.NewOssClient()
 	if ossClient == nil {
 		err = fmt.Errorf("初始化OSS服务失败")
@@ -1277,10 +1321,6 @@ func (this *ReportUploadCommonController) UploadImg() {
 		return
 	}
 
-	defer func() {
-		os.Remove(fpath)
-	}()
-
 	item := new(models.Resource)
 	item.ResourceUrl = resourceUrl
 	item.ResourceType = 1
@@ -1785,7 +1825,11 @@ func (this *ReportController) SetDayWeekReportUpdateRule() {
 		br.ErrMsg = "设置暂停时间失败, Err: " + err.Error()
 		return
 	}
-
+	// 同步到crm数据库
+	go func() {
+		var syncReq services.ChapterTypeSyncReq
+		_, _ = services.ReportChapterTypeSync(&syncReq)
+	}()
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"
@@ -1840,6 +1884,10 @@ func (this *ReportController) SetDayWeekReportEnableRule() {
 		br.ErrMsg = "设置永久停更失败, Err: " + err.Error()
 		return
 	}
+	go func() {
+		var syncReq services.ChapterTypeSyncReq
+		_, _ = services.ReportChapterTypeSync(&syncReq)
+	}()
 
 	br.Ret = 200
 	br.Success = true
@@ -2411,6 +2459,12 @@ func (this *ReportController) EditDayWeekChapter() {
 	// 更新章节及指标
 	contentSub := ""
 	if req.Content != "" {
+		e := utils.ContentXssCheck(req.Content)
+		if e != nil {
+			br.Msg = "存在非法标签"
+			br.ErrMsg = "存在非法标签, Err: " + e.Error()
+			return
+		}
 		contentClean, e := services.FilterReportContentBr(req.Content)
 		if e != nil {
 			br.Msg = "内容去除前后空格失败"
@@ -2882,6 +2936,12 @@ func (this *ReportController) PublishDayWeekReportChapter() {
 	// 更新章节信息
 	contentSub := ""
 	if req.Content != "" {
+		e := utils.ContentXssCheck(req.Content)
+		if e != nil {
+			br.Msg = "存在非法标签"
+			br.ErrMsg = "存在非法标签, Err: " + e.Error()
+			return
+		}
 		contentClean, e := services.FilterReportContentBr(req.Content)
 		if e != nil {
 			br.Msg = "内容去除前后空格失败"

+ 239 - 57
controllers/report_chapter_type.go

@@ -2,8 +2,8 @@ package controllers
 
 import (
 	"encoding/json"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"eta/eta_api/models"
+	"eta/eta_api/services"
 	"eta/eta_api/utils"
 	"time"
 )
@@ -39,35 +39,29 @@ func (this *ReportChapterTypeController) List() {
 		br.Msg = "请选择报告类型"
 		return
 	}
-
-	pageSize, _ := this.GetInt("PageSize")
-	currentIndex, _ := this.GetInt("CurrentIndex")
-	var startSize int
-	if pageSize <= 0 {
-		pageSize = utils.PageSize20
-	}
-	if currentIndex <= 0 {
-		currentIndex = 1
-	}
-	startSize = paging.StartIndex(currentIndex, pageSize)
-
 	cond := ` AND research_type = ?`
 	pars := make([]interface{}, 0)
 	pars = append(pars, reportType)
-	total, e := models.GetReportChapterTypeCount(cond, pars)
+	list, e := models.GetReportChapterTypePageList(cond, pars)
 	if e != nil {
 		br.Msg = "获取失败"
-		br.ErrMsg = "获取报告章节列表总数失败, Err: " + e.Error()
+		br.ErrMsg = "获取报告章节列表失败, Err: " + e.Error()
 		return
 	}
-	list, e := models.GetReportChapterTypePageList(cond, pars, startSize, pageSize)
+	mappingList, e := models.GetChapterTypePermissionByResearchType(reportType)
 	if e != nil {
 		br.Msg = "获取失败"
-		br.ErrMsg = "获取报告章节列表失败, Err: " + e.Error()
+		br.ErrMsg = "获取章节类型权限列表失败, Err: " + e.Error()
 		return
 	}
+	mappingMap := make(map[int][]int)
+	for _, v := range mappingList {
+		mappingMap[v.ReportChapterTypeId] = append(mappingMap[v.ReportChapterTypeId], v.ChartPermissionId)
+	}
+
 	respList := make([]*models.ReportChapterTypeListItem, 0)
 	for i := range list {
+		permissionIds, _ := mappingMap[list[i].ReportChapterTypeId]
 		respList = append(respList, &models.ReportChapterTypeListItem{
 			ReportChapterTypeId:   list[i].ReportChapterTypeId,
 			ReportChapterTypeName: list[i].ReportChapterTypeName,
@@ -79,13 +73,13 @@ func (this *ReportChapterTypeController) List() {
 			WordsImage:            list[i].YbBottomIcon, // 此处的不一样
 			EditImgUrl:            list[i].EditImgUrl,
 			IsShow:                list[i].IsShow,
+			Enabled:               list[i].Enabled,
+			ChartPermissionIdList: permissionIds,
 		})
 	}
 
-	resp := new(models.ReportChapterTypePageListResp)
-	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.ReportChapterTypeListResp)
 	resp.List = respList
-	resp.Paging = page
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -144,38 +138,83 @@ func (this *ReportChapterTypeController) Add() {
 
 	nowTime := time.Now().Local()
 	item := new(models.ReportChapterType)
+	maxSort, e := item.GetMaxSort()
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取章节最大排序失败, Err:" + e.Error()
+		return
+	}
 	item.ReportChapterTypeName = req.ReportChapterTypeName
-	item.Sort = req.Sort
+	item.Sort = maxSort + 1
 	item.Enabled = 1
 	item.CreatedTime = nowTime
 	item.LastUpdatedTime = nowTime
 	item.ResearchType = req.ResearchType
-	item.ReportChapterTypeName = req.ReportChapterTypeName
-	item.SelectedImage = req.SelectedImage
-	item.UnselectedImage = req.UnselectedImage
-	item.PcSelectedImage = req.SelectedImage
-	item.PcUnselectedImage = req.UnselectedImage
-	item.EditImgUrl = req.EditImgUrl
 	item.IsSet = 0
-	item.YbIconUrl = req.UnselectedImage
-	item.YbBottomIcon = req.WordsImage
-	item.IsShow = req.IsShow
-	item.ReportChapterTypeThumb = req.EditImgUrl
-	item.BannerUrl = req.UnselectedImage
 	item.ReportChapterTypeKey = req.ReportChapterTypeName
 	item.TickerTitle = req.ReportChapterTypeName
+
 	if e = item.Create(); e != nil {
 		br.Msg = "操作失败"
 		br.ErrMsg = "新增报告章节失败, Err:" + e.Error()
 		return
 	}
 
+	// todo 更新章节权限
+	cond = ` and product_id=1`
+	pars = make([]interface{}, 0)
+	permissionList, e := services.GetChartPermissionList(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取品种列表失败, Err: " + e.Error()
+		return
+	}
+	permissionIdName := make(map[int]string)
+	for i := range permissionList {
+		permissionIdName[permissionList[i].ChartPermissionId] = permissionList[i].PermissionName
+	}
+
+	researchType := item.ResearchType
+	newPermissions := make([]*models.ReportChapterTypePermission, 0)       // 报告章节权限表(新)
+	newWeekPermissions := make([]*models.ChartPermissionChapterMapping, 0) // 报告章节权限表(老)
+	for i := range req.ChartPermissionIdList {
+		newPermissions = append(newPermissions, &models.ReportChapterTypePermission{
+			ReportChapterTypeId:   item.ReportChapterTypeId,
+			ReportChapterTypeName: item.ReportChapterTypeName,
+			ChartPermissionId:     req.ChartPermissionIdList[i],
+			PermissionName:        permissionIdName[req.ChartPermissionIdList[i]],
+			ResearchType:          researchType,
+			CreatedTime:           nowTime,
+		})
+		if researchType == utils.REPORT_TYPE_WEEK {
+			newWeekPermissions = append(newWeekPermissions, &models.ChartPermissionChapterMapping{
+				ChartPermissionId:   req.ChartPermissionIdList[i],
+				ReportChapterTypeId: item.ReportChapterTypeId,
+				ResearchType:        researchType,
+			})
+		}
+	}
+
+	// 设置权限
+	e = models.SetReportChapterTypePermission(item.ReportChapterTypeId, researchType, newPermissions, newWeekPermissions)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "设置章节类型权限失败, Err: " + e.Error()
+		return
+	}
 	// 清除小程序端的章节缓存
 	{
 		key := "hongze_yb:report_chapter_type:GetEffectTypeID"
 		_ = utils.Rc.Delete(key)
 	}
 
+	//todo 同步更新crm章节权限和章节类型
+	go func() {
+		var syncReq services.ChapterTypeSyncReq
+		syncReq.ResearchType = researchType
+		syncReq.ReportChapterTypeId = item.ReportChapterTypeId
+		_, _ = services.ReportChapterTypeSync(&syncReq)
+	}()
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"
@@ -242,36 +281,54 @@ func (this *ReportChapterTypeController) Edit() {
 		return
 	}
 	originName := item.ReportChapterTypeName
+	//更新章节权限
+	// todo 更新章节权限
+	cond = ` and product_id=1`
+	pars = make([]interface{}, 0)
+	permissionList, e := services.GetChartPermissionList(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取品种列表失败, Err: " + e.Error()
+		return
+	}
+	permissionIdName := make(map[int]string)
+	nowTime := time.Now().Local()
+	for i := range permissionList {
+		permissionIdName[permissionList[i].ChartPermissionId] = permissionList[i].PermissionName
+	}
 
-	item.ReportChapterTypeName = req.ReportChapterTypeName
-	item.Sort = req.Sort
-	item.ResearchType = req.ResearchType
-	item.SelectedImage = req.SelectedImage
-	item.UnselectedImage = req.UnselectedImage
-	item.PcSelectedImage = req.SelectedImage
-	item.PcUnselectedImage = req.UnselectedImage
-	item.EditImgUrl = req.EditImgUrl
-	item.YbIconUrl = req.UnselectedImage
-	item.YbBottomIcon = req.WordsImage
-	item.IsShow = req.IsShow
-	item.ReportChapterTypeThumb = req.EditImgUrl
-	item.BannerUrl = req.UnselectedImage
-	item.ReportChapterTypeKey = req.ReportChapterTypeName
-	item.TickerTitle = req.ReportChapterTypeName
-	updateCols := []string{"ReportChapterTypeName", "Sort", "ResearchType", "SelectedImage", "UnselectedImage",
-		"PcSelectedImage", "PcUnselectedImage", "EditImgUrl", "YbIconUrl", "YbBottomIcon", "IsShow",
-		"ReportChapterTypeThumb", "BannerUrl", "ReportChapterTypeKey", "TickerTitle",
+	researchType := item.ResearchType
+	newPermissions := make([]*models.ReportChapterTypePermission, 0)       // 报告章节权限表(新)
+	newWeekPermissions := make([]*models.ChartPermissionChapterMapping, 0) // 报告章节权限表(老)
+	for i := range req.ChartPermissionIdList {
+		newPermissions = append(newPermissions, &models.ReportChapterTypePermission{
+			ReportChapterTypeId:   item.ReportChapterTypeId,
+			ReportChapterTypeName: item.ReportChapterTypeName,
+			ChartPermissionId:     req.ChartPermissionIdList[i],
+			PermissionName:        permissionIdName[req.ChartPermissionIdList[i]],
+			ResearchType:          researchType,
+			CreatedTime:           nowTime,
+		})
+		if researchType == utils.REPORT_TYPE_WEEK {
+			newWeekPermissions = append(newWeekPermissions, &models.ChartPermissionChapterMapping{
+				ChartPermissionId:   req.ChartPermissionIdList[i],
+				ReportChapterTypeId: item.ReportChapterTypeId,
+				ResearchType:        researchType,
+			})
+		}
 	}
-	if e = item.Update(updateCols); e != nil {
+
+	// 设置权限
+	e = models.SetReportChapterTypePermission(item.ReportChapterTypeId, researchType, newPermissions, newWeekPermissions)
+	if e != nil {
 		br.Msg = "操作失败"
-		br.ErrMsg = "更新报告章节失败, Err:" + e.Error()
+		br.ErrMsg = "设置章节类型权限失败, Err: " + e.Error()
 		return
 	}
-
 	// 更新研报章节表冗余
 	if originName != req.ReportChapterTypeName {
 		go func() {
-			_ = models.UpdateReportChapterTypeNameByTypeId(item.ReportChapterTypeId, req.ReportChapterTypeName)
+			_ = models.UpdateReportChapterTypeNameByTypeId(req.ReportChapterTypeId, req.ReportChapterTypeName)
 		}()
 	}
 
@@ -281,6 +338,12 @@ func (this *ReportChapterTypeController) Edit() {
 		_ = utils.Rc.Delete(key)
 	}
 
+	go func() {
+		var syncReq services.ChapterTypeSyncReq
+		syncReq.ResearchType = researchType
+		syncReq.ReportChapterTypeId = item.ReportChapterTypeId
+		_, _ = services.ReportChapterTypeSync(&syncReq)
+	}()
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"
@@ -398,10 +461,12 @@ func (this *ReportChapterTypeController) AuthSetting() {
 		br.Msg = "章节不存在或已被删除"
 		return
 	}
-	permissionList, e := models.GetChartPermissionList()
+	cond := ` and product_id=1`
+	pars := make([]interface{}, 0)
+	permissionList, e := services.GetChartPermissionList(cond, pars)
 	if e != nil {
-		br.Msg = "操作失败"
-		br.ErrMsg = "获取权限列表失败, Err: " + e.Error()
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取品种列表失败, Err: " + e.Error()
 		return
 	}
 	permissionIdName := make(map[int]string)
@@ -500,3 +565,120 @@ func (this *ReportChapterTypeController) PermissionList() {
 	br.Msg = "获取成功"
 	br.Data = respList
 }
+
+// Move
+// @Title 移动章节类型
+// @Description 移动章节类型
+// @Param	request	body models.PermissionMoveReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /chapter_type/move [post]
+func (this *ReportChapterTypeController) Move() {
+	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 models.ReportChapterTypeMoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+
+	if req.ReportChapterTypeId == 0 {
+		br.Msg = "请选择要移动的章节类型"
+		return
+	}
+	e, msg := services.MoveReportChapterType(&req)
+	if e != nil {
+		br.Msg = msg
+		br.ErrMsg = "移动品种失败, Err: " + e.Error()
+		return
+	}
+	go func() {
+		var syncReq services.ChapterTypeSyncReq
+		_, _ = services.ReportChapterTypeSync(&syncReq)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// SetEnabled
+// @Title 设置启用/禁用
+// @Description 移动章节类型
+// @Param	request	body models.PermissionMoveReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /chapter_type/enabled/set [post]
+func (this *ReportChapterTypeController) SetEnabled() {
+	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 models.ReportChapterTypeEnabledReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+
+	if req.ReportChapterTypeId == 0 {
+		br.Msg = "请选择正确的章节类型"
+		return
+	}
+	if req.Enabled != 0 && req.Enabled != 1 {
+		br.Msg = "请选择正确的启用禁用状态"
+		return
+	}
+	ob := new(models.ReportChapterType)
+	item, err := models.GetReportChapterTypeById(req.ReportChapterTypeId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "章节不存在"
+			br.ErrMsg = "章节不存在, Err:" + err.Error()
+			return
+		}
+		br.Msg = "获取章节信息失败"
+		br.ErrMsg = "获取章节信息失败, Err:" + err.Error()
+		return
+	}
+	if item == nil {
+		br.Msg = "章节不存在"
+		return
+	}
+	//设置分类启用、禁用状态
+	err = ob.SetEnabled(req.ReportChapterTypeId, req.Enabled)
+	if err != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "设置报告章节状态失败, Err: " + err.Error()
+		return
+	}
+	go func() {
+		var syncReq services.ChapterTypeSyncReq
+		_, _ = services.ReportChapterTypeSync(&syncReq)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 176 - 0
controllers/resource.go

@@ -2,12 +2,16 @@ package controllers
 
 import (
 	"bufio"
+	"encoding/base64"
 	"eta/eta_api/models"
 	"eta/eta_api/services"
 	"eta/eta_api/utils"
 	"fmt"
+	"github.com/h2non/filetype"
 	"github.com/kgiannakakis/mp3duration/src/mp3duration"
 	"io"
+	"io/ioutil"
+	"net/http"
 	"os"
 	"path"
 	"regexp"
@@ -21,6 +25,11 @@ type ResourceController struct {
 	BaseCommonController
 }
 
+// ResourceAuthController 文件资源
+type ResourceAuthController struct {
+	BaseAuthController
+}
+
 // @Title 图片上传
 // @Description 图片上传接口
 // @Param   file   query   file  true       "文件"
@@ -38,6 +47,20 @@ func (this *ResourceController) Upload() {
 		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
 		return
 	}
+
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "读取文件失败, Err: " + e.Error()
+		return
+	}
+	pass := filetype.IsImage(fileData)
+	if !pass {
+		br.Msg = "文件格式有误"
+		br.ErrMsg = "文件格式有误"
+		return
+	}
+
 	uploadFileName := h.Filename //上传的文件名
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
@@ -135,6 +158,20 @@ func (this *ResourceController) VideoUpload() {
 		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
 		return
 	}
+
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "读取文件失败, Err: " + e.Error()
+		return
+	}
+	pass := filetype.IsVideo(fileData)
+	if !pass {
+		br.Msg = "文件格式有误"
+		br.ErrMsg = "文件格式有误"
+		return
+	}
+
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
@@ -347,6 +384,19 @@ func (this *ResourceController) VoiceUpload() {
 	}
 	uploadFileName := h.Filename //上传的文件名
 
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "读取文件失败, Err: " + e.Error()
+		return
+	}
+	pass := filetype.IsAudio(fileData)
+	if !pass {
+		br.Msg = "文件格式有误"
+		br.ErrMsg = "文件格式有误"
+		return
+	}
+
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
@@ -605,6 +655,20 @@ func (this *ResourceController) UploadImageBase64() {
 			br.ErrMsg = "获取资源信息失败,Err:" + e.Error()
 			return
 		}
+
+		fileData, e := ioutil.ReadAll(f)
+		if e != nil {
+			br.Msg = "上传失败"
+			br.ErrMsg = "读取文件失败, Err: " + e.Error()
+			return
+		}
+		pass := filetype.IsImage(fileData)
+		if !pass {
+			br.Msg = "文件格式有误"
+			br.ErrMsg = "文件格式有误"
+			return
+		}
+
 		ext = path.Ext(h.Filename)
 		dateDir := time.Now().Format("20060102")
 		uploadDir = utils.STATIC_DIR + "hongze/" + dateDir
@@ -785,6 +849,20 @@ func (this *ResourceController) UploadV2() {
 		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
 		return
 	}
+
+	fileData, e := ioutil.ReadAll(f)
+	if e != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "读取文件失败, Err: " + e.Error()
+		return
+	}
+	pass := filetype.IsImage(fileData)
+	if !pass {
+		br.Msg = "文件格式有误"
+		br.ErrMsg = "文件格式有误"
+		return
+	}
+
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
@@ -914,3 +992,101 @@ func (this *ResourceController) OssSTSToken() {
 	//	br.Success = true
 	//}
 }
+
+// FileDownload
+// @Title 文件下载
+// @Description 文件下载
+// @Param   FileUrl  query  string  true  "文件路径"
+// @Success 200 Ret=200 操作成功
+// @router /file/download [get]
+func (this *ResourceAuthController) FileDownload() {
+	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
+	}
+	//fileName := this.GetString("FileName")
+	//fileName = strings.TrimSpace(fileName)
+	//if fileName == "" {
+	//	br.Msg = "参数有误"
+	//	return
+	//}
+	fileEncode := this.GetString("FileUrl")
+	fileEncode = strings.TrimSpace(fileEncode)
+	if fileEncode == "" {
+		br.Msg = "参数有误"
+		return
+	}
+	fileByte, e := base64.StdEncoding.DecodeString(fileEncode)
+	if e != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "文件地址解析失败, Err: " + e.Error()
+		return
+	}
+	fileUrl := string(fileByte)
+	fileArr := strings.Split(fileUrl, "/")
+	if len(fileArr) == 0 {
+		br.Msg = "文件地址有误"
+		return
+	}
+	fileName := fileArr[len(fileArr)-1]
+	//fmt.Println(fileName)
+
+	// 获取文件
+	down, e := http.Get(fileUrl)
+	if e != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "文件下载失败, http get: " + e.Error()
+		return
+	}
+	defer down.Body.Close()
+	if down.StatusCode != http.StatusOK {
+		br.Msg = "下载失败"
+		br.ErrMsg = fmt.Sprintf("文件下载失败, http status: %d", down.StatusCode)
+		return
+	}
+
+	// 生成本地文件
+	localFilePath := fmt.Sprintf("%s%s", utils.GetRandStringNoSpecialChar(6), fileName)
+	localFile, e := os.Create(localFilePath)
+	if e != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "生成本地文件失败, Err: " + e.Error()
+		return
+	}
+	defer func() {
+		if e = localFile.Close(); e != nil {
+			fmt.Println("local file close err: ", e.Error())
+		}
+		if e = os.Remove(localFilePath); e != nil {
+			fmt.Println("local file remove err: ", e.Error())
+		}
+	}()
+
+	// 写入响应流
+	//_, e = io.Copy(this.Ctx.ResponseWriter, down.Body)
+	_, e = io.Copy(localFile, down.Body)
+	if e != nil {
+		br.Msg = "下载失败"
+		br.ErrMsg = "复制文件资源失败, Err: " + e.Error()
+		return
+	}
+	// 设置响应头
+	//this.Ctx.ResponseWriter.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
+	//this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/octet-stream")
+
+	br.Ret = 200
+	br.Msg = "下载成功"
+	br.Success = true
+	this.Ctx.Output.Download(localFilePath, fileName)
+}

+ 1141 - 0
controllers/speech_recognition/speech_recognition.go

@@ -0,0 +1,1141 @@
+package speech_recognition
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/services"
+	"eta/eta_api/services/alarm_msg"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"os"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type SpeechRecognitionController struct {
+	controllers.BaseAuthController
+}
+
+type SpeechRecognitionCommonController struct {
+	controllers.BaseCommonController
+}
+
+// RecTaskCallback
+// @Title 语音识别回调
+// @Description 语音识别回调
+// @Param	request	body services.TencentRecTaskCallback true "type json string"
+// @Success 200 string "操作成功"
+// @router /rec_task/callback [post]
+func (this *SpeechRecognitionCommonController) RecTaskCallback() {
+	// 此接口返回指定响应体
+	br := new(services.TencentRecTaskCallbackResp)
+	var errMsg string
+	defer func() {
+		if errMsg != "" {
+			br.Code = 403
+			br.Message = "回调失败"
+			go alarm_msg.SendAlarmMsg(fmt.Sprintf("语音识别回调失败, ErrMsg: %s", errMsg), 1)
+		} else {
+			br.Code = 0
+			br.Message = "success"
+		}
+		_ = this.JSON(br, false, false)
+	}()
+
+	code, _ := this.GetInt("code", -1)
+	requestId, _ := this.GetInt("requestId", 0)
+	detail := this.GetString("resultDetail")
+	utils.FileLog.Info(fmt.Sprintf("RecTaskCallback, requestId: %d", requestId))
+
+	// 获取taskId对应的API请求及语音识别
+	logOb := new(speech_recognition.SpeechRecognitionApiLog)
+	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionApiLogCols.RequestId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, requestId)
+	apiLog, e := logOb.GetItemByCondition(cond, pars, "")
+	if e != nil {
+		errMsg = "获取API记录失败"
+		utils.FileLog.Info("API回调-获取请求记录失败, Err: " + e.Error())
+		return
+	}
+	speechOb := new(speech_recognition.SpeechRecognition)
+	speechItem, e := speechOb.GetItemById(apiLog.SpeechRecognitionId)
+	if e != nil {
+		errMsg = "获取语音识别失败"
+		utils.FileLog.Info("获取语音识别失败, Err: " + e.Error())
+		return
+	}
+
+	// API结果返回有误
+	nowTime := time.Now().Local()
+	if code != speech_recognition.ApiRequestCodeSuccess {
+		convertRemark := speech_recognition.ApiErrMsgMapping[code]
+		if convertRemark == "" {
+			convertRemark = fmt.Sprintf("未知错误: %d", code)
+		}
+		speechItem.ConvertRemark = convertRemark
+		speechItem.State = speech_recognition.SpeechRecognitionStateFail
+		speechItem.ModifyTime = nowTime
+		speechCols := []string{speech_recognition.SpeechRecognitionCols.ConvertRemark, speech_recognition.SpeechRecognitionCols.State, speech_recognition.SpeechRecognitionCols.ModifyTime}
+
+		apiLog.RequestCode = code
+		apiLog.RequestResult = convertRemark
+		apiLog.ModifyTime = nowTime
+		apiLogCols := []string{speech_recognition.SpeechRecognitionApiLogCols.RequestCode, speech_recognition.SpeechRecognitionApiLogCols.RequestResult, speech_recognition.SpeechRecognitionApiLogCols.ModifyTime}
+
+		// 更新语音识别及API记录
+		if e := speech_recognition.UpdateSpeechAndApiLog(speechItem, speechCols, apiLog, apiLogCols); e != nil {
+			errMsg = "更新API返回结果失败"
+			utils.FileLog.Info("更新API返回结果失败, Err: " + e.Error())
+		}
+		return
+	}
+
+	// 解析转写段落内容
+	sentences := make([]*services.TencentRecTaskSentenceDetail, 0)
+	if e := json.Unmarshal([]byte(detail), &sentences); e != nil {
+		errMsg = "解析语音识别内容失败"
+		utils.FileLog.Info("解析语音识别内容失败, Err: " + e.Error())
+		return
+	}
+	contents := make([]*speech_recognition.SpeechRecognitionContent, 0)
+	sorts := 0 // API返回的结果本身是已排过序的
+	var abstract string
+	var abstractLimit int
+	for _, v := range sentences {
+		sorts += 1
+		t := new(speech_recognition.SpeechRecognitionContent)
+		t.SpeechRecognitionId = speechItem.SpeechRecognitionId
+		t.Sort = sorts
+		t.Content = v.FinalSentence
+		t.StartMs = v.StartMs
+		t.EndMs = v.EndMs
+		t.CreateTime = nowTime
+		t.ModifyTime = nowTime
+		contents = append(contents, t)
+		// 取前几段作为摘要保存
+		if abstractLimit < 5 {
+			abstractLimit += 1
+			abstract += v.FinalSentence
+		}
+	}
+
+	speechItem.Abstract = abstract
+	speechItem.State = speech_recognition.SpeechRecognitionStateSuccess
+	speechItem.ModifyTime = nowTime
+	speechCols := []string{speech_recognition.SpeechRecognitionCols.Abstract, speech_recognition.SpeechRecognitionCols.State, speech_recognition.SpeechRecognitionCols.ModifyTime}
+
+	apiLog.RequestCode = code
+	apiLog.RequestResult = detail
+	apiLog.ModifyTime = time.Now().Local()
+	apiLogCols := []string{speech_recognition.SpeechRecognitionApiLogCols.RequestCode, speech_recognition.SpeechRecognitionApiLogCols.RequestResult, speech_recognition.SpeechRecognitionApiLogCols.ModifyTime}
+
+	// 新增解析内容并更新语音识别及API记录
+	if e := speech_recognition.CreateContentAndUpdateSpeechAndApiLog(contents, speechItem, speechCols, apiLog, apiLogCols); e != nil {
+		errMsg = "新增API返回结果失败"
+		utils.FileLog.Info("新增API返回结果失败, Err: " + e.Error())
+	}
+}
+
+// Convert
+// @Title 语音转换
+// @Description 语音转换
+// @Param	request	body speech_recognition.SpeechRecognitionConvertReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /convert [post]
+func (this *SpeechRecognitionController) Convert() {
+	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 speech_recognition.SpeechRecognitionConvertReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "请选择目录"
+		return
+	}
+	if len(req.Files) == 0 {
+		br.Msg = "请上传转写文件"
+		return
+	}
+	for _, r := range req.Files {
+		if r.FileName == "" && r.ResourceUrl == "" {
+			br.Msg = "转写文件有误,请检查"
+			return
+		}
+	}
+	sortMax, e := services.GetSpeechMenuMaxSort(req.MenuId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取语音识别目录下最大排序失败, Err: " + e.Error()
+		return
+	}
+
+	speeches := make([]*speech_recognition.SpeechRecognition, 0)
+	nowTime := time.Now().Local()
+	for _, v := range req.Files {
+		sortMax += 1
+		t := new(speech_recognition.SpeechRecognition)
+		t.FileName = v.FileName
+		t.ResourceUrl = v.ResourceUrl
+		t.MenuId = req.MenuId
+		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+		t.UniqueCode = utils.MD5(fmt.Sprintf("%s_%s", t.TableName(), timestamp))
+		t.SysUserId = sysUser.AdminId
+		t.SysUserName = sysUser.RealName
+		t.State = speech_recognition.SpeechRecognitionStateWait
+		t.Sort = sortMax
+		t.FileSecond = v.FileSecond
+		t.FileSize = v.FileSize
+		t.CreateTime = nowTime
+		t.ModifyTime = nowTime
+		// CreateMulti拿不到主键, 此处用循环新增获取
+		if e := t.Create(); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "批量新增转写文件失败, Err: " + e.Error()
+			return
+		}
+		speeches = append(speeches, t)
+	}
+
+	// 批量转写语音
+	go func() {
+		services.BatchConvertSpeech(speeches)
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// ConvertList
+// @Title 转换列表
+// @Description 转换列表
+// @Success 200 {object} speech_recognition.SpeechRecognitionItem
+// @router /convert_list [get]
+func (this *SpeechRecognitionController) ConvertList() {
+	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
+	}
+
+	// 仅取待转换和转换失败的
+	states := []int{speech_recognition.SpeechRecognitionStateWait, speech_recognition.SpeechRecognitionStateFail}
+	speechOb := new(speech_recognition.SpeechRecognition)
+	cond := fmt.Sprintf(` AND %s = ? AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.SysUserId, speech_recognition.SpeechRecognitionCols.State, utils.GetOrmInReplace(len(states)))
+	pars := make([]interface{}, 0)
+	pars = append(pars, sysUser.AdminId, states)
+	list, e := speechOb.GetItemsByCondition(cond, pars, []string{}, "")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取转写文件列表失败, Err: " + e.Error()
+		return
+	}
+	resp := make([]*speech_recognition.SpeechRecognitionItem, 0)
+	for _, v := range list {
+		resp = append(resp, speech_recognition.FormatSpeechRecognition2Item(v))
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Save
+// @Title 保存内容
+// @Description 保存内容
+// @Param	request	body speech_recognition.SpeechRecognitionSaveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /save [post]
+func (this *SpeechRecognitionController) Save() {
+	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 speech_recognition.SpeechRecognitionSaveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.SpeechRecognitionId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
+		return
+	}
+	if len(req.Contents) == 0 {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "操作成功"
+		return
+	}
+	req.FileName = strings.TrimSpace(req.FileName)
+	if req.FileName == "" {
+		br.Msg = "请输入文件名称"
+		return
+	}
+
+	speechOb := new(speech_recognition.SpeechRecognition)
+	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "转写文件不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
+		return
+	}
+	if req.FileName != speechItem.FileName {
+		// 校验重名
+		{
+			cond := fmt.Sprintf(` AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.SpeechRecognitionId)
+			pars := make([]interface{}, 0)
+			pars = append(pars, req.FileName, req.SpeechRecognitionId)
+			exists, e := speechOb.GetItemByCondition(cond, pars, "")
+			if e != nil && e.Error() != utils.ErrNoRow() {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取同名转写文件失败, Err: " + e.Error()
+				return
+			}
+			if exists != nil && exists.SpeechRecognitionId > 0 {
+				br.Msg = "文件名称已存在,请重新输入"
+				return
+			}
+		}
+	}
+
+	// 取前几段作为摘要保存
+	var abstractNum int
+	var abstract string
+	for _, v := range req.Contents {
+		if abstractNum < 5 {
+			abstractNum += 1
+			abstract += v.Content
+		}
+	}
+	speechItem.FileName = req.FileName
+	speechItem.Abstract = abstract
+	speechItem.ModifyTime = time.Now().Local()
+	speechCols := []string{speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.Abstract, speech_recognition.SpeechRecognitionCols.ModifyTime}
+
+	// 标签
+	tagMappings := make([]*speech_recognition.SpeechRecognitionTagMapping, 0)
+	for _, v := range req.TagIds {
+		tagMappings = append(tagMappings, &speech_recognition.SpeechRecognitionTagMapping{
+			SpeechRecognitionId: req.SpeechRecognitionId,
+			TagId:               v,
+		})
+	}
+
+	// 保存修改
+	if e = speechOb.SpeechSave(speechItem, speechCols, req.Contents, tagMappings); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "语音识别保存失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// RemoveFile
+// @Title (软)删除文件
+// @Description (软)删除文件
+// @Param	request	body speech_recognition.SpeechRecognitionRemoveFileReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /remove_file [post]
+func (this *SpeechRecognitionController) RemoveFile() {
+	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 speech_recognition.SpeechRecognitionRemoveFileReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.SpeechRecognitionId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
+		return
+	}
+
+	speechOb := new(speech_recognition.SpeechRecognition)
+	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "转写文件不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	speechItem.FileState = speech_recognition.SpeechRecognitionFileRemoveFlag
+	speechItem.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionCols.FileState, speech_recognition.SpeechRecognitionCols.ModifyTime}
+	if e = speechItem.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "软删除转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Rename
+// @Title 重命名
+// @Description 重命名
+// @Param	request	body speech_recognition.SpeechRecognitionRenameReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /rename [post]
+func (this *SpeechRecognitionController) Rename() {
+	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 speech_recognition.SpeechRecognitionRenameReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.SpeechRecognitionId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
+		return
+	}
+	req.FileName = strings.TrimSpace(req.FileName)
+	if req.FileName == "" {
+		br.Msg = "请输入文件名称"
+		return
+	}
+
+	speechOb := new(speech_recognition.SpeechRecognition)
+	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "转写文件不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	// 重名校验
+	{
+		cond := fmt.Sprintf(` AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.SpeechRecognitionId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.FileName, req.SpeechRecognitionId)
+		exists, e := speechOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名转写文件失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionId > 0 {
+			br.Msg = "文件名称已存在,请重新输入"
+			return
+		}
+	}
+
+	speechItem.FileName = req.FileName
+	speechItem.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionCols.FileName, speech_recognition.SpeechRecognitionCols.ModifyTime}
+	if e = speechItem.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "转写文件重命名失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Remove
+// @Title 删除
+// @Description 删除
+// @Param	request	body speech_recognition.SpeechRecognitionRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /remove [post]
+func (this *SpeechRecognitionController) Remove() {
+	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 speech_recognition.SpeechRecognitionRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.SpeechRecognitionId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
+		return
+	}
+
+	speechOb := new(speech_recognition.SpeechRecognition)
+	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	if e = speechItem.Del(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	// 清除关联
+	go func() {
+		contentOb := new(speech_recognition.SpeechRecognitionContent)
+		_ = contentOb.ClearContentBySpeechId(req.SpeechRecognitionId)
+		mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
+		_ = mappingOb.ClearMappingBySpeechId(req.SpeechRecognitionId)
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// SaveTag
+// @Title 保存标签
+// @Description 保存标签
+// @Param	request	body speech_recognition.SpeechRecognitionSaveTagReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /save_tag [post]
+func (this *SpeechRecognitionController) SaveTag() {
+	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 speech_recognition.SpeechRecognitionSaveTagReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.SpeechRecognitionId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
+		return
+	}
+
+	speechOb := new(speech_recognition.SpeechRecognition)
+	_, e := speechOb.GetItemById(req.SpeechRecognitionId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "转写文件不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	// 清除原标签
+	mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
+	if e = mappingOb.ClearMappingBySpeechId(req.SpeechRecognitionId); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "清除转写文件标签失败, Err: " + e.Error()
+		return
+	}
+
+	// 保存新标签
+	if len(req.TagIds) > 0 {
+		mappings := make([]*speech_recognition.SpeechRecognitionTagMapping, 0)
+		for _, v := range req.TagIds {
+			if v <= 0 {
+				continue
+			}
+			mappings = append(mappings, &speech_recognition.SpeechRecognitionTagMapping{
+				TagId:               v,
+				SpeechRecognitionId: req.SpeechRecognitionId,
+			})
+		}
+		if e = mappingOb.CreateMulti(mappings); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "批量新增转写文件标签失败, Err: " + e.Error()
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// List
+// @Title 语音识别列表
+// @Description 语音识别列表
+// @Param   FileName  query  string  false  "文件名称"
+// @Param   StartTime  query  string  false  "开始时间"
+// @Param   EndTime  query  string  false  "结束时间"
+// @Param   CreateUserIds  query  string  false  "创建人ID"
+// @Param   TagId  query  int  false  "标签ID"
+// @Param   TagIds  query  string  false  "标签ID"
+// @Param   MenuId  query  int  false  "目录ID"
+// @Param   IsTagMenu  query  bool  false  "是否为标签目录"
+// @Success 200 {object} speech_recognition.SpeechRecognitionListResp
+// @router /list [get]
+func (this *SpeechRecognitionController) List() {
+	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
+	}
+	params := new(speech_recognition.SpeechRecognitionListReq)
+	if e := this.ParseForm(params); e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	params.FileName = strings.TrimSpace(params.FileName)
+
+	dataResp := new(speech_recognition.SpeechRecognitionListResp)
+	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionCols.State)
+	pars := make([]interface{}, 0)
+	pars = append(pars, speech_recognition.SpeechRecognitionStateSuccess)
+
+	// 筛选项
+	{
+		if params.FileName != "" {
+			cond += fmt.Sprintf(` AND %s LIKE ?`, speech_recognition.SpeechRecognitionCols.FileName)
+			pars = append(pars, fmt.Sprint("%", params.FileName, "%"))
+		}
+		if params.StartTime != "" && params.EndTime != "" {
+			_, e := time.Parse(utils.FormatDate, params.StartTime)
+			if e != nil {
+				br.Msg = "开始时间格式有误"
+				return
+			}
+			_, e = time.Parse(utils.FormatDate, params.EndTime)
+			if e != nil {
+				br.Msg = "结束时间格式有误"
+				return
+			}
+			st := fmt.Sprintf("%s 00:00:00", params.StartTime)
+			ed := fmt.Sprintf("%s 23:59:59", params.EndTime)
+			cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, speech_recognition.SpeechRecognitionCols.CreateTime)
+			pars = append(pars, st, ed)
+		}
+		if params.CreateUserId != "" {
+			userArr := strings.Split(strings.TrimSpace(params.CreateUserId), ",")
+			if len(userArr) > 0 {
+				userIds := make([]int, 0)
+				for _, v := range userArr {
+					t, _ := strconv.Atoi(v)
+					userIds = append(userIds, t)
+				}
+				if len(userIds) == 0 {
+					br.Data = dataResp
+					br.Ret = 200
+					br.Success = true
+					br.Msg = "获取成功"
+					return
+				}
+				cond += fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.SysUserId, utils.GetOrmInReplace(len(userIds)))
+				pars = append(pars, userIds)
+			}
+		}
+		// 语音识别目录-筛选子目录集合
+		if params.MenuId > 0 && !params.IsTagMenu {
+			{
+				menuOb := new(speech_recognition.SpeechRecognitionMenu)
+				menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
+				if e != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取语音识别目录列表失败, Err: " + e.Error()
+					return
+				}
+				childIds := services.GetSpeechRecognitionMenuChildrenRecursive(menus, params.MenuId)
+				menuIds := make([]int, 0)
+				menuIds = append(menuIds, params.MenuId)
+				if len(childIds) > 0 {
+					menuIds = append(menuIds, childIds...)
+				}
+				cond += fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.MenuId, utils.GetOrmInReplace(len(menuIds)))
+				pars = append(pars, menuIds)
+			}
+		}
+		// 标签目录-筛选目录下所有标签
+		tagIds := make([]int, 0)
+		if params.MenuId > 0 && params.IsTagMenu {
+			{
+				menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+				menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
+				if e != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取标签目录列表失败, Err: " + e.Error()
+					return
+				}
+				childIds := services.GetSpeechRecognitionTagMenuChildrenRecursive(menus, params.MenuId)
+				menuIds := make([]int, 0)
+				menuIds = append(menuIds, params.MenuId)
+				if len(childIds) > 0 {
+					menuIds = append(menuIds, childIds...)
+				}
+				// 获取目录下所有标签
+				tagOb := new(speech_recognition.SpeechRecognitionTag)
+				ids, e := tagOb.GetTagIdsByMenuIds(menuIds)
+				if e != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "通过目录IDs获取标签IDs失败, Err: " + e.Error()
+					return
+				}
+				// 此处查询无结果直接返回
+				if len(ids) == 0 {
+					br.Data = dataResp
+					br.Ret = 200
+					br.Success = true
+					br.Msg = "获取成功"
+					return
+				}
+				tagIds = ids
+			}
+		}
+
+		// 标签筛选
+		if params.TagId > 0 && params.TagIds == "" {
+			tagIds = append(tagIds, params.TagId)
+		}
+		if params.TagId <= 0 && params.TagIds != "" {
+			tagArr := strings.Split(params.TagIds, ",")
+			if len(tagArr) > 0 {
+				for _, v := range tagArr {
+					t, _ := strconv.Atoi(v)
+					tagIds = append(tagIds, t)
+				}
+			}
+		}
+		if len(tagIds) > 0 {
+			mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
+			tagSpeechIds, e := mappingOb.GetSpeechIdsByTagIds(tagIds)
+			if e != nil {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取标签关联语音识别失败, Err: " + e.Error()
+				return
+			}
+			if len(tagSpeechIds) == 0 {
+				br.Data = dataResp
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				return
+			}
+			cond += fmt.Sprintf(` AND %s IN (%s)`, speech_recognition.SpeechRecognitionCols.SpeechRecognitionId, utils.GetOrmInReplace(len(tagSpeechIds)))
+			pars = append(pars, tagSpeechIds)
+		}
+	}
+
+	// 分页列表
+	speechOb := new(speech_recognition.SpeechRecognition)
+	total, e := speechOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取语音识别列表总数失败, Err: " + e.Error()
+		return
+	}
+	var startSize int
+	if params.PageSize <= 0 {
+		params.PageSize = utils.PageSize20
+	}
+	if params.CurrentIndex <= 0 {
+		params.CurrentIndex = 1
+	}
+	startSize = utils.StartIndex(params.CurrentIndex, params.PageSize)
+	list, e := speechOb.GetPageItemsByCondition(cond, pars, []string{}, "", startSize, params.PageSize)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取语音识别列表失败, Err: " + e.Error()
+		return
+	}
+
+	// 获取标签
+	speechIds := make([]int, 0)
+	for _, v := range list {
+		speechIds = append(speechIds, v.SpeechRecognitionId)
+	}
+	mappingTags, e := speech_recognition.GetSpeechRecognitionTagsBySpeechIds(speechIds)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取语音识别列表标签失败, Err: " + e.Error()
+		return
+	}
+	speechDetailTags := make(map[int][]*speech_recognition.SpeechRecognitionDetailTag)
+	for _, v := range mappingTags {
+		if speechDetailTags[v.SpeechRecognitionId] == nil {
+			speechDetailTags[v.SpeechRecognitionId] = make([]*speech_recognition.SpeechRecognitionDetailTag, 0)
+		}
+		speechDetailTags[v.SpeechRecognitionId] = append(speechDetailTags[v.SpeechRecognitionId], &speech_recognition.SpeechRecognitionDetailTag{
+			TagId:   v.TagId,
+			TagName: v.TagName,
+		})
+	}
+
+	respList := make([]*speech_recognition.SpeechRecognitionDetailItem, 0)
+	for _, v := range list {
+		t := speech_recognition.FormatSpeechRecognition2DetailItem(v, make([]*speech_recognition.SpeechRecognitionContentItem, 0), speechDetailTags[v.SpeechRecognitionId], make([]*speech_recognition.SpeechRecognitionMenuItem, 0))
+		respList = append(respList, t)
+	}
+
+	page := paging.GetPaging(params.CurrentIndex, params.PageSize, total)
+	dataResp.Paging = page
+	dataResp.List = respList
+	br.Data = dataResp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Detail
+// @Title 语音识别详情
+// @Description 语音识别详情
+// @Param   SpeechRecognitionId  query  int  true  "语音识别ID"
+// @Success 200 {object} speech_recognition.SpeechRecognitionDetailItem
+// @router /detail [get]
+func (this *SpeechRecognitionController) 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
+	}
+	speechId, _ := this.GetInt("SpeechRecognitionId")
+	if speechId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", speechId)
+		return
+	}
+
+	speechOb := new(speech_recognition.SpeechRecognition)
+	speechItem, e := speechOb.GetItemById(speechId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "转写文件不存在,请刷新页面"
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	// 获取内容
+	contents := make([]*speech_recognition.SpeechRecognitionContentItem, 0)
+	{
+		contentOb := new(speech_recognition.SpeechRecognitionContent)
+		cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionContentCols.SpeechRecognitionId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, speechId)
+		list, e := contentOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionContentCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取语音识别内容失败, Err: " + e.Error()
+			return
+		}
+		for _, v := range list {
+			if v.Content == "" {
+				continue
+			}
+			contents = append(contents, speech_recognition.FormatSpeechRecognitionContent2Item(v))
+		}
+	}
+
+	// 跟踪目录路径
+	menuPath := make([]*speech_recognition.SpeechRecognitionMenuItem, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionMenu)
+		menus, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC, %s ASC", speech_recognition.SpeechRecognitionMenuCols.ParentId, speech_recognition.SpeechRecognitionMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menuPath = services.GetSpeechRecognitionMenuPathRecursive(menus, speechItem.MenuId)
+		sort.Slice(menuPath, func(i, j int) bool {
+			return menuPath[i].Level < menuPath[j].Level
+		})
+	}
+
+	// 获取标签
+	tags, e := speech_recognition.GetSpeechRecognitionTagBySpeechId(speechId)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取语音识别标签失败, Err: " + e.Error()
+		return
+	}
+	detail := speech_recognition.FormatSpeechRecognition2DetailItem(speechItem, contents, tags, menuPath)
+
+	br.Data = detail
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Export
+// @Title 导出内容
+// @Description 导出内容
+// @Param	request	body speech_recognition.SpeechRecognitionContentExportReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /export [get]
+func (this *SpeechRecognitionController) Export() {
+	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
+	}
+	req := new(speech_recognition.SpeechRecognitionContentExportReq)
+	if e := this.ParseForm(req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.SpeechRecognitionId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, SpeechRecognitionId: %d", req.SpeechRecognitionId)
+		return
+	}
+
+	speechOb := new(speech_recognition.SpeechRecognition)
+	speechItem, e := speechOb.GetItemById(req.SpeechRecognitionId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "转写文件不存在,请刷新页面"
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取转写文件失败, Err: " + e.Error()
+		return
+	}
+
+	contentOb := new(speech_recognition.SpeechRecognitionContent)
+	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionContentCols.SpeechRecognitionId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.SpeechRecognitionId)
+	contents, e := contentOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionContentCols.Sort))
+	if e != nil {
+		br.Msg = "导出失败"
+		br.ErrMsg = "获取语音识别内容失败, Err: " + e.Error()
+		return
+	}
+	if len(contents) == 0 {
+		br.Msg = "无内容导出"
+		return
+	}
+	if req.ExportType != services.SpeechRecognitionExportTypeTxt && req.ExportType != services.SpeechRecognitionExportTypeDocx && req.ExportType != services.SpeechRecognitionExportTypePdf {
+		br.Msg = "导出类型有误"
+		return
+	}
+
+	suffixMap := map[int]string{services.SpeechRecognitionExportTypeTxt: ".txt", services.SpeechRecognitionExportTypeDocx: ".docx", services.SpeechRecognitionExportTypePdf: ".pdf"}
+	suffix := suffixMap[req.ExportType]
+	if suffix == "" {
+		suffix = ".txt"
+	}
+	downloadPath, e := services.SpeechRecognitionContentExport(req.ExportType, req.Timestamp, speechItem.FileName, contents)
+	if e != nil {
+		br.Msg = "导出文件失败"
+		br.ErrMsg = "导出语音识别内容文件失败, Err: " + e.Error()
+		_ = os.Remove(downloadPath)
+		return
+	}
+	defer func() {
+		_ = os.Remove(downloadPath)
+	}()
+
+	downloadName := fmt.Sprintf("%s%s", speechItem.FileName, suffix)
+	this.Ctx.Output.Download(downloadPath, downloadName)
+}
+
+// CheckFileName
+// @Title 文件重名校验
+// @Description 文件重名校验
+// @Param	request	body speech_recognition.SpeechRecognitionConvertCheckNameReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /convert/check_name [post]
+func (this *SpeechRecognitionController) CheckFileName() {
+	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 speech_recognition.SpeechRecognitionConvertCheckNameReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	req.FileName = strings.TrimSpace(req.FileName)
+	if req.FileName == "" {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, FileName: %s", req.FileName)
+		return
+	}
+
+	checkResult := true
+	speechOb := new(speech_recognition.SpeechRecognition)
+	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionCols.FileName)
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.FileName)
+	exists, e := speechOb.GetItemByCondition(cond, pars, "")
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取同名转写文件失败, Err: " + e.Error()
+		return
+	}
+	if exists != nil && exists.SpeechRecognitionId > 0 {
+		checkResult = false
+		br.Data = checkResult
+		br.Msg = fmt.Sprintf("相同文件名称已存在: %s", req.FileName)
+		return
+	}
+
+	br.Data = checkResult
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 534 - 0
controllers/speech_recognition/speech_recognition_menu.go

@@ -0,0 +1,534 @@
+package speech_recognition
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/services"
+	"eta/eta_api/utils"
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type SpeechRecognitionMenuController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增分类
+// @Description 新增分类
+// @Param	request	body speech_recognition.SpeechRecognitionMenuAddReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/add [post]
+func (this *SpeechRecognitionMenuController) Add() {
+	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 speech_recognition.SpeechRecognitionMenuAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	// 校验同级目录是否有重名
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	{
+		cond := fmt.Sprintf(` AND %s = ? AND %s = ?`, speech_recognition.SpeechRecognitionMenuCols.MenuName, speech_recognition.SpeechRecognitionMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, req.ParentId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	// 获取目录层级和同级最大排序
+	level := 1
+	rootId := 0
+	{
+		if req.ParentId > 0 {
+			parentMenu, e := menuOb.GetItemById(req.ParentId)
+			if e != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取父级目录失败, Err: " + e.Error()
+				return
+			}
+			level += parentMenu.Level
+			rootId = parentMenu.RootId
+		}
+	}
+	sortMax, e := services.GetSpeechMenuMaxSort(req.ParentId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取语音识别目录下最大排序失败, Err: " + e.Error()
+		return
+	}
+
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	menuOb.UniqueCode = utils.MD5(fmt.Sprintf("%s_%s", menuOb.TableName(), timestamp))
+	menuOb.MenuName = req.MenuName
+	menuOb.ParentId = req.ParentId
+	menuOb.Level = level
+	menuOb.Sort = sortMax + 1
+	menuOb.RootId = rootId
+	menuOb.CreateTime = time.Now().Local()
+	menuOb.ModifyTime = time.Now().Local()
+	if e = menuOb.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑分类
+// @Description 编辑分类
+// @Param	request	body speech_recognition.SpeechRecognitionMenuEditReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/edit [post]
+func (this *SpeechRecognitionMenuController) Edit() {
+	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 speech_recognition.SpeechRecognitionMenuEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "目录不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验同级目录是否有重名
+	{
+		cond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionMenuCols.MenuName, speech_recognition.SpeechRecognitionMenuCols.ParentId, speech_recognition.SpeechRecognitionMenuCols.SpeechRecognitionMenuId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, menuItem.ParentId, req.MenuId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	menuItem.MenuName = req.MenuName
+	menuItem.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionMenuCols.MenuName, speech_recognition.SpeechRecognitionMenuCols.ModifyTime}
+	if e = menuItem.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Remove
+// @Title 删除分类
+// @Description 删除分类
+// @Param	request	body speech_recognition.SpeechRecognitionMenuRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/remove [post]
+func (this *SpeechRecognitionMenuController) Remove() {
+	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 speech_recognition.SpeechRecognitionMenuRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 删除校验
+	checkResult, menuIds, e := services.CheckSpeechRecognitionMenuRemove(menuItem.SpeechRecognitionMenuId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "目录删除校验失败, Err: " + e.Error()
+		return
+	}
+
+	switch checkResult.CheckResult {
+	case services.SpeechMenuCheckRemoveTypePass:
+		// 可删除
+		if e = menuItem.Del(); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "删除目录失败, Err: " + e.Error()
+			return
+		}
+	case services.SpeechMenuCheckRemoveTypeRefused:
+		// 不可删除
+		br.Msg = checkResult.Tips
+		return
+	case services.SpeechMenuCheckRemoveTypeWarning:
+		// 删除目录及子目录
+		if e = menuOb.MultiDel(menuIds); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "批量删除目录失败, Err: " + e.Error()
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// RemoveCheck
+// @Title 删除校验
+// @Description 删除校验
+// @Param	request	body speech_recognition.SpeechRecognitionMenuRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/remove_check [post]
+func (this *SpeechRecognitionMenuController) RemoveCheck() {
+	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 speech_recognition.SpeechRecognitionMenuRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	resp, _, e := services.CheckSpeechRecognitionMenuRemove(menuItem.SpeechRecognitionMenuId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "目录删除校验失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// List
+// @Title 目录列表
+// @Description 目录列表
+// @Param   ParentId  query  int  false  "父级ID"
+// @Success 200 {object} speech_recognition.SpeechRecognitionMenuNodeItem
+// @router /menu/list [get]
+func (this *SpeechRecognitionMenuController) List() {
+	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
+	}
+	// 前端采用懒加载, 所以只查询子目录和内容
+	parentId, _ := this.GetInt("ParentId")
+
+	level := 0
+	menuOb := new(speech_recognition.SpeechRecognitionMenu)
+	if parentId > 0 {
+		parentMenu, e := menuOb.GetItemById(parentId)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取父级目录失败, Err: " + e.Error()
+			return
+		}
+		level = parentMenu.Level + 1
+	}
+	menus := make([]*speech_recognition.SpeechRecognitionMenu, 0)
+	{
+		cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := menuOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+
+	speeches := make([]*speech_recognition.SpeechRecognition, 0)
+	{
+		speechOb := new(speech_recognition.SpeechRecognition)
+		cond := fmt.Sprintf(` AND %s = ? AND %s = ?`, speech_recognition.SpeechRecognitionCols.MenuId, speech_recognition.SpeechRecognitionCols.State)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId, speech_recognition.SpeechRecognitionStateSuccess)
+		list, e := speechOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC, %s DESC", speech_recognition.SpeechRecognitionCols.Sort, speech_recognition.SpeechRecognitionCols.CreateTime))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取语音识别列表失败, Err: " + e.Error()
+			return
+		}
+		speeches = list
+	}
+
+	resp := make([]*speech_recognition.SpeechRecognitionMenuNodeItem, 0)
+	if len(menus) == 0 && len(speeches) == 0 {
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
+	for _, v := range menus {
+		resp = append(resp, &speech_recognition.SpeechRecognitionMenuNodeItem{
+			UniqueCode: v.UniqueCode,
+			NodeType:   speech_recognition.SpeechRecognitionMenuNodeTypeDefault,
+			MenuId:     v.SpeechRecognitionMenuId,
+			MenuName:   v.MenuName,
+			ParentId:   v.ParentId,
+			Level:      v.Level,
+			Sort:       v.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, v.CreateTime),
+		})
+	}
+	for _, v := range speeches {
+		resp = append(resp, &speech_recognition.SpeechRecognitionMenuNodeItem{
+			UniqueCode:            v.UniqueCode,
+			NodeType:              speech_recognition.SpeechRecognitionMenuNodeTypeSpeech,
+			SpeechRecognitionId:   v.SpeechRecognitionId,
+			SpeechRecognitionName: v.FileName,
+			ParentId:              v.MenuId,
+			Level:                 level,
+			Sort:                  v.Sort,
+			CreateTime:            utils.TimeTransferString(utils.FormatDateTime, v.CreateTime),
+		})
+	}
+	sort.Slice(resp, func(i, j int) bool {
+		return resp[i].Sort < resp[j].Sort
+	})
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Tree
+// @Title 目录树
+// @Description 目录树
+// @Success 200 {object} speech_recognition.SpeechRecognitionMenuItem
+// @router /menu/tree [get]
+func (this *SpeechRecognitionMenuController) Tree() {
+	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
+	}
+
+	menus := make([]*speech_recognition.SpeechRecognitionMenu, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionMenu)
+		list, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC, %s ASC", speech_recognition.SpeechRecognitionMenuCols.ParentId, speech_recognition.SpeechRecognitionMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+
+	// 递归处理成目录树
+	resp := services.GetSpeechRecognitionMenuTreeRecursive(menus, 0)
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Move
+// @Title 移动目录/语音识别
+// @Description 移动目录/语音识别
+// @Param	request	body speech_recognition.SpeechRecognitionMenuMoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /menu/move [post]
+func (this *SpeechRecognitionMenuController) Move() {
+	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 speech_recognition.SpeechRecognitionMenuMoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 && req.SpeechId <= 0 {
+		br.Msg = "请选择目录或语音识别"
+		return
+	}
+
+	e, _ := services.MoveSpeechMenu(req)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "移动目录/语音识别失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 384 - 0
controllers/speech_recognition/speech_recognition_tag.go

@@ -0,0 +1,384 @@
+package speech_recognition
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/services"
+	"eta/eta_api/utils"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type SpeechRecognitionTagController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增标签
+// @Description 新增标签
+// @Param	request	body speech_recognition.SpeechRecognitionTagAddReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/add [post]
+func (this *SpeechRecognitionTagController) Add() {
+	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 speech_recognition.SpeechRecognitionTagAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "请选择标签目录"
+		return
+	}
+	req.TagName = strings.TrimSpace(req.TagName)
+	if req.TagName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	// 校验标签是否有重名
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	{
+		cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionTagCols.TagName)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.TagName)
+		exists, e := tagOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名标签失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagId > 0 {
+			br.Msg = "标签名称已存在,请重新输入"
+			return
+		}
+	}
+	sortMax, e := services.GetSpeechTagMenuMaxSort(req.MenuId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签目录下最大排序失败, Err: " + e.Error()
+		return
+	}
+
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	tagOb.UniqueCode = utils.MD5(fmt.Sprintf("%s_%s", tagOb.TableName(), timestamp))
+	tagOb.TagName = req.TagName
+	tagOb.MenuId = req.MenuId
+	tagOb.Sort = sortMax + 1
+	tagOb.CreateTime = time.Now().Local()
+	tagOb.ModifyTime = time.Now().Local()
+	if e := tagOb.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增标签失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = tagOb.SpeechRecognitionTagId
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑标签
+// @Description 编辑标签
+// @Param	request	body speech_recognition.SpeechRecognitionTagEditReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/edit [post]
+func (this *SpeechRecognitionTagController) Edit() {
+	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 speech_recognition.SpeechRecognitionTagEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.TagId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, TagId: %d", req.TagId)
+		return
+	}
+	req.TagName = strings.TrimSpace(req.TagName)
+	if req.TagName == "" {
+		br.Msg = "请输入标签名称"
+		return
+	}
+
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	tagItem, e := tagOb.GetItemById(req.TagId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "标签不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验标签是否有重名
+	{
+		cond := fmt.Sprintf(` AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionTagCols.TagName, speech_recognition.SpeechRecognitionTagCols.SpeechRecognitionTagId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.TagName, req.TagId)
+		exists, e := tagOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名标签失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagId > 0 {
+			br.Msg = "标签名称已存在,请重新输入"
+			return
+		}
+	}
+
+	tagItem.TagName = req.TagName
+	tagItem.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionTagCols.TagName, speech_recognition.SpeechRecognitionTagCols.ModifyTime}
+	if e = tagItem.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新标签失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = tagItem.SpeechRecognitionTagId
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Remove
+// @Title 删除标签
+// @Description 删除标签
+// @Param	request	body speech_recognition.SpeechRecognitionTagRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/remove [post]
+func (this *SpeechRecognitionTagController) Remove() {
+	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 speech_recognition.SpeechRecognitionTagRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.TagId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, TagId: %d", req.TagId)
+		return
+	}
+
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	tagItem, e := tagOb.GetItemById(req.TagId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验标签是否关联转写文件
+	{
+		mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
+		cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionTagMappingCols.TagId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.TagId)
+		count, e := mappingOb.GetCountByCondition(cond, pars)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取标签关联转写文件数失败, Err: " + e.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "标签关联转写文件,删除失败!"
+			return
+		}
+	}
+
+	if e = tagItem.Del(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除标签失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// RemoveCheck
+// @Title 删除标签校验
+// @Description 删除标签校验
+// @Param	request	body speech_recognition.SpeechRecognitionTagRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/remove_check [post]
+func (this *SpeechRecognitionTagController) RemoveCheck() {
+	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 speech_recognition.SpeechRecognitionTagRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.TagId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, TagId: %d", req.TagId)
+		return
+	}
+
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	_, e := tagOb.GetItemById(req.TagId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签失败, Err: " + e.Error()
+		return
+	}
+
+	resp := new(speech_recognition.SpeechRecognitionMenuRemoveCheckResp)
+	// 校验标签是否关联转写文件
+	mappingOb := new(speech_recognition.SpeechRecognitionTagMapping)
+	cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionTagMappingCols.TagId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.TagId)
+	count, e := mappingOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签关联转写文件数失败, Err: " + e.Error()
+		return
+	}
+	if count > 0 {
+		resp.CheckResult = 1
+		resp.Tips = "标签关联转写文件,删除失败!"
+	} else {
+		resp.Tips = "校验通过,可以删除"
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// List
+// @Title 标签列表
+// @Description 标签列表
+// @Param   Keywords  query  string  false  "标签名称"
+// @Success 200 {object} speech_recognition.SpeechRecognitionTagItem
+// @router /tag/list [get]
+func (this *SpeechRecognitionTagController) List() {
+	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
+	}
+
+	keywords := this.GetString("Keywords")
+	keywords = strings.TrimSpace(keywords)
+
+	tagOb := new(speech_recognition.SpeechRecognitionTag)
+	cond := ``
+	pars := make([]interface{}, 0)
+	if keywords != "" {
+		kw := fmt.Sprint("%", keywords, "%")
+		cond = fmt.Sprintf(` AND %s LIKE ?`, speech_recognition.SpeechRecognitionTagCols.TagName)
+		pars = append(pars, kw)
+	}
+	list, e := tagOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s DESC", speech_recognition.SpeechRecognitionTagCols.CreateTime))
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取标签列表失败, Err: " + e.Error()
+		return
+	}
+
+	resp := make([]*speech_recognition.SpeechRecognitionTagItem, 0)
+	for _, v := range list {
+		resp = append(resp, speech_recognition.FormatSpeechRecognitionTag2Item(v))
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 535 - 0
controllers/speech_recognition/speech_recognition_tag_menu.go

@@ -0,0 +1,535 @@
+package speech_recognition
+
+import (
+	"encoding/json"
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/speech_recognition"
+	"eta/eta_api/services"
+	"eta/eta_api/utils"
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// SpeechRecognitionTagMenuController 标签目录
+type SpeechRecognitionTagMenuController struct {
+	controllers.BaseAuthController
+}
+
+// Add
+// @Title 新增分类
+// @Description 新增分类
+// @Param	request	body speech_recognition.SpeechRecognitionTagMenuAddReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/add [post]
+func (this *SpeechRecognitionTagMenuController) Add() {
+	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 speech_recognition.SpeechRecognitionTagMenuAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	// 校验同级目录是否有重名
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	{
+		cond := fmt.Sprintf(` AND %s = ? AND %s = ?`, speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, req.ParentId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	// 获取目录层级和同级最大排序
+	level := 1
+	rootId := 0
+	{
+		if req.ParentId > 0 {
+			parentMenu, e := menuOb.GetItemById(req.ParentId)
+			if e != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取父级目录失败, Err: " + e.Error()
+				return
+			}
+			level += parentMenu.Level
+			rootId = parentMenu.RootId
+		}
+	}
+	sortMax, e := services.GetSpeechTagMenuMaxSort(req.ParentId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取标签目录下最大排序失败, Err: " + e.Error()
+		return
+	}
+
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+	menuOb.UniqueCode = utils.MD5(fmt.Sprintf("%s_%s", menuOb.TableName(), timestamp))
+	menuOb.MenuName = req.MenuName
+	menuOb.ParentId = req.ParentId
+	menuOb.Level = level
+	menuOb.Sort = sortMax + 1
+	menuOb.RootId = rootId
+	menuOb.CreateTime = time.Now().Local()
+	menuOb.ModifyTime = time.Now().Local()
+	if e = menuOb.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑分类
+// @Description 编辑分类
+// @Param	request	body speech_recognition.SpeechRecognitionTagMenuEditReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/edit [post]
+func (this *SpeechRecognitionTagMenuController) Edit() {
+	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 speech_recognition.SpeechRecognitionTagMenuEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+	req.MenuName = strings.TrimSpace(req.MenuName)
+	if req.MenuName == "" {
+		br.Msg = "请输入目录名称"
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "目录不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验同级目录是否有重名
+	{
+		cond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s <> ?`, speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ParentId, speech_recognition.SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.MenuName, menuItem.ParentId, req.MenuId)
+		exists, e := menuOb.GetItemByCondition(cond, pars, "")
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取同名目录失败, Err: " + e.Error()
+			return
+		}
+		if exists != nil && exists.SpeechRecognitionTagMenuId > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			return
+		}
+	}
+
+	menuItem.MenuName = req.MenuName
+	menuItem.ModifyTime = time.Now().Local()
+	updateCols := []string{speech_recognition.SpeechRecognitionTagMenuCols.MenuName, speech_recognition.SpeechRecognitionTagMenuCols.ModifyTime}
+	if e = menuItem.Update(updateCols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新目录失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Remove
+// @Title 删除分类
+// @Description 删除分类
+// @Param	request	body speech_recognition.SpeechRecognitionTagMenuRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/remove [post]
+func (this *SpeechRecognitionTagMenuController) Remove() {
+	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 speech_recognition.SpeechRecognitionTagMenuRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	// 删除校验
+	checkResult, menuIds, e := services.CheckSpeechRecognitionTagMenuRemove(menuItem.SpeechRecognitionTagMenuId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "目录删除校验失败, Err: " + e.Error()
+		return
+	}
+
+	switch checkResult.CheckResult {
+	case services.SpeechMenuCheckRemoveTypePass:
+		// 可删除
+		if e = menuItem.Del(); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "删除目录失败, Err: " + e.Error()
+			return
+		}
+	case services.SpeechMenuCheckRemoveTypeRefused:
+		// 不可删除
+		br.Msg = checkResult.Tips
+		return
+	case services.SpeechMenuCheckRemoveTypeWarning:
+		// 删除目录及子目录
+		if e = menuOb.MultiDel(menuIds); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "批量删除目录失败, Err: " + e.Error()
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// RemoveCheck
+// @Title 删除校验
+// @Description 删除校验
+// @Param	request	body speech_recognition.SpeechRecognitionMenuRemoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/remove_check [post]
+func (this *SpeechRecognitionTagMenuController) RemoveCheck() {
+	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 speech_recognition.SpeechRecognitionMenuRemoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MenuId: %d", req.MenuId)
+		return
+	}
+
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	menuItem, e := menuOb.GetItemById(req.MenuId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "操作成功"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取目录失败, Err: " + e.Error()
+		return
+	}
+
+	resp, _, e := services.CheckSpeechRecognitionTagMenuRemove(menuItem.SpeechRecognitionTagMenuId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "目录删除校验失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// List
+// @Title 目录列表
+// @Description 目录列表
+// @Param   ParentId  query  int  false  "父级ID"
+// @Success 200 {object} speech_recognition.SpeechRecognitionTagMenuNodeItem
+// @router /tag/menu/list [get]
+func (this *SpeechRecognitionTagMenuController) List() {
+	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
+	}
+	// 前端采用懒加载, 所以只查询子目录和内容
+	parentId, _ := this.GetInt("ParentId")
+
+	level := 0
+	menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+	if parentId > 0 {
+		parentMenu, e := menuOb.GetItemById(parentId)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取父级目录失败, Err: " + e.Error()
+			return
+		}
+		level = parentMenu.Level + 1
+	}
+	menus := make([]*speech_recognition.SpeechRecognitionTagMenu, 0)
+	{
+		cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionTagMenuCols.ParentId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := menuOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", speech_recognition.SpeechRecognitionTagMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+
+	tags := make([]*speech_recognition.SpeechRecognitionTag, 0)
+	{
+		tagOb := new(speech_recognition.SpeechRecognitionTag)
+		cond := fmt.Sprintf(` AND %s = ?`, speech_recognition.SpeechRecognitionTagCols.MenuId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, parentId)
+		list, e := tagOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC, %s DESC", speech_recognition.SpeechRecognitionTagMenuCols.Sort, speech_recognition.SpeechRecognitionTagMenuCols.CreateTime))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取标签列表失败, Err: " + e.Error()
+			return
+		}
+		tags = list
+	}
+
+	resp := make([]*speech_recognition.SpeechRecognitionTagMenuNodeItem, 0)
+	if len(menus) == 0 && len(tags) == 0 {
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
+	for _, v := range menus {
+		resp = append(resp, &speech_recognition.SpeechRecognitionTagMenuNodeItem{
+			UniqueCode: v.UniqueCode,
+			NodeType:   speech_recognition.SpeechRecognitionMenuNodeTypeDefault,
+			MenuId:     v.SpeechRecognitionTagMenuId,
+			MenuName:   v.MenuName,
+			ParentId:   v.ParentId,
+			Level:      v.Level,
+			Sort:       v.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, v.CreateTime),
+		})
+	}
+	for _, v := range tags {
+		resp = append(resp, &speech_recognition.SpeechRecognitionTagMenuNodeItem{
+			UniqueCode: v.UniqueCode,
+			NodeType:   speech_recognition.SpeechRecognitionTagMenuNodeTypeTag,
+			TagId:      v.SpeechRecognitionTagId,
+			TagName:    v.TagName,
+			ParentId:   v.MenuId,
+			Level:      level,
+			Sort:       v.Sort,
+			CreateTime: utils.TimeTransferString(utils.FormatDateTime, v.CreateTime),
+		})
+	}
+	sort.Slice(resp, func(i, j int) bool {
+		return resp[i].Sort < resp[j].Sort
+	})
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Tree
+// @Title 目录树
+// @Description 目录树
+// @Success 200 {object} speech_recognition.SpeechRecognitionTagMenuItem
+// @router /tag/menu/tree [get]
+func (this *SpeechRecognitionTagMenuController) Tree() {
+	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
+	}
+
+	menus := make([]*speech_recognition.SpeechRecognitionTagMenu, 0)
+	{
+		menuOb := new(speech_recognition.SpeechRecognitionTagMenu)
+		list, e := menuOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC, %s ASC", speech_recognition.SpeechRecognitionTagMenuCols.ParentId, speech_recognition.SpeechRecognitionTagMenuCols.Sort))
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取目录列表失败, Err: " + e.Error()
+			return
+		}
+		menus = list
+	}
+
+	// 递归处理成目录树
+	resp := services.GetSpeechRecognitionTagMenuTreeRecursive(menus, 0)
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Move
+// @Title 移动标签/目录
+// @Description 移动标签/目录
+// @Param	request	body speech_recognition.SpeechRecognitionTagMenuMoveReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /tag/menu/move [post]
+func (this *SpeechRecognitionTagMenuController) Move() {
+	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 speech_recognition.SpeechRecognitionTagMenuMoveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MenuId <= 0 && req.TagId <= 0 {
+		br.Msg = "请选择目录或标签"
+		return
+	}
+
+	e, _ := services.MoveSpeechTagMenu(req)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "移动目录/标签失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 2 - 2
controllers/sys_user.go

@@ -76,7 +76,7 @@ func (this *SysUserController) Login() {
 	account := utils.MD5(req.Username)
 	token := utils.GenToken(account)
 	sysSession := new(system.SysSession)
-	sysSession.UserName = req.Username
+	sysSession.UserName = sysUser.AdminName
 	sysSession.SysUserId = sysUser.AdminId
 	sysSession.ExpiredTime = time.Now().AddDate(0, 0, 90)
 	sysSession.IsRemember = isRemember
@@ -100,7 +100,7 @@ func (this *SysUserController) Login() {
 
 	resp := new(system.LoginResp)
 	resp.Authorization = token
-	resp.Authorization = "authorization=" + token + "$account=" + account
+	resp.Authorization = "authorization=" + token
 	resp.RealName = sysUser.RealName
 	resp.AdminName = sysUser.AdminName
 	resp.RoleName = sysUser.RoleName

+ 2 - 2
controllers/user_login.go

@@ -513,7 +513,7 @@ func (this *UserLoginController) Login() {
 	account := utils.MD5(sysUser.AdminName)
 	token := utils.GenToken(account)
 	sysSession := new(system.SysSession)
-	sysSession.UserName = req.Username
+	sysSession.UserName = sysUser.AdminName
 	sysSession.SysUserId = sysUser.AdminId
 	sysSession.ExpiredTime = time.Now().AddDate(0, 0, 90)
 	sysSession.IsRemember = 0 // 均需要做过期校验
@@ -535,7 +535,7 @@ func (this *UserLoginController) Login() {
 
 	resp := new(system.LoginResp)
 	resp.Authorization = token
-	resp.Authorization = "authorization=" + token + "$account=" + account
+	resp.Authorization = "authorization=" + token
 	resp.RealName = sysUser.RealName
 	resp.AdminName = sysUser.AdminName
 	resp.RoleName = sysUser.RoleName

+ 14 - 5
go.mod

@@ -3,6 +3,7 @@ module eta/eta_api
 go 1.21.7
 
 require (
+	baliance.com/gooxml v1.0.1
 	github.com/PuerkitoBio/goquery v1.9.1
 	github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.2
 	github.com/alibabacloud-go/alimt-20181012/v2 v2.2.0
@@ -19,12 +20,15 @@ require (
 	github.com/beevik/etree v1.3.0
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-ldap/ldap v3.0.3+incompatible
-	github.com/go-redis/redis/v8 v8.11.5
+	github.com/go-redis/redis/v8 v8.11.6-0.20220405070650-99c79f7041fc
 	github.com/go-sql-driver/mysql v1.7.0
 	github.com/go-xorm/xorm v0.7.9
 	github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b
 	github.com/gorilla/websocket v1.5.1
+	github.com/h2non/filetype v1.1.3
+	github.com/jung-kurt/gofpdf v1.16.2
 	github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53
+	github.com/microcosm-cc/bluemonday v1.0.26
 	github.com/minio/minio-go/v7 v7.0.69
 	github.com/mojocn/base64Captcha v1.3.6
 	github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19
@@ -33,10 +37,12 @@ require (
 	github.com/shopspring/decimal v1.3.1
 	github.com/silenceper/wechat/v2 v2.1.6
 	github.com/tealeg/xlsx v1.0.5
+	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/asr v1.0.873
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.880
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses v1.0.880
 	github.com/xuri/excelize/v2 v2.8.1
 	github.com/yidane/formula v0.0.0-20220322063702-c9da84ba3476
+	golang.org/x/net v0.21.0
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 )
 
@@ -54,6 +60,7 @@ require (
 	github.com/aliyun/credentials-go v1.3.1 // indirect
 	github.com/andybalholm/cascadia v1.3.2 // indirect
 	github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02 // indirect
+	github.com/aymerick/douceur v0.2.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -61,6 +68,7 @@ require (
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/dustin/go-humanize v1.0.1 // indirect
 	github.com/fatih/structs v1.1.0 // indirect
+	github.com/fsnotify/fsnotify v1.6.0 // indirect
 	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac // indirect
@@ -70,6 +78,7 @@ require (
 	github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9 // indirect
 	github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9 // indirect
 	github.com/google/uuid v1.6.0 // indirect
+	github.com/gorilla/css v1.0.0 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
@@ -94,8 +103,8 @@ require (
 	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/rs/xid v1.5.0 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
-	github.com/sirupsen/logrus v1.9.0 // indirect
-	github.com/spf13/cast v1.4.1 // indirect
+	github.com/sirupsen/logrus v1.9.3 // indirect
+	github.com/spf13/cast v1.5.0 // indirect
 	github.com/tidwall/gjson v1.14.1 // indirect
 	github.com/tidwall/match v1.1.1 // indirect
 	github.com/tidwall/pretty v1.2.0 // indirect
@@ -103,11 +112,11 @@ require (
 	github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
 	github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
 	golang.org/x/crypto v0.19.0 // indirect
-	golang.org/x/image v0.14.0 // indirect
+	golang.org/x/image v0.15.0 // indirect
 	golang.org/x/net v0.21.0 // indirect
 	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
-	golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
+	golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
 	google.golang.org/protobuf v1.30.0 // indirect
 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 	gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect

+ 37 - 8
go.sum

@@ -1,3 +1,5 @@
+baliance.com/gooxml v1.0.1 h1:fG5lmxmjEVFfbKQ2NuyCuU3hMuuOb5avh5a38SZNO1o=
+baliance.com/gooxml v1.0.1/go.mod h1:+gpUgmkAF4zCtwOFPNRLDAvpVRWoKs5EeQTSv/HYFnw=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
@@ -89,6 +91,8 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoU
 github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
 github.com/aws/aws-sdk-go v1.51.2 h1:Ruwgz5aqIXin5Yfcgc+PCzoqW5tEGb9aDL/JWDsre7k=
 github.com/aws/aws-sdk-go v1.51.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
+github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
+github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
 github.com/beego/bee/v2 v2.1.0 h1:4WngbAnkvVOyKy74WXcRH3clon76wkjhuzrV2mx2fQU=
 github.com/beego/bee/v2 v2.1.0/go.mod h1:wDhKy5TNxv46LHKsK2gyxo38ObCOm9PbCN89lWHK3EU=
 github.com/beego/beego/v2 v2.1.0 h1:Lk0FtQGvDQCx5V5yEu4XwDsIgt+QOlNjt5emUa3/ZmA=
@@ -101,6 +105,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
 github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=
 github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
@@ -146,9 +151,12 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
+github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
+github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/garyburd/redigo v1.6.3/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw=
 github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -159,8 +167,9 @@ github.com/go-ldap/ldap v3.0.3+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
-github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
 github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-redis/redis/v8 v8.11.6-0.20220405070650-99c79f7041fc h1:jZY+lpZB92nvBo2f31oPC/ivGll6NcsnEOORm8Fkr4M=
+github.com/go-redis/redis/v8 v8.11.6-0.20220405070650-99c79f7041fc/go.mod h1:25mL1NKxbJhB63ihiK8MnNeTRd+xAizd6bOdydrTLUQ=
 github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -231,9 +240,13 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
+github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
+github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
 github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
+github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
+github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -258,7 +271,10 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
+github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc=
+github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
 github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53 h1:+8X3HMX8A2QhvNg3dImiQTCiVUt6BQXz1mW+/DrWI+k=
 github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53/go.mod h1:E61jD6q4yJ6Cu9uDGRAfiENM1G5TVZhOog0Y3+GgTpQ=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -290,6 +306,8 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
+github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
 github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
 github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
 github.com/minio/minio-go/v7 v7.0.69 h1:l8AnsQFyY1xiwa/DaQskY4NXSLA2yrGsW5iD9nRPVS0=
@@ -331,14 +349,16 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
 github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
+github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
+github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
 github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
 github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -382,6 +402,7 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
 github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
+github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
 github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
@@ -396,13 +417,15 @@ github.com/silenceper/wechat/v2 v2.1.6 h1:2br2DxNzhksmvIBJ+PfMqjqsvoZmd/5BnMIfjK
 github.com/silenceper/wechat/v2 v2.1.6/go.mod h1:7Iu3EhQYVtDUJAj+ZVRy8yom75ga7aDWv8RurLkVm0s=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
 github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
 github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
+github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
 github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -419,6 +442,9 @@ github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2K
 github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
 github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
 github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/asr v1.0.873 h1:CbeN5Fdzq3xea36+ZKPQcuRwwJk0ZYQRxcyWkyK5768=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/asr v1.0.873/go.mod h1:vzSh5OxbOCyFt+SdlEd9oCQGBb1oObkD7Xfod/UPvVk=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.873/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.880 h1:0Ok1pZ06/zZMCiW8Dm8wYOGJK1HCU5OXwNSyE5UVOAM=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.880/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ses v1.0.880 h1:PnzU5KS7x3LQGE0yetGLEGwJtLb6Uzsd79mbCiRh1rw=
@@ -482,9 +508,10 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
 golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
-golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
-golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
+golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
+golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -561,6 +588,7 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -590,8 +618,9 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
 golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
+golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

+ 14 - 1
models/business_conf.go

@@ -42,7 +42,11 @@ const (
 	BusinessConfLoginEmailTemplateContent = "LoginEmailTemplateContent"
 	BusinessConfLdapBindUserSuffix        = "LdapBindUserSuffix"
 	BusinessConfLdapUserFilter            = "LdapUserFilter"
-	BusinessConfSmsJhgjVariable           = "SmsJhgjVariable" // 聚合国际短信变量
+
+	BusinessConfTencentApiSecretId           = "TencentApiSecretId"           // 腾讯云API-密钥对
+	BusinessConfTencentApiSecretKey          = "TencentApiSecretKey"          // 腾讯云API-密钥对
+	BusinessConfTencentApiRecTaskCallbackUrl = "TencentApiRecTaskCallbackUrl" // 腾讯云API-语音识别回调地址
+	BusinessConfSmsJhgjVariable              = "SmsJhgjVariable"              // 聚合国际短信变量
 )
 
 const (
@@ -52,6 +56,15 @@ const (
 	BusinessConfEmailClientSmtp        = "smtp" // 普通邮箱标记
 )
 
+// FromSceneMap 数据源名称与数据源ID的对应关系
+var FromSceneMap = map[int]string{
+	1: "SmartReportSheetSize",
+	2: "ReportSheetSize",
+	3: "EnReportSheetSize",
+	4: "CnPptSheetSize",
+	5: "EnPptSheetSize",
+}
+
 // BusinessConf 商户配置表
 type BusinessConf struct {
 	Id         int    `orm:"column(id);pk"`

+ 195 - 27
models/chart_permission.go

@@ -1,44 +1,212 @@
 package models
 
 import (
+	"eta/eta_api/utils"
+	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"time"
 )
 
 // ChartPermission 报告权限表
 type ChartPermission struct {
-	ChartPermissionId   int       `orm:"column(chart_permission_id);pk" description:"问题ID"`
-	ChartPermissionName string    `description:"名称"`
-	PermissionName      string    `description:"权限名"`
-	Sort                int       `description:"排序"`
-	Enabled             int       `description:"是否可用"`
-	CreatedTime         time.Time `description:"创建时间"`
-	LastUpdatedTime     time.Time `description:"更新时间"`
-	TeleconferenceSort  int       `description:"电话会类型排序"`
-	Remark              string    `description:"备注"`
-	ClassifyName        string    `description:"分类名称"`
-	ProductName         string    `description:"产品名称"`
-	ProductId           int       `description:"产品ID"`
-	ImageURL            string    `description:"图片地址"`
-	ShowType            int       `description:"1:查研观向小程序展示"`
-	IsOther             int       `description:"是否是其他,用于查研观向小程序后台展示"`
-	IsReport            int       `description:"是否是报告,用于查研观向小程序前台报告展示"`
-	CygxAuth            int       `description:"是否是权限,用于查研观向小程序前台权限校验"`
-	YbImgUrl            string    `description:"研报小程序报告列表icon"`
-	PriceDrivenState    int       `description:"品种价格驱动开启状态 0-关闭 1-开启"`
+	ChartPermissionId     int       `orm:"column(chart_permission_id);pk" description:"问题ID" json:"chart_permission_id"`
+	ChartPermissionName   string    `description:"名称" json:"chart_permission_name"`
+	PermissionName        string    `description:"权限名" json:"permission_name"`
+	Sort                  int       `description:"排序" json:"sort"`
+	Enabled               int       `description:"是否可用" json:"enabled"`
+	CreatedTime           time.Time `description:"创建时间" json:"created_time"`
+	LastUpdatedTime       time.Time `description:"更新时间" json:"last_updated_time"`
+	TeleconferenceSort    int       `description:"电话会类型排序" json:"teleconference_sort"`
+	Remark                string    `description:"备注" json:"remark"`
+	ClassifyName          string    `description:"分类名称" json:"classify_name"`
+	ProductName           string    `description:"产品名称" json:"product_name"`
+	ProductId             int       `description:"产品ID" json:"product_id"`
+	ImageURL              string    `orm:"column(image_url);" description:"图片地址" json:"image_url"`
+	ShowType              int       `description:"1:查研观向小程序展示" json:"show_type"`
+	IsOther               int       `description:"是否是其他,用于查研观向小程序后台展示" json:"is_other"`
+	IsReport              int       `description:"是否是报告,用于查研观向小程序前台报告展示" json:"is_report"`
+	CygxAuth              int       `description:"是否是权限,用于查研观向小程序前台权限校验" json:"cygx_auth"`
+	PermissionType        int       `description:"1主观,2客观" json:"permission_type"`
+	YbImgUrl              string    `description:"研报小程序报告列表icon" json:"yb_img_url"`
+	ProductPermissionName string    `description:"种类权限名称" json:"product_permission_name"`
+	PriceDrivenState      int       `description:"品种价格驱动开启状态 0-关闭 1-开启" json:"price_driven_state"`
+	ImageUrlM             string    `description:"图片地址(查研观向移动端)" json:"image_url_m"`
+	ParentId              int       `description:"父级权限id" json:"parent_id"`
+	IsPublic              int       `description:"是否是公有权限1:公有权限,0私有权限" json:"is_public"`
+}
+
+type ChartPermissionItem struct {
+	PermissionId   int    `description:"品种权限ID"`
+	PermissionName string `description:"品种权限名称"`
+	ParentId       int    `description:"父级ID"`
+	IsPublic       int    `description:"是否是公有权限1:公有权限,0私有权限" `
+	Enabled        int    `description:"是否可用:1可用,0不可用" `
+	Sort           int    `description:"排序"`
+	CreateTime     string `description:"创建时间"`
+	Child          []*ChartPermissionItem
 }
 
 // Update 更新
-func (chartPermissionInfo *ChartPermission) Update(cols []string) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
-	_, err = o.Update(chartPermissionInfo, cols...)
+func (c *ChartPermission) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.Update(c, cols...)
+	return
+}
+
+type PermissionAddReq struct {
+	PermissionName string `description:"品种权限名称"`
+	ParentId       int    `description:"父级ID"`
+	Enabled        int    `description:"是否可用 0禁用, 1启用"` //启用,禁用操作会关联二级品种
+	IsPublic       int    `description:"是否是公有权限1:公有权限,0私有权限"`
+}
+
+type PermissionEditReq struct {
+	PermissionId        int    `description:"品种权限Id"` // 如果ID存在,则是更新操作,否则是新增操作
+	PermissionName      string `description:"品种权限名称"`
+	ParentId            int    `description:"父级ID"`
+	Enabled             int    `description:"是否可用 0禁用, 1启用"` //启用,禁用操作会关联二级品种
+	IsPublic            int    `description:"是否是公有权限1:公有权限,0私有权限"`
+	PublicPermissionIds []int  `description:"公有权限的ID列表"` //一级品种没有公有私有属性
+}
+
+type PermissionEnabledReq struct {
+	PermissionId int `description:"品种权限Id"`        // 如果ID存在,则是更新操作,否则是新增操作
+	Enabled      int `description:"是否可用 0禁用, 1启用"` //启用,禁用操作会关联二级品种
+}
+
+type PermissionMoveReq struct {
+	PermissionId int `description:"品种id"`
+	//	ParentChartPermissionId int `description:"父级品种id"`
+	PrevPermissionId int `description:"上一个兄弟节点品种id"`
+	NextPermissionId int `description:"下一个兄弟节点品种id"`
+}
+
+func (c *ChartPermission) SetEnabled(id, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	sql := ` UPDATE chart_permission SET enabled =?  WHERE id = ?`
+	_, err = to.Raw(sql, enabled, id).Exec()
+	if err != nil {
+		return
+	}
+	sql = ` UPDATE chart_permission SET enabled =?  WHERE parent_id = ?`
+	_, err = to.Raw(sql, enabled, id).Exec()
+	if err != nil {
+		return
+	}
+	return
+}
+
+// Create 新增权限
+func (c *ChartPermission) Create() (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	id, err := o.Insert(c)
+	if err != nil {
+		return
+	}
+	c.ChartPermissionId = int(id)
+	return
+}
+
+// SetIsPublic 更新公有私有权限
+func (c *ChartPermission) SetIsPublic(ids []int, parentId, isPublic int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `update chart_permission set is_public=? WHERE parent_id = ?  and  chart_permission_id IN (` + utils.GetOrmInReplace(len(ids)) + `)`
+	_, err = o.Raw(sql, isPublic, parentId, ids).Exec()
+	return
+}
+
+// UpdatesByParentId 更新启动禁用
+func (c *ChartPermission) UpdateClassifyNameByParentId(parentId int, classifyName string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `update chart_permission set classify_name=? WHERE parent_id = ?`
+	_, err = o.Raw(sql, classifyName, parentId).Exec()
+	return
+}
+
+// SetEnabledByParentId 更新启动禁用
+func (c *ChartPermission) SetEnabledByParentId(parentId, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` UPDATE chart_permission SET enabled =?  WHERE parent_id = ?`
+	_, err = o.Raw(sql, enabled, parentId).Exec()
+	return
+}
+
+// SetEnabledByChartPermissionId 更新启动禁用
+func (c *ChartPermission) SetEnabledByChartPermissionId(chartPermissionId, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` UPDATE chart_permission SET enabled =?  WHERE chart_permission_id = ?`
+	_, err = o.Raw(sql, enabled, chartPermissionId).Exec()
+	return
+}
+
+// GetItemById 查询品种
+func (c *ChartPermission) GetItemById(chartPermissionId int) (item *ChartPermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select * from chart_permission WHERE chart_permission_id = ?`
+	err = o.Raw(sql, chartPermissionId).QueryRow(&item)
+	return
+}
+
+// GetItemsByCondition 查询列表
+func (c *ChartPermission) GetItemsByCondition(condition string, pars []interface{}) (items []*ChartPermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select * from chart_permission WHERE 1=1 ` + condition + ` order by sort asc, chart_permission_id asc`
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// GetItemByCondition 查询列表
+func (c *ChartPermission) GetItemByCondition(condition string, pars []interface{}) (item *ChartPermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select * from chart_permission WHERE 1=1 ` + condition
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+// UpdateChartPermissionSortByParentId 根据父类id更新排序
+func UpdateChartPermissionSortByParentId(parentId, chartPermissionId, nowSort int, updateSort string, productId int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` update chart_permission set sort = ` + updateSort + ` WHERE parent_id=? AND product_id = ? AND (sort > ? `
+	if chartPermissionId > 0 {
+		sql += ` or ( chart_permission_id > ` + fmt.Sprint(chartPermissionId) + ` and sort = ` + fmt.Sprint(nowSort) + `))`
+	} else {
+		sql += `)`
+	}
+	_, err = o.Raw(sql, parentId, productId, nowSort).Exec()
+	return
+}
+
+// GetMaxSort 获取最大的排序值
+func (c *ChartPermission) GetMaxSort() (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select max(sort) from chart_permission `
+	err = o.Raw(sql).QueryRow(&maxSort)
+	return
+}
+
+// GetMaxSortByParentId 获取最大的排序值
+func (c *ChartPermission) GetMaxSortByParentId(parentId int) (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select max(sort) from chart_permission WHERE parent_id=? `
+	err = o.Raw(sql, parentId).QueryRow(&maxSort)
 	return
 }
 
-// GetChartPermissionList 获取品种权限列表
-func GetChartPermissionList() (list []*ChartPermission, err error) {
-	o := orm.NewOrmUsingDB("weekly")
-	sql := `SELECT * FROM chart_permission ORDER BY product_id ASC, sort ASC`
-	_, err = o.Raw(sql).QueryRows(&list)
+// GetFirstChartPermissionByParentId 获取当前父级分类下,且排序数相同 的排序第一条的数据
+func (c *ChartPermission) GetFirstChartPermissionByParentId(parentId int) (item *ChartPermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `select * from chart_permission WHERE parent_id=? ORDER BY sort ASC, chart_permission_id ASC LIMIT 1`
+	err = o.Raw(sql, parentId).QueryRow(&item)
 	return
 }

+ 130 - 43
models/classify.go

@@ -2,6 +2,7 @@ package models
 
 import (
 	"eta/eta_api/utils"
+	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"time"
@@ -39,38 +40,40 @@ type Classify struct {
 	RelateTel         int       `description:"是否在电话会中可选: 0-否; 1-是"`
 	RelateVideo       int       `description:"是否在路演视频中可选: 0-否; 1-是"`
 	IsMassSend        int       `description:"1:群发,0:非群发"`
+	Enabled           int       `description:"是否可用,1可用,0禁用"`
 }
 
 type ClassifyAddReq struct {
-	ClassifyName      string                 `description:"分类名称"`
-	ParentId          int                    `description:"父级分类id,没有父级分类传0"`
-	Abstract          string                 `description:"栏目简介"`
-	Descript          string                 `description:"分享描述"`
-	ReportAuthor      string                 `description:"栏目作者"`
-	AuthorDescript    string                 `description:"作者简介"`
-	ColumnImgUrl      string                 `description:"栏目配图"`
-	ReportImgUrl      string                 `description:"报告配图"`
-	HeadImgUrl        string                 `description:"头部banner"`
-	AvatarImgUrl      string                 `description:"头像"`
-	HomeImgUrl        string                 `description:"首页配图"`
-	ClassifyLabel     string                 `description:"分类标签"`
-	ShowType          int                    `description:"展示类型:1-列表 2-专栏"`
-	HasTeleconference int                    `description:"是否有电话会:0-否 1-是"`
-	VipTitle          string                 `description:"研究员头衔"`
-	Sort              int                    `description:"后台排序"`
-	IsShow            int                    `description:"是否在小程序显示:1-显示 0-隐藏"`
-	YbFiccSort        int                    `description:"小程序FICC页排序"`
-	YbFiccIcon        string                 `description:"小程序FICC页icon"`
-	YbFiccPcIcon      string                 `description:"小程序PC端FICC页背景图"`
-	YbIconUrl         string                 `description:"小程序已购页icon"`
-	YbBgUrl           string                 `description:"小程序已购详情背景图"`
-	YbListImg         string                 `description:"小程序研报列表封面图"`
-	YbShareBgImg      string                 `description:"小程序研报详情分享背景图"`
-	YbRightBanner     string                 `description:"Pc端详情页,右侧,报告合集背景图"`
-	MenuList          []*ClassifyMenuSaveReq `description:"子目录列表"`
-	ClassifyMenuId    int                    `description:"二级分类-子目录ID"`
-	RelateTel         int                    `description:"是否在电话会中可选: 0-否; 1-是"`
-	RelateVideo       int                    `description:"是否在路演视频中可选: 0-否; 1-是"`
+	ClassifyName          string `description:"分类名称"`
+	ParentId              int    `description:"父级分类id,没有父级分类传0"`
+	ChartPermissionIdList []int  `description:"权限id数组"`
+	/*Abstract              string                 `description:"栏目简介"`
+	Descript              string                 `description:"分享描述"`
+	ReportAuthor          string                 `description:"栏目作者"`
+	AuthorDescript        string                 `description:"作者简介"`
+	ColumnImgUrl          string                 `description:"栏目配图"`
+	ReportImgUrl          string                 `description:"报告配图"`
+	HeadImgUrl            string                 `description:"头部banner"`
+	AvatarImgUrl          string                 `description:"头像"`
+	HomeImgUrl            string                 `description:"首页配图"`
+	ClassifyLabel         string                 `description:"分类标签"`
+	ShowType              int                    `description:"展示类型:1-列表 2-专栏"`
+	HasTeleconference     int                    `description:"是否有电话会:0-否 1-是"`
+	VipTitle              string                 `description:"研究员头衔"`
+	Sort                  int                    `description:"后台排序"`
+	IsShow                int                    `description:"是否在小程序显示:1-显示 0-隐藏"`
+	YbFiccSort            int                    `description:"小程序FICC页排序"`
+	YbFiccIcon            string                 `description:"小程序FICC页icon"`
+	YbFiccPcIcon          string                 `description:"小程序PC端FICC页背景图"`
+	YbIconUrl             string                 `description:"小程序已购页icon"`
+	YbBgUrl               string                 `description:"小程序已购详情背景图"`
+	YbListImg             string                 `description:"小程序研报列表封面图"`
+	YbShareBgImg          string                 `description:"小程序研报详情分享背景图"`
+	YbRightBanner         string                 `description:"Pc端详情页,右侧,报告合集背景图"`
+	MenuList              []*ClassifyMenuSaveReq `description:"子目录列表"`
+	ClassifyMenuId        int                    `description:"二级分类-子目录ID"`
+	RelateTel             int                    `description:"是否在电话会中可选: 0-否; 1-是"`
+	RelateVideo           int                    `description:"是否在路演视频中可选: 0-否; 1-是"`*/
 }
 
 func GetClassifyByName(classifyName string, parentId int) (item *Classify, err error) {
@@ -140,8 +143,11 @@ func DeleteClassify(classifyId int) (err error) {
 // 修改分类
 func EditClassify(req *EditClassifyReq) (err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := `UPDATE classify SET classify_name = ?,abstract=?, parent_id= ?,descript=?,report_author=?,author_descript=?,column_img_url=?,head_img_url=?,avatar_img_url=?,report_img_url=?,home_img_url=?,classify_label=?,show_type=?,has_teleconference=?,vip_title=?,modify_time= NOW() WHERE id = ? `
-	_, err = o.Raw(sql, req.ClassifyName, req.Abstract, req.ParentId, req.Descript, req.ReportAuthor, req.AuthorDescript, req.ColumnImgUrl, req.HeadImgUrl, req.AvatarImgUrl, req.ReportImgUrl, req.HomeImgUrl, req.ClassifyLabel, req.ShowType, req.HasTeleconference, req.VipTitle, req.ClassifyId).Exec()
+	//sql := `UPDATE classify SET classify_name = ?,abstract=?, parent_id= ?,descript=?,report_author=?,author_descript=?,column_img_url=?,head_img_url=?,avatar_img_url=?,report_img_url=?,home_img_url=?,classify_label=?,show_type=?,has_teleconference=?,vip_title=?,modify_time= NOW() WHERE id = ? `
+	//_, err = o.Raw(sql, req.ClassifyName, req.Abstract, req.ParentId, req.Descript, req.ReportAuthor, req.AuthorDescript, req.ColumnImgUrl, req.HeadImgUrl, req.AvatarImgUrl, req.ReportImgUrl, req.HomeImgUrl, req.ClassifyLabel, req.ShowType, req.HasTeleconference, req.VipTitle, req.ClassifyId).Exec()
+	sql := `UPDATE classify SET classify_name = ?,parent_id= ?,modify_time= NOW() WHERE id = ? `
+	_, err = o.Raw(sql, req.ClassifyName, req.ParentId, req.ClassifyId).Exec()
+
 	return
 }
 
@@ -185,19 +191,20 @@ type ClassifyList struct {
 	YbRightBanner     string    `description:"Pc端详情页,右侧,报告合集背景图"`
 	RelateTel         int       `description:"是否在电话会中可选: 0-否; 1-是"`
 	RelateVideo       int       `description:"是否在路演视频中可选: 0-否; 1-是"`
+	Enabled           int       `description:"是否可用,1可用,0禁用"`
 	Child             []*ClassifyItem
 	ClassifyMenuList  []*ClassifyMenu
 }
 
 type ClassifyItem struct {
 	Classify
-	ClassifyMenuId   int `description:"二级分类-子目录ID"`
-	ClassifyMenuList []*ClassifyMenu
+	ClassifyMenuId        int `description:"二级分类-子目录ID"`
+	ClassifyMenuList      []*ClassifyMenu
+	ChartPermissionIdList []int `description:"绑定的权限ID"`
 }
 
 type ClassifyListResp struct {
-	List   []*ClassifyList
-	Paging *paging.PagingItem `description:"分页数据"`
+	List []*ClassifyList
 }
 
 type ClassifyPermissionListResp struct {
@@ -206,7 +213,7 @@ type ClassifyPermissionListResp struct {
 }
 
 // 获取分类列表
-func GetClassifyList(startSize, pageSize int, keyWord, companyType string, hideDayWeek int) (items []*ClassifyList, err error) {
+func GetClassifyList(keyWord, companyType string, hideDayWeek, enabled int) (items []*ClassifyList, err error) {
 	sql := ``
 	companyTypeSqlStr := ``
 	if companyType == "ficc" {
@@ -214,6 +221,9 @@ func GetClassifyList(startSize, pageSize int, keyWord, companyType string, hideD
 	} else if companyType == "权益" {
 		companyTypeSqlStr = " AND (id = 40 or parent_id = 40)  "
 	}
+	if enabled == 1 {
+		companyTypeSqlStr += ` AND enabled = 1 `
+	}
 	pars := make([]interface{}, 0)
 	if keyWord != "" {
 		sql = `SELECT * FROM (
@@ -224,17 +234,17 @@ func GetClassifyList(startSize, pageSize int, keyWord, companyType string, hideD
                    WHERE id IN( SELECT parent_id FROM classify
                    WHERE parent_id>0 ` + companyTypeSqlStr + `  AND classify_name LIKE ? )
                    )AS t
-                   ORDER BY sort ASC,create_time ASC
-                   LIMIT ?,? `
+                   ORDER BY sort ASC,create_time ASC`
 		pars = utils.GetLikeKeywordPars(pars, keyWord, 2)
 	} else {
 		sql = `SELECT * FROM classify WHERE parent_id=0 ` + companyTypeSqlStr
 		if hideDayWeek == 1 {
 			sql += ` AND classify_name <> '晨报' AND classify_name <> '周报' `
 		}
-		sql += ` ORDER BY sort ASC, create_time ASC LIMIT ?,? `
+
+		sql += ` ORDER BY sort ASC, create_time ASC`
 	}
-	pars = append(pars, startSize, pageSize)
+	pars = append(pars)
 
 	o := orm.NewOrmUsingDB("rddp")
 	_, err = o.Raw(sql, pars...).QueryRows(&items)
@@ -312,7 +322,7 @@ func GetClassifyChild(parentId int, keyWord string) (items []*Classify, err erro
 	return
 }
 
-func GetClassifyChildByParentIds(parentId []int, keyWord string) (items []*Classify, err error) {
+func GetClassifyChildByParentIds(parentId []int, keyWord string, enabled int) (items []*Classify, err error) {
 	parentIdLen := len(parentId)
 	if parentIdLen == 0 {
 		return
@@ -322,11 +332,16 @@ func GetClassifyChildByParentIds(parentId []int, keyWord string) (items []*Class
 	pars := make([]interface{}, 0)
 	pars = append(pars, parentId)
 	if keyWord != "" {
-		sql = `SELECT * FROM classify WHERE parent_id IN (` + utils.GetOrmInReplace(parentIdLen) + `) AND classify_name LIKE ? ORDER BY create_time ASC `
+		sql = `SELECT * FROM classify WHERE parent_id IN (` + utils.GetOrmInReplace(parentIdLen) + `) AND classify_name LIKE ? `
 		pars = append(pars, utils.GetLikeKeyword(keyWord))
 	} else {
-		sql = `SELECT * FROM classify WHERE parent_id IN (` + utils.GetOrmInReplace(parentIdLen) + `) ORDER BY create_time ASC `
+		sql = `SELECT * FROM classify WHERE parent_id IN (` + utils.GetOrmInReplace(parentIdLen) + `) `
 	}
+
+	if enabled == 1 {
+		sql += ` AND enabled=1 `
+	}
+	sql += ` ORDER BY create_time ASC `
 	_, err = o.Raw(sql, pars...).QueryRows(&items)
 
 	return
@@ -401,3 +416,75 @@ type RelateTelSecClassifyWithPermissions struct {
 	ClassifyName       string `description:"分类名称"`
 	ChartPermissionIds string `description:"权限IDs"`
 }
+
+// UpdateClassifySortByParentId 根据父类id更新排序
+func UpdateClassifySortByParentId(parentId, permissionId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` update classify set sort = ` + updateSort + ` WHERE parent_id=? AND sort > ? `
+	if permissionId > 0 {
+		sql += ` or ( id > ` + fmt.Sprint(permissionId) + ` and sort = ` + fmt.Sprint(nowSort) + `)`
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// GetMaxSortByParentId 获取最大的排序值
+func (classifyInfo *Classify) GetMaxSortByParentId(parentId int) (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT max(sort) AS sort FROM classify WHERE parent_id = ? `
+	err = o.Raw(sql, parentId).QueryRow(&maxSort)
+	return
+}
+
+// GetMaxSort 获取最大的排序值
+func (classifyInfo *Classify) GetMaxSort() (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT max(sort) AS sort FROM classify`
+	err = o.Raw(sql).QueryRow(&maxSort)
+	return
+}
+
+// GetFirstClassifyByParentId 获取当前父级分类下,且排序数相同 的排序第一条的数据
+func (classifyInfo *Classify) GetFirstClassifyByParentId(parentId int) (item *Classify, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM classify WHERE parent_id = ? order by sort asc, id asc limit 1`
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+type ClassifyMoveReq struct {
+	ClassifyId     int `description:"分类ID"`
+	PrevClassifyId int `description:"上一个兄弟节点分类id"`
+	NextClassifyId int `description:"下一个兄弟节点分类id"`
+}
+
+type ClassifySetEnabledReq struct {
+	ClassifyId int `description:"分类ID"`
+	Enabled    int `description:"是否可用,1可用,0禁用"`
+}
+
+func (classifyInfo *Classify) SetEnabled(id, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	sql := ` UPDATE classify SET enabled =?  WHERE id = ?`
+	_, err = to.Raw(sql, enabled, id).Exec()
+	if err != nil {
+		return
+	}
+	sql = ` UPDATE classify SET enabled =?  WHERE parent_id = ?`
+	_, err = to.Raw(sql, enabled, id).Exec()
+	if err != nil {
+		return
+	}
+	return
+}

+ 9 - 9
models/company/company_permission.go

@@ -37,15 +37,15 @@ type PermissionSetItemType struct {
 }
 
 type PermissionSetList struct {
-	ClassifyName string `description:"分类"`
-	Items        []*PermissionSetItem
-	CheckList    []int
+	PermissionName string `description:"分类"`
+	Child          []*PermissionSetItem
+	CheckList      []int
 }
 
 type PermissionSetListType struct {
-	ClassifyName string `description:"分类"`
-	Items        []*PermissionSetItemType
-	CheckList    []int
+	PermissionName string `description:"分类"`
+	Child          []*PermissionSetItemType
+	CheckList      []int
 }
 
 type PermissionSetResp struct {
@@ -55,7 +55,7 @@ type PermissionSetResp struct {
 }
 
 func GetPermissionSetItems(productId int, classifyName string) (items []*PermissionSetItem, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM chart_permission WHERE enabled=1 AND product_id=? AND classify_name=?  AND permission_type=0 ORDER BY sort ASC `
 	_, err = o.Raw(sql, productId, classifyName).QueryRows(&items)
 	return
@@ -95,7 +95,7 @@ type PermissionVarietyList struct {
 }
 
 func GetPermissionVarietyItems(productId int, classifyName string) (items []*PermissionVarietyItem, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM chart_permission WHERE enabled=1 AND product_id=? AND classify_name=? GROUP BY permission_name ORDER BY sort ASC `
 	_, err = o.Raw(sql, productId, classifyName).QueryRows(&items)
 	return
@@ -103,7 +103,7 @@ func GetPermissionVarietyItems(productId int, classifyName string) (items []*Per
 
 // GetChartPermissionListById 根据权限id获取产品权限详情
 func GetChartPermissionListById(chartPermissionId int) (item *ChartPermission, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := `SELECT * FROM chart_permission WHERE chart_permission_id =? `
 	err = o.Raw(sql, chartPermissionId).QueryRow(&item)
 	return

+ 37 - 0
models/data_manage/chart_classify.go

@@ -20,6 +20,7 @@ type ChartClassify struct {
 	UniqueCode        string    `description:"唯一编码"`
 	Sort              int       `description:"排序字段,越小越靠前,默认值:10"`
 	Source            int       `description:"1:ETA图库;2:商品价格曲线"`
+	IsJoinPermission  int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
 }
 
 func AddChartClassify(item *ChartClassify) (lastId int64, err error) {
@@ -148,6 +149,8 @@ type ChartClassifyItems struct {
 	SeasonEndDate       string `description:"季节性图开始日期"`
 	Children            []*ChartClassifyItems
 	Button              ChartClassifyItemsButton `description:"按钮权限"`
+	IsJoinPermission    int                      `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth       bool                     `description:"是否有数据权限,默认:false"`
 }
 
 // ChartClassifyItemsButton 操作按钮
@@ -325,3 +328,37 @@ func GetChartClassifyByParentIdAndName(parentId int, classifyName string, classi
 	err = o.Raw(sql, parentId, classifyName, classifyId).QueryRow(&item)
 	return
 }
+
+// GetChartClassifyByIdList
+// @Description:  根据分类ID列表获取分类
+// @author: Roc
+// @datetime 2024-04-01 13:21:48
+// @param classifyId []int
+// @return items []*ChartClassify
+// @return err error
+func GetChartClassifyByIdList(classifyIdList []int) (items []*ChartClassify, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_classify WHERE chart_classify_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, classifyIdList).QueryRows(&items)
+
+	return
+}
+
+// GetChartClassifyBySourceAndIsJoinPermission
+// @Description: 根据分类类型和是否涉密获取分类列表
+// @author: Roc
+// @datetime 2024-03-29 10:30:21
+// @param source int
+// @param isJoinPermission int
+// @return items []*ChartClassify
+// @return err error
+func GetChartClassifyBySourceAndIsJoinPermission(source, isJoinPermission int) (items []*ChartClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM chart_classify WHERE source = ? AND is_join_permission = ? `
+	_, err = o.Raw(sql, source, isJoinPermission).QueryRows(&items)
+	return
+}

+ 7 - 7
models/data_manage/chart_edb_mapping.go

@@ -46,7 +46,7 @@ func AddChartEdbMapping(items []*ChartEdbMapping) (err error) {
 func GetChartEdbMappingList(chartInfoId int) (list []*ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.classify_id,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,
-b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type,
+b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type,b.is_join_permission,
 a.is_convert, a.convert_type, a.convert_value, a.convert_unit, a.convert_en_unit 
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
@@ -58,7 +58,7 @@ a.is_convert, a.convert_type, a.convert_value, a.convert_unit, a.convert_en_unit
 
 func GetChartEdbMappingListByChartInfoIds(chartInfoIds string) (list []*ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type
+	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.edb_type,b.classify_id,b.is_join_permission
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
 			 WHERE chart_info_id in (` + chartInfoIds + `) 
@@ -69,7 +69,7 @@ func GetChartEdbMappingListByChartInfoIds(chartInfoIds string) (list []*ChartEdb
 
 func GetChartEdbMappingListByEdbInfoId(edbInfoStr string) (list []*ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,source_name,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type
+	sql := ` SELECT edb_info_id,source_name,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type,classify_id,is_join_permission
              FROM edb_info
 			 WHERE edb_info_id IN(` + edbInfoStr + `)
 			ORDER BY FIELD(edb_info_id,` + edbInfoStr + `)
@@ -85,7 +85,7 @@ func GetChartEdbMappingListByEdbInfoIdList(edbIdList []int) (list []*ChartEdbInf
 		return
 	}
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,source_name,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type
+	sql := ` SELECT edb_info_id,source_name,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,max_value,min_value,edb_type,classify_id,is_join_permission
              FROM edb_info
 			 WHERE edb_info_id IN(` + utils.GetOrmInReplace(num) + `)
 			ORDER BY FIELD(edb_info_id,` + utils.GetOrmInReplace(num) + `)
@@ -101,7 +101,7 @@ func GetChartEdbMappingListByIdList(chartInfoIdList []int) (list []*ChartEdbInfo
 		return
 	}
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type,b.edb_type AS edb_info_category_type
+	sql := ` SELECT a.*,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type,b.edb_type AS edb_info_category_type,b.classify_id,b.is_join_permission
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
 			 WHERE chart_info_id in (` + utils.GetOrmInReplace(num) + `) 
@@ -145,7 +145,7 @@ func GetEtaEdbChartEdbMapping(chartInfoId int) (item *ChartEdbInfoMapping, err e
 	o := orm.NewOrmUsingDB("data")
 	aField := `a.chart_edb_mapping_id,a.chart_info_id,a.edb_info_id,a.create_time,a.modify_time,a.unique_code,a.max_data,a.min_data,a.is_order,a.is_axis,a.edb_info_type,a.lead_value,a.lead_unit,a.chart_style,a.chart_color,a.predict_chart_color,a.chart_width,a.source as mapping_source`
 
-	sql := ` SELECT ` + aField + `,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type
+	sql := ` SELECT ` + aField + `,b.source_name,b.source,b.sub_source,b.edb_code,b.edb_name,b.edb_name_en,b.frequency,b.unit,b.unit_en,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.unique_code,b.edb_info_type AS edb_info_category_type,b.classify_id,b.is_join_permission
              FROM chart_edb_mapping AS a
 			 INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
 			 WHERE a.chart_info_id=? AND a.source = ?
@@ -193,7 +193,7 @@ func GetChartEdbMappingListV2(chartInfoId int) (list []*ChartEdbInfoMapping, err
 // GetChartEdbMappingByEdbInfoId 根据指标id获取edb_mapping
 func GetChartEdbMappingByEdbInfoId(edbInfoId int) (item *ChartEdbInfoMapping, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,source_name,classify_id,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,edb_type,max_value,min_value
+	sql := ` SELECT edb_info_id,source_name,classify_id,source,sub_source,edb_code,edb_name,edb_name_en,frequency,unit,unit_en,start_date,end_date,modify_time,latest_date,latest_value,unique_code,edb_info_type AS edb_info_category_type,edb_type,max_value,min_value,is_join_permission
              FROM edb_info
 			 WHERE edb_info_id = ? limit 1`
 	err = o.Raw(sql, edbInfoId).QueryRow(&item)

+ 65 - 4
models/data_manage/chart_info.go

@@ -54,11 +54,13 @@ type ChartInfo struct {
 	MarkersAreas      string `description:"标识区"`
 	Unit              string `description:"中文单位名称"`
 	UnitEn            string `description:"英文单位名称"`
+	IsJoinPermission  int    `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
 }
 
 type ChartInfoMore struct {
 	ChartInfo
-	IsEnChart bool `description:"是否展示英文标识"`
+	IsEnChart     bool `description:"是否展示英文标识"`
+	HaveOperaAuth bool `description:"是否有数据权限,默认:false"`
 }
 
 func AddChartInfo(item *ChartInfo) (lastId int64, err error) {
@@ -497,6 +499,8 @@ type ChartEdbInfoMapping struct {
 	ConvertValue        float64 `description:"数据转换值"`
 	ConvertUnit         string  `description:"数据转换单位"`
 	ConvertEnUnit       string  `description:"数据转换单位"`
+	IsJoinPermission    int     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth       bool    `description:"是否有数据权限,默认:false"`
 }
 
 type QuarterData struct {
@@ -1452,6 +1456,8 @@ type ChartInfoView struct {
 	Instructions      string          `description:"图表说明"`
 	MarkersLines      string          `description:"标识线"`
 	MarkersAreas      string          `description:"标识区"`
+	IsJoinPermission  int             `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth     bool            `description:"是否有数据权限,默认:false"`
 }
 
 type ChartViewButton struct {
@@ -1566,12 +1572,47 @@ func GetChartInfoListGroupByUserId(edbIdList []string) (items []*ChartInfo, err
 		return
 	}
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT * FROM chart_info WHERE chart_info_id in (` + utils.GetOrmInReplace(num) + `) GROUP BY sys_user_id `
+	sql := ` SELECT * FROM chart_info WHERE chart_info_id in (` + utils.GetOrmInReplace(num) + `) ORDER BY chart_info_id desc `
 
 	_, err = o.Raw(sql, edbIdList).QueryRows(&items)
 	return
 }
 
+// GetChartInfoListByChartIdList
+// @Description: 根据图表id列表获取列表信息
+// @param edbIdList
+// @return items
+// @return err
+func GetChartInfoListByChartIdList(charIdList []string) (items []*ChartInfo, err error) {
+	num := len(charIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM chart_info WHERE chart_info_id in (` + utils.GetOrmInReplace(num) + `) ORDER BY chart_info_id desc `
+
+	_, err = o.Raw(sql, charIdList).QueryRows(&items)
+	return
+}
+
+// GetChartInfoListByUserId
+// @Description: 根据图表id列表获取列表信息
+// @param userIdList []int
+// @param source int
+// @return items
+// @return err
+func GetChartInfoListByUserId(userIdList []int, source int) (items []*ChartInfo, err error) {
+	num := len(userIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM chart_info WHERE source = ? AND  sys_user_id in (` + utils.GetOrmInReplace(num) + `) ORDER BY chart_info_id desc `
+
+	_, err = o.Raw(sql, source, userIdList).QueryRows(&items)
+	return
+}
+
 // ModifyChartInfoUserIdByCodeList 根据指标code列表修改创建人
 func ModifyChartInfoUserIdByCodeList(edbIdList []string, userId int, userName string) (err error) {
 	num := len(edbIdList)
@@ -1584,6 +1625,26 @@ func ModifyChartInfoUserIdByCodeList(edbIdList []string, userId int, userName st
 	return
 }
 
+// ModifyChartInfoUserIdByOldUserId
+// @Description:  根据旧的用户id修改创建人
+// @author: Roc
+// @datetime 2024-03-25 19:14:59
+// @param oldUserId int
+// @param userId int
+// @param userName string
+// @return err error
+func ModifyChartInfoUserIdByOldUserId(oldUserIdList []int, userId int, userName string) (err error) {
+	num := len(oldUserIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `UPDATE chart_info SET sys_user_id=?,sys_user_real_name=? WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userId, userName, oldUserIdList).Exec()
+
+	return
+}
+
 // BarChartInfoReq 柱方图预览请求数据
 type BarChartInfoReq struct {
 	EdbInfoIdList []BarChartInfoEdbItemReq `description:"指标信息"`
@@ -1909,7 +1970,7 @@ type RollingCorrelationChartDataResp struct {
 func GetChartInfoAllByClassifyId(source, classifyId int) (items []*ChartClassifyItems, err error) {
 	o := orm.NewOrmUsingDB("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
+             unique_code,sys_user_id,sys_user_real_name,date_type,start_date,end_date,chart_type,calendar,season_start_date,season_end_date,is_join_permission
             FROM chart_info WHERE chart_classify_id = ? AND source = ?  ORDER BY sort asc,create_time DESC `
 	_, err = o.Raw(sql, classifyId, source).QueryRows(&items)
 	return
@@ -1939,7 +2000,7 @@ func GetChartInfoByAdminIdAndClassify(sourceList []int, adminId, classifyId int)
 
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT chart_info_id,chart_classify_id,chart_name AS chart_classify_name,
-             unique_code,sys_user_id,sys_user_real_name,date_type,start_date,end_date,chart_type,calendar,season_start_date,season_end_date
+             unique_code,sys_user_id,sys_user_real_name,date_type,start_date,end_date,chart_type,calendar,season_start_date,season_end_date,is_join_permission
             FROM chart_info where source in (` + utils.GetOrmInReplace(num) + `)  AND sys_user_id = ? AND chart_classify_id = ? ORDER BY sort asc,create_time ASC `
 	_, err = o.Raw(sql, sourceList, adminId, classifyId).QueryRows(&items)
 	return

+ 976 - 0
models/data_manage/data_manage_permission/chart.go

@@ -0,0 +1,976 @@
+package data_manage_permission
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"time"
+)
+
+// ChartInfoPermission
+// @Description: 图表信息权限表
+type ChartInfoPermission struct {
+	ChartInfoPermissionId int64     `json:"chart_info_permission_id" orm:"column(chart_info_permission_id);pk"`
+	ChartInfoId           int32     `json:"chart_info_id"` // 图表id
+	Source                int32     `json:"source"`        // 1:ETA图库;2:商品价格曲线;3:相关性图
+	SysUserId             int32     `json:"sys_user_id"`   // 系统用户id
+	ModifyTime            time.Time `json:"modify_time"`   // 变更时间
+	CreateTime            time.Time `json:"create_time"`   // 关系建立时间
+}
+
+// ChartClassifyPermission
+// @Description: 图表分类权限表
+type ChartClassifyPermission struct {
+	ChartClassifyPermissionId int64     `json:"chart_classify_permission_id" orm:"column(chart_classify_permission_id);pk"`
+	ChartClassifyId           int32     `json:"chart_classify_id"` // 分类id
+	Source                    int32     `json:"source"`            // 分类来源: 1-图库; 2-商品价格曲线; 3-相关性图表; 6-拟合方程图表; 7-统计特征
+	SysUserId                 int32     `json:"sys_user_id"`       // 系统用户id
+	ModifyTime                time.Time `json:"modify_time"`       // 变更时间
+	CreateTime                time.Time `json:"create_time"`       // 关系建立时间
+}
+
+// SetIsPermissionByChartClassifyIdList
+// @Description: 设置图表分类是否涉密
+// @author: Roc
+// @datetime 2024-04-01 10:53:23
+// @param classifyIdList []int
+// @param chartClassifySource int
+// @return err error
+func SetIsPermissionByChartClassifyIdList(classifyIdList []int, chartClassifySource int) (err error) {
+	num := len(classifyIdList)
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	//// 获取已经配置涉密的分类权限
+	//chartClassifyList := make([]*ChartClassify, 0)
+	//sql := `SELECT * FROM chart_classify WHERE is_join_permission = ? `
+	//_, err = o.Raw(sql, 1).QueryRows(&chartClassifyList)
+	//if err != nil {
+	//	return
+	//}
+	//chartClassifyMap := make(map[int]*ChartClassify)
+	//for _, v := range chartClassifyList {
+	//	chartClassifyMap[v.ClassifyId] = v
+	//}
+
+	// 先将所有已经设置了涉密的分类设置为不涉密
+	sql := `UPDATE chart_classify SET is_join_permission=?,modify_time=now() WHERE is_join_permission = 1 AND source = ?`
+	_, err = o.Raw(sql, 0, chartClassifySource).Exec()
+	if err != nil {
+		return
+	}
+
+	if num > 0 {
+		// 将对应的分类设置为涉密
+		sql = `UPDATE chart_classify SET is_join_permission=?,modify_time=now() WHERE source = ? AND chart_classify_id in (` + utils.GetOrmInReplace(num) + `) `
+		_, err = o.Raw(sql, 1, chartClassifySource, classifyIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// SetPermissionByChartIdList
+// @Description: 根据图表ID列表设置图表的用户权限
+// @author: Roc
+// @datetime 2024-04-01 10:26:17
+// @param chartIdList []string
+// @param userIdList []int
+// @param source int
+// @return err error
+func SetPermissionByChartIdList(chartIdList []string, userIdList []int, source int) (err error) {
+	chartNum := len(chartIdList)
+	if chartNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 获取已经配置的图表权限用户
+	chartInfoPermissionList := make([]*ChartInfoPermission, 0)
+	sql := `SELECT * FROM chart_info_permission WHERE source = ? AND chart_info_id in (` + utils.GetOrmInReplace(chartNum) + `) `
+	_, err = o.Raw(sql, source, chartIdList).QueryRows(&chartInfoPermissionList)
+	if err != nil {
+		return
+	}
+	chartInfoPermissionMap := make(map[string]*ChartInfoPermission)
+	for _, v := range chartInfoPermissionList {
+		chartInfoPermissionMap[fmt.Sprint(v.ChartInfoId, "_", v.SysUserId)] = v
+	}
+
+	// 标记图表是否纳入权限管控
+	{
+		// 默认 标记图表为纳入权限管控
+		isJoinPermission := 1
+		// 用户不选的情况下,说明是要给这些图表移除权限管控
+		if len(userIdList) <= 0 {
+			// 标记图表为不纳入权限管控
+			isJoinPermission = 0
+		}
+		sql = `UPDATE chart_info SET is_join_permission=?,modify_time=now() WHERE source = ? AND chart_info_id in (` + utils.GetOrmInReplace(chartNum) + `) `
+		_, err = o.Raw(sql, isJoinPermission, source, chartIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// 待添加的配置项
+	addList := make([]*ChartInfoPermission, 0)
+
+	// 遍历待配置的图表和用户,筛选出需要添加的配置项
+	for _, chartInfoIdStr := range chartIdList {
+		chartInfoId, tmpErr := strconv.ParseInt(chartInfoIdStr, 10, 64)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		for _, userId := range userIdList {
+			key := fmt.Sprint(chartInfoId, "_", userId)
+			if _, ok := chartInfoPermissionMap[key]; ok {
+				// 如果存在那么就移除,说明不需要处理了
+				delete(chartInfoPermissionMap, key)
+			} else {
+				// 如果不存在,那么就添加
+				addList = append(addList, &ChartInfoPermission{
+					//PermissionId: 0,
+					ChartInfoId: int32(chartInfoId),
+					SysUserId:   int32(userId),
+					Source:      int32(source),
+					ModifyTime:  time.Now(),
+					CreateTime:  time.Now(),
+				})
+			}
+		}
+	}
+
+	// 添加待配置项
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(500, addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除废弃的配置项
+	{
+		// 待移除的配置项
+		deletePermissionIdList := make([]int64, 0)
+		for _, v := range chartInfoPermissionMap {
+			deletePermissionIdList = append(deletePermissionIdList, v.ChartInfoPermissionId)
+		}
+
+		deletePermissionIdNum := len(deletePermissionIdList)
+		if deletePermissionIdNum > 0 {
+			sql = "DELETE FROM chart_info_permission WHERE chart_info_permission_id in (" + utils.GetOrmInReplace(deletePermissionIdNum) + ")"
+			_, err = o.Raw(sql, deletePermissionIdList).Exec()
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// SetPermissionByChartClassifyIdList
+// @Description: 根据图表分类ID列表设置分类的用户权限
+// @author: Roc
+// @datetime 2024-03-28 14:53:04
+// @param classifyIdList []int
+// @param userIdList []int
+// @return err error
+func SetPermissionByChartClassifyIdList(classifyIdList []int, userIdList []int, classifyType int) (err error) {
+	userNum := len(userIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 获取当前选择用户已经配置的图表分类权限
+	classifyPermissionList := make([]*ChartClassifyPermission, 0)
+	sql := `SELECT * FROM chart_classify_permission WHERE source = ? AND sys_user_id in (` + utils.GetOrmInReplace(userNum) + `) `
+	_, err = o.Raw(sql, classifyType, userIdList).QueryRows(&classifyPermissionList)
+	if err != nil {
+		return
+	}
+	classifyPermissionMap := make(map[string]*ChartClassifyPermission)
+	for _, v := range classifyPermissionList {
+		classifyPermissionMap[fmt.Sprint(v.ChartClassifyId, "_", v.SysUserId)] = v
+	}
+
+	// 待添加的配置项
+	addList := make([]*ChartClassifyPermission, 0)
+
+	// 遍历待配置的图表和用户,筛选出需要添加的配置项
+	for _, userId := range userIdList {
+		for _, classifyId := range classifyIdList {
+			key := fmt.Sprint(classifyId, "_", userId)
+			if _, ok := classifyPermissionMap[key]; ok {
+				// 如果存在那么就移除,说明不需要处理了
+				delete(classifyPermissionMap, key)
+			} else {
+				// 如果不存在,那么就提那家
+				addList = append(addList, &ChartClassifyPermission{
+					//PermissionId: 0,
+					ChartClassifyId: int32(classifyId),
+					Source:          int32(classifyType),
+					SysUserId:       int32(userId),
+					ModifyTime:      time.Now(),
+					CreateTime:      time.Now(),
+				})
+			}
+		}
+	}
+
+	// 添加待配置项
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(500, addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除废弃的配置项
+	{
+		// 获取移除的配置项
+		deletePermissionIdList := make([]int64, 0)
+		for _, v := range classifyPermissionMap {
+			deletePermissionIdList = append(deletePermissionIdList, v.ChartClassifyPermissionId)
+		}
+
+		deletePermissionIdNum := len(deletePermissionIdList)
+		if deletePermissionIdNum > 0 {
+			sql = "DELETE FROM chart_classify_permission WHERE chart_classify_permission_id in (" + utils.GetOrmInReplace(deletePermissionIdNum) + ")"
+			_, err = o.Raw(sql, deletePermissionIdList).Exec()
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// GetPermissionChartClassifyIdListByUserId
+// @Description: 根据用户ID获取已经配置的分类id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param userId int
+// @param classifyType int
+// @return chartClassifyIdList []int
+// @return err error
+func GetPermissionChartClassifyIdListByUserId(userId int, classifyType int) (chartClassifyIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT chart_classify_id FROM chart_classify_permission WHERE source = ? AND sys_user_id = ? `
+	_, err = o.Raw(sql, classifyType, userId).QueryRows(&chartClassifyIdList)
+
+	return
+}
+
+// GetPermissionUserIdListByChartId
+// @Description: 根据图表ID获取已经配置的用户id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param dataId int
+// @param source int
+// @return chartIdList []int
+// @return err error
+func GetPermissionUserIdListByChartId(dataId int, source int) (userIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT sys_user_id FROM chart_info_permission WHERE source = ? AND chart_info_id= ? `
+	_, err = o.Raw(sql, source, dataId).QueryRows(&userIdList)
+
+	return
+}
+
+// GetPermissionUserIdListByChartClassifyId
+// @Description: 根据图表分类ID获取已经配置的用户id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param classifyId int
+// @param source int
+// @return userIdList []int
+// @return err error
+func GetPermissionUserIdListByChartClassifyId(classifyId int, source int) (userIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT sys_user_id FROM chart_classify_permission WHERE source = ? AND chart_classify_id= ? `
+	_, err = o.Raw(sql, source, classifyId).QueryRows(&userIdList)
+
+	return
+}
+
+// GetPermissionChartIdList
+// @Description: 获取用户权限的图表列表
+// @author: Roc
+// @datetime 2024-03-28 16:50:47
+// @param userId int
+// @param chartInfoId int
+// @return idList []int
+// @return err error
+func GetPermissionChartIdList(userId, chartInfoId int) (idList []int, err error) {
+	pars := []interface{}{userId}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT chart_info_id FROM chart_info_permission WHERE sys_user_id = ? `
+	if chartInfoId > 0 {
+		sql += ` AND chart_info_id = ? `
+		pars = append(pars, chartInfoId)
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&idList)
+
+	return
+}
+
+// GetPermissionChartClassifyIdList
+// @Description: 获取用户权限的图表分类列表
+// @author: Roc
+// @datetime 2024-03-28 16:50:47
+// @param userId int
+// @param classifyId int
+// @return idList []int
+// @return err error
+func GetPermissionChartClassifyIdList(userId, classifyId int) (idList []int, err error) {
+	pars := []interface{}{userId}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT chart_classify_id FROM chart_classify_permission WHERE sys_user_id = ? `
+	if classifyId > 0 {
+		sql += ` AND chart_classify_id = ? `
+		pars = append(pars, classifyId)
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&idList)
+
+	return
+}
+
+// InheritParentClassifyByChartClassifyId
+// @Description: 继承父级分类的图表权限信息
+// @author: Roc
+// @datetime 2024-04-07 21:02:51
+// @param dataSource int
+// @param chartSource int
+// @param classifyId int
+// @param parentClassifyId int
+// @param classifyName string
+// @param uniqueCode string
+// @return err error
+func InheritParentClassifyByChartClassifyId(dataSource, chartSource, classifyId, parentClassifyId int, classifyName, uniqueCode string) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 将对应的分类设置为涉密
+	sql := `UPDATE chart_classify SET is_join_permission=?,modify_time=now() WHERE source = ? AND chart_classify_id = ? `
+	_, err = o.Raw(sql, 1, chartSource, classifyId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 添加未授权记录
+	{
+		// 获取父级未授权的用户记录
+		var parentRecordItems []*ChartInfoClassifyPermissionNoAuthRecord
+		sql = `SELECT * FROM data_permission_classify_no_auth_record WHERE classify_id = ? AND source = ? AND sub_source = ? ORDER BY data_permission_classify_no_auth_record_id desc LIMIT ?,? `
+		_, err = o.Raw(sql, parentClassifyId, dataSource, chartSource).QueryRows(&parentRecordItems)
+
+		addNoAuthRecordItems := make([]*ChartInfoClassifyPermissionNoAuthRecord, 0)
+		for _, v := range parentRecordItems {
+			addNoAuthRecordItems = append(addNoAuthRecordItems, &ChartInfoClassifyPermissionNoAuthRecord{
+				ChartInfoClassifyPermissionNoAuthRecordId: 0,
+				Source:       v.Source,
+				OpUniqueCode: uniqueCode,
+				ClassifyId:   fmt.Sprint(classifyId),
+				ClassifyName: classifyName,
+				SysUserId:    v.SysUserId,
+				CreateTime:   time.Now(),
+			})
+		}
+
+		// 添加待配置项
+		if len(addNoAuthRecordItems) > 0 {
+			_, err = o.InsertMulti(500, addNoAuthRecordItems)
+			if err != nil {
+				return
+			}
+		}
+
+	}
+
+	// 添加授权记录
+	{
+		// 获取父级分类已经授权的用户
+		parentClassifyPermissionList := make([]*ChartClassifyPermission, 0)
+		sql = `SELECT * FROM chart_classify_permission WHERE source = ? AND chart_classify_id = ? `
+		_, err = o.Raw(sql, chartSource, parentClassifyId).QueryRows(&parentClassifyPermissionList)
+		if err != nil {
+			return
+		}
+
+		addList := make([]*ChartClassifyPermission, 0)
+		for _, v := range parentClassifyPermissionList {
+			// 如果不存在,那么就提那家
+			addList = append(addList, &ChartClassifyPermission{
+				//PermissionId: 0,
+				ChartClassifyId: int32(classifyId),
+				Source:          int32(chartSource),
+				SysUserId:       v.SysUserId,
+				ModifyTime:      time.Now(),
+				CreateTime:      time.Now(),
+			})
+		}
+		// 添加待配置项
+		if len(addList) > 0 {
+			_, err = o.InsertMulti(500, addList)
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// ChartInfoPermissionNoAuthRecord
+// @Description: 图表数据权限未授权记录表
+type ChartInfoPermissionNoAuthRecord struct {
+	ChartInfoPermissionNoAuthRecordId int64     `json:"chart_info_permission_no_auth_record_id"  orm:"column(chart_info_permission_no_auth_record_id);pk"` // 资产数据操作记录id
+	OpUniqueCode                      string    `json:"op_unique_code"`                                                                                    // 操作的唯一编码,主要是记录统一操作的日志
+	Source                            int32     `json:"source"`                                                                                            // 1:ETA图库;2:商品价格曲线;3:相关性图
+	ChartInfoId                       int32     `json:"chart_info_id"`                                                                                     // 指标id
+	ChartName                         string    `json:"chart_name"`                                                                                        // 图表名称
+	SysUserId                         int32     `json:"sys_user_id"`                                                                                       // 系统用户id
+	CreateTime                        time.Time `json:"create_time"`                                                                                       // 创建时间
+}
+
+// AddChartInfoPermissionNoAuthRecordBySourceAndDataIdList
+// @Description: 添加未授权用户记录
+// @author: Roc
+// @datetime 2024-04-07 15:25:49
+// @param source int
+// @param chartSource int
+// @param dataList []DataItem
+// @param noAuthUserIdList []int 未授权用户
+// @param authUserIdList []int 已授权用户
+// @param uniqueCode
+// @param content string
+// @param opUserId int
+// @return err error
+func AddChartInfoPermissionNoAuthRecordBySourceAndDataIdList(source, chartSource int, dataList []DataItem, noAuthUserIdList, authUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	num := len(dataList)
+	if num <= 0 {
+		return
+	}
+	dataIdList := make([]int, 0)
+	for _, v := range dataList {
+		dataIdList = append(dataIdList, v.DataId)
+	}
+	userNum := len(noAuthUserIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据指标获取已经存在的未授权记录
+	var existList []*ChartInfoPermissionNoAuthRecord
+	sql := `SELECT * FROM chart_info_permission_no_auth_record WHERE  source = ? AND chart_info_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, chartSource, dataIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*ChartInfoPermissionNoAuthRecord)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*ChartInfoPermissionNoAuthRecord)
+		}
+
+		key := fmt.Sprint(v.Source, "_", v.ChartInfoId)
+		tmpUserExistMap[key] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*ChartInfoPermissionNoAuthRecord, 0)
+	for _, userId := range noAuthUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range dataList {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(chartSource, "_", dataItem.DataId)
+				_, ok := tmpUserExistMap[key]
+				if ok {
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &ChartInfoPermissionNoAuthRecord{
+				ChartInfoPermissionNoAuthRecordId: 0,
+				OpUniqueCode:                      uniqueCode,
+				Source:                            int32(chartSource),
+				ChartInfoId:                       int32(dataItem.DataId),
+				ChartName:                         dataItem.DataName,
+				SysUserId:                         int32(userId),
+				CreateTime:                        time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  3,
+				Source:                  int32(source),
+				SubSource:               int32(chartSource),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 已经授权了的用户,需要删除未授权记录
+	authUserIdNum := len(authUserIdList)
+	if authUserIdNum > 0 {
+		sql = `DELETE FROM chart_info_permission_no_auth_record WHERE  source = ? AND sys_user_id in (` + utils.GetOrmInReplace(authUserIdNum) + `) AND chart_info_id in (` + utils.GetOrmInReplace(num) + `)`
+		_, err = o.Raw(sql, chartSource, authUserIdList, dataIdList).Exec()
+	}
+
+	return
+}
+
+// DeleteChartInfoPermissionNoAuthRecordBySourceAndDataIdList
+// @Description: 根据来源和数据id列表删除记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param chartSource int
+// @param dataIdList []string
+// @return err error
+func DeleteChartInfoPermissionNoAuthRecordBySourceAndDataIdList(chartSource int, dataIdList []string) (err error) {
+	num := len(dataIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+
+	sql := `DELETE FROM chart_info_permission_no_auth_record WHERE source = ? AND chart_info_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, chartSource, dataIdList).Exec()
+
+	return
+}
+
+func GetChartInfoDataPermissionNoAuthRecordListByUserId(userId int32, chartSource, startSize, pageSize int) (total int, items []*DataPermissionNoAuthRecord, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 获取总数
+	sql := `SELECT count(1) AS total FROM chart_info_permission_no_auth_record WHERE sys_user_id = ? AND source = ? `
+	err = o.Raw(sql, userId, chartSource).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT chart_info_permission_no_auth_record_id as data_permission_no_auth_record_id,op_unique_code,source as sub_source,chart_info_id as data_id,chart_name as data_name,sys_user_id,create_time FROM chart_info_permission_no_auth_record WHERE sys_user_id = ? AND source = ? ORDER BY chart_info_permission_no_auth_record_id desc LIMIT ?,? `
+	_, err = o.Raw(sql, userId, chartSource, startSize, pageSize).QueryRows(&items)
+
+	return
+}
+
+type ChartInfoClassifyPermissionNoAuthRecord struct {
+	ChartInfoClassifyPermissionNoAuthRecordId int64     `json:"chart_info_classify_permission_no_auth_record_id" orm:"column(chart_info_classify_permission_no_auth_record_id);pk"` // 资产分类数据操作记录id
+	Source                                    int32     `json:"source"`                                                                                                             // 子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)
+	OpUniqueCode                              string    `json:"op_unique_code"`                                                                                                     // 操作的唯一编码,主要是记录统一操作的日志
+	ClassifyId                                string    `json:"classify_id"`                                                                                                        // 图表资产分类id
+	ClassifyName                              string    `json:"classify_name"`                                                                                                      // 图表资产分类名称
+	SysUserId                                 int32     `json:"sys_user_id"`                                                                                                        // 系统用户id
+	CreateTime                                time.Time `json:"create_time"`                                                                                                        // 创建时间
+}
+
+// AddChartInfoClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据分类添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 16:44:21
+// @param source int
+// @param chartSource int
+// @param classifyInfoList []ClassifyDataItem
+// @param noAuthUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddChartInfoClassifyNoAuthRecordBySourceAndClassifyIdList(source, chartSource int, classifyInfoList []ClassifyDataItem, noAuthUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	num := len(classifyInfoList)
+	if num <= 0 {
+		return
+	}
+	// 分类id
+	classifyIdList := make([]int, 0)
+	for _, v := range classifyInfoList {
+		classifyIdList = append(classifyIdList, v.ClassifyId)
+	}
+
+	userNum := len(noAuthUserIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据分类获取已经存在的未授权记录
+	var existList []*ChartInfoClassifyPermissionNoAuthRecord
+	sql := `SELECT * FROM chart_info_classify_permission_no_auth_record WHERE source = ? AND classify_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, chartSource, classifyIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*ChartInfoClassifyPermissionNoAuthRecord)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*ChartInfoClassifyPermissionNoAuthRecord)
+		}
+
+		key := fmt.Sprint(v.Source, "_", v.ClassifyId)
+		tmpUserExistMap[key] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*ChartInfoClassifyPermissionNoAuthRecord, 0)
+	for _, userId := range noAuthUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range classifyInfoList {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(chartSource, "_", dataItem.ClassifyId)
+				_, ok := tmpUserExistMap[key]
+				if ok {
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &ChartInfoClassifyPermissionNoAuthRecord{
+				ChartInfoClassifyPermissionNoAuthRecordId: 0,
+				Source:       int32(chartSource),
+				OpUniqueCode: uniqueCode,
+				ClassifyId:   fmt.Sprint(dataItem.ClassifyId),
+				ClassifyName: dataItem.ClassifyName,
+				SysUserId:    int32(userId),
+				CreateTime:   time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  4,
+				Source:                  int32(source),
+				SubSource:               int32(chartSource),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除已经公开了的分类权限,需要删除未授权记录
+	authUserIdNum := len(classifyIdList)
+	if authUserIdNum > 0 {
+		sql = `DELETE FROM chart_info_classify_permission_no_auth_record WHERE source = ? AND classify_id not in (` + utils.GetOrmInReplace(num) + `)`
+		_, err = o.Raw(sql, chartSource, classifyIdList).Exec()
+	}
+
+	return
+}
+
+// AddChartInfoClassifyNoAuthRecordBySourceAndUserIdList
+// @Description: 根据用户添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 20:12:44
+// @param source int
+// @param chartSource int
+// @param noAuthClassifyMap map[int]ClassifyDataItem
+// @param configUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddChartInfoClassifyNoAuthRecordBySourceAndUserIdList(source, chartSource int, noAuthClassifyMap map[int]ClassifyDataItem, configUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	// 当前配置用户
+	configUserNum := len(configUserIdList)
+	if configUserNum <= 0 {
+		return
+	}
+
+	//// 总共的涉密分类
+	//noAuthClassifyInfoNum := len(noAuthClassifyMap)
+	//if noAuthClassifyInfoNum <= 0 {
+	//	return
+	//}
+
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据当前配置用户获取已经存在的未授权记录
+	var existList []*ChartInfoClassifyPermissionNoAuthRecord
+	sql := `SELECT * FROM chart_info_classify_permission_no_auth_record WHERE source = ? AND sys_user_id in (` + utils.GetOrmInReplace(configUserNum) + `)`
+	_, err = o.Raw(sql, chartSource, configUserIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*ChartInfoClassifyPermissionNoAuthRecord)
+	delRecordIdMap := make(map[int64]int64)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*ChartInfoClassifyPermissionNoAuthRecord)
+		}
+
+		tmpUserExistMap[v.ClassifyId] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+
+		// 已经配置了的记录id
+		delRecordIdMap[v.ChartInfoClassifyPermissionNoAuthRecordId] = v.ChartInfoClassifyPermissionNoAuthRecordId
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*ChartInfoClassifyPermissionNoAuthRecord, 0)
+	for _, userId := range configUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range noAuthClassifyMap {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(dataItem.ClassifyId)
+				tmpUserRecord, ok := tmpUserExistMap[key]
+				if ok {
+					delete(delRecordIdMap, tmpUserRecord.ChartInfoClassifyPermissionNoAuthRecordId)
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &ChartInfoClassifyPermissionNoAuthRecord{
+				ChartInfoClassifyPermissionNoAuthRecordId: 0,
+				Source:       int32(chartSource),
+				OpUniqueCode: uniqueCode,
+				ClassifyId:   fmt.Sprint(dataItem.ClassifyId),
+				ClassifyName: dataItem.ClassifyName,
+				SysUserId:    int32(userId),
+				CreateTime:   time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 content,
+				Remark:                  content,
+				OpType:                  4,
+				Source:                  int32(source),
+				SubSource:               int32(chartSource),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 需要删除未授权记录
+	delRecordIdNum := len(delRecordIdMap)
+	if delRecordIdNum > 0 {
+		delRecordIdList := make([]int64, 0)
+		for _, v := range delRecordIdMap {
+			delRecordIdList = append(delRecordIdList, v)
+		}
+		sql = `DELETE FROM chart_info_classify_permission_no_auth_record WHERE chart_info_classify_permission_no_auth_record_id in (` + utils.GetOrmInReplace(delRecordIdNum) + `) `
+		_, err = o.Raw(sql, delRecordIdList).Exec()
+	}
+
+	return
+}
+
+// DeleteChartInfoClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据来源和删除分类授权记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param chartSource int
+// @return err error
+func DeleteChartInfoClassifyNoAuthRecordBySourceAndClassifyIdList(chartSource int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	sql := `DELETE FROM chart_info_classify_permission_no_auth_record WHERE source = ?`
+	_, err = o.Raw(sql, chartSource).Exec()
+
+	return
+}
+
+// GetChartInfoDataPermissionClassifyNoAuthRecordListByUserId
+// @Description: 根据用户获取未授权的资产分类记录
+// @author: Roc
+// @datetime 2024-04-07 20:14:49
+// @param userId int
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionClassifyNoAuthRecord
+// @return err error
+func GetChartInfoDataPermissionClassifyNoAuthRecordListByUserId(userId int32, chartSource, startSize, pageSize int) (total int, items []*DataPermissionClassifyNoAuthRecord, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 获取总数
+	sql := `SELECT count(1) AS total FROM chart_info_classify_permission_no_auth_record WHERE sys_user_id = ? AND source = ? `
+	err = o.Raw(sql, userId, chartSource).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT chart_info_classify_permission_no_auth_record_id as data_permission_classify_no_auth_record_id,source as sub_source,op_unique_code,classify_id,classify_name,sys_user_id,create_time  FROM chart_info_classify_permission_no_auth_record WHERE sys_user_id = ? AND source = ? ORDER BY chart_info_classify_permission_no_auth_record_id desc LIMIT ?,? `
+	_, err = o.Raw(sql, userId, chartSource, startSize, pageSize).QueryRows(&items)
+
+	return
+}

+ 489 - 0
models/data_manage/data_manage_permission/classify_no_auth_record.go

@@ -0,0 +1,489 @@
+package data_manage_permission
+
+import (
+	"errors"
+	"eta/eta_api/utils"
+	"time"
+)
+
+// DataPermissionClassifyNoAuthRecord
+// @Description: 资产分类数据权限未授权记录表
+type DataPermissionClassifyNoAuthRecord struct {
+	DataPermissionClassifyNoAuthRecordId int64     `json:"data_permission_classify_no_auth_record_id" orm:"column(data_permission_classify_no_auth_record_id);pk"` // 资产分类数据操作记录id
+	Source                               int32     `json:"source"`                                                                                                 // 数据来源,1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格
+	SubSource                            int32     `json:"sub_source"`                                                                                             // 子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)
+	OpUniqueCode                         string    `json:"op_unique_code"`                                                                                         // 操作的唯一编码,主要是记录统一操作的日志
+	ClassifyId                           string    `json:"classify_id"`                                                                                            // 资产分类id(指标、图表、表格)
+	ClassifyName                         string    `json:"classify_name"`                                                                                          // 资产分类名称(指标、图表、表格)
+	SysUserId                            int32     `json:"sys_user_id"`                                                                                            // 系统用户id
+	CreateTime                           time.Time `json:"create_time"`                                                                                            // 创建时间
+}
+
+type ClassifyDataItem struct {
+	ClassifyId   int    // 资产分类id(指标、图表、表格)
+	ClassifyName string // 资产名称(指标、图表、表格)
+}
+
+//
+//// AddClassifyNoAuthRecordBySourceAndClassifyIdList
+//// @Description: 根据分类添加用户分类未授权记录
+//// @author: Roc
+//// @datetime 2024-04-07 16:44:21
+//// @param source int
+//// @param subSource int
+//// @param classifyInfoList []ClassifyDataItem
+//// @param noAuthUserIdList []int
+//// @param uniqueCode string
+//// @param content string
+//// @param opUserId int
+//// @return err error
+//func AddClassifyNoAuthRecordBySourceAndClassifyIdList(source, subSource int, classifyInfoList []ClassifyDataItem, noAuthUserIdList []int, uniqueCode, content string, opUserId int) (err error) {
+//	num := len(classifyInfoList)
+//	if num <= 0 {
+//		return
+//	}
+//	// 分类id
+//	classifyIdList := make([]int, 0)
+//	for _, v := range classifyInfoList {
+//		classifyIdList = append(classifyIdList, v.ClassifyId)
+//	}
+//
+//	userNum := len(noAuthUserIdList)
+//	if userNum <= 0 {
+//		return
+//	}
+//	o, err := orm.NewOrmUsingDB("data").Begin()
+//	if err != nil {
+//		return
+//	}
+//	defer func() {
+//		if err != nil {
+//			_ = o.Rollback()
+//		} else {
+//			_ = o.Commit()
+//		}
+//	}()
+//
+//	// 根据分类获取已经存在的未授权记录
+//	var existList []*DataPermissionClassifyNoAuthRecord
+//	sql := `SELECT * FROM data_permission_classify_no_auth_record WHERE source = ? AND sub_source = ? AND classify_id in (` + utils.GetOrmInReplace(num) + `)`
+//	_, err = o.Raw(sql, source, subSource, classifyIdList).QueryRows(&existList)
+//	if err != nil {
+//		return
+//	}
+//
+//	// 已经标记了的数据
+//	existMap := make(map[int32]map[string]*DataPermissionClassifyNoAuthRecord)
+//	for _, v := range existList {
+//		tmpUserExistMap, ok := existMap[v.SysUserId]
+//		if !ok {
+//			tmpUserExistMap = make(map[string]*DataPermissionClassifyNoAuthRecord)
+//		}
+//
+//		key := fmt.Sprint(v.Source, "_", v.SubSource, "_", v.ClassifyId)
+//		tmpUserExistMap[key] = v
+//		existMap[v.SysUserId] = tmpUserExistMap
+//	}
+//
+//	addMessageList := make([]*DataPermissionMessage, 0)
+//	addRecordList := make([]*DataPermissionClassifyNoAuthRecord, 0)
+//	for _, userId := range noAuthUserIdList {
+//		isAdd := false
+//
+//		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+//
+//		for _, dataItem := range classifyInfoList {
+//			// 判断是否已经存在,已经存在就过滤
+//			if userExistOk {
+//				key := fmt.Sprint(source, "_", subSource, "_", dataItem.ClassifyId)
+//				_, ok := tmpUserExistMap[key]
+//				if ok {
+//					continue
+//				}
+//			}
+//
+//			isAdd = true
+//			addRecordList = append(addRecordList, &DataPermissionClassifyNoAuthRecord{
+//				DataPermissionClassifyNoAuthRecordId: 0,
+//				Source:                               int32(source),
+//				SubSource:                            int32(subSource),
+//				OpUniqueCode:                         uniqueCode,
+//				ClassifyId:                           fmt.Sprint(dataItem.ClassifyId),
+//				ClassifyName:                         dataItem.ClassifyName,
+//				SysUserId:                            int32(userId),
+//				CreateTime:                           time.Now(),
+//			})
+//		}
+//
+//		// 有记录的话,需要添加消息
+//		if isAdd {
+//			addMessageList = append(addMessageList, &DataPermissionMessage{
+//				DataPermissionMessageId: 0,
+//				SendUserId:              int32(opUserId),
+//				ReceiveUserId:           int32(userId),
+//				Content:                 content,
+//				Remark:                  content,
+//				OpType:                  4,
+//				Source:                  int32(source),
+//				SubSource:               int32(subSource),
+//				OpUniqueCode:            uniqueCode,
+//				IsRead:                  0,
+//				CreateTime:              time.Now(),
+//				ModifyTime:              time.Now(),
+//			})
+//		}
+//	}
+//
+//	// 添加消息
+//	if len(addMessageList) > 0 {
+//		_, err = o.InsertMulti(500, addMessageList)
+//		if err != nil {
+//			return
+//		}
+//	}
+//
+//	// 添加记录
+//	if len(addRecordList) > 0 {
+//		_, err = o.InsertMulti(500, addRecordList)
+//		if err != nil {
+//			return
+//		}
+//	}
+//
+//	// 移除已经公开了的分类权限,需要删除未授权记录
+//	authUserIdNum := len(classifyIdList)
+//	if authUserIdNum > 0 {
+//		sql = `DELETE FROM data_permission_classify_no_auth_record WHERE source = ? AND sub_source = ? AND classify_id not in (` + utils.GetOrmInReplace(num) + `)`
+//		_, err = o.Raw(sql, source, subSource, classifyIdList).Exec()
+//	}
+//
+//	return
+//}
+//
+//// AddClassifyNoAuthRecordBySourceAndUserIdList
+//// @Description: 根据用户添加用户分类未授权记录
+//// @author: Roc
+//// @datetime 2024-04-07 20:12:44
+//// @param source int
+//// @param subSource int
+//// @param noAuthClassifyMap map[int]ClassifyDataItem
+//// @param configUserIdList []int
+//// @param uniqueCode string
+//// @param content string
+//// @param opUserId int
+//// @return err error
+//func AddClassifyNoAuthRecordBySourceAndUserIdList(source, subSource int, noAuthClassifyMap map[int]ClassifyDataItem, configUserIdList []int, uniqueCode, content string, opUserId int) (err error) {
+//	// 当前配置用户
+//	configUserNum := len(configUserIdList)
+//	if configUserNum <= 0 {
+//		return
+//	}
+//
+//	//// 总共的涉密分类
+//	//noAuthClassifyInfoNum := len(noAuthClassifyMap)
+//	//if noAuthClassifyInfoNum <= 0 {
+//	//	return
+//	//}
+//
+//	o, err := orm.NewOrmUsingDB("data").Begin()
+//	if err != nil {
+//		return
+//	}
+//	defer func() {
+//		if err != nil {
+//			_ = o.Rollback()
+//		} else {
+//			_ = o.Commit()
+//		}
+//	}()
+//
+//	// 根据当前配置用户获取已经存在的未授权记录
+//	var existList []*DataPermissionClassifyNoAuthRecord
+//	sql := `SELECT * FROM data_permission_classify_no_auth_record WHERE source = ? AND sub_source = ? AND sys_user_id in (` + utils.GetOrmInReplace(configUserNum) + `)`
+//	_, err = o.Raw(sql, source, subSource, configUserIdList).QueryRows(&existList)
+//	if err != nil {
+//		return
+//	}
+//
+//	// 已经标记了的数据
+//	existMap := make(map[int32]map[string]*DataPermissionClassifyNoAuthRecord)
+//	delRecordIdMap := make(map[int64]int64)
+//	for _, v := range existList {
+//		tmpUserExistMap, ok := existMap[v.SysUserId]
+//		if !ok {
+//			tmpUserExistMap = make(map[string]*DataPermissionClassifyNoAuthRecord)
+//		}
+//
+//		tmpUserExistMap[v.ClassifyId] = v
+//		existMap[v.SysUserId] = tmpUserExistMap
+//
+//		// 已经配置了的记录id
+//		delRecordIdMap[v.DataPermissionClassifyNoAuthRecordId] = v.DataPermissionClassifyNoAuthRecordId
+//	}
+//
+//	addMessageList := make([]*DataPermissionMessage, 0)
+//	addRecordList := make([]*DataPermissionClassifyNoAuthRecord, 0)
+//	for _, userId := range configUserIdList {
+//		isAdd := false
+//
+//		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+//
+//		for _, dataItem := range noAuthClassifyMap {
+//			// 判断是否已经存在,已经存在就过滤
+//			if userExistOk {
+//				key := fmt.Sprint(dataItem.ClassifyId)
+//				tmpUserRecord, ok := tmpUserExistMap[key]
+//				if ok {
+//					delete(delRecordIdMap, tmpUserRecord.DataPermissionClassifyNoAuthRecordId)
+//					continue
+//				}
+//			}
+//
+//			isAdd = true
+//			addRecordList = append(addRecordList, &DataPermissionClassifyNoAuthRecord{
+//				DataPermissionClassifyNoAuthRecordId: 0,
+//				Source:                               int32(source),
+//				SubSource:                            int32(subSource),
+//				OpUniqueCode:                         uniqueCode,
+//				ClassifyId:                           fmt.Sprint(dataItem.ClassifyId),
+//				ClassifyName:                         dataItem.ClassifyName,
+//				SysUserId:                            int32(userId),
+//				CreateTime:                           time.Now(),
+//			})
+//		}
+//
+//		// 有记录的话,需要添加消息
+//		if isAdd {
+//			addMessageList = append(addMessageList, &DataPermissionMessage{
+//				DataPermissionMessageId: 0,
+//				SendUserId:              int32(opUserId),
+//				ReceiveUserId:           int32(userId),
+//				Content:                 content,
+//				Remark:                  content,
+//				OpType:                  4,
+//				Source:                  int32(source),
+//				SubSource:               int32(subSource),
+//				OpUniqueCode:            uniqueCode,
+//				IsRead:                  0,
+//				CreateTime:              time.Now(),
+//				ModifyTime:              time.Now(),
+//			})
+//		}
+//	}
+//
+//	// 添加消息
+//	if len(addMessageList) > 0 {
+//		_, err = o.InsertMulti(500, addMessageList)
+//		if err != nil {
+//			return
+//		}
+//	}
+//
+//	// 添加记录
+//	if len(addRecordList) > 0 {
+//		_, err = o.InsertMulti(500, addRecordList)
+//		if err != nil {
+//			return
+//		}
+//	}
+//
+//	// 需要删除未授权记录
+//	delRecordIdNum := len(delRecordIdMap)
+//	if delRecordIdNum > 0 {
+//		delRecordIdList := make([]int64, 0)
+//		for _, v := range delRecordIdMap {
+//			delRecordIdList = append(delRecordIdList, v)
+//		}
+//		sql = `DELETE FROM data_permission_classify_no_auth_record WHERE data_permission_classify_no_auth_record_id in (` + utils.GetOrmInReplace(delRecordIdNum) + `) `
+//		_, err = o.Raw(sql, delRecordIdList).Exec()
+//	}
+//
+//	return
+//}
+//
+//// DeleteClassifyNoAuthRecordBySourceAndClassifyIdList
+//// @Description: 根据来源和删除分类授权记录
+//// @author: Roc
+//// @datetime 2024-04-07 14:47:37
+//// @param source int
+//// @param subSource int
+//// @return err error
+//func DeleteClassifyNoAuthRecordBySourceAndClassifyIdList(source, subSource int) (err error) {
+//	o := orm.NewOrmUsingDB("data")
+//
+//	sql := `DELETE FROM data_permission_classify_no_auth_record WHERE source = ? AND sub_source = ?`
+//	_, err = o.Raw(sql, source, subSource).Exec()
+//
+//	return
+//}
+//
+//// GetDataPermissionClassifyNoAuthRecordListByUserId
+//// @Description: 根据用户获取未授权的资产分类记录
+//// @author: Roc
+//// @datetime 2024-04-07 20:14:49
+//// @param userId int
+//// @param source int
+//// @param subSource int
+//// @param startSize int
+//// @param pageSize int
+//// @return total int
+//// @return items []*DataPermissionClassifyNoAuthRecord
+//// @return err error
+//func GetDataPermissionClassifyNoAuthRecordListByUserId(userId, source, subSource int32, startSize, pageSize int) (total int, items []*DataPermissionClassifyNoAuthRecord, err error) {
+//	o := orm.NewOrmUsingDB("data")
+//
+//	// 获取总数
+//	sql := `SELECT count(1) AS total FROM data_permission_classify_no_auth_record WHERE sys_user_id = ? AND source = ? AND sub_source = ? `
+//	err = o.Raw(sql, userId, source, subSource).QueryRow(&total)
+//	if err != nil {
+//		return
+//	}
+//
+//	sql = `SELECT * FROM data_permission_classify_no_auth_record WHERE sys_user_id = ? AND source = ? AND sub_source = ? ORDER BY data_permission_classify_no_auth_record_id desc LIMIT ?,? `
+//	_, err = o.Raw(sql, userId, source, subSource, startSize, pageSize).QueryRows(&items)
+//
+//	return
+//}
+
+// AddClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据分类添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 16:44:21
+// @param source int
+// @param subSource int
+// @param classifyInfoList []ClassifyDataItem
+// @param noAuthUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddClassifyNoAuthRecordBySourceAndClassifyIdList(source, subSource int, classifyInfoList []ClassifyDataItem, noAuthUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	switch source {
+	case 3, 4:
+		edbClassifyType := 0
+		if source == 4 {
+			edbClassifyType = 1
+		}
+		err = AddEdbInfoClassifyNoAuthRecordBySourceAndClassifyIdList(source, edbClassifyType, classifyInfoList, noAuthUserIdList, uniqueCode, title, content, opUserId)
+	case 5:
+		//图库
+		chartSource := utils.CHART_SOURCE_DEFAULT
+		err = AddChartInfoClassifyNoAuthRecordBySourceAndClassifyIdList(source, chartSource, classifyInfoList, noAuthUserIdList, uniqueCode, title, content, opUserId)
+
+	case 6:
+		// ETA表格
+		err = AddExcelInfoClassifyNoAuthRecordBySourceAndClassifyIdList(source, subSource, classifyInfoList, noAuthUserIdList, uniqueCode, title, content, opUserId)
+
+	default:
+		err = errors.New("错误的source")
+		return
+	}
+
+	return
+}
+
+// AddClassifyNoAuthRecordBySourceAndUserIdList
+// @Description: 根据用户添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 20:12:44
+// @param source int
+// @param subSource int
+// @param noAuthClassifyMap map[int]ClassifyDataItem
+// @param configUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddClassifyNoAuthRecordBySourceAndUserIdList(source, subSource int, noAuthClassifyMap map[int]ClassifyDataItem, configUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	switch source {
+	case 3, 4:
+		edbClassifyType := 0
+		if source == 4 {
+			edbClassifyType = 1
+		}
+		err = AddEdbInfoClassifyNoAuthRecordBySourceAndUserIdList(source, edbClassifyType, noAuthClassifyMap, configUserIdList, uniqueCode, title, content, opUserId)
+	case 5:
+		//图库
+		chartSource := utils.CHART_SOURCE_DEFAULT
+		err = AddChartInfoClassifyNoAuthRecordBySourceAndUserIdList(source, chartSource, noAuthClassifyMap, configUserIdList, uniqueCode, title, content, opUserId)
+
+	case 6:
+		// ETA表格
+		err = AddExcelInfoClassifyNoAuthRecordBySourceAndUserIdList(source, subSource, noAuthClassifyMap, configUserIdList, uniqueCode, title, content, opUserId)
+
+	default:
+		err = errors.New("错误的source")
+		return
+	}
+
+	return
+}
+
+// DeleteClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据来源和删除分类授权记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param source int
+// @param subSource int
+// @return err error
+func DeleteClassifyNoAuthRecordBySourceAndClassifyIdList(source, subSource int) (err error) {
+	switch source {
+	case 3, 4:
+		edbClassifyType := 0
+		if source == 4 {
+			edbClassifyType = 1
+		}
+		err = DeleteEdbInfoClassifyNoAuthRecordBySourceAndClassifyIdList(edbClassifyType)
+	case 5:
+		//图库
+		chartSource := utils.CHART_SOURCE_DEFAULT
+		err = DeleteChartInfoClassifyNoAuthRecordBySourceAndClassifyIdList(chartSource)
+
+	case 6:
+		// ETA表格
+		err = DeleteExcelInfoClassifyNoAuthRecordBySourceAndClassifyIdList(subSource)
+
+	default:
+		err = errors.New("错误的source")
+		return
+	}
+
+	return
+}
+
+// GetDataPermissionClassifyNoAuthRecordListByUserId
+// @Description: 根据用户获取未授权的资产分类记录
+// @author: Roc
+// @datetime 2024-04-07 20:14:49
+// @param userId int
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionClassifyNoAuthRecord
+// @return err error
+func GetDataPermissionClassifyNoAuthRecordListByUserId(userId, source, subSource int32, startSize, pageSize int) (total int, items []*DataPermissionClassifyNoAuthRecord, err error) {
+	switch source {
+	case 3, 4:
+		edbClassifyType := 0
+		if source == 4 {
+			edbClassifyType = 1
+		}
+		total, items, err = GetEdbInfoDataPermissionClassifyNoAuthRecordListByUserId(userId, edbClassifyType, startSize, pageSize)
+	case 5:
+		//图库
+		chartSource := utils.CHART_SOURCE_DEFAULT
+		total, items, err = GetChartInfoDataPermissionClassifyNoAuthRecordListByUserId(userId, chartSource, startSize, pageSize)
+
+	case 6:
+		// ETA表格
+		total, items, err = GetExcelInfoDataPermissionClassifyNoAuthRecordListByUserId(userId, subSource, startSize, pageSize)
+
+	default:
+		err = errors.New("错误的source")
+		return
+	}
+
+	return
+}

+ 989 - 0
models/data_manage/data_manage_permission/edb.go

@@ -0,0 +1,989 @@
+package data_manage_permission
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"time"
+)
+
+// EdbInfoPermission
+// @Description: 指标权限表
+type EdbInfoPermission struct {
+	EdbInfoPermissionId int64     `json:"edb_info_permission_id" orm:"column(edb_info_permission_id);pk"`
+	EdbInfoId           int32     `json:"edb_info_id"`   // 指标id
+	EdbInfoType         int32     `json:"edb_info_type"` // 指标类型,0:普通指标,1:预测指标
+	SysUserId           int32     `json:"sys_user_id"`   // 系统用户id
+	ModifyTime          time.Time `json:"modify_time"`   // 变更时间
+	CreateTime          time.Time `json:"create_time"`   // 关系建立时间
+}
+
+// EdbClassifyPermission
+// @Description: 指标分类权限表
+type EdbClassifyPermission struct {
+	EdbClassifyPermissionId int64     `json:"edb_classify_permission_id" orm:"column(edb_classify_permission_id);pk"`
+	EdbClassifyId           int32     `json:"edb_classify_id"`   // 分类id
+	EdbClassifyType         int32     `json:"edb_classify_type"` // 分类类型,0:普通指标分类,1:预测指标分类
+	SysUserId               int32     `json:"sys_user_id"`       // 系统用户id
+	ModifyTime              time.Time `json:"modify_time"`       // 变更时间
+	CreateTime              time.Time `json:"create_time"`       // 关系建立时间
+}
+
+// SetIsPermissionEdbChartByEdbClassifyIdList
+// @Description: 设置指标分类是否涉密
+// @author: Roc
+// @datetime 2024-03-27 14:15:42
+// @param classifyIdList []int
+func SetIsPermissionEdbChartByEdbClassifyIdList(classifyIdList []int, classifyType int) (err error) {
+	num := len(classifyIdList)
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	//// 获取已经配置涉密的分类权限
+	//edbClassifyList := make([]*EdbClassify, 0)
+	//sql := `SELECT * FROM edb_classify WHERE is_join_permission = ? `
+	//_, err = o.Raw(sql, 1).QueryRows(&edbClassifyList)
+	//if err != nil {
+	//	return
+	//}
+	//edbClassifyMap := make(map[int]*EdbClassify)
+	//for _, v := range edbClassifyList {
+	//	edbClassifyMap[v.ClassifyId] = v
+	//}
+
+	// 先将所有已经设置了涉密的分类设置为不涉密
+	sql := `UPDATE edb_classify SET is_join_permission=?,modify_time=now() WHERE is_join_permission = 1 AND classify_type = ?`
+	_, err = o.Raw(sql, 0, classifyType).Exec()
+	if err != nil {
+		return
+	}
+
+	if num > 0 {
+		// 将对应的分类设置为涉密
+		sql = `UPDATE edb_classify SET is_join_permission=?,modify_time=now() WHERE classify_type = ? AND classify_id in (` + utils.GetOrmInReplace(num) + `) `
+		_, err = o.Raw(sql, 1, classifyType, classifyIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// SetPermissionByEdbIdList
+// @Description: 根据指标ID列表设置指标的用户权限
+// @author: Roc
+// @datetime 2024-03-27 14:03:42
+// @param edbIdList []string
+// @param userIdList []int
+// @param chartInfoType int
+// @return err error
+func SetPermissionByEdbIdList(edbIdList []string, userIdList []int, edbInfoType int) (err error) {
+	edbNum := len(edbIdList)
+	if edbNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 获取已经配置的指标权限用户
+	edbInfoPermissionList := make([]*EdbInfoPermission, 0)
+	sql := `SELECT * FROM edb_info_permission WHERE edb_info_type = ? AND edb_info_id in (` + utils.GetOrmInReplace(edbNum) + `) `
+	_, err = o.Raw(sql, edbInfoType, edbIdList).QueryRows(&edbInfoPermissionList)
+	if err != nil {
+		return
+	}
+	edbInfoPermissionMap := make(map[string]*EdbInfoPermission)
+	for _, v := range edbInfoPermissionList {
+		edbInfoPermissionMap[fmt.Sprint(v.EdbInfoId, "_", v.SysUserId)] = v
+	}
+
+	// 标记指标是否纳入权限管控
+	{
+		// 默认 标记指标为纳入权限管控
+		isJoinPermission := 1
+		// 用户不选的情况下,说明是要给这些指标移除权限管控
+		if len(userIdList) <= 0 {
+			// 标记指标为不纳入权限管控
+			isJoinPermission = 0
+		}
+		sql = `UPDATE edb_info SET is_join_permission=?,modify_time=now() WHERE edb_info_type = ? AND edb_info_id in (` + utils.GetOrmInReplace(edbNum) + `) `
+		_, err = o.Raw(sql, isJoinPermission, edbInfoType, edbIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// 待添加的配置项
+	addList := make([]*EdbInfoPermission, 0)
+
+	// 遍历待配置的指标和用户,筛选出需要添加的配置项
+	for _, edbInfoIdStr := range edbIdList {
+		edbInfoId, tmpErr := strconv.ParseInt(edbInfoIdStr, 10, 64)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		for _, userId := range userIdList {
+			key := fmt.Sprint(edbInfoId, "_", userId)
+			if _, ok := edbInfoPermissionMap[key]; ok {
+				// 如果存在那么就移除,说明不需要处理了
+				delete(edbInfoPermissionMap, key)
+			} else {
+				// 如果不存在,那么就添加
+				addList = append(addList, &EdbInfoPermission{
+					//PermissionId: 0,
+					EdbInfoId:   int32(edbInfoId),
+					SysUserId:   int32(userId),
+					EdbInfoType: int32(edbInfoType),
+					ModifyTime:  time.Now(),
+					CreateTime:  time.Now(),
+				})
+			}
+		}
+	}
+
+	// 添加待配置项
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(500, addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除废弃的配置项
+	{
+		// 待移除的配置项
+		deletePermissionIdList := make([]int64, 0)
+		for _, v := range edbInfoPermissionMap {
+			deletePermissionIdList = append(deletePermissionIdList, v.EdbInfoPermissionId)
+		}
+
+		deletePermissionIdNum := len(deletePermissionIdList)
+		if deletePermissionIdNum > 0 {
+			sql = "DELETE FROM edb_info_permission WHERE edb_info_permission_id in (" + utils.GetOrmInReplace(deletePermissionIdNum) + ")"
+			_, err = o.Raw(sql, deletePermissionIdList).Exec()
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// SetPermissionByEdbClassifyIdList
+// @Description: 根据指标分类ID列表设置分类的用户权限
+// @author: Roc
+// @datetime 2024-03-28 14:53:04
+// @param classifyIdList []int
+// @param userIdList []int
+// @return err error
+func SetPermissionByEdbClassifyIdList(classifyIdList []int, userIdList []int, classifyType int) (err error) {
+	userNum := len(userIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 获取当前选择用户已经配置的指标分类权限
+	classifyPermissionList := make([]*EdbClassifyPermission, 0)
+	sql := `SELECT * FROM edb_classify_permission WHERE edb_classify_type = ? AND sys_user_id in (` + utils.GetOrmInReplace(userNum) + `) `
+	_, err = o.Raw(sql, classifyType, userIdList).QueryRows(&classifyPermissionList)
+	if err != nil {
+		return
+	}
+	classifyPermissionMap := make(map[string]*EdbClassifyPermission)
+	for _, v := range classifyPermissionList {
+		classifyPermissionMap[fmt.Sprint(v.EdbClassifyId, "_", v.SysUserId)] = v
+	}
+
+	// 待添加的配置项
+	addList := make([]*EdbClassifyPermission, 0)
+
+	// 遍历待配置的指标和用户,筛选出需要添加的配置项
+	for _, userId := range userIdList {
+		for _, classifyId := range classifyIdList {
+			key := fmt.Sprint(classifyId, "_", userId)
+			if _, ok := classifyPermissionMap[key]; ok {
+				// 如果存在那么就移除,说明不需要处理了
+				delete(classifyPermissionMap, key)
+			} else {
+				// 如果不存在,那么就提那家
+				addList = append(addList, &EdbClassifyPermission{
+					//PermissionId: 0,
+					EdbClassifyId:   int32(classifyId),
+					EdbClassifyType: int32(classifyType),
+					SysUserId:       int32(userId),
+					ModifyTime:      time.Now(),
+					CreateTime:      time.Now(),
+				})
+			}
+		}
+	}
+
+	// 添加待配置项
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(500, addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除废弃的配置项
+	{
+		// 获取移除的配置项
+		deletePermissionIdList := make([]int64, 0)
+		for _, v := range classifyPermissionMap {
+			deletePermissionIdList = append(deletePermissionIdList, v.EdbClassifyPermissionId)
+		}
+
+		deletePermissionIdNum := len(deletePermissionIdList)
+		if deletePermissionIdNum > 0 {
+			sql = "DELETE FROM edb_classify_permission WHERE edb_classify_permission_id in (" + utils.GetOrmInReplace(deletePermissionIdNum) + ")"
+			_, err = o.Raw(sql, deletePermissionIdList).Exec()
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// GetPermissionEdbClassifyIdListByUserId
+// @Description: 根据用户ID获取已经配置的分类id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param userId int
+// @param classifyType int
+// @return edbClassifyIdList []int
+// @return err error
+func GetPermissionEdbClassifyIdListByUserId(userId int, classifyType int) (edbClassifyIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT edb_classify_id FROM edb_classify_permission WHERE edb_classify_type = ? AND sys_user_id = ? `
+	_, err = o.Raw(sql, classifyType, userId).QueryRows(&edbClassifyIdList)
+
+	return
+}
+
+// GetPermissionUserIdListByEdbId
+// @Description: 根据指标ID获取已经配置的用户id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param dataId int
+// @param edbInfoType int
+// @return userIdList []int
+// @return err error
+func GetPermissionUserIdListByEdbId(dataId int, edbInfoType int) (userIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT sys_user_id FROM edb_info_permission WHERE edb_info_type = ? AND edb_info_id= ? `
+	_, err = o.Raw(sql, edbInfoType, dataId).QueryRows(&userIdList)
+
+	return
+}
+
+// GetPermissionUserIdListByEdbClassifyId
+// @Description: 根据指标分类ID获取已经配置的用户id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param classifyId int
+// @param edbClassifyType int
+// @return userIdList []int
+// @return err error
+func GetPermissionUserIdListByEdbClassifyId(classifyId int, edbClassifyType int) (userIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT sys_user_id FROM edb_classify_permission WHERE edb_classify_type = ? AND edb_classify_id= ? `
+	_, err = o.Raw(sql, edbClassifyType, classifyId).QueryRows(&userIdList)
+
+	return
+}
+
+// GetPermissionEdbIdList
+// @Description: 获取用户权限的指标列表
+// @author: Roc
+// @datetime 2024-03-28 16:50:47
+// @param userId int
+// @param edbInfoId int
+// @return idList []int
+// @return err error
+func GetPermissionEdbIdList(userId, edbInfoId int) (idList []int, err error) {
+	pars := []interface{}{userId}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT edb_info_id FROM edb_info_permission WHERE sys_user_id = ? `
+	if edbInfoId > 0 {
+		sql += ` AND edb_info_id = ? `
+		pars = append(pars, edbInfoId)
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&idList)
+
+	return
+}
+
+// GetPermissionEdbClassifyIdList
+// @Description: 获取用户权限的指标分类列表
+// @author: Roc
+// @datetime 2024-03-28 16:50:47
+// @param userId int
+// @param classifyId int
+// @return idList []int
+// @return err error
+func GetPermissionEdbClassifyIdList(userId, classifyId int) (idList []int, err error) {
+	pars := []interface{}{userId}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT edb_classify_id FROM edb_classify_permission WHERE sys_user_id = ? `
+	if classifyId > 0 {
+		sql += ` AND edb_classify_id = ? `
+		pars = append(pars, classifyId)
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&idList)
+
+	return
+}
+
+// InheritParentClassifyByEdbClassifyId
+// @Description: 继承父级分类的指标权限信息
+// @author: Roc
+// @datetime 2024-04-07 21:02:51
+// @param source int
+// @param classifyType int
+// @param classifyId int
+// @param parentClassifyId int
+// @param classifyName string
+// @param uniqueCode string
+// @return err error
+func InheritParentClassifyByEdbClassifyId(source, classifyType, classifyId, parentClassifyId int, classifyName, uniqueCode string) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 将对应的分类设置为涉密
+	sql := `UPDATE edb_classify SET is_join_permission=?,modify_time=now() WHERE classify_type = ? AND classify_id = ? `
+	_, err = o.Raw(sql, 1, classifyType, classifyId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 添加未授权记录
+	{
+		// 获取父级未授权的用户记录
+		var parentRecordItems []*EdbInfoClassifyPermissionNoAuthRecord
+		sql = `SELECT * FROM edb_info_classify_permission_no_auth_record WHERE classify_id = ? AND edb_classify_type = ? ORDER BY edb_info_classify_permission_no_auth_record_id desc LIMIT ?,? `
+		_, err = o.Raw(sql, parentClassifyId, source, classifyType).QueryRows(&parentRecordItems)
+
+		addNoAuthRecordItems := make([]*EdbInfoClassifyPermissionNoAuthRecord, 0)
+		for _, v := range parentRecordItems {
+			addNoAuthRecordItems = append(addNoAuthRecordItems, &EdbInfoClassifyPermissionNoAuthRecord{
+				EdbInfoClassifyPermissionNoAuthRecordId: 0,
+				EdbClassifyType:                         v.EdbClassifyType,
+				OpUniqueCode:                            uniqueCode,
+				ClassifyId:                              fmt.Sprint(classifyId),
+				ClassifyName:                            classifyName,
+				SysUserId:                               v.SysUserId,
+				CreateTime:                              time.Now(),
+			})
+		}
+
+		// 添加待配置项
+		if len(addNoAuthRecordItems) > 0 {
+			_, err = o.InsertMulti(500, addNoAuthRecordItems)
+			if err != nil {
+				return
+			}
+		}
+
+	}
+
+	// 添加授权记录
+	{
+		// 获取父级分类已经授权的用户
+		parentClassifyPermissionList := make([]*EdbClassifyPermission, 0)
+		sql = `SELECT * FROM edb_classify_permission WHERE edb_classify_type = ? AND edb_classify_id = ? `
+		_, err = o.Raw(sql, classifyType, parentClassifyId).QueryRows(&parentClassifyPermissionList)
+		if err != nil {
+			return
+		}
+
+		addList := make([]*EdbClassifyPermission, 0)
+		for _, v := range parentClassifyPermissionList {
+			// 如果不存在,那么就提那家
+			addList = append(addList, &EdbClassifyPermission{
+				//PermissionId: 0,
+				EdbClassifyId:   int32(classifyId),
+				EdbClassifyType: int32(classifyType),
+				SysUserId:       v.SysUserId,
+				ModifyTime:      time.Now(),
+				CreateTime:      time.Now(),
+			})
+		}
+		// 添加待配置项
+		if len(addList) > 0 {
+			_, err = o.InsertMulti(500, addList)
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// EdbInfoPermissionNoAuthRecord
+// @Description: 指标数据权限未授权记录表
+type EdbInfoPermissionNoAuthRecord struct {
+	EdbInfoPermissionNoAuthRecordId int64     `json:"edb_info_permission_no_auth_record_id"  orm:"column(edb_info_permission_no_auth_record_id);pk"` // 资产数据操作记录id
+	OpUniqueCode                    string    `json:"op_unique_code"`                                                                                // 操作的唯一编码,主要是记录统一操作的日志
+	EdbInfoType                     int32     `json:"edb_info_type"`                                                                                 // 指标类型,0:普通指标,1:预测指标
+	EdbInfoId                       int32     `json:"edb_info_id"`                                                                                   // 指标id
+	EdbCode                         string    `json:"edb_code"`                                                                                      // 指标编码
+	EdbName                         string    `json:"edb_name"`                                                                                      // 指标名称
+	SysUserId                       int32     `json:"sys_user_id"`                                                                                   // 系统用户id
+	CreateTime                      time.Time `json:"create_time"`                                                                                   // 创建时间
+}
+
+// AddEdbInfoPermissionNoAuthRecordBySourceAndDataIdList
+// @Description: 添加未授权用户记录
+// @author: Roc
+// @datetime 2024-04-07 15:25:49
+// @param source int
+// @param edbInfoType int
+// @param dataList []DataItem
+// @param noAuthUserIdList []int 未授权用户
+// @param authUserIdList []int 已授权用户
+// @param uniqueCode
+// @param content string
+// @param opUserId int
+// @return err error
+func AddEdbInfoPermissionNoAuthRecordBySourceAndDataIdList(source, edbInfoType int, dataList []DataItem, noAuthUserIdList, authUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	num := len(dataList)
+	if num <= 0 {
+		return
+	}
+	dataIdList := make([]int, 0)
+	for _, v := range dataList {
+		dataIdList = append(dataIdList, v.DataId)
+	}
+	userNum := len(noAuthUserIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据指标获取已经存在的未授权记录
+	var existList []*EdbInfoPermissionNoAuthRecord
+	sql := `SELECT * FROM edb_info_permission_no_auth_record WHERE  edb_info_type = ? AND edb_info_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, edbInfoType, dataIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*EdbInfoPermissionNoAuthRecord)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*EdbInfoPermissionNoAuthRecord)
+		}
+
+		key := fmt.Sprint(v.EdbInfoType, "_", v.EdbInfoId)
+		tmpUserExistMap[key] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*EdbInfoPermissionNoAuthRecord, 0)
+	for _, userId := range noAuthUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range dataList {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(edbInfoType, "_", dataItem.DataId)
+				_, ok := tmpUserExistMap[key]
+				if ok {
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &EdbInfoPermissionNoAuthRecord{
+				EdbInfoPermissionNoAuthRecordId: 0,
+				OpUniqueCode:                    uniqueCode,
+				EdbInfoType:                     int32(edbInfoType),
+				EdbInfoId:                       int32(dataItem.DataId),
+				EdbCode:                         dataItem.DataCode,
+				EdbName:                         dataItem.DataName,
+				SysUserId:                       int32(userId),
+				CreateTime:                      time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  3,
+				Source:                  int32(source),
+				SubSource:               int32(edbInfoType),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 已经授权了的用户,需要删除未授权记录
+	authUserIdNum := len(authUserIdList)
+	if authUserIdNum > 0 {
+		sql = `DELETE FROM edb_info_permission_no_auth_record WHERE  edb_info_type = ? AND sys_user_id in (` + utils.GetOrmInReplace(authUserIdNum) + `) AND edb_info_id in (` + utils.GetOrmInReplace(num) + `)`
+		_, err = o.Raw(sql, edbInfoType, authUserIdList, dataIdList).Exec()
+	}
+
+	return
+}
+
+// DeleteEdbInfoPermissionNoAuthRecordBySourceAndDataIdList
+// @Description: 根据来源和数据id列表删除记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param source int
+// @param subSource int
+// @param dataIdList []string
+// @return err error
+func DeleteEdbInfoPermissionNoAuthRecordBySourceAndDataIdList(edbInfoType int, dataIdList []string) (err error) {
+	num := len(dataIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+
+	sql := `DELETE FROM edb_info_permission_no_auth_record WHERE edb_info_type = ? AND edb_info_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, edbInfoType, dataIdList).Exec()
+
+	return
+}
+
+// GetEdbInfoDataPermissionNoAuthRecordListByUserId
+// @Description: 获取明细数据
+// @author: Roc
+// @datetime 2024-04-10 14:23:15
+// @param userId int32
+// @param edbInfoType int32
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionNoAuthRecord
+// @return err error
+func GetEdbInfoDataPermissionNoAuthRecordListByUserId(userId int32, edbInfoType, startSize, pageSize int) (total int, items []*DataPermissionNoAuthRecord, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 获取总数
+	sql := `SELECT count(1) AS total FROM edb_info_permission_no_auth_record WHERE sys_user_id = ? AND edb_info_type = ? `
+	err = o.Raw(sql, userId, edbInfoType).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT edb_info_permission_no_auth_record_id as data_permission_no_auth_record_id,op_unique_code,edb_info_type as sub_source,edb_info_id as data_id,edb_code as data_code,edb_name as data_name,sys_user_id,create_time FROM edb_info_permission_no_auth_record WHERE sys_user_id = ? AND edb_info_type = ? ORDER BY edb_info_permission_no_auth_record_id desc LIMIT ?,? `
+	_, err = o.Raw(sql, userId, edbInfoType, startSize, pageSize).QueryRows(&items)
+
+	return
+}
+
+type EdbInfoClassifyPermissionNoAuthRecord struct {
+	EdbInfoClassifyPermissionNoAuthRecordId int64     `json:"edb_info_classify_permission_no_auth_record_id" orm:"column(edb_info_classify_permission_no_auth_record_id);pk"` // 资产分类数据操作记录id
+	EdbClassifyType                         int32     `json:"edb_classify_type"`                                                                                              // 子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)
+	OpUniqueCode                            string    `json:"op_unique_code"`                                                                                                 // 操作的唯一编码,主要是记录统一操作的日志
+	ClassifyId                              string    `json:"classify_id"`                                                                                                    // 资产分类id(指标、图表、表格)
+	ClassifyName                            string    `json:"classify_name"`                                                                                                  // 资产分类名称(指标、图表、表格)
+	SysUserId                               int32     `json:"sys_user_id"`                                                                                                    // 系统用户id
+	CreateTime                              time.Time `json:"create_time"`                                                                                                    // 创建时间
+}
+
+// AddEdbInfoClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据分类添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 16:44:21
+// @param source int
+// @param edbClassifyType int
+// @param classifyInfoList []ClassifyDataItem
+// @param noAuthUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddEdbInfoClassifyNoAuthRecordBySourceAndClassifyIdList(source, edbClassifyType int, classifyInfoList []ClassifyDataItem, noAuthUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	num := len(classifyInfoList)
+	if num <= 0 {
+		return
+	}
+	// 分类id
+	classifyIdList := make([]int, 0)
+	for _, v := range classifyInfoList {
+		classifyIdList = append(classifyIdList, v.ClassifyId)
+	}
+
+	userNum := len(noAuthUserIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据分类获取已经存在的未授权记录
+	var existList []*EdbInfoClassifyPermissionNoAuthRecord
+	sql := `SELECT * FROM edb_info_classify_permission_no_auth_record WHERE edb_classify_type = ? AND classify_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, edbClassifyType, classifyIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*EdbInfoClassifyPermissionNoAuthRecord)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*EdbInfoClassifyPermissionNoAuthRecord)
+		}
+
+		key := fmt.Sprint(v.EdbClassifyType, "_", v.ClassifyId)
+		tmpUserExistMap[key] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*EdbInfoClassifyPermissionNoAuthRecord, 0)
+	for _, userId := range noAuthUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range classifyInfoList {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(edbClassifyType, "_", dataItem.ClassifyId)
+				_, ok := tmpUserExistMap[key]
+				if ok {
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &EdbInfoClassifyPermissionNoAuthRecord{
+				EdbInfoClassifyPermissionNoAuthRecordId: 0,
+				EdbClassifyType:                         int32(edbClassifyType),
+				OpUniqueCode:                            uniqueCode,
+				ClassifyId:                              fmt.Sprint(dataItem.ClassifyId),
+				ClassifyName:                            dataItem.ClassifyName,
+				SysUserId:                               int32(userId),
+				CreateTime:                              time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  4,
+				Source:                  int32(source),
+				SubSource:               int32(edbClassifyType),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除已经公开了的分类权限,需要删除未授权记录
+	authUserIdNum := len(classifyIdList)
+	if authUserIdNum > 0 {
+		sql = `DELETE FROM edb_info_classify_permission_no_auth_record WHERE edb_classify_type = ? AND classify_id not in (` + utils.GetOrmInReplace(num) + `)`
+		_, err = o.Raw(sql, edbClassifyType, classifyIdList).Exec()
+	}
+
+	return
+}
+
+// AddEdbInfoClassifyNoAuthRecordBySourceAndUserIdList
+// @Description: 根据用户添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 20:12:44
+// @param source int
+// @param edbClassifyType int
+// @param noAuthClassifyMap map[int]ClassifyDataItem
+// @param configUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddEdbInfoClassifyNoAuthRecordBySourceAndUserIdList(source, edbClassifyType int, noAuthClassifyMap map[int]ClassifyDataItem, configUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	// 当前配置用户
+	configUserNum := len(configUserIdList)
+	if configUserNum <= 0 {
+		return
+	}
+
+	//// 总共的涉密分类
+	//noAuthClassifyInfoNum := len(noAuthClassifyMap)
+	//if noAuthClassifyInfoNum <= 0 {
+	//	return
+	//}
+
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据当前配置用户获取已经存在的未授权记录
+	var existList []*EdbInfoClassifyPermissionNoAuthRecord
+	sql := `SELECT * FROM edb_info_classify_permission_no_auth_record WHERE edb_classify_type = ? AND sys_user_id in (` + utils.GetOrmInReplace(configUserNum) + `)`
+	_, err = o.Raw(sql, edbClassifyType, configUserIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*EdbInfoClassifyPermissionNoAuthRecord)
+	delRecordIdMap := make(map[int64]int64)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*EdbInfoClassifyPermissionNoAuthRecord)
+		}
+
+		tmpUserExistMap[v.ClassifyId] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+
+		// 已经配置了的记录id
+		delRecordIdMap[v.EdbInfoClassifyPermissionNoAuthRecordId] = v.EdbInfoClassifyPermissionNoAuthRecordId
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*EdbInfoClassifyPermissionNoAuthRecord, 0)
+	for _, userId := range configUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range noAuthClassifyMap {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(dataItem.ClassifyId)
+				tmpUserRecord, ok := tmpUserExistMap[key]
+				if ok {
+					delete(delRecordIdMap, tmpUserRecord.EdbInfoClassifyPermissionNoAuthRecordId)
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &EdbInfoClassifyPermissionNoAuthRecord{
+				EdbInfoClassifyPermissionNoAuthRecordId: 0,
+				EdbClassifyType:                         int32(edbClassifyType),
+				OpUniqueCode:                            uniqueCode,
+				ClassifyId:                              fmt.Sprint(dataItem.ClassifyId),
+				ClassifyName:                            dataItem.ClassifyName,
+				SysUserId:                               int32(userId),
+				CreateTime:                              time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  4,
+				Source:                  int32(source),
+				SubSource:               int32(edbClassifyType),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 需要删除未授权记录
+	delRecordIdNum := len(delRecordIdMap)
+	if delRecordIdNum > 0 {
+		delRecordIdList := make([]int64, 0)
+		for _, v := range delRecordIdMap {
+			delRecordIdList = append(delRecordIdList, v)
+		}
+		sql = `DELETE FROM edb_info_classify_permission_no_auth_record WHERE edb_info_classify_permission_no_auth_record_id in (` + utils.GetOrmInReplace(delRecordIdNum) + `) `
+		_, err = o.Raw(sql, delRecordIdList).Exec()
+	}
+
+	return
+}
+
+// DeleteEdbInfoClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据来源和删除分类授权记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param source int
+// @param edbClassifyType int
+// @return err error
+func DeleteEdbInfoClassifyNoAuthRecordBySourceAndClassifyIdList(edbClassifyType int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	sql := `DELETE FROM edb_info_classify_permission_no_auth_record WHERE edb_classify_type = ?`
+	_, err = o.Raw(sql, edbClassifyType).Exec()
+
+	return
+}
+
+// GetEdbInfoDataPermissionClassifyNoAuthRecordListByUserId
+// @Description: 根据用户获取未授权的资产分类记录
+// @author: Roc
+// @datetime 2024-04-07 20:14:49
+// @param userId int
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionClassifyNoAuthRecord
+// @return err error
+func GetEdbInfoDataPermissionClassifyNoAuthRecordListByUserId(userId int32, edbClassifyType, startSize, pageSize int) (total int, items []*DataPermissionClassifyNoAuthRecord, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 获取总数
+	sql := `SELECT count(1) AS total FROM edb_info_classify_permission_no_auth_record WHERE sys_user_id = ? AND edb_classify_type = ? `
+	err = o.Raw(sql, userId, edbClassifyType).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT edb_info_classify_permission_no_auth_record_id as data_permission_classify_no_auth_record_id,edb_classify_type as sub_source,op_unique_code,classify_id,classify_name,sys_user_id,create_time  FROM edb_info_classify_permission_no_auth_record WHERE sys_user_id = ? AND edb_classify_type = ? ORDER BY edb_info_classify_permission_no_auth_record_id desc LIMIT ?,? `
+	_, err = o.Raw(sql, userId, edbClassifyType, startSize, pageSize).QueryRows(&items)
+
+	return
+}

+ 973 - 0
models/data_manage/data_manage_permission/excel.go

@@ -0,0 +1,973 @@
+package data_manage_permission
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"time"
+)
+
+type ExcelInfoPermission struct {
+	ExcelInfoPermissionId int64     `json:"excel_info_permission_id" orm:"column(excel_info_permission_id);pk"`
+	ExcelInfoId           int32     `json:"excel_info_id"` // ETA表格id
+	Source                int32     `json:"source"`        // 表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1
+	SysUserId             int32     `json:"sys_user_id"`   // 系统用户id
+	ModifyTime            time.Time `json:"modify_time"`   // 变更时间
+	CreateTime            time.Time `json:"create_time"`   // 关系建立时间
+}
+
+type ExcelClassifyPermission struct {
+	ExcelClassifyPermissionId int64     `json:"excel_classify_permission_id" orm:"column(excel_classify_permission_id);pk"`
+	ExcelClassifyId           int32     `json:"excel_classify_id"` // 分类id
+	Source                    int32     `json:"source"`            // 表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1
+	SysUserId                 int32     `json:"sys_user_id"`       // 系统用户id
+	ModifyTime                time.Time `json:"modify_time"`       // 变更时间
+	CreateTime                time.Time `json:"create_time"`       // 关系建立时间
+}
+
+// SetIsPermissionByExcelClassifyIdList
+// @Description: 设置表格分类是否涉密
+// @author: Roc
+// @datetime 2024-04-01 10:53:23
+// @param classifyIdList []int
+// @param excelClassifySource int
+// @return err error
+func SetIsPermissionByExcelClassifyIdList(classifyIdList []int, excelClassifySource int) (err error) {
+	num := len(classifyIdList)
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	//// 获取已经配置涉密的分类权限
+	//excelClassifyList := make([]*ExcelClassify, 0)
+	//sql := `SELECT * FROM excel_classify WHERE is_join_permission = ? `
+	//_, err = o.Raw(sql, 1).QueryRows(&excelClassifyList)
+	//if err != nil {
+	//	return
+	//}
+	//excelClassifyMap := make(map[int]*ExcelClassify)
+	//for _, v := range excelClassifyList {
+	//	excelClassifyMap[v.ClassifyId] = v
+	//}
+
+	// 先将所有已经设置了涉密的分类设置为不涉密
+	sql := `UPDATE excel_classify SET is_join_permission=?,modify_time=now() WHERE is_join_permission = 1 AND source = ?`
+	_, err = o.Raw(sql, 0, excelClassifySource).Exec()
+	if err != nil {
+		return
+	}
+
+	if num > 0 {
+		// 将对应的分类设置为涉密
+		sql = `UPDATE excel_classify SET is_join_permission=?,modify_time=now() WHERE source = ? AND excel_classify_id in (` + utils.GetOrmInReplace(num) + `) `
+		_, err = o.Raw(sql, 1, excelClassifySource, classifyIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+// SetPermissionByExcelIdList
+// @Description: 根据表格ID列表设置表格的用户权限
+// @author: Roc
+// @datetime 2024-04-01 10:26:17
+// @param excelIdList []string
+// @param userIdList []int
+// @param source int
+// @return err error
+func SetPermissionByExcelIdList(excelIdList []string, userIdList []int, source int) (err error) {
+	excelNum := len(excelIdList)
+	if excelNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 获取已经配置的表格权限用户
+	excelInfoPermissionList := make([]*ExcelInfoPermission, 0)
+	sql := `SELECT * FROM excel_info_permission WHERE source = ? AND excel_info_id in (` + utils.GetOrmInReplace(excelNum) + `) `
+	_, err = o.Raw(sql, source, excelIdList).QueryRows(&excelInfoPermissionList)
+	if err != nil {
+		return
+	}
+	excelInfoPermissionMap := make(map[string]*ExcelInfoPermission)
+	for _, v := range excelInfoPermissionList {
+		excelInfoPermissionMap[fmt.Sprint(v.ExcelInfoId, "_", v.SysUserId)] = v
+	}
+
+	// 标记表格是否纳入权限管控
+	{
+		// 默认 标记表格为纳入权限管控
+		isJoinPermission := 1
+		// 用户不选的情况下,说明是要给这些表格移除权限管控
+		if len(userIdList) <= 0 {
+			// 标记表格为不纳入权限管控
+			isJoinPermission = 0
+		}
+		sql = `UPDATE excel_info SET is_join_permission=?,modify_time=now() WHERE source = ? AND excel_info_id in (` + utils.GetOrmInReplace(excelNum) + `) `
+		_, err = o.Raw(sql, isJoinPermission, source, excelIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// 待添加的配置项
+	addList := make([]*ExcelInfoPermission, 0)
+
+	// 遍历待配置的表格和用户,筛选出需要添加的配置项
+	for _, excelInfoIdStr := range excelIdList {
+		excelInfoId, tmpErr := strconv.ParseInt(excelInfoIdStr, 10, 64)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		for _, userId := range userIdList {
+			key := fmt.Sprint(excelInfoId, "_", userId)
+			if _, ok := excelInfoPermissionMap[key]; ok {
+				// 如果存在那么就移除,说明不需要处理了
+				delete(excelInfoPermissionMap, key)
+			} else {
+				// 如果不存在,那么就添加
+				addList = append(addList, &ExcelInfoPermission{
+					//PermissionId: 0,
+					ExcelInfoId: int32(excelInfoId),
+					SysUserId:   int32(userId),
+					Source:      int32(source),
+					ModifyTime:  time.Now(),
+					CreateTime:  time.Now(),
+				})
+			}
+		}
+	}
+
+	// 添加待配置项
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(500, addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除废弃的配置项
+	{
+		// 待移除的配置项
+		deletePermissionIdList := make([]int64, 0)
+		for _, v := range excelInfoPermissionMap {
+			deletePermissionIdList = append(deletePermissionIdList, v.ExcelInfoPermissionId)
+		}
+
+		deletePermissionIdNum := len(deletePermissionIdList)
+		if deletePermissionIdNum > 0 {
+			sql = "DELETE FROM excel_info_permission WHERE excel_info_permission_id in (" + utils.GetOrmInReplace(deletePermissionIdNum) + ")"
+			_, err = o.Raw(sql, deletePermissionIdList).Exec()
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// SetPermissionByExcelClassifyIdList
+// @Description: 根据表格分类ID列表设置分类的用户权限
+// @author: Roc
+// @datetime 2024-03-28 14:53:04
+// @param classifyIdList []int
+// @param userIdList []int
+// @return err error
+func SetPermissionByExcelClassifyIdList(classifyIdList []int, userIdList []int, classifyType int) (err error) {
+	userNum := len(userIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 获取当前选择用户已经配置的表格分类权限
+	classifyPermissionList := make([]*ExcelClassifyPermission, 0)
+	sql := `SELECT * FROM excel_classify_permission WHERE source = ? AND sys_user_id in (` + utils.GetOrmInReplace(userNum) + `) `
+	_, err = o.Raw(sql, classifyType, userIdList).QueryRows(&classifyPermissionList)
+	if err != nil {
+		return
+	}
+	classifyPermissionMap := make(map[string]*ExcelClassifyPermission)
+	for _, v := range classifyPermissionList {
+		classifyPermissionMap[fmt.Sprint(v.ExcelClassifyId, "_", v.SysUserId)] = v
+	}
+
+	// 待添加的配置项
+	addList := make([]*ExcelClassifyPermission, 0)
+
+	// 遍历待配置的表格和用户,筛选出需要添加的配置项
+	for _, userId := range userIdList {
+		for _, classifyId := range classifyIdList {
+			key := fmt.Sprint(classifyId, "_", userId)
+			if _, ok := classifyPermissionMap[key]; ok {
+				// 如果存在那么就移除,说明不需要处理了
+				delete(classifyPermissionMap, key)
+			} else {
+				// 如果不存在,那么就提那家
+				addList = append(addList, &ExcelClassifyPermission{
+					//PermissionId: 0,
+					ExcelClassifyId: int32(classifyId),
+					Source:          int32(classifyType),
+					SysUserId:       int32(userId),
+					ModifyTime:      time.Now(),
+					CreateTime:      time.Now(),
+				})
+			}
+		}
+	}
+
+	// 添加待配置项
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(500, addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除废弃的配置项
+	{
+		// 获取移除的配置项
+		deletePermissionIdList := make([]int64, 0)
+		for _, v := range classifyPermissionMap {
+			deletePermissionIdList = append(deletePermissionIdList, v.ExcelClassifyPermissionId)
+		}
+
+		deletePermissionIdNum := len(deletePermissionIdList)
+		if deletePermissionIdNum > 0 {
+			sql = "DELETE FROM excel_classify_permission WHERE excel_classify_permission_id in (" + utils.GetOrmInReplace(deletePermissionIdNum) + ")"
+			_, err = o.Raw(sql, deletePermissionIdList).Exec()
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// GetPermissionExcelClassifyIdListByUserId
+// @Description: 根据用户ID获取已经配置的分类id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param userId int
+// @param classifyType int
+// @return excelClassifyIdList []int
+// @return err error
+func GetPermissionExcelClassifyIdListByUserId(userId int, classifyType int) (excelClassifyIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT excel_classify_id FROM excel_classify_permission WHERE source = ? AND sys_user_id = ? `
+	_, err = o.Raw(sql, classifyType, userId).QueryRows(&excelClassifyIdList)
+
+	return
+}
+
+// GetPermissionUserIdListByExcelId
+// @Description: 根据表格ID获取已经配置的用户id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param dataId int
+// @param source int
+// @return userIdList []int
+// @return err error
+func GetPermissionUserIdListByExcelId(dataId int, source int) (userIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT sys_user_id FROM excel_info_permission WHERE source = ? AND excel_info_id= ? `
+	_, err = o.Raw(sql, source, dataId).QueryRows(&userIdList)
+
+	return
+}
+
+// GetPermissionUserIdListByExcelClassifyId
+// @Description: 根据表格分类ID获取已经配置的用户id列表
+// @author: Roc
+// @datetime 2024-03-29 16:24:46
+// @param classifyId int
+// @param source int
+// @return userIdList []int
+// @return err error
+func GetPermissionUserIdListByExcelClassifyId(classifyId int, source int) (userIdList []int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT sys_user_id FROM excel_classify_permission WHERE source = ? AND excel_classify_id= ? `
+	_, err = o.Raw(sql, source, classifyId).QueryRows(&userIdList)
+
+	return
+}
+
+// GetPermissionExcelIdList
+// @Description: 获取用户权限的表格列表
+// @author: Roc
+// @datetime 2024-03-28 16:50:47
+// @param userId int
+// @param excelInfoId int
+// @return idList []int
+// @return err error
+func GetPermissionExcelIdList(userId, excelInfoId int) (idList []int, err error) {
+	pars := []interface{}{userId}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT excel_info_id FROM excel_info_permission WHERE sys_user_id = ? `
+	if excelInfoId > 0 {
+		sql += ` AND excel_info_id = ? `
+		pars = append(pars, excelInfoId)
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&idList)
+
+	return
+}
+
+// GetPermissionExcelClassifyIdList
+// @Description: 获取用户权限的表格分类列表
+// @author: Roc
+// @datetime 2024-03-28 16:50:47
+// @param userId int
+// @param classifyId int
+// @return idList []int
+// @return err error
+func GetPermissionExcelClassifyIdList(userId, classifyId int) (idList []int, err error) {
+	pars := []interface{}{userId}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT excel_classify_id FROM excel_classify_permission WHERE sys_user_id = ? `
+	if classifyId > 0 {
+		sql += ` AND excel_classify_id = ? `
+		pars = append(pars, classifyId)
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&idList)
+
+	return
+}
+
+// InheritParentClassifyByExcelClassifyId
+// @Description: 继承父级分类的ETA表格权限信息
+// @author: Roc
+// @datetime 2024-04-07 21:02:51
+// @param dataSource int
+// @param excelSource int
+// @param classifyId int
+// @param parentClassifyId int
+// @param classifyName string
+// @param uniqueCode string
+// @return err error
+func InheritParentClassifyByExcelClassifyId(dataSource, excelSource, classifyId, parentClassifyId int, classifyName, uniqueCode string) (err error) {
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 将对应的分类设置为涉密
+	sql := `UPDATE excel_classify SET is_join_permission=?,modify_time=now() WHERE source = ? AND excel_classify_id = ? `
+	_, err = o.Raw(sql, 1, excelSource, classifyId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 添加未授权记录
+	{
+		// 获取父级未授权的用户记录
+		var parentRecordItems []*ExcelInfoClassifyPermissionNoAuthRecord
+		sql = `SELECT * FROM data_permission_classify_no_auth_record WHERE classify_id = ? AND source = ? AND sub_source = ? ORDER BY data_permission_classify_no_auth_record_id desc LIMIT ?,? `
+		_, err = o.Raw(sql, parentClassifyId, dataSource, excelSource).QueryRows(&parentRecordItems)
+
+		addNoAuthRecordItems := make([]*ExcelInfoClassifyPermissionNoAuthRecord, 0)
+		for _, v := range parentRecordItems {
+			addNoAuthRecordItems = append(addNoAuthRecordItems, &ExcelInfoClassifyPermissionNoAuthRecord{
+				ExcelInfoClassifyPermissionNoAuthRecordId: 0,
+				Source:       v.Source,
+				OpUniqueCode: uniqueCode,
+				ClassifyId:   fmt.Sprint(classifyId),
+				ClassifyName: classifyName,
+				SysUserId:    v.SysUserId,
+				CreateTime:   time.Now(),
+			})
+		}
+
+		// 添加待配置项
+		if len(addNoAuthRecordItems) > 0 {
+			_, err = o.InsertMulti(500, addNoAuthRecordItems)
+			if err != nil {
+				return
+			}
+		}
+
+	}
+
+	// 添加授权记录
+	{
+		// 获取父级分类已经授权的用户
+		parentClassifyPermissionList := make([]*ExcelClassifyPermission, 0)
+		sql = `SELECT * FROM excel_classify_permission WHERE source = ? AND excel_classify_id = ? `
+		_, err = o.Raw(sql, excelSource, parentClassifyId).QueryRows(&parentClassifyPermissionList)
+		if err != nil {
+			return
+		}
+
+		addList := make([]*ExcelClassifyPermission, 0)
+		for _, v := range parentClassifyPermissionList {
+			// 如果不存在,那么就提那家
+			addList = append(addList, &ExcelClassifyPermission{
+				//PermissionId: 0,
+				ExcelClassifyId: int32(classifyId),
+				Source:          int32(excelSource),
+				SysUserId:       v.SysUserId,
+				ModifyTime:      time.Now(),
+				CreateTime:      time.Now(),
+			})
+		}
+		// 添加待配置项
+		if len(addList) > 0 {
+			_, err = o.InsertMulti(500, addList)
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	return
+}
+
+// ExcelInfoPermissionNoAuthRecord
+// @Description: ETA表格数据权限未授权记录表
+type ExcelInfoPermissionNoAuthRecord struct {
+	ExcelInfoPermissionNoAuthRecordId int64     `json:"excel_info_permission_no_auth_record_id"  orm:"column(excel_info_permission_no_auth_record_id);pk"` // 资产数据操作记录id
+	OpUniqueCode                      string    `json:"op_unique_code"`                                                                                    // 操作的唯一编码,主要是记录统一操作的日志
+	Source                            int32     `json:"source"`                                                                                            // 表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1
+	ExcelInfoId                       int32     `json:"excel_info_id"`                                                                                     // 指标id
+	ExcelName                         string    `json:"excel_name"`                                                                                        // 图表名称
+	SysUserId                         int32     `json:"sys_user_id"`                                                                                       // 系统用户id
+	CreateTime                        time.Time `json:"create_time"`                                                                                       // 创建时间
+}
+
+// AddExcelInfoPermissionNoAuthRecordBySourceAndDataIdList
+// @Description: 添加未授权用户记录
+// @author: Roc
+// @datetime 2024-04-07 15:25:49
+// @param source int
+// @param excelSource int
+// @param dataList []DataItem
+// @param noAuthUserIdList []int 未授权用户
+// @param authUserIdList []int 已授权用户
+// @param uniqueCode
+// @param content string
+// @param opUserId int
+// @return err error
+func AddExcelInfoPermissionNoAuthRecordBySourceAndDataIdList(source, excelSource int, dataList []DataItem, noAuthUserIdList, authUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	num := len(dataList)
+	if num <= 0 {
+		return
+	}
+	dataIdList := make([]int, 0)
+	for _, v := range dataList {
+		dataIdList = append(dataIdList, v.DataId)
+	}
+	userNum := len(noAuthUserIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据指标获取已经存在的未授权记录
+	var existList []*ExcelInfoPermissionNoAuthRecord
+	sql := `SELECT * FROM excel_info_permission_no_auth_record WHERE  source = ? AND excel_info_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, excelSource, dataIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*ExcelInfoPermissionNoAuthRecord)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*ExcelInfoPermissionNoAuthRecord)
+		}
+
+		key := fmt.Sprint(v.Source, "_", v.ExcelInfoId)
+		tmpUserExistMap[key] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*ExcelInfoPermissionNoAuthRecord, 0)
+	for _, userId := range noAuthUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range dataList {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(excelSource, "_", dataItem.DataId)
+				_, ok := tmpUserExistMap[key]
+				if ok {
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &ExcelInfoPermissionNoAuthRecord{
+				ExcelInfoPermissionNoAuthRecordId: 0,
+				OpUniqueCode:                      uniqueCode,
+				Source:                            int32(excelSource),
+				ExcelInfoId:                       int32(dataItem.DataId),
+				ExcelName:                         dataItem.DataName,
+				SysUserId:                         int32(userId),
+				CreateTime:                        time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  3,
+				Source:                  int32(source),
+				SubSource:               int32(excelSource),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 已经授权了的用户,需要删除未授权记录
+	authUserIdNum := len(authUserIdList)
+	if authUserIdNum > 0 {
+		sql = `DELETE FROM excel_info_permission_no_auth_record WHERE  source = ? AND sys_user_id in (` + utils.GetOrmInReplace(authUserIdNum) + `) AND excel_info_id in (` + utils.GetOrmInReplace(num) + `)`
+		_, err = o.Raw(sql, excelSource, authUserIdList, dataIdList).Exec()
+	}
+
+	return
+}
+
+// DeleteExcelInfoPermissionNoAuthRecordBySourceAndDataIdList
+// @Description: 根据来源和数据id列表删除记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param excelSource int
+// @param dataIdList []string
+// @return err error
+func DeleteExcelInfoPermissionNoAuthRecordBySourceAndDataIdList(excelSource int, dataIdList []string) (err error) {
+	num := len(dataIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+
+	sql := `DELETE FROM excel_info_permission_no_auth_record WHERE source = ? AND excel_info_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, excelSource, dataIdList).Exec()
+
+	return
+}
+
+func GetExcelInfoDataPermissionNoAuthRecordListByUserId(userId, excelSource int32, startSize, pageSize int) (total int, items []*DataPermissionNoAuthRecord, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 获取总数
+	sql := `SELECT count(1) AS total FROM excel_info_permission_no_auth_record WHERE sys_user_id = ? AND source = ? `
+	err = o.Raw(sql, userId, excelSource).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT excel_info_permission_no_auth_record_id as data_permission_no_auth_record_id,op_unique_code,source as sub_source,excel_info_id as data_id,excel_name as data_name,sys_user_id,create_time FROM excel_info_permission_no_auth_record WHERE sys_user_id = ? AND source = ? ORDER BY excel_info_permission_no_auth_record_id desc LIMIT ?,? `
+	_, err = o.Raw(sql, userId, excelSource, startSize, pageSize).QueryRows(&items)
+
+	return
+}
+
+type ExcelInfoClassifyPermissionNoAuthRecord struct {
+	ExcelInfoClassifyPermissionNoAuthRecordId int64     `json:"excel_info_classify_permission_no_auth_record_id" orm:"column(excel_info_classify_permission_no_auth_record_id);pk"` // 资产分类数据操作记录id
+	Source                                    int32     `json:"source"`                                                                                                             // 子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)
+	OpUniqueCode                              string    `json:"op_unique_code"`                                                                                                     // 操作的唯一编码,主要是记录统一操作的日志
+	ClassifyId                                string    `json:"classify_id"`                                                                                                        // ETA表格资产分类id
+	ClassifyName                              string    `json:"classify_name"`                                                                                                      // ETA表格资产分类名称
+	SysUserId                                 int32     `json:"sys_user_id"`                                                                                                        // 系统用户id
+	CreateTime                                time.Time `json:"create_time"`                                                                                                        // 创建时间
+}
+
+// AddExcelInfoClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据分类添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 16:44:21
+// @param source int
+// @param excelSource int
+// @param classifyInfoList []ClassifyDataItem
+// @param noAuthUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddExcelInfoClassifyNoAuthRecordBySourceAndClassifyIdList(source, excelSource int, classifyInfoList []ClassifyDataItem, noAuthUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	num := len(classifyInfoList)
+	if num <= 0 {
+		return
+	}
+	// 分类id
+	classifyIdList := make([]int, 0)
+	for _, v := range classifyInfoList {
+		classifyIdList = append(classifyIdList, v.ClassifyId)
+	}
+
+	userNum := len(noAuthUserIdList)
+	if userNum <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据分类获取已经存在的未授权记录
+	var existList []*ExcelInfoClassifyPermissionNoAuthRecord
+	sql := `SELECT * FROM excel_info_classify_permission_no_auth_record WHERE source = ? AND classify_id in (` + utils.GetOrmInReplace(num) + `)`
+	_, err = o.Raw(sql, excelSource, classifyIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*ExcelInfoClassifyPermissionNoAuthRecord)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*ExcelInfoClassifyPermissionNoAuthRecord)
+		}
+
+		key := fmt.Sprint(v.Source, "_", v.ClassifyId)
+		tmpUserExistMap[key] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*ExcelInfoClassifyPermissionNoAuthRecord, 0)
+	for _, userId := range noAuthUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range classifyInfoList {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(excelSource, "_", dataItem.ClassifyId)
+				_, ok := tmpUserExistMap[key]
+				if ok {
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &ExcelInfoClassifyPermissionNoAuthRecord{
+				ExcelInfoClassifyPermissionNoAuthRecordId: 0,
+				Source:       int32(excelSource),
+				OpUniqueCode: uniqueCode,
+				ClassifyId:   fmt.Sprint(dataItem.ClassifyId),
+				ClassifyName: dataItem.ClassifyName,
+				SysUserId:    int32(userId),
+				CreateTime:   time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  4,
+				Source:                  int32(source),
+				SubSource:               int32(excelSource),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除已经公开了的分类权限,需要删除未授权记录
+	authUserIdNum := len(classifyIdList)
+	if authUserIdNum > 0 {
+		sql = `DELETE FROM excel_info_classify_permission_no_auth_record WHERE source = ? AND classify_id not in (` + utils.GetOrmInReplace(num) + `)`
+		_, err = o.Raw(sql, excelSource, classifyIdList).Exec()
+	}
+
+	return
+}
+
+// AddExcelInfoClassifyNoAuthRecordBySourceAndUserIdList
+// @Description: 根据用户添加用户分类未授权记录
+// @author: Roc
+// @datetime 2024-04-07 20:12:44
+// @param source int
+// @param excelSource int
+// @param noAuthClassifyMap map[int]ClassifyDataItem
+// @param configUserIdList []int
+// @param uniqueCode string
+// @param content string
+// @param opUserId int
+// @return err error
+func AddExcelInfoClassifyNoAuthRecordBySourceAndUserIdList(source, excelSource int, noAuthClassifyMap map[int]ClassifyDataItem, configUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	// 当前配置用户
+	configUserNum := len(configUserIdList)
+	if configUserNum <= 0 {
+		return
+	}
+
+	//// 总共的涉密分类
+	//noAuthClassifyInfoNum := len(noAuthClassifyMap)
+	//if noAuthClassifyInfoNum <= 0 {
+	//	return
+	//}
+
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 根据当前配置用户获取已经存在的未授权记录
+	var existList []*ExcelInfoClassifyPermissionNoAuthRecord
+	sql := `SELECT * FROM excel_info_classify_permission_no_auth_record WHERE source = ? AND sys_user_id in (` + utils.GetOrmInReplace(configUserNum) + `)`
+	_, err = o.Raw(sql, excelSource, configUserIdList).QueryRows(&existList)
+	if err != nil {
+		return
+	}
+
+	// 已经标记了的数据
+	existMap := make(map[int32]map[string]*ExcelInfoClassifyPermissionNoAuthRecord)
+	delRecordIdMap := make(map[int64]int64)
+	for _, v := range existList {
+		tmpUserExistMap, ok := existMap[v.SysUserId]
+		if !ok {
+			tmpUserExistMap = make(map[string]*ExcelInfoClassifyPermissionNoAuthRecord)
+		}
+
+		tmpUserExistMap[v.ClassifyId] = v
+		existMap[v.SysUserId] = tmpUserExistMap
+
+		// 已经配置了的记录id
+		delRecordIdMap[v.ExcelInfoClassifyPermissionNoAuthRecordId] = v.ExcelInfoClassifyPermissionNoAuthRecordId
+	}
+
+	addMessageList := make([]*DataPermissionMessage, 0)
+	addRecordList := make([]*ExcelInfoClassifyPermissionNoAuthRecord, 0)
+	for _, userId := range configUserIdList {
+		isAdd := false
+
+		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+
+		for _, dataItem := range noAuthClassifyMap {
+			// 判断是否已经存在,已经存在就过滤
+			if userExistOk {
+				key := fmt.Sprint(dataItem.ClassifyId)
+				tmpUserRecord, ok := tmpUserExistMap[key]
+				if ok {
+					delete(delRecordIdMap, tmpUserRecord.ExcelInfoClassifyPermissionNoAuthRecordId)
+					continue
+				}
+			}
+
+			isAdd = true
+			addRecordList = append(addRecordList, &ExcelInfoClassifyPermissionNoAuthRecord{
+				ExcelInfoClassifyPermissionNoAuthRecordId: 0,
+				Source:       int32(excelSource),
+				OpUniqueCode: uniqueCode,
+				ClassifyId:   fmt.Sprint(dataItem.ClassifyId),
+				ClassifyName: dataItem.ClassifyName,
+				SysUserId:    int32(userId),
+				CreateTime:   time.Now(),
+			})
+		}
+
+		// 有记录的话,需要添加消息
+		if isAdd {
+			addMessageList = append(addMessageList, &DataPermissionMessage{
+				DataPermissionMessageId: 0,
+				SendUserId:              int32(opUserId),
+				ReceiveUserId:           int32(userId),
+				Content:                 title,
+				Remark:                  content,
+				OpType:                  4,
+				Source:                  int32(source),
+				SubSource:               int32(excelSource),
+				OpUniqueCode:            uniqueCode,
+				IsRead:                  0,
+				CreateTime:              time.Now(),
+				ModifyTime:              time.Now(),
+			})
+		}
+	}
+
+	// 添加消息
+	if len(addMessageList) > 0 {
+		_, err = o.InsertMulti(500, addMessageList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 添加记录
+	if len(addRecordList) > 0 {
+		_, err = o.InsertMulti(500, addRecordList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 需要删除未授权记录
+	delRecordIdNum := len(delRecordIdMap)
+	if delRecordIdNum > 0 {
+		delRecordIdList := make([]int64, 0)
+		for _, v := range delRecordIdMap {
+			delRecordIdList = append(delRecordIdList, v)
+		}
+		sql = `DELETE FROM excel_info_classify_permission_no_auth_record WHERE excel_info_classify_permission_no_auth_record_id in (` + utils.GetOrmInReplace(delRecordIdNum) + `) `
+		_, err = o.Raw(sql, delRecordIdList).Exec()
+	}
+
+	return
+}
+
+// DeleteExcelInfoClassifyNoAuthRecordBySourceAndClassifyIdList
+// @Description: 根据来源和删除分类授权记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param source int
+// @param excelSource int
+// @return err error
+func DeleteExcelInfoClassifyNoAuthRecordBySourceAndClassifyIdList(excelSource int) (err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	sql := `DELETE FROM excel_info_classify_permission_no_auth_record WHERE source = ?`
+	_, err = o.Raw(sql, excelSource).Exec()
+
+	return
+}
+
+// GetExcelInfoDataPermissionClassifyNoAuthRecordListByUserId
+// @Description: 根据用户获取未授权的资产分类记录
+// @author: Roc
+// @datetime 2024-04-07 20:14:49
+// @param userId int
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionClassifyNoAuthRecord
+// @return err error
+func GetExcelInfoDataPermissionClassifyNoAuthRecordListByUserId(userId, excelSource int32, startSize, pageSize int) (total int, items []*DataPermissionClassifyNoAuthRecord, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 获取总数
+	sql := `SELECT count(1) AS total FROM excel_info_classify_permission_no_auth_record WHERE sys_user_id = ? AND source = ? `
+	err = o.Raw(sql, userId, excelSource).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT excel_info_classify_permission_no_auth_record_id as data_permission_classify_no_auth_record_id,source as sub_source,op_unique_code,classify_id,classify_name,sys_user_id,create_time  FROM excel_info_classify_permission_no_auth_record WHERE sys_user_id = ? AND source = ? ORDER BY excel_info_classify_permission_no_auth_record_id desc LIMIT ?,? `
+	_, err = o.Raw(sql, userId, excelSource, startSize, pageSize).QueryRows(&items)
+
+	return
+}

+ 152 - 0
models/data_manage/data_manage_permission/message.go

@@ -0,0 +1,152 @@
+package data_manage_permission
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// DataPermissionMessage
+// @Description: 数据权限变更消息表
+type DataPermissionMessage struct {
+	DataPermissionMessageId int64     `json:"data_permission_message_id" orm:"column(data_permission_message_id);pk"`
+	SendUserId              int32     `json:"send_user_id"`    // 发送人ID
+	ReceiveUserId           int32     `json:"receive_user_id"` // 接收者ID
+	Content                 string    `json:"content"`         // 消息内容
+	Remark                  string    `json:"remark"`          // 备注信息
+	OpType                  int32     `json:"op_type"`         // 操作类型,1:单个资产转移,2:资产模块转移,3:资产授权,4:资产分类授权
+	Source                  int32     `description:"来源id"`
+	SubSource               int32     `description:"子来源id"`
+	OpUniqueCode            string    `json:"op_unique_code"` // 操作编码
+	IsRead                  int32     `json:"is_read"`        // 是否已读:0-未读;1-已读
+	CreateTime              time.Time `json:"create_time"`    // 创建时间
+	ModifyTime              time.Time `json:"modify_time"`    // 修改时间
+}
+
+var DataPermissionMessageCols = struct {
+	DataPermissionMessageId string
+	SendUserId              string
+	ReceiveUserId           string
+	Content                 string
+	Remark                  string
+	OpType                  string
+	Source                  string
+	SubSource               string
+	OpUniqueCode            string
+	IsRead                  string
+	CreateTime              string
+	ModifyTime              string
+}{
+	DataPermissionMessageId: "data_permission_message_id",
+	SendUserId:              "send_user_id",
+	ReceiveUserId:           "receive_user_id",
+	Content:                 "content",
+	Remark:                  "remark",
+	OpType:                  "op_type",
+	Source:                  "source",
+	SubSource:               "sub_source",
+	OpUniqueCode:            "op_unique_code",
+	IsRead:                  "is_read",
+	CreateTime:              "create_time",
+	ModifyTime:              "modify_time",
+}
+
+func (m *DataPermissionMessage) TableName() string {
+	return "data_permission_message"
+}
+
+func (m *DataPermissionMessage) PrimaryId() string {
+	return DataPermissionMessageCols.DataPermissionMessageId
+}
+
+func (m *DataPermissionMessage) Create() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.DataPermissionMessageId = id
+	return
+}
+
+func (m *DataPermissionMessage) CreateMulti(items []*DataPermissionMessage) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.InsertMulti(500, items)
+	return
+}
+
+func (m *DataPermissionMessage) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *DataPermissionMessage) Del() (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.DataPermissionMessageId).Exec()
+	return
+}
+
+func (m *DataPermissionMessage) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *DataPermissionMessage) GetItemById(id int) (item *DataPermissionMessage, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *DataPermissionMessage) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *DataPermissionMessage) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*DataPermissionMessage, err error) {
+	o := orm.NewOrmUsingDB("data")
+	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)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// FormatDataPermissionMessage2Item 格式化消息
+func FormatDataPermissionMessage2Item(origin *DataPermissionMessage) (item *DataPermissionMessageItem) {
+	item = &DataPermissionMessageItem{
+		DataPermissionMessageId: origin.DataPermissionMessageId,
+		SendUserId:              origin.SendUserId,
+		ReceiveUserId:           origin.ReceiveUserId,
+		Content:                 origin.Content,
+		Remark:                  origin.Remark,
+		OpType:                  origin.OpType,
+		Source:                  origin.Source,
+		SubSource:               origin.SubSource,
+		OpUniqueCode:            origin.OpUniqueCode,
+		IsRead:                  origin.IsRead,
+		CreateTime:              utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime),
+		ModifyTime:              utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime),
+	}
+	return
+}

+ 103 - 0
models/data_manage/data_manage_permission/move.go

@@ -0,0 +1,103 @@
+package data_manage_permission
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+)
+
+// ModifyDataUserIdByOldUserId
+// @Description:  根据旧用户id修改新用户id
+// @author: Roc
+// @datetime 2024-03-25 17:59:32
+// @param oldUserId int
+// @param userId int
+// @return err error
+func ModifyDataUserIdByOldUserId(oldUserIdList []int, userId int, userName string, isMoveManual, isMoveMysteelChemical, isMoveEdb, isMovePredictEdb, isMoveChart, isMoveExcel bool) (err error) {
+	num := len(oldUserIdList)
+	if num <= 0 {
+		return
+	}
+
+	if userId <= 0 {
+		return
+	}
+
+	// 手工指标库
+	if isMoveManual {
+		edbTo, tmpErr := orm.NewOrmUsingDB("edb").Begin()
+		if tmpErr != nil {
+			return
+		}
+		defer func() {
+			if err != nil {
+				_ = edbTo.Rollback()
+			} else {
+				_ = edbTo.Commit()
+			}
+		}()
+		sql := `UPDATE edbinfo SET user_id=? WHERE user_id in (` + utils.GetOrmInReplace(num) + `) `
+		_, err = edbTo.Raw(sql, userId, oldUserIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// ETA指标库
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 钢联化工数据库
+	if isMoveMysteelChemical {
+		sql := `UPDATE base_from_mysteel_chemical_index SET sys_user_id=?,sys_user_real_name=? WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `)  `
+		_, err = o.Raw(sql, userId, userName, oldUserIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// ETA指标库
+	if isMoveEdb {
+		sql := `UPDATE edb_info SET sys_user_id=?,sys_user_real_name=? WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `) and edb_info_type = ?`
+		_, err = o.Raw(sql, userId, userName, oldUserIdList, 0).Exec()
+		if err != nil {
+			return
+		}
+	}
+	// 预测指标
+	if isMovePredictEdb {
+		sql := `UPDATE edb_info SET sys_user_id=?,sys_user_real_name=? WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `) and edb_info_type = ?`
+		_, err = o.Raw(sql, userId, userName, oldUserIdList, 1).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// ETA表格
+	if isMoveChart {
+		sql := `UPDATE chart_info SET sys_user_id=?,sys_user_real_name=? WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `) `
+		_, err = o.Raw(sql, userId, userName, oldUserIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	// ETA表格
+	if isMoveExcel {
+		sql := `UPDATE excel_info SET sys_user_id=?,sys_user_real_name=? WHERE is_delete=0 AND sys_user_id in (` + utils.GetOrmInReplace(num) + `) `
+		_, err = o.Raw(sql, userId, userName, oldUserIdList).Exec()
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}

+ 85 - 0
models/data_manage/data_manage_permission/move_record.go

@@ -0,0 +1,85 @@
+package data_manage_permission
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// DataPermissionMoveRecord
+// @Description: 数据资产转移记录表
+type DataPermissionMoveRecord struct {
+	DataPermissionMoveRecordId int64     `json:"data_permission_move_record_id" orm:"column(data_permission_move_record_id);pk"` // 数据操作记录id
+	Source                     int32     `json:"source"`                                                                         // 数据来源,1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格
+	SubSource                  int32     `json:"sub_source"`                                                                     // 子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)
+	OpUniqueCode               string    `json:"op_unique_code"`                                                                 // 操作的唯一编码,主要是记录统一操作的日志
+	DataId                     string    `json:"data_id"`                                                                        // 资产id(指标、图表、表格)
+	DataCode                   string    `json:"data_code"`                                                                      // 资产code(指标、图表、表格)
+	DataName                   string    `json:"data_name"`                                                                      // 资产名称(指标、图表、表格)
+	OriginalUserId             int32     `json:"original_user_id"`                                                               // 原创建人id
+	OriginalUserName           string    `json:"original_user_name"`                                                             // 原创建人名称
+	NewUserId                  int32     `json:"new_user_id"`                                                                    // 新创建人id
+	NewUserName                string    `json:"new_user_name"`                                                                  // 新创建人名称
+	CreateTime                 time.Time `json:"create_time"`                                                                    // 创建时间
+}
+
+// AddDataPermissionMoveRecord
+// @Description: 添加资产转移的操作记录
+// @param dataPermissionMoveRecordList
+// @param dataPermissionMessage
+// @return err
+func AddDataPermissionMoveRecord(dataPermissionMoveRecordList []*DataPermissionMoveRecord, dataPermissionMessage *DataPermissionMessage) (err error) {
+	num := len(dataPermissionMoveRecordList)
+	if num <= 0 {
+		return
+	}
+	o, err := orm.NewOrmUsingDB("data").Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+
+	// 添加操作记录
+	_, err = o.InsertMulti(500, dataPermissionMoveRecordList)
+	if err != nil {
+		return
+	}
+
+	// 添加消息通知
+	_, err = o.Insert(dataPermissionMessage)
+
+	return
+}
+
+// GetDataPermissionMoveRecordListByOpUniqueCode
+// @Description: 根据操作唯一编码获取操作记录
+// @author: Roc
+// @datetime 2024-04-07 20:15:22
+// @param opUniqueCode string
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionMoveRecord
+// @return err error
+func GetDataPermissionMoveRecordListByOpUniqueCode(opUniqueCode string, source, subSource, startSize, pageSize int) (total int, items []*DataPermissionMoveRecord, err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	// 获取总数
+	sql := `SELECT count(1) AS total FROM data_permission_move_record WHERE op_unique_code = ? AND source = ? AND sub_source = ? `
+	err = o.Raw(sql, opUniqueCode, source, subSource).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	sql = `SELECT * FROM data_permission_move_record WHERE op_unique_code = ? AND source = ? AND sub_source = ? ORDER BY data_permission_move_record_id desc LIMIT ?,? `
+	_, err = o.Raw(sql, opUniqueCode, source, subSource, startSize, pageSize).QueryRows(&items)
+
+	return
+}

+ 316 - 0
models/data_manage/data_manage_permission/no_auth_record.go

@@ -0,0 +1,316 @@
+package data_manage_permission
+
+import (
+	"errors"
+	"eta/eta_api/utils"
+	"time"
+)
+
+// DataPermissionNoAuthRecord
+// @Description: 资产数据权限设置记录表
+type DataPermissionNoAuthRecord struct {
+	DataPermissionNoAuthRecordId int64     `json:"data_permission_no_auth_record_id" orm:"column(data_permission_no_auth_record_id);pk"` // 资产数据操作记录id
+	Source                       int32     `json:"source"`                                                                               // 数据来源,1:手工数据指标 2:钢联化工数据库 3:ETA指标库 4:ETA预测指标 5:图库 6:ETA表格
+	SubSource                    int32     `json:"sub_source"`                                                                           // 子来源 :ETA表格中的各种表格类型,以及图表的来源(这个是后续的扩展方向)
+	OpUniqueCode                 string    `json:"op_unique_code"`                                                                       // 操作的唯一编码,主要是记录统一操作的日志
+	DataId                       string    `json:"data_id"`                                                                              // 资产id(指标、图表、表格)
+	DataCode                     string    `json:"data_code"`                                                                            // 资产code(指标、图表、表格)
+	DataName                     string    `json:"data_name"`                                                                            // 资产名称(指标、图表、表格)
+	SysUserId                    int32     `json:"sys_user_id"`                                                                          // 系统用户id
+	CreateTime                   time.Time `json:"create_time"`                                                                          // 创建时间
+}
+
+type DataItem struct {
+	DataId   int    `json:"data_id"`   // 资产id(指标、图表、表格)
+	DataCode string `json:"data_code"` // 资产code(指标、图表、表格)
+	DataName string `json:"data_name"` // 资产名称(指标、图表、表格)
+}
+
+// AddRecordBySourceAndDataIdList
+// @Description: 添加未授权用户记录
+// @author: Roc
+// @datetime 2024-04-07 15:25:49
+// @param source int
+// @param subSource int
+// @param dataList []DataItem
+// @param noAuthUserIdList []int 未授权用户
+// @param authUserIdList []int 已授权用户
+// @param uniqueCode
+// @param content string
+// @param opUserId int
+// @return err error
+func AddRecordBySourceAndDataIdList(source, subSource int, dataList []DataItem, noAuthUserIdList, authUserIdList []int, uniqueCode, title, content string, opUserId int) (err error) {
+	switch source {
+	case 3, 4:
+		edbInfoType := 0
+		if source == 4 {
+			edbInfoType = 1
+		}
+		err = AddEdbInfoPermissionNoAuthRecordBySourceAndDataIdList(source, edbInfoType, dataList, noAuthUserIdList, authUserIdList, uniqueCode, title, content, opUserId)
+
+	case 5:
+		//图库
+		chartSource := utils.CHART_SOURCE_DEFAULT
+		err = AddChartInfoPermissionNoAuthRecordBySourceAndDataIdList(source, chartSource, dataList, noAuthUserIdList, authUserIdList, uniqueCode, title, content, opUserId)
+
+	case 6:
+		// ETA表格
+		err = AddExcelInfoPermissionNoAuthRecordBySourceAndDataIdList(source, subSource, dataList, noAuthUserIdList, authUserIdList, uniqueCode, title, content, opUserId)
+
+	default:
+		return errors.New("错误的source")
+	}
+	return
+}
+
+// AddRecordBySourceAndDataIdList
+// @Description: 添加未授权用户记录
+// @author: Roc
+// @datetime 2024-04-07 15:25:49
+// @param source int
+// @param subSource int
+// @param dataList []DataItem
+// @param noAuthUserIdList []int 未授权用户
+// @param authUserIdList []int 已授权用户
+// @param uniqueCode
+// @param content string
+// @param opUserId int
+// @return err error
+//func AddRecordBySourceAndDataIdList(source, subSource int, dataList []DataItem, noAuthUserIdList, authUserIdList []int, uniqueCode, content string, opUserId int) (err error) {
+//	num := len(dataList)
+//	if num <= 0 {
+//		return
+//	}
+//	dataIdList := make([]string, 0)
+//	for _, v := range dataList {
+//		dataIdList = append(dataIdList, v.DataId)
+//	}
+//	userNum := len(noAuthUserIdList)
+//	if userNum <= 0 {
+//		return
+//	}
+//	o, err := orm.NewOrmUsingDB("data").Begin()
+//	if err != nil {
+//		return
+//	}
+//	defer func() {
+//		if err != nil {
+//			_ = o.Rollback()
+//		} else {
+//			_ = o.Commit()
+//		}
+//	}()
+//
+//	// 根据指标获取已经存在的未授权记录
+//	var existList []*DataPermissionNoAuthRecord
+//	sql := `SELECT * FROM data_permission_no_auth_record WHERE source = ? AND sub_source = ? AND data_id in (` + utils.GetOrmInReplace(num) + `)`
+//	_, err = o.Raw(sql, source, subSource, dataIdList).QueryRows(&existList)
+//	if err != nil {
+//		return
+//	}
+//
+//	// 已经标记了的数据
+//	existMap := make(map[int32]map[string]*DataPermissionNoAuthRecord)
+//	for _, v := range existList {
+//		tmpUserExistMap, ok := existMap[v.SysUserId]
+//		if !ok {
+//			tmpUserExistMap = make(map[string]*DataPermissionNoAuthRecord)
+//		}
+//
+//		key := fmt.Sprint(v.Source, "_", v.SubSource, "_", v.DataId)
+//		tmpUserExistMap[key] = v
+//		existMap[v.SysUserId] = tmpUserExistMap
+//	}
+//
+//	addMessageList := make([]*DataPermissionMessage, 0)
+//	addRecordList := make([]*DataPermissionNoAuthRecord, 0)
+//	for _, userId := range noAuthUserIdList {
+//		isAdd := false
+//
+//		tmpUserExistMap, userExistOk := existMap[int32(userId)]
+//
+//		for _, dataItem := range dataList {
+//			// 判断是否已经存在,已经存在就过滤
+//			if userExistOk {
+//				key := fmt.Sprint(source, "_", subSource, "_", dataItem.DataId)
+//				_, ok := tmpUserExistMap[key]
+//				if ok {
+//					continue
+//				}
+//			}
+//
+//			isAdd = true
+//			addRecordList = append(addRecordList, &DataPermissionNoAuthRecord{
+//				DataPermissionNoAuthRecordId: 0,
+//				Source:                       int32(source),
+//				SubSource:                    int32(subSource),
+//				OpUniqueCode:                 uniqueCode,
+//				DataId:                       dataItem.DataId,
+//				DataCode:                     dataItem.DataCode,
+//				DataName:                     dataItem.DataName,
+//				SysUserId:                    int32(userId),
+//				CreateTime:                   time.Now(),
+//			})
+//		}
+//
+//		// 有记录的话,需要添加消息
+//		if isAdd {
+//			addMessageList = append(addMessageList, &DataPermissionMessage{
+//				DataPermissionMessageId: 0,
+//				SendUserId:              int32(opUserId),
+//				ReceiveUserId:           int32(userId),
+//				Content:                 content,
+//				Remark:                  content,
+//				OpType:                  3,
+//				Source:                  int32(source),
+//				SubSource:               int32(subSource),
+//				OpUniqueCode:            uniqueCode,
+//				IsRead:                  0,
+//				CreateTime:              time.Now(),
+//				ModifyTime:              time.Now(),
+//			})
+//		}
+//	}
+//
+//	// 添加消息
+//	if len(addMessageList) > 0 {
+//		_, err = o.InsertMulti(500, addMessageList)
+//		if err != nil {
+//			return
+//		}
+//	}
+//
+//	// 添加记录
+//	if len(addRecordList) > 0 {
+//		_, err = o.InsertMulti(500, addRecordList)
+//		if err != nil {
+//			return
+//		}
+//	}
+//
+//	// 已经授权了的用户,需要删除未授权记录
+//	authUserIdNum := len(authUserIdList)
+//	if authUserIdNum > 0 {
+//		sql = `DELETE FROM data_permission_no_auth_record WHERE  source = ? AND sub_source = ? AND sys_user_id in (` + utils.GetOrmInReplace(authUserIdNum) + `) AND data_id in (` + utils.GetOrmInReplace(num) + `)`
+//		_, err = o.Raw(sql, source, subSource, authUserIdList, dataIdList).Exec()
+//	}
+//
+//	return
+//}
+
+// DeleteRecordBySourceAndDataIdList
+// @Description: 根据来源和数据id列表删除记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param source int
+// @param subSource int
+// @param dataIdList []string
+// @return err error
+func DeleteRecordBySourceAndDataIdList(source, subSource int, dataIdList []string) (err error) {
+	switch source {
+	case 3, 4:
+		edbInfoType := 0
+		if source == 4 {
+			edbInfoType = 1
+		}
+		err = DeleteEdbInfoPermissionNoAuthRecordBySourceAndDataIdList(edbInfoType, dataIdList)
+	case 5:
+		//图库
+		chartSource := utils.CHART_SOURCE_DEFAULT
+		err = DeleteChartInfoPermissionNoAuthRecordBySourceAndDataIdList(chartSource, dataIdList)
+
+	case 6:
+		// ETA表格
+		err = DeleteExcelInfoPermissionNoAuthRecordBySourceAndDataIdList(subSource, dataIdList)
+
+	default:
+		return errors.New("错误的source")
+	}
+	return
+}
+
+// DeleteRecordBySourceAndDataIdList
+// @Description: 根据来源和数据id列表删除记录
+// @author: Roc
+// @datetime 2024-04-07 14:47:37
+// @param source int
+// @param subSource int
+// @param dataIdList []string
+// @return err error
+//func DeleteRecordBySourceAndDataIdList(source, subSource int, dataIdList []string) (err error) {
+//	num := len(dataIdList)
+//	if num <= 0 {
+//		return
+//	}
+//	o := orm.NewOrmUsingDB("data")
+//
+//	sql := `DELETE FROM data_permission_no_auth_record WHERE source = ? AND sub_source = ? AND data_id in (` + utils.GetOrmInReplace(num) + `)`
+//	_, err = o.Raw(sql, source, subSource, dataIdList).Exec()
+//
+//	return
+//}
+
+// GetDataPermissionNoAuthRecordListByUserId
+// @Description: 根据用户获取未授权的资产记录
+// @author: Roc
+// @datetime 2024-04-07 20:15:01
+// @param userId int
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionNoAuthRecord
+// @return err error
+//func GetDataPermissionNoAuthRecordListByUserId(userId, source, subSource int32, startSize, pageSize int) (total int, items []*DataPermissionNoAuthRecord, err error) {
+//	o := orm.NewOrmUsingDB("data")
+//
+//	// 获取总数
+//	sql := `SELECT count(1) AS total FROM data_permission_no_auth_record WHERE sys_user_id = ? AND source = ? AND sub_source = ? `
+//	err = o.Raw(sql, userId, source, subSource).QueryRow(&total)
+//	if err != nil {
+//		return
+//	}
+//
+//	sql = `SELECT * FROM data_permission_no_auth_record WHERE sys_user_id = ? AND source = ? AND sub_source = ? ORDER BY data_permission_no_auth_record_id desc LIMIT ?,? `
+//	_, err = o.Raw(sql, userId, source, subSource, startSize, pageSize).QueryRows(&items)
+//
+//	return
+//}
+
+// GetDataPermissionNoAuthRecordListByUserId
+// @Description: 根据用户获取未授权的资产记录
+// @author: Roc
+// @datetime 2024-04-07 20:15:01
+// @param userId int
+// @param source int
+// @param subSource int
+// @param startSize int
+// @param pageSize int
+// @return total int
+// @return items []*DataPermissionNoAuthRecord
+// @return err error
+func GetDataPermissionNoAuthRecordListByUserId(userId, source, subSource int32, startSize, pageSize int) (total int, items []*DataPermissionNoAuthRecord, err error) {
+	switch source {
+	case 3, 4:
+		edbInfoType := 0
+		if source == 4 {
+			edbInfoType = 1
+		}
+		total, items, err = GetEdbInfoDataPermissionNoAuthRecordListByUserId(userId, edbInfoType, startSize, pageSize)
+	case 5:
+		//图库
+		chartSource := utils.CHART_SOURCE_DEFAULT
+		total, items, err = GetChartInfoDataPermissionNoAuthRecordListByUserId(userId, chartSource, startSize, pageSize)
+
+	case 6:
+		// ETA表格
+		total, items, err = GetExcelInfoDataPermissionNoAuthRecordListByUserId(userId, subSource, startSize, pageSize)
+
+	default:
+		err = errors.New("错误的source")
+		return
+	}
+
+	return
+}

+ 89 - 0
models/data_manage/data_manage_permission/req_and_resp.go

@@ -0,0 +1,89 @@
+package data_manage_permission
+
+import "github.com/rdlucklib/rdluck_tools/paging"
+
+// MoveEdbChartReq 转移指标/图表的请求
+type MoveEdbChartReq struct {
+	Source       int      `description:"来源id"`
+	SubSource    int      `description:"子来源id"`
+	DataIdList   []string `description:"指标/图表唯一id列表"`
+	NoDataIdList []string `description:"指标/图表唯一id列表"`
+	NewUserId    int      `description:"新的创建人id"`
+	IsSelectAll  bool     `description:"是否选择所有指标"`
+	ClassifyId   string   `description:"分类id,支持多选,用英文,隔开"`
+	Keyword      string   `description:"关键字"`
+	UserId       int      `description:"旧的创建人id"`
+}
+
+// MoveAllEdbChartReq 转移所有的指标/图表的请求
+type MoveAllEdbChartReq struct {
+	Source    []int `description:"来源id"`
+	OldUserId []int `description:"旧的创建人id"`
+	NewUserId int   `description:"新的创建人id"`
+}
+
+// SetDataIsPermissionReq
+// @Description: 设置数据分类权限请求
+type SetDataIsPermissionReq struct {
+	Source         int   `description:"来源id"`
+	SubSource      int   `description:"子来源id"`
+	ClassifyIdList []int `description:"指标/图表/表格分类唯一id列表,如果为空,说明要给这些指标移除权限管控"`
+}
+
+// SetEdbChartPermissionReq
+// @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:"是否选择所有指标"`
+	ClassifyId   string   `description:"分类id,支持多选,用英文,隔开"`
+	Keyword      string   `description:"关键字"`
+}
+
+// SetEdbChartClassifyPermissionReq
+// @Description: 设置数据分类权限请求
+type SetEdbChartClassifyPermissionReq struct {
+	Source         int   `description:"来源id"`
+	SubSource      int   `description:"子来源id"`
+	UserList       []int `description:"赋权用户id列表,如果为空,说明要给这些数据分类移除权限管控"`
+	ClassifyIdList []int `description:"指标/图表/表格分类唯一id列表"`
+}
+
+// DataPermissionMessageItem
+// @Description: 数据权限变更消息结构体
+type DataPermissionMessageItem struct {
+	DataPermissionMessageId int64  `orm:"column(data_permission_message_id);pk"`
+	SendUserId              int32  // 发送人ID
+	ReceiveUserId           int32  // 接收者ID
+	Content                 string // 消息内容
+	Remark                  string // 备注信息
+	OpType                  int32  // 操作类型,1:单个资产转移,2:资产模块转移,3:资产授权,4:资产分类授权
+	Source                  int32  `description:"来源id"`
+	SubSource               int32  `description:"子来源id"`
+	OpUniqueCode            string // 操作编码
+	IsRead                  int32  // 是否已读:0-未读;1-已读
+	CreateTime              string // 创建时间
+	ModifyTime              string // 修改时间
+}
+
+// DataPermissionMessageListResp 资产数据列表响应体
+type DataPermissionMessageListResp struct {
+	List        []*DataPermissionMessageItem
+	Paging      *paging.PagingItem `description:"分页数据"`
+	UnreadTotal int                `description:"消息未读数"`
+}
+
+// DataPermissionMessageReadReq 资产数据消息已读请求体
+type DataPermissionMessageReadReq struct {
+	MessageId int `description:"资产数据消息ID"`
+}
+
+// MessageDetailListResp 消息详情
+type MessageDetailListResp struct {
+	Paging *paging.PagingItem
+	List   interface{}
+}

+ 75 - 37
models/data_manage/edb_classify.go

@@ -9,19 +9,20 @@ import (
 )
 
 type EdbClassify struct {
-	ClassifyId      int       `orm:"column(classify_id);pk"`
-	ClassifyType    uint8     `description:"分类类型,0:普通指标分类,1:预测指标分类"`
-	ClassifyName    string    `description:"分类名称"`
-	ParentId        int       `description:"父级id"`
-	RootId          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"`
+	ClassifyId       int       `orm:"column(classify_id);pk"`
+	ClassifyType     uint8     `description:"分类类型,0:普通指标分类,1:预测指标分类"`
+	ClassifyName     string    `description:"分类名称"`
+	ParentId         int       `description:"父级id"`
+	RootId           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"`
+	IsJoinPermission int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
 }
 
 func AddEdbClassify(item *EdbClassify) (lastId int64, err error) {
@@ -179,33 +180,37 @@ func GetAllEdbClassifyByType(classifyType int) (items []*EdbClassifyItems, err e
 }
 
 type EdbClassifyItems struct {
-	ClassifyId      int `description:"分类id"`
-	EdbInfoId       int `description:"指标id"`
-	ClassifyName    string
-	ClassifyNameEn  string
-	ParentId        int
-	RootId          int    `description:"顶级id"`
-	Level           int    `description:"层级"`
-	Sort            int    `description:"排序字段,越小越靠前,默认值:10"`
-	UniqueCode      string `description:"唯一编码"`
-	Source          int    `description:"来源id"`
-	SourceName      string `description:"来源名称"`
-	SysUserId       int    `description:"创建人id"`
-	SysUserRealName string `description:"创建人姓名"`
-	StartDate       string
-	EdbCode         string
-	EdbType         int `description:"指标类型:1:基础指标,2:计算指标"`
-	Children        []*EdbClassifyItems
-	Button          EdbClassifyItemsButton `description:"操作权限"`
+	ClassifyId       int `description:"分类id"`
+	EdbInfoId        int `description:"指标id"`
+	ClassifyName     string
+	ClassifyNameEn   string
+	ParentId         int
+	RootId           int    `description:"顶级id"`
+	Level            int    `description:"层级"`
+	Sort             int    `description:"排序字段,越小越靠前,默认值:10"`
+	UniqueCode       string `description:"唯一编码"`
+	Source           int    `description:"来源id"`
+	SourceName       string `description:"来源名称"`
+	SysUserId        int    `description:"创建人id"`
+	SysUserRealName  string `description:"创建人姓名"`
+	StartDate        string
+	EdbCode          string
+	EdbType          int `description:"指标类型:1:基础指标,2:计算指标"`
+	Children         []*EdbClassifyItems
+	Button           EdbClassifyItemsButton `description:"操作权限"`
+	IsJoinPermission int                    `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth    bool                   `description:"是否有数据权限"`
 }
 
 type EdbClassifyIdItems struct {
-	ClassifyId   int `description:"分类id"`
-	ClassifyName string
-	UniqueCode   string `description:"唯一编码"`
-	ParentId     int    `description:"父级分类id"`
-	Level        int    `description:"层级"`
-	RootId       int    `description:"顶级分类id"`
+	ClassifyId       int `description:"分类id"`
+	ClassifyName     string
+	UniqueCode       string `description:"唯一编码"`
+	ParentId         int    `description:"父级分类id"`
+	Level            int    `description:"层级"`
+	RootId           int    `description:"顶级分类id"`
+	IsJoinPermission int    `description:"是否加入权限管控,0:不加入;1:加入;默认:0" json:"-"`
+	HaveOperaAuth    bool   `description:"是否有该数据权限,默认:false"`
 }
 
 type EdbClassifyItemList []*EdbClassifyItems
@@ -552,3 +557,36 @@ func GetEdbClassifyByParentIdAndName(parentId int, classifyName string, classify
 	err = o.Raw(sql, parentId, classifyName, classifyId).QueryRow(&item)
 	return
 }
+
+// GetEdbClassifyByIdList
+// @Description: 根据分类id列表获取分类列表
+// @author: Roc
+// @datetime 2024-03-29 10:30:21
+// @param classifyId int
+// @return item *EdbClassify
+// @return err error
+func GetEdbClassifyByIdList(classifyIdList []int) (item []*EdbClassify, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM edb_classify WHERE classify_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, classifyIdList).QueryRows(&item)
+	return
+}
+
+// GetEdbClassifyByClassifyTypeAndIsJoinPermission
+// @Description: 根据分类类型和是否涉密获取分类列表
+// @author: Roc
+// @datetime 2024-03-29 10:30:21
+// @param classifyType int
+// @param isJoinPermission int
+// @return items []*EdbClassify
+// @return err error
+func GetEdbClassifyByClassifyTypeAndIsJoinPermission(classifyType, isJoinPermission int) (items []*EdbClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM edb_classify WHERE   classify_type = ? AND is_join_permission = ? `
+	_, err = o.Raw(sql, classifyType, isJoinPermission).QueryRows(&items)
+	return
+}

+ 23 - 0
models/data_manage/edb_config.go

@@ -0,0 +1,23 @@
+package data_manage
+
+import "github.com/beego/beego/v2/client/orm"
+
+type EdbConfig struct {
+	ConfigValue string `description:"详情"`
+}
+
+// EdbConfigUpdate 修改配置
+func EdbConfigUpdate(newValue, configCode string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `UPDATE edb_config SET  config_value=?   WHERE config_code=  ?`
+	_, err = o.Raw(sql, newValue, configCode).Exec()
+	return
+}
+
+// GetConfigDetailByCode 根据配置编码获取配置的值
+func GetConfigDetailByCode(configCode string) (item *EdbConfig, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT config_value FROM edb_config WHERE config_code=? `
+	err = o.Raw(sql, configCode).QueryRow(&item)
+	return
+}

+ 95 - 32
models/data_manage/edb_info.go

@@ -58,12 +58,14 @@ type EdbInfo struct {
 	IndicatorCode    string  `description:"指标代码"`
 	StockCode        string  `description:"证券代码"`
 	Extra            string  `description:"指标额外配置"`
+	IsJoinPermission int     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
 }
 
 type EdbInfoFullClassify struct {
 	*EdbInfo
 	CorrelationStr string `description:"相关性系数字符串"`
 	ClassifyList   []*EdbClassifyIdItems
+	HaveOperaAuth  bool `description:"是否有数据权限,默认:false"`
 }
 
 func AddEdbInfo(item *EdbInfo) (lastId int64, err error) {
@@ -73,14 +75,15 @@ func AddEdbInfo(item *EdbInfo) (lastId int64, err error) {
 }
 
 type BaseEdbNameItem struct {
-	EdbInfoId   int    `description:"指标id"`
-	EdbInfoType int    `description:"指标类型,0:普通指标,1:预测指标"`
-	SourceName  string `description:"来源名称"`
-	Source      int    `description:"来源id"`
-	EdbCode     string `description:"指标编码"`
-	EdbName     string `description:"指标名称"`
-	Frequency   string `description:"频率"`
-	Unit        string `description:"单位"`
+	EdbInfoId     int    `description:"指标id"`
+	EdbInfoType   int    `description:"指标类型,0:普通指标,1:预测指标"`
+	SourceName    string `description:"来源名称"`
+	Source        int    `description:"来源id"`
+	EdbCode       string `description:"指标编码"`
+	EdbName       string `description:"指标名称"`
+	Frequency     string `description:"频率"`
+	Unit          string `description:"单位"`
+	HaveOperaAuth bool   `description:"是否有数据权限,默认:false"`
 }
 
 type BaseEdbInfoResp struct {
@@ -352,6 +355,8 @@ type EdbInfoList struct {
 	IndicatorCode    string                  `description:"指标代码"`
 	StockCode        string                  `description:"证券代码"`
 	NoUpdate         int8                    `description:"是否停止更新,0:继续更新;1:停止更新"`
+	IsJoinPermission int                     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth    bool                    `description:"是否有数据权限,默认:false"`
 }
 
 type EdbDataInsertConfigItem struct {
@@ -1522,13 +1527,21 @@ func GetEdbInfoByConditionCount(condition string, pars []interface{}) (count int
 }
 
 // GetEdbInfoListByCondition 根据条件获取指标列表数据
-func GetEdbInfoListByCondition(condition string, pars []interface{}, startSize, pageSize int) (items []*EdbInfoList, err error) {
+func GetEdbInfoListByCondition(condition string, pars []interface{}, startSize, pageSize int, orderDesc string) (items []*EdbInfoList, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT * FROM edb_info WHERE 1=1 `
 	if condition != "" {
 		sql += condition
 	}
-	sql += ` ORDER BY edb_info_id ASC LIMIT ?,? `
+
+	if orderDesc == `` {
+		orderDesc = ` ASC `
+	}
+
+	sql += ` ORDER BY edb_info_id `
+	sql += orderDesc
+	sql += ` LIMIT ?,? `
+
 	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
 	return
 }
@@ -1558,6 +1571,41 @@ func GetEdbInfoListGroupByUserId(edbIdList []string) (items []*EdbInfo, err erro
 	return
 }
 
+// GetEdbInfoListByEdbInfoId
+// @Description: 根据指标id列表获取列表信息
+// @param edbIdList
+// @return items
+// @return err
+func GetEdbInfoListByEdbInfoId(edbIdList []string) (items []*EdbInfo, err error) {
+	num := len(edbIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM edb_info WHERE edb_info_id in (` + utils.GetOrmInReplace(num) + `) `
+
+	_, err = o.Raw(sql, edbIdList).QueryRows(&items)
+	return
+}
+
+// GetEdbInfoListByUserId
+// @Description: 根据指标id列表获取列表信息
+// @param userIdList []int
+// @param edbInfoType int
+// @return items
+// @return err
+func GetEdbInfoListByUserId(userIdList []int, edbInfoType int) (items []*EdbInfo, err error) {
+	num := len(userIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM edb_info WHERE edb_info_type = ? AND sys_user_id in (` + utils.GetOrmInReplace(num) + `) `
+
+	_, err = o.Raw(sql, edbInfoType, userIdList).QueryRows(&items)
+	return
+}
+
 // ModifyEdbInfoUserIdByCodeList 根据指标code列表修改创建人
 func ModifyEdbInfoUserIdByCodeList(edbIdList []string, userId int, userName string) (err error) {
 	num := len(edbIdList)
@@ -1570,6 +1618,26 @@ func ModifyEdbInfoUserIdByCodeList(edbIdList []string, userId int, userName stri
 	return
 }
 
+// ModifyEdbInfoUserIdByOldUserId
+// @Description:  根据旧用户id修改新用户id
+// @author: Roc
+// @datetime 2024-03-25 19:17:09
+// @param edbIdList []string
+// @param userId int
+// @param userName string
+// @return err error
+func ModifyEdbInfoUserIdByOldUserId(oldUserIdList []int, edbInfoType, userId int, userName string) (err error) {
+	num := len(oldUserIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `UPDATE edb_info SET sys_user_id=?,sys_user_real_name=? WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `) and edb_info_type = ?`
+	_, err = o.Raw(sql, userId, userName, oldUserIdList, edbInfoType).Exec()
+
+	return
+}
+
 // MoveEdbChartList 图表/指标信息
 type MoveEdbChartList struct {
 	DataId         string `description:"指标/图表唯一id"`
@@ -1586,22 +1654,16 @@ type MoveEdbChartListResp struct {
 	List   []MoveEdbChartList
 }
 
-// MoveEdbChartReq 转移指标/图表的请求
-type MoveEdbChartReq struct {
-	Source     int      `description:"来源id"`
-	DataIdList []string `description:"指标/图表唯一id列表"`
-	NewUserId  int      `description:"新的创建人id"`
-}
-
 type EdbChartClassifyResp struct {
 	List []*EdbChartClassify
 }
 
 type EdbChartClassify struct {
-	ClassifyId   int
-	ClassifyName string
-	ParentId     int
-	Child        []*EdbChartClassify
+	ClassifyId       int
+	ClassifyName     string
+	ParentId         int
+	IsJoinPermission int `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	Child            []*EdbChartClassify
 }
 
 // EdbInfoDataSeasonalResp 指标季节性数据返回
@@ -1620,7 +1682,7 @@ type SetEdbDataInsertConfigReq struct {
 // GetEdbInfoByClassifyId 用于分类展示
 func GetEdbInfoByClassifyId(classifyId, edbInfoType, adminId int) (items []*EdbClassifyItems, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT edb_info_id,classify_id,edb_name_source 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 FROM edb_info WHERE classify_id = ? AND edb_info_type = ?`
+	sql := ` SELECT edb_info_id,classify_id,edb_name_source 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 classify_id = ? AND edb_info_type = ?`
 
 	pars := []interface{}{classifyId, edbInfoType}
 	// 如果筛选了用户id
@@ -1663,16 +1725,17 @@ func GetEdbInfoAndClassifyListByEdbIdList(edbIdList []int) (items []*EdbAndClass
 
 // TraceEdbInfoResp 指标追溯数据返回
 type TraceEdbInfoResp struct {
-	EdbInfoId   int                `description:"指标id"`
-	EdbInfoType int                `description:"指标类型: 0-普通指标; 1-预测指标"`
-	EdbName     string             `description:"指标名称"`
-	EdbType     int                `description:"指标类型: 1-基础指标; 2-计算指标"`
-	RuleTitle   string             `description:"指标规则"`
-	UniqueCode  string             `description:"唯一编码"`
-	ClassifyId  int                `description:"分类ID"`
-	Child       []TraceEdbInfoResp `description:"下级来源"`
-	IsStop      int8               `description:"是否终止"`
-	EdbInfo     *EdbInfo           `description:"指标信息" json:"-"`
+	EdbInfoId     int                `description:"指标id"`
+	EdbInfoType   int                `description:"指标类型: 0-普通指标; 1-预测指标"`
+	EdbName       string             `description:"指标名称"`
+	EdbType       int                `description:"指标类型: 1-基础指标; 2-计算指标"`
+	RuleTitle     string             `description:"指标规则"`
+	UniqueCode    string             `description:"唯一编码"`
+	ClassifyId    int                `description:"分类ID"`
+	Child         []TraceEdbInfoResp `description:"下级来源"`
+	IsStop        int8               `description:"是否终止"`
+	EdbInfo       *EdbInfo           `description:"指标信息" json:"-"`
+	HaveOperaAuth bool               `description:"是否有数据权限,默认:false"`
 }
 
 // BeforeAndAfterDateDataResp 前后几期数据

+ 7 - 5
models/data_manage/edb_info_calculate.go

@@ -162,11 +162,12 @@ func DeleteCalculateData(edbInfoId int) (err error) {
 }
 
 type EdbInfoBase struct {
-	EdbInfoId  int    `description:"指标id"`
-	EdbName    string `description:"指标名称"`
-	Frequency  string `description:"频度"`
-	Unit       string `description:"单位"`
-	ClassifyId int    `description:"分类id"`
+	EdbInfoId     int    `description:"指标id"`
+	EdbName       string `description:"指标名称"`
+	Frequency     string `description:"频度"`
+	Unit          string `description:"单位"`
+	ClassifyId    int    `description:"分类id"`
+	HaveOperaAuth bool   `description:"是否有数据权限,默认:false"`
 }
 
 type CalculateEdbInfoItem struct {
@@ -607,4 +608,5 @@ type CalculateMultiEdbSearchItem struct {
 	SysUserRealName string
 	EndValue        float64 `description:"数据的最新值(预测日期的最新值)"`
 	EndDate         string  `description:"终止日期"`
+	HaveOperaAuth   bool    `description:"是否有数据权限,默认:false"`
 }

+ 21 - 0
models/data_manage/edb_terminal.go

@@ -127,3 +127,24 @@ func (item *EdbTerminal) Update(cols []string) (err error) {
 	_, err = o.Update(item, cols...)
 	return
 }
+
+// GetEdbTerminalByCode 根据终端编码获取终端信息
+func GetEdbTerminalByCode(terminalCode string) (item *EdbTerminal, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM edb_terminal WHERE terminal_code = ? `
+	err = o.Raw(sql, terminalCode).QueryRow(&item)
+	return
+}
+
+type TerminalCodeCountGroup struct {
+	TerminalCode string
+	Total        int
+}
+
+// GetEdbCountGroupByTerminal 获取终端code分组总数
+func GetEdbCountGroupByTerminal(source int) (list []TerminalCodeCountGroup, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `select terminal_code,count(1) total from edb_info where source = ? AND no_update=0 AND terminal_code != "" group by terminal_code; `
+	_, err = o.Raw(sql, source).QueryRows(&list)
+	return
+}

+ 56 - 0
models/data_manage/excel/excel_classify.go

@@ -1,6 +1,7 @@
 package excel
 
 import (
+	"eta/eta_api/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"time"
@@ -20,6 +21,7 @@ type ExcelClassify struct {
 	IsDelete          int       `description:"排序字段,越小越靠前,默认值:10"`
 	CreateTime        time.Time `description:"创建时间"`
 	ModifyTime        time.Time `description:"修改时间"`
+	IsJoinPermission  int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
 }
 
 // AddExcelClassify 添加excel分类
@@ -49,6 +51,39 @@ func GetExcelClassifyById(classifyId int) (item *ExcelClassify, err error) {
 	return
 }
 
+// GetExcelClassifyByIdList
+// @Description: 根据分类id列表获取所有分类信息
+// @author: Roc
+// @datetime 2024-04-07 16:24:04
+// @param classifyIdList []int
+// @return items []*ExcelClassify
+// @return err error
+func GetExcelClassifyByIdList(classifyIdList []int) (items []*ExcelClassify, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM excel_classify WHERE excel_classify_id in (` + utils.GetOrmInReplace(num) + `) AND is_delete=0 `
+	_, err = o.Raw(sql, classifyIdList).QueryRows(&items)
+	return
+}
+
+// GetExcelClassifyBySourceAndIsJoinPermission
+// @Description: 根据分类id列表获取所有分类信息
+// @author: Roc
+// @datetime 2024-04-07 16:24:04
+// @param classifyIdList []int
+// @return items []*ExcelClassify
+// @return err error
+func GetExcelClassifyBySourceAndIsJoinPermission(source, isJoinPermission int) (items []*ExcelClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM excel_classify WHERE source = ? AND is_join_permission = ? `
+	_, err = o.Raw(sql, source, isJoinPermission).QueryRows(&items)
+
+	return
+}
+
 func GetChildClassifyById(classifyId int) (items []*ExcelClassify, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := `SELECT * FROM excel_classify WHERE parent_id=? AND is_delete=0 `
@@ -95,6 +130,8 @@ type ExcelClassifyItems struct {
 	SysUserRealName   string `description:"创建人姓名"`
 	StartDate         string `description:"自定义开始日期"`
 	Children          []*ExcelClassifyItems
+	IsJoinPermission  int  `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth     bool `description:"是否有数据权限"`
 }
 
 func GetExcelClassifyByCondition(condition string, pars []interface{}) (item *ExcelClassify, err error) {
@@ -170,3 +207,22 @@ func GetExcelClassifyViewById(classifyId int) (item *ExcelClassifyView, err erro
 func ExcelClassifyItemBySort(p1, p2 *ExcelClassifyItems) bool {
 	return p1.Sort < p2.Sort
 }
+
+// GetClassifyByIdList
+// @Description: 根据分类ID列表获取分类列表
+// @author: Roc
+// @datetime 2024-04-02 19:40:30
+// @param classifyIdList []int
+// @return items []*ExcelClassify
+// @return err error
+func GetClassifyByIdList(classifyIdList []int) (items []*ExcelClassify, err error) {
+	num := len(classifyIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM excel_classify WHERE excel_classify_id in (` + utils.GetOrmInReplace(num) + `) AND is_delete=0 `
+	_, err = o.Raw(sql, classifyIdList).QueryRows(&items)
+
+	return
+}

+ 132 - 34
models/data_manage/excel/excel_info.go

@@ -1,6 +1,7 @@
 package excel
 
 import (
+	"eta/eta_api/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"time"
@@ -8,21 +9,22 @@ import (
 
 // ExcelInfo excel表格详情表
 type ExcelInfo struct {
-	ExcelInfoId     int       `orm:"column(excel_info_id);pk"`
-	Source          int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
-	ExcelType       int       `description:"表格类型,1:指标列,2:日期列,默认:1"`
-	ExcelName       string    `description:"表格名称"`
-	UniqueCode      string    `description:"表格唯一编码"`
-	ExcelClassifyId int       `description:"表格分类id"`
-	SysUserId       int       `description:"操作人id"`
-	SysUserRealName string    `description:"操作人真实姓名"`
-	Content         string    `description:"表格内容"`
-	ExcelImage      string    `description:"表格图片"`
-	FileUrl         string    `description:"表格下载地址"`
-	Sort            int       `description:"排序字段,数字越小越排前面"`
-	IsDelete        int       `description:"是否删除,0:未删除,1:已删除"`
-	ModifyTime      time.Time `description:"最近修改日期"`
-	CreateTime      time.Time `description:"创建日期"`
+	ExcelInfoId      int       `orm:"column(excel_info_id);pk"`
+	Source           int       `description:"表格来源,1:excel插件的表格,2:自定义表格,3:混合表格,4:自定义分析,默认:1"`
+	ExcelType        int       `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName        string    `description:"表格名称"`
+	UniqueCode       string    `description:"表格唯一编码"`
+	ExcelClassifyId  int       `description:"表格分类id"`
+	SysUserId        int       `description:"操作人id"`
+	SysUserRealName  string    `description:"操作人真实姓名"`
+	Content          string    `description:"表格内容"`
+	ExcelImage       string    `description:"表格图片"`
+	FileUrl          string    `description:"表格下载地址"`
+	Sort             int       `description:"排序字段,数字越小越排前面"`
+	IsDelete         int       `description:"是否删除,0:未删除,1:已删除"`
+	ModifyTime       time.Time `description:"最近修改日期"`
+	CreateTime       time.Time `description:"创建日期"`
+	IsJoinPermission int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
 }
 
 // Update 更新 excel表格基础信息
@@ -33,19 +35,21 @@ func (excelInfo *ExcelInfo) Update(cols []string) (err error) {
 }
 
 type MyExcelInfoList struct {
-	ExcelInfoId     int       `orm:"column(excel_info_id);pk"`
-	Source          int       `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
-	ExcelType       int       `description:"表格类型,1:指标列,2:日期列,默认:1"`
-	ExcelName       string    `description:"表格名称"`
-	UniqueCode      string    `description:"表格唯一编码"`
-	ExcelClassifyId int       `description:"表格分类id"`
-	SysUserId       int       `description:"操作人id"`
-	SysUserRealName string    `description:"操作人真实姓名"`
-	ExcelImage      string    `description:"表格图片"`
-	FileUrl         string    `description:"表格下载地址"`
-	Sort            int       `description:"排序字段,数字越小越排前面"`
-	ModifyTime      time.Time `description:"最近修改日期"`
-	CreateTime      time.Time `description:"创建日期"`
+	ExcelInfoId      int       `orm:"column(excel_info_id);pk"`
+	Source           int       `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	ExcelType        int       `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName        string    `description:"表格名称"`
+	UniqueCode       string    `description:"表格唯一编码"`
+	ExcelClassifyId  int       `description:"表格分类id"`
+	SysUserId        int       `description:"操作人id"`
+	SysUserRealName  string    `description:"操作人真实姓名"`
+	ExcelImage       string    `description:"表格图片"`
+	FileUrl          string    `description:"表格下载地址"`
+	Sort             int       `description:"排序字段,数字越小越排前面"`
+	ModifyTime       time.Time `description:"最近修改日期"`
+	CreateTime       time.Time `description:"创建日期"`
+	IsJoinPermission int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth    bool      `description:"是否有数据权限"`
 }
 
 // AddExcelInfo 新增表格
@@ -122,7 +126,7 @@ func EditExcelInfo(excelInfo *ExcelInfo, updateExcelInfoParams []string, excelEd
 func GetExcelInfoAll() (items []*ExcelClassifyItems, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT excel_info_id,excel_classify_id,excel_name AS excel_classify_name,
-             unique_code,sys_user_id,sys_user_real_name,start_date
+             unique_code,sys_user_id,sys_user_real_name,is_join_permission
             FROM excel_info where is_delete=0 ORDER BY sort asc,create_time ASC `
 	_, err = o.Raw(sql).QueryRows(&items)
 	return
@@ -132,7 +136,7 @@ func GetExcelInfoAll() (items []*ExcelClassifyItems, err error) {
 func GetNoContentExcelInfoAll(source, userId int) (items []*ExcelClassifyItems, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT excel_info_id,excel_classify_id,excel_name AS excel_classify_name,
-             unique_code,sys_user_id,sys_user_real_name,sort
+             unique_code,sys_user_id,sys_user_real_name,sort,is_join_permission
             FROM excel_info where is_delete=0 AND source = ?  `
 
 	pars := []interface{}{source}
@@ -187,6 +191,19 @@ func GetExcelInfoCountByCondition(condition string, pars []interface{}) (count i
 	return
 }
 
+func GetNoContentExcelInfoListByCondition(condition string, pars []interface{}, startSize, pageSize int) (items []*ExcelClassifyItems, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT excel_info_id,excel_classify_id,excel_name AS excel_classify_name,
+             unique_code,sys_user_id,sys_user_real_name,sort,is_join_permission FROM excel_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+
+	sql += ` AND is_delete=0 ORDER BY excel_info_id DESC LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
 func GetExcelInfoByCondition(condition string, pars []interface{}) (item *ExcelInfo, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT * FROM excel_info WHERE 1=1 AND is_delete=0 `
@@ -308,7 +325,7 @@ func GetExcelInfoByClassifyIdAndName(classifyId int, excelName string) (item *Ex
 // GetNoContentExcelListByCondition 获取没有content的excel表格列表数据
 func GetNoContentExcelListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*MyExcelInfoList, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time,is_join_permission
 FROM excel_info WHERE 1=1 AND is_delete=0 `
 	if condition != "" {
 		sql += condition
@@ -332,7 +349,7 @@ func GetExcelListCountByCondition(condition string, pars []interface{}) (count i
 // GetExcelViewInfoByExcelInfoId 根据excelInfoId 获取ETA表格详情
 func GetExcelViewInfoByExcelInfoId(excelInfoId int) (item *MyExcelInfoList, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time FROM excel_info WHERE excel_info_id = ? AND is_delete=0 `
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time,is_join_permission FROM excel_info WHERE excel_info_id = ? AND is_delete=0 `
 	err = o.Raw(sql, excelInfoId).QueryRow(&item)
 	return
 }
@@ -357,7 +374,7 @@ func UpdateExcelInfoClassifyId(classifyId, excelInfoId int) (err error) {
 // GetNoContentExcelInfoByName 根据名称 获取eta表格详情
 func GetNoContentExcelInfoByName(excelName string, source int) (item *MyExcelInfoList, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time 
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time,is_join_permission 
  FROM excel_info WHERE excel_name = ? AND source = ? AND is_delete=0 `
 	err = o.Raw(sql, excelName, source).QueryRow(&item)
 
@@ -367,12 +384,21 @@ func GetNoContentExcelInfoByName(excelName string, source int) (item *MyExcelInf
 // GetNoContentExcelInfoByUniqueCode 根据unique_code来获取excel表格详情
 func GetNoContentExcelInfoByUniqueCode(uniqueCode string) (item *MyExcelInfoList, err error) {
 	o := orm.NewOrmUsingDB("data")
-	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time 
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time,is_join_permission 
  FROM excel_info WHERE unique_code=? AND is_delete=0 `
 	err = o.Raw(sql, uniqueCode).QueryRow(&item)
 	return
 }
 
+// GetNoContentExcelInfoByExcelId 根据表格id来获取excel表格详情
+func GetNoContentExcelInfoByExcelId(excelInfoId int) (item *MyExcelInfoList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT excel_info_id,source,excel_type,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time,is_join_permission 
+ FROM excel_info WHERE excel_info_id=? AND is_delete=0 `
+	err = o.Raw(sql, excelInfoId).QueryRow(&item)
+	return
+}
+
 // AddExcelInfoAndSheet 新增excel
 func AddExcelInfoAndSheet(excelInfo *ExcelInfo, sheetParamsList []AddExcelSheetParams) (err error) {
 	o, err := orm.NewOrmUsingDB("data").Begin()
@@ -525,3 +551,75 @@ func GetExcelMaxSortByClassifyId(classifyId int, source int) (sort int, err erro
 	err = o.Raw(sql, classifyId, source).QueryRow(&sort)
 	return
 }
+
+// GetNoContentExcelListByExcelInfoIdList
+// @Description: 根据ETA表格ID列表获取列表信息
+// @param excelInfoIdList []string
+// @return items
+// @return err
+func GetNoContentExcelListByExcelInfoIdList(excelInfoIdList []string) (items []*MyExcelInfoList, err error) {
+	num := len(excelInfoIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE excel_info_id in (` + utils.GetOrmInReplace(num) + `) order by excel_info_id DESC `
+	_, err = o.Raw(sql, excelInfoIdList).QueryRows(&items)
+
+	return
+}
+
+// GetNoContentExcelListByUserId
+// @Description: 根据ETA表格ID列表获取列表信息
+// @param userIdList []int
+// @return items
+// @return err
+func GetNoContentExcelListByUserId(userIdList []int) (items []*MyExcelInfoList, err error) {
+	num := len(userIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE excel_info_id in (` + utils.GetOrmInReplace(num) + `) order by excel_info_id DESC `
+	_, err = o.Raw(sql, userIdList).QueryRows(&items)
+
+	return
+}
+
+// ModifyExcelInfoUserIdByCodeList
+// @Description: 根据编码列表修改表格信息
+// @author: Roc
+// @datetime 2024-03-26 14:16:30
+// @param excelIdList []string
+// @param userId int
+// @param userName string
+// @return err error
+func ModifyExcelInfoUserIdByCodeList(excelIdList []string, userId int, userName string) (err error) {
+	num := len(excelIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `UPDATE excel_info SET sys_user_id=?,sys_user_real_name=? WHERE excel_info_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userId, userName, excelIdList).Exec()
+	return
+}
+
+// ModifyExcelInfoUserIdByOldUserId
+// @Description:  根据旧的用户id修改创建人
+// @author: Roc
+// @datetime 2024-03-25 19:14:59
+// @param oldUserId int
+// @param userId int
+// @param userName string
+// @return err error
+func ModifyExcelInfoUserIdByOldUserId(oldUserIdList []int, userId int, userName string) (err error) {
+	num := len(oldUserIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `UPDATE excel_info SET sys_user_id=?,sys_user_real_name=? WHERE is_delete=0 AND sys_user_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userId, userName, oldUserIdList).Exec()
+	return
+}

+ 10 - 7
models/data_manage/excel/request/excel_info.go

@@ -97,13 +97,16 @@ type TableDataReq struct {
 
 // EdbInfoData 自定义表格的数据
 type EdbInfoData struct {
-	EdbInfoId    int             `description:"指标ID"`
-	Tag          string          `description:"标签"`
-	EdbName      string          `description:"指标名称"`
-	EdbAliasName string          `description:"指标别名"`
-	Frequency    string          `description:"频度"`
-	Unit         string          `description:"单位"`
-	Data         []ManualDataReq `description:"单元格数据列表"`
+	EdbInfoId        int             `description:"指标ID"`
+	Tag              string          `description:"标签"`
+	EdbName          string          `description:"指标名称"`
+	EdbAliasName     string          `description:"指标别名"`
+	Frequency        string          `description:"频度"`
+	Unit             string          `description:"单位"`
+	ClassifyId       int             `description:"所属分类" json:"-"`
+	IsJoinPermission int             `description:"是否加入权限管控,0:不加入;1:加入;默认:0" json:"-"`
+	HaveOperaAuth    bool            `description:"是否有数据权限,默认:false"`
+	Data             []ManualDataReq `description:"单元格数据列表"`
 }
 
 // ManualDataReq 自定义表格的单元格数据

+ 28 - 19
models/data_manage/excel/response/excel_info.go

@@ -26,6 +26,13 @@ type ExcelTableDetailResp struct {
 	ExcelImage string `description:"表格截图"`
 	ExcelName  string `description:"表格名称"`
 	TableInfo  excel.TableData
+	Config     ExcelTableDetailConfigResp
+}
+
+// ExcelTableDetailConfigResp
+// @Description: Excel表格的配置信息
+type ExcelTableDetailConfigResp struct {
+	FontSize int
 }
 
 // TableCellResp 单元格
@@ -49,25 +56,27 @@ type TableDetailResp struct {
 
 // ExcelInfoDetail excel表格详情(前端使用)
 type ExcelInfoDetail struct {
-	ExcelInfoId     int                   `orm:"column(excel_info_id);pk"`
-	Source          int                   `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
-	ExcelType       int                   `description:"表格类型,1:指标列,2:日期列,默认:1"`
-	ExcelName       string                `description:"表格名称"`
-	UniqueCode      string                `description:"表格唯一编码"`
-	ExcelClassifyId int                   `description:"表格分类id"`
-	SysUserId       int                   `description:"操作人id"`
-	SysUserRealName string                `description:"操作人真实姓名"`
-	Content         string                `description:"表格内容"`
-	ExcelImage      string                `description:"表格图片"`
-	FileUrl         string                `description:"表格下载地址"`
-	Sort            int                   `description:"排序字段,数字越小越排前面"`
-	IsDelete        int                   `description:"是否删除,0:未删除,1:已删除"`
-	ModifyTime      time.Time             `description:"最近修改日期"`
-	CreateTime      time.Time             `description:"创建日期"`
-	TableData       interface{}           `description:"表格内容"`
-	Button          ExcelInfoDetailButton `description:"操作权限"`
-	CanEdit         bool                  `description:"是否可编辑"`
-	Editor          string                `description:"编辑人"`
+	ExcelInfoId      int                   `orm:"column(excel_info_id);pk"`
+	Source           int                   `description:"表格来源,1:excel插件的表格,2:自定义表格,默认:1"`
+	ExcelType        int                   `description:"表格类型,1:指标列,2:日期列,默认:1"`
+	ExcelName        string                `description:"表格名称"`
+	UniqueCode       string                `description:"表格唯一编码"`
+	ExcelClassifyId  int                   `description:"表格分类id"`
+	SysUserId        int                   `description:"操作人id"`
+	SysUserRealName  string                `description:"操作人真实姓名"`
+	Content          string                `description:"表格内容"`
+	ExcelImage       string                `description:"表格图片"`
+	FileUrl          string                `description:"表格下载地址"`
+	Sort             int                   `description:"排序字段,数字越小越排前面"`
+	IsDelete         int                   `description:"是否删除,0:未删除,1:已删除"`
+	ModifyTime       time.Time             `description:"最近修改日期"`
+	CreateTime       time.Time             `description:"创建日期"`
+	TableData        interface{}           `description:"表格内容"`
+	Button           ExcelInfoDetailButton `description:"操作权限"`
+	CanEdit          bool                  `description:"是否可编辑"`
+	Editor           string                `description:"编辑人"`
+	IsJoinPermission int                   `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth    bool                  `description:"是否有数据权限"`
 }
 
 // ExcelInfoDetailButton 操作按钮

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

@@ -30,4 +30,5 @@ type FindExcelInfo struct {
 	Button          ExcelInfoDetailButton `description:"操作权限"`
 	CanEdit         bool                  `description:"是否可编辑"`
 	Editor          string                `description:"编辑人"`
+	HaveOperaAuth   bool                  `description:"是否有数据权限,默认:false"`
 }

+ 3 - 1
models/data_manage/my_chart.go

@@ -327,6 +327,8 @@ type MyChartList struct {
 	IsEnChart           bool   `description:"是否展示英文标识"`
 	Disabled            int    `description:"是否禁用,0:启用,1:禁用,默认:0"`
 	Source              int    `description:"1:ETA图库;2:商品价格曲线"`
+	IsJoinPermission    int    `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth       bool   `description:"是否有数据权限,默认:false"`
 }
 
 type MyChartListResp struct {
@@ -337,7 +339,7 @@ type MyChartListResp struct {
 func GetMyChartListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*MyChartList, err error) {
 	o := orm.NewOrmUsingDB("data")
 
-	field := `a.my_chart_id,c.admin_id,c.sort,c.create_time as c_ctime,b.chart_info_id,b.chart_name,b.chart_name_en,b.chart_classify_id,b.sys_user_id,b.sys_user_real_name,b.unique_code,b.create_time,b.modify_time,b.date_type,b.start_date,b.end_date,b.is_set_name,b.edb_info_ids,b.chart_type,b.calendar,b.season_start_date,b.season_end_date,b.chart_image,b.edb_end_date,b.disabled,b.source `
+	field := `a.my_chart_id,c.admin_id,c.sort,c.create_time as c_ctime,b.chart_info_id,b.chart_name,b.chart_name_en,b.chart_classify_id,b.sys_user_id,b.sys_user_real_name,b.unique_code,b.create_time,b.modify_time,b.date_type,b.start_date,b.end_date,b.is_set_name,b.edb_info_ids,b.chart_type,b.calendar,b.season_start_date,b.season_end_date,b.chart_image,b.edb_end_date,b.disabled,b.source,b.is_join_permission `
 	//MyChartClassifyName string `description:"分类名称,多个用英文逗号分割"`
 	//MyChartClassifyId   string `description:"分类id,多个用英文逗号分割"`
 	sql := ` SELECT * FROM ( SELECT ` + field + ` FROM my_chart AS a

+ 63 - 2
models/data_manage/mysteel_chemical_index.go

@@ -281,15 +281,22 @@ func GetMysteelChemicalIndexCount(condition string, pars []interface{}) (count i
 }
 
 // GetMysteelChemicalIndexList 根据分类id获取钢联化工频度数据列表
-func GetMysteelChemicalIndexList(condition string, pars []interface{}, startSize, pageSize int) (items []*BaseFromMysteelChemicalIndex, err error) {
+func GetMysteelChemicalIndexList(condition string, pars []interface{}, startSize, pageSize int, orderDesc string) (items []*BaseFromMysteelChemicalIndex, err error) {
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT * FROM base_from_mysteel_chemical_index WHERE 1=1 `
 
 	if condition != "" {
 		sql += condition
 	}
-	sql += ` ORDER BY base_from_mysteel_chemical_index_id ASC LIMIT ?,? `
+
+	if orderDesc == `` {
+		orderDesc = ` ASC `
+	}
+	sql += ` ORDER BY base_from_mysteel_chemical_index_id `
+	sql += orderDesc
+	sql += ` LIMIT ?,? `
 	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+
 	return
 }
 
@@ -301,8 +308,42 @@ func GetMysteelChemicalIndexListGroupByUserId(edbIdList []string) (items []*Base
 	}
 	o := orm.NewOrmUsingDB("data")
 	sql := ` SELECT * FROM base_from_mysteel_chemical_index WHERE base_from_mysteel_chemical_index_id in (` + utils.GetOrmInReplace(num) + `) GROUP BY sys_user_id `
+	_, err = o.Raw(sql, edbIdList).QueryRows(&items)
 
+	return
+}
+
+// GetMysteelChemicalIndexListByIndexId
+// @Description: 根据指标id列表获取列表信息
+// @param edbIdList
+// @return items
+// @return err
+func GetMysteelChemicalIndexListByIndexId(edbIdList []string) (items []*BaseFromMysteelChemicalIndex, err error) {
+	num := len(edbIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_mysteel_chemical_index WHERE base_from_mysteel_chemical_index_id in (` + utils.GetOrmInReplace(num) + `) `
 	_, err = o.Raw(sql, edbIdList).QueryRows(&items)
+
+	return
+}
+
+// GetMysteelChemicalIndexListByUserId
+// @Description: 根据用户id列表获取列表信息
+// @param userIdList
+// @return items
+// @return err
+func GetMysteelChemicalIndexListByUserId(userIdList []int) (items []*BaseFromMysteelChemicalIndex, err error) {
+	num := len(userIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_mysteel_chemical_index WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userIdList).QueryRows(&items)
+
 	return
 }
 
@@ -318,6 +359,26 @@ func ModifyMysteelChemicalIndexUserIdByCodeList(edbIdList []string, userId int,
 	return
 }
 
+// ModifyMysteelChemicalIndexUserIdByOldUserId
+// @Description: 根据旧用户id修改新用户id
+// @author: Roc
+// @datetime 2024-03-25 17:59:08
+// @param oldUserId int
+// @param userId int
+// @param userName string
+// @return err error
+func ModifyMysteelChemicalIndexUserIdByOldUserId(oldUserIdList []int, userId int, userName string) (err error) {
+	num := len(oldUserIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := `UPDATE base_from_mysteel_chemical_index SET sys_user_id=?,sys_user_real_name=? WHERE sys_user_id in (` + utils.GetOrmInReplace(num) + `)  `
+	_, err = o.Raw(sql, userId, userName, oldUserIdList).Exec()
+
+	return
+}
+
 // GetMysteelChemicalIndexAdminList 获取所有指标创建人
 func GetMysteelChemicalIndexAdminList() (list []int, err error) {
 	o := orm.NewOrmUsingDB("data")

+ 7 - 2
models/data_manage/response/predit_edb_info.go

@@ -19,15 +19,20 @@ type PredictEdbInfoListResp struct {
 
 // PredictEdbInfoDataResp 预测指标数据返回
 type PredictEdbInfoDataResp struct {
-	EdbInfo      *data_manage.EdbInfo
+	EdbInfo      *EdbInfoFull
 	Button       data_manage.EdbClassifyItemsButton
 	DataList     interface{}
 	ClassifyList []*data_manage.EdbClassifyIdItems `description:"父级分类列表"`
 }
 
+type EdbInfoFull struct {
+	*data_manage.EdbInfo
+	HaveOperaAuth bool `description:"是否有数据权限,默认:false"`
+}
+
 // PredictEdbInfo 预测指标详情
 type PredictEdbInfo struct {
-	data_manage.EdbInfo
+	*EdbInfoFull
 	RuleType       int                                   `description:"预测规则,1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值"`
 	FixedValue     float64                               `description:"固定值"`
 	CalculateList  []*data_manage.EdbInfoCalculateDetail `description:"关联指标"`

+ 46 - 0
models/db.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_api/models/data_manage"
 	"eta/eta_api/models/data_manage/chart_theme"
 	"eta/eta_api/models/data_manage/cross_variety"
+	"eta/eta_api/models/data_manage/data_manage_permission"
 	"eta/eta_api/models/data_manage/edb_refresh"
 	"eta/eta_api/models/data_manage/excel"
 	future_good2 "eta/eta_api/models/data_manage/future_good"
@@ -17,6 +18,7 @@ import (
 	"eta/eta_api/models/sandbox"
 	"eta/eta_api/models/semantic_analysis"
 	"eta/eta_api/models/smart_report"
+	"eta/eta_api/models/speech_recognition"
 	"eta/eta_api/models/system"
 	"eta/eta_api/models/yb"
 	"eta/eta_api/utils"
@@ -186,6 +188,12 @@ func init() {
 	// 初始化指标刷新
 	initEdbRefresh()
 
+	// 语音识别
+	initSpeechRecognition()
+
+	// 初始化数据资产权限的一些表
+	initDataMangePerMission()
+
 	// 初始化部分数据表变量(直接init会有顺序问题=_=!)
 	data_manage.InitEdbSourceVar()
 }
@@ -549,3 +557,41 @@ func initEdbRefresh() {
 		new(edb_refresh.EdbRefreshMapping),       // 指标刷新时间配置关系表
 	)
 }
+
+// initSpeechRecognition 语音识别
+func initSpeechRecognition() {
+	orm.RegisterModel(
+		new(speech_recognition.SpeechRecognition),           // 语音识别表
+		new(speech_recognition.SpeechRecognitionApiLog),     // 语音识别-API请求日志
+		new(speech_recognition.SpeechRecognitionContent),    // 语音识别-转换内容表
+		new(speech_recognition.SpeechRecognitionMenu),       // 语音识别-目录表
+		new(speech_recognition.SpeechRecognitionTag),        // 语音识别-标签表
+		new(speech_recognition.SpeechRecognitionTagMenu),    // 语音识别-标签目录表
+		new(speech_recognition.SpeechRecognitionTagMapping), // 语音识别-标签关联表
+	)
+}
+
+// initDataMangePerMission
+// @Description: 初始化数据资产权限的一些表
+// @author: Roc
+// @datetime 2024-03-27 14:03:11
+func initDataMangePerMission() {
+	orm.RegisterModel(
+		new(data_manage_permission.EdbInfoPermission),                       // 指标权限表
+		new(data_manage_permission.EdbClassifyPermission),                   // 指标分类权限表
+		new(data_manage_permission.ChartInfoPermission),                     // 图表权限表
+		new(data_manage_permission.ChartClassifyPermission),                 // 图表分类权限表
+		new(data_manage_permission.ExcelInfoPermission),                     // ETA表格权限表
+		new(data_manage_permission.ExcelClassifyPermission),                 // ETA表格分类权限表
+		new(data_manage_permission.DataPermissionMessage),                   // 数据权限变更消息表
+		new(data_manage_permission.DataPermissionMoveRecord),                // 数据资产转移记录表
+		new(data_manage_permission.EdbInfoPermissionNoAuthRecord),           // 指标资产数据未授权分类记录表
+		new(data_manage_permission.ChartInfoPermissionNoAuthRecord),         // 图表资产数据未授权分类记录表
+		new(data_manage_permission.ExcelInfoPermissionNoAuthRecord),         // ETA表格资产数据未授权分类记录表
+		new(data_manage_permission.EdbInfoClassifyPermissionNoAuthRecord),   // 指标资产分类数据未授权分类记录表
+		new(data_manage_permission.ChartInfoClassifyPermissionNoAuthRecord), // 图表资产分类数据未授权分类记录表
+		new(data_manage_permission.ExcelInfoClassifyPermissionNoAuthRecord), // ETA表格资产分类数据未授权分类记录表
+		new(data_manage_permission.DataPermissionClassifyNoAuthRecord),      // 资产分类数据权限未授权记录表
+		new(data_manage_permission.DataPermissionNoAuthRecord),              // 资产数据权限设置记录表
+	)
+}

+ 12 - 1
models/en_classify_permission.go

@@ -1,9 +1,9 @@
 package models
 
 import (
+	"eta/eta_api/utils"
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"eta/eta_api/utils"
 	"strings"
 	"time"
 )
@@ -128,6 +128,17 @@ func ClearAndCreateEnClassifyPermissions(classifyId int, permissions []*EnClassi
 	return
 }
 
+func CreateEnClassifyPermissions(permissions []*EnClassifyPermission) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	if len(permissions) > 0 {
+		if _, e := o.InsertMulti(len(permissions), permissions); e != nil {
+			err = fmt.Errorf("insert multi err: %s", e.Error())
+			return
+		}
+	}
+	return
+}
+
 type EnClassifyPermissionEditReq struct {
 	ClassifyId    int   `description:"分类ID"`
 	EnPermissions []int `description:"权限IDs"`

+ 75 - 7
models/en_permission.go

@@ -16,6 +16,7 @@ type EnPermission struct {
 	Sort             int       `description:"排序"`
 	CreateTime       time.Time `description:"创建时间"`
 	ModifyTime       time.Time `description:"修改时间"`
+	Enabled          int       `description:"是否可用,1可用,0禁用"`
 }
 
 var EnPermissionColumns = struct {
@@ -26,6 +27,7 @@ var EnPermissionColumns = struct {
 	Sort             string
 	CreateTime       string
 	ModifyTime       string
+	Enabled          string
 }{
 	EnPermissionId:   "en_permission_id",
 	EnPermissionName: "en_permission_name",
@@ -34,6 +36,7 @@ var EnPermissionColumns = struct {
 	Sort:             "sort",
 	CreateTime:       "create_time",
 	ModifyTime:       "modify_time",
+	Enabled:          "enabled",
 }
 
 func (m *EnPermission) TableName() string {
@@ -122,19 +125,26 @@ func (m *EnPermission) GetPageItemsByCondition(startSize, pageSize int, conditio
 }
 
 type EnPermissionAddReq struct {
-	EnPermissionName string `description:"品种权限名称"`
+	PermissionName   string `description:"品种权限名称"`
 	CnPermissionName string `description:"对应的中文权限名称"`
 	ParentId         int    `description:"父级ID"`
-	Sort             int    `description:"排序"`
+	Enabled          int    `description:"是否可用,1可用,0禁用"`
 }
 
 type EnPermissionEditReq struct {
-	EnPermissionId int `description:"英文品种权限ID"`
-	EnPermissionAddReq
+	PermissionId     int    `description:"英文品种权限ID"`
+	PermissionName   string `description:"品种权限名称"`
+	CnPermissionName string `description:"对应的中文权限名称"`
+	ParentId         int    `description:"父级ID"`
+}
+
+type EnPermissionEnabledReq struct {
+	PermissionId int `description:"英文品种权限ID"`
+	Enabled      int `description:"是否可用,1可用,0禁用"`
 }
 
 type EnPermissionRemoveReq struct {
-	EnPermissionId int `description:"英文品种权限ID"`
+	PermissionId int `description:"英文品种权限ID"`
 }
 
 type EnPermissionPageListResp struct {
@@ -143,13 +153,20 @@ type EnPermissionPageListResp struct {
 }
 
 type EnPermissionItem struct {
-	EnPermissionId   int    `description:"英文品种权限ID"`
-	EnPermissionName string `description:"品种权限名称"`
+	PermissionId     int    `description:"英文品种权限ID"`
+	PermissionName   string `description:"品种权限名称"`
 	CnPermissionName string `description:"对应的中文权限名称"`
 	ParentId         int    `description:"父级ID"`
 	Sort             int    `description:"排序"`
 	CreateTime       string `description:"创建时间"`
 	Child            []*EnPermissionItem
+	Enabled          int `description:"是否可用,1可用,0禁用"`
+}
+
+type EnPermissionMoveReq struct {
+	PermissionId     int `description:"品种id"`
+	PrevPermissionId int `description:"上一个兄弟节点品种id"`
+	NextPermissionId int `description:"下一个兄弟节点品种id"`
 }
 
 func GetEnPermissionUnionList(condition string, pars []interface{}) (items []*EnPermission, err error) {
@@ -203,3 +220,54 @@ func ClearEnPermissionsByPermissionId(permissionId int) (err error) {
 	}
 	return
 }
+
+// UpdateEnPermissionSortByParentId 根据父类id更新排序
+func UpdateEnPermissionSortByParentId(parentId, permissionId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` update en_permission set sort = ` + updateSort + ` WHERE parent_id=? AND sort > ? `
+	if permissionId > 0 {
+		sql += ` or ( en_permission_id > ` + fmt.Sprint(permissionId) + ` and sort = ` + fmt.Sprint(nowSort) + `)`
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// GetMaxSortByParentId 获取最大的排序值
+func (m *EnPermission) GetMaxSortByParentId(parentId int) (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := fmt.Sprintf(`SELECT max(%s) AS sort FROM %s WHERE %s = ? `, EnPermissionColumns.Sort, m.TableName(), EnPermissionColumns.ParentId)
+	err = o.Raw(sql, parentId).QueryRow(&maxSort)
+	return
+}
+
+// GetMaxSort 获取最大的排序值
+func (m *EnPermission) GetMaxSort() (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := fmt.Sprintf(`SELECT max(%s) AS sort FROM %s`, EnPermissionColumns.Sort, m.TableName())
+	err = o.Raw(sql).QueryRow(&maxSort)
+	return
+}
+
+// GetFirstEnPermissionByParentId 获取当前父级分类下,且排序数相同 的排序第一条的数据
+func (m *EnPermission) GetFirstEnPermissionByParentId(parentId int) (item *EnPermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? order by sort asc, en_permission_id asc limit 1`, m.TableName(), EnPermissionColumns.ParentId)
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+// SetEnabled 更新启动禁用
+func (m *EnPermission) SetEnabled(parentId, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := fmt.Sprintf(`UPDATE %s SET %s = ?  WHERE %s = ?`, m.TableName(), EnPermissionColumns.Enabled, EnPermissionColumns.ParentId)
+	_, err = o.Raw(sql, enabled, parentId).Exec()
+	return
+}
+
+// SetEnabledByPermissionId 更新启动禁用
+func (m *EnPermission) SetEnabledByPermissionId(permissionId, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := fmt.Sprintf(`UPDATE %s SET %s = ?  WHERE %s = ?`, m.TableName(), EnPermissionColumns.Enabled, EnPermissionColumns.EnPermissionId)
+	_, err = o.Raw(sql, enabled, permissionId).Exec()
+	return
+}

+ 58 - 0
models/english_classify.go

@@ -0,0 +1,58 @@
+package models
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+)
+
+// UpdateEnglishClassifySortByParentId 根据父类id更新排序
+func UpdateEnglishClassifySortByParentId(parentId, permissionId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` update english_classify set sort = ` + updateSort + ` WHERE parent_id=? AND sort > ? `
+	if permissionId > 0 {
+		sql += ` or ( id > ` + fmt.Sprint(permissionId) + ` and sort = ` + fmt.Sprint(nowSort) + `)`
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// GetMaxSortByParentId 获取最大的排序值
+func (classifyInfo *EnglishClassify) GetMaxSortByParentId(parentId int) (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT max(sort) AS sort FROM english_classify WHERE parent_id = ? `
+	err = o.Raw(sql, parentId).QueryRow(&maxSort)
+	return
+}
+
+// GetMaxSort 获取最大的排序值
+func (classifyInfo *EnglishClassify) GetMaxSort() (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT max(sort) AS sort FROM english_classify`
+	err = o.Raw(sql).QueryRow(&maxSort)
+	return
+}
+
+// GetFirstClassifyByParentId 获取当前父级分类下,且排序数相同 的排序第一条的数据
+func (classifyInfo *EnglishClassify) GetFirstClassifyByParentId(parentId int) (item *Classify, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM english_classify WHERE parent_id = ? order by sort asc, id asc limit 1`
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+type EnglishClassifyMoveReq struct {
+	ClassifyId     int `description:"分类ID"`
+	PrevClassifyId int `description:"上一个兄弟节点分类id"`
+	NextClassifyId int `description:"下一个兄弟节点分类id"`
+}
+
+type EnClassifyAddReq struct {
+	EnPermissions []int  `description:"权限IDs"`
+	ClassifyName  string `description:"分类名称"`
+	ParentId      int    `description:"父级分类id"`
+}
+
+type EnClassifyEditReq struct {
+	ClassifyId int `description:"分类ID"`
+	EnClassifyAddReq
+}

+ 55 - 37
models/english_report.go

@@ -422,63 +422,49 @@ type EnglishClassifyList struct {
 	IsShow        int       `description:"是否在小程序显示:1-显示 0-隐藏"`
 	//ClassifyType  int       `description:"分类类型:0英文报告,1英文线上路演"`
 	EnPermissions []int `description:"英文权限IDs"`
+	Enabled       int   `description:"是否可用,1可用,0禁用"`
 	Child         []*EnglishClassifyList
 }
 
 type EnglishClassifyListResp struct {
-	List   []*EnglishClassifyList
-	Paging *paging.PagingItem `description:"分页数据"`
+	List []*EnglishClassifyList
 }
 
 // GetEnglishClassifyRootId 获取一级分类列表
-func GetEnglishClassifyRootId(startSize, pageSize int, keyword string) (items []*EnglishClassifyList, err error) {
+func GetEnglishClassifyRootId(keyword string, enabled int) (items []*EnglishClassifyList, err error) {
 	sql := ``
 	o := orm.NewOrmUsingDB("rddp")
+	cond := ""
+	if enabled == 1 {
+		cond = " AND enabled=1 "
+	}
 	if keyword != "" {
 		sql = `SELECT * FROM (
 			                   SELECT * FROM english_classify
-                   WHERE parent_id=0 AND classify_name ?
+                   WHERE parent_id=0 ` + cond + ` AND classify_name LIKE ? 
                    UNION
                    SELECT * FROM english_classify
                    WHERE id IN(SELECT parent_id FROM english_classify
-                   WHERE parent_id>0 AND classify_name LIKE ?)
+                   WHERE parent_id>0 ` + cond + ` AND classify_name LIKE ? )
                    )AS t
-                   ORDER BY sort ASC,create_time ASC
-                   LIMIT ?,? `
-		_, err = o.Raw(sql, utils.GetLikeKeyword(keyword), utils.GetLikeKeyword(keyword), startSize, pageSize).QueryRows(&items)
+                   ORDER BY sort ASC,create_time ASC`
+		_, err = o.Raw(sql, utils.GetLikeKeyword(keyword), utils.GetLikeKeyword(keyword)).QueryRows(&items)
 	} else {
-		sql = `SELECT * FROM english_classify WHERE parent_id=0 ORDER BY sort ASC,create_time ASC LIMIT ?,? `
-		_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+		sql = `SELECT * FROM english_classify WHERE parent_id=0 ` + cond + ` ORDER BY sort ASC,create_time ASC `
+		_, err = o.Raw(sql).QueryRows(&items)
 	}
 	return
 }
 
-func GetEnglishClassifyListCount(keyword string) (count int, err error) {
-	sqlCount := ``
-	o := orm.NewOrmUsingDB("rddp")
-	if keyword != "" {
-		sqlCount = `SELECT  COUNT(1) AS count FROM (
-               SELECT * FROM english_classify
-               WHERE parent_id=0 AND classify_name LIKE ?
-               UNION
-               SELECT * FROM english_classify
-               WHERE id IN(SELECT parent_id FROM english_classify
-               WHERE parent_id>0 AND classify_name LIKE ?)
-               )AS t `
-		err = o.Raw(sqlCount, utils.GetLikeKeyword(keyword), utils.GetLikeKeyword(keyword)).QueryRow(&count)
-	} else {
-		sqlCount = `SELECT COUNT(1) AS count FROM english_classify WHERE parent_id=0`
-		err = o.Raw(sqlCount).QueryRow(&count)
-	}
-
-	return
-}
-
-func GetEnglishClassifyListByRootId(rootIds []int, keyword string) (items []*EnglishClassifyList, err error) {
+func GetEnglishClassifyListByRootId(rootIds []int, keyword string, enabled int) (items []*EnglishClassifyList, err error) {
 	sql := ``
 	pars := make([]interface{}, 0)
 
 	o := orm.NewOrmUsingDB("rddp")
+	cond := ""
+	if enabled == 1 {
+		cond = " AND enabled=1 "
+	}
 	if keyword != "" {
 		sql = `SELECT
 	a.*
@@ -486,12 +472,12 @@ FROM
 	english_classify a
 	LEFT JOIN english_classify b ON a.root_id = b.id
 	LEFT JOIN english_classify c ON a.parent_id = c.id
-	WHERE a.parent_id>0 and a.classify_name LIKE ? and a.root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `)`
+	WHERE a.parent_id>0  ` + cond + ` and a.classify_name LIKE ? and a.root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `)`
 		pars = append(pars, utils.GetLikeKeyword(keyword))
 		pars = append(pars, rootIds)
 		_, err = o.Raw(sql, pars).QueryRows(&items)
 	} else {
-		sql = `SELECT * FROM english_classify WHERE parent_id>0 and root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `) `
+		sql = `SELECT * FROM english_classify WHERE parent_id>0  ` + cond + ` and root_id IN (` + utils.GetOrmInReplace(len(rootIds)) + `) `
 		_, err = o.Raw(sql, rootIds).QueryRows(&items)
 	}
 	return
@@ -548,6 +534,7 @@ type EnglishClassify struct {
 	ShowType      int       `description:"展示类型:1-列表 2-专栏"`
 	IsShow        int       `description:"是否在小程序显示:1-显示 0-隐藏"`
 	//ClassifyType  int       `description:"分类类型:0英文报告,1英文线上路演"`
+	Enabled int `description:"是否可用,1可用,0禁用"`
 }
 
 func AddEnglishClassify(item *EnglishClassify) (lastId int64, err error) {
@@ -621,10 +608,10 @@ func GetEnglishClassifyCountsByName(name string, parentId int) (count int, err e
 }
 
 // GetEnglishFirstClassifyList 获取一级、二级分类列表
-func GetEnglishFirstClassifyList(startSize, pageSize int) (items []*EnglishClassifyList, err error) {
+func GetEnglishFirstClassifyList() (items []*EnglishClassifyList, err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := `SELECT * FROM english_classify WHERE parent_id=0  ORDER BY sort ASC,create_time ASC LIMIT ?,? `
-	_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+	sql := `SELECT * FROM english_classify WHERE parent_id=0  ORDER BY sort ASC,create_time`
+	_, err = o.Raw(sql).QueryRows(&items)
 	return
 }
 
@@ -895,3 +882,34 @@ func UpdateEnglishReportsStateBySecondIds(oldState, newState int, secondIds []in
 	_, err = o.Raw(sql, oldState, newState, secondIds).Exec()
 	return
 }
+
+type EnglishClassifySetEnabledReq struct {
+	ClassifyId int `description:"分类ID"`
+	Enabled    int `description:"是否可用,1可用,0禁用"`
+}
+
+func (classifyInfo *EnglishClassify) SetEnabled(id, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	sql := ` UPDATE english_classify SET enabled =?  WHERE id = ?`
+	_, err = to.Raw(sql, enabled, id).Exec()
+	if err != nil {
+		return
+	}
+	sql = ` UPDATE english_classify SET enabled =?  WHERE parent_id = ? or root_id = ?`
+	_, err = to.Raw(sql, enabled, id, id).Exec()
+	if err != nil {
+		return
+	}
+	return
+}

+ 13 - 6
models/permission.go

@@ -13,15 +13,22 @@ type ChartPermissionSearchKeyWordMapping struct {
 }
 
 func GetPermission(classifyNameSecond string) (items []*ChartPermissionSearchKeyWordMapping, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := `SELECT * FROM chart_permission_search_key_word_mapping AS a WHERE a.from='rddp' AND a.key_word=? `
 	_, err = o.Raw(sql, classifyNameSecond).QueryRows(&items)
 	return
 }
 
+func GetAllPermissionMapping() (items []*ChartPermissionSearchKeyWordMapping, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM chart_permission_search_key_word_mapping AS a WHERE a.from='rddp'`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
 // EditChartPermissionSearchKeyWordMappingMulti 修改报告报告权限(先删除原有的权限,再添加新的权限)
 func EditChartPermissionSearchKeyWordMappingMulti(keyword string, permissionIdList []int) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	to, err := o.Begin()
 	if err != nil {
 		return
@@ -59,14 +66,14 @@ func EditChartPermissionSearchKeyWordMappingMulti(keyword string, permissionIdLi
 func AddChartPermissionChapterMapping(chartPermissionId int, reportId int64) (err error) {
 	sql := `INSERT INTO chart_permission_chapter_mapping (chart_permission_id, report_chapter_type_id,research_type)
            VALUES(?,?,?)`
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	_, err = o.Raw(sql, chartPermissionId, reportId, "rddp").Exec()
 	return
 }
 
 func RemoveChartPermissionChapterMapping(reportId int64) (err error) {
 	sql := ` DELETE FROM chart_permission_chapter_mapping WHERE research_type=? AND report_chapter_type_id=? `
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	_, err = o.Raw(sql, "rddp", reportId).Exec()
 	return
 }
@@ -77,7 +84,7 @@ type ChartPermissionMappingIdName struct {
 }
 
 func GetChartPermissionNameFromMappingByKeyword(keyword string, source string) (list []*ChartPermissionMappingIdName, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := " SELECT b.chart_permission_id AS permission_id,b.permission_name FROM chart_permission_search_key_word_mapping AS a INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id WHERE a.`from` = ? AND a.key_word = ? "
 	_, err = o.Raw(sql, source, keyword).QueryRows(&list)
 
@@ -86,7 +93,7 @@ func GetChartPermissionNameFromMappingByKeyword(keyword string, source string) (
 
 // UpdateChartPermissionNameFromMappingByKeyword 根据关键词及来源更新新关键词
 func UpdateChartPermissionNameFromMappingByKeyword(newKeyword, keyword, source string) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := " UPDATE chart_permission_search_key_word_mapping SET key_word = ? WHERE key_word = ? AND `from` = ? "
 	_, err = o.Raw(sql, newKeyword, keyword, source).Exec()
 	return

+ 100 - 36
models/report_chapter_type.go

@@ -2,8 +2,8 @@ package models
 
 import (
 	"eta/eta_api/utils"
+	"fmt"
 	"github.com/beego/beego/v2/client/orm"
-	"github.com/rdlucklib/rdluck_tools/paging"
 	"time"
 )
 
@@ -32,25 +32,25 @@ type ReportChapterType struct {
 	YbBottomIcon           string    `description:"研报小程序详情底部icon"`
 }
 
-func (item *ReportChapterType) Create() (err error) {
-	o := orm.NewOrmUsingDB("weekly")
-	id, err := o.Insert(item)
+func (r *ReportChapterType) Create() (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	id, err := o.Insert(r)
 	if err != nil {
 		return
 	}
-	item.ReportChapterTypeId = int(id)
+	r.ReportChapterTypeId = int(id)
 	return
 }
 
-func (item *ReportChapterType) Update(cols []string) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
-	_, err = o.Update(item, cols...)
+func (r *ReportChapterType) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	_, err = o.Update(r, cols...)
 	return
 }
 
 // DeleteReportChapterType 删除章节类型及相关权限
 func DeleteReportChapterType(typeId int, reportType string) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	to, err := o.Begin()
 	if err != nil {
 		return
@@ -81,7 +81,7 @@ func DeleteReportChapterType(typeId int, reportType string) (err error) {
 
 // GetReportChapterTypeById 获取章节类型
 func GetReportChapterTypeById(reportChapterTypeId int) (item *ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE report_chapter_type_id = ? `
 	err = o.Raw(sql, reportChapterTypeId).QueryRow(&item)
 	return
@@ -89,7 +89,7 @@ func GetReportChapterTypeById(reportChapterTypeId int) (item *ReportChapterType,
 
 // GetReportChapterTypeList 获取章节类型列表
 func GetReportChapterTypeList() (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE enabled = 1 `
 	_, err = o.Raw(sql).QueryRows(&list)
 	return
@@ -97,7 +97,7 @@ func GetReportChapterTypeList() (list []*ReportChapterType, err error) {
 
 // GetReportChapterTypeListByResearchType 通过报告类型获取章节类型列表
 func GetReportChapterTypeListByResearchType(researchType string) (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE research_type = ? AND enabled = 1`
 	_, err = o.Raw(sql, researchType).QueryRows(&list)
 	return
@@ -105,7 +105,7 @@ func GetReportChapterTypeListByResearchType(researchType string) (list []*Report
 
 // GetAllReportChapterTypeListByResearchType 通过报告类型获取章节类型列表
 func GetAllReportChapterTypeListByResearchType(researchType string) (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE research_type = ?`
 	_, err = o.Raw(sql, researchType).QueryRows(&list)
 	return
@@ -113,7 +113,7 @@ func GetAllReportChapterTypeListByResearchType(researchType string) (list []*Rep
 
 // GetAllReportChapterTypeList 通过传入的条件获取所有的章节类型列表
 func GetAllReportChapterTypeList(condition string, pars []interface{}) (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE 1=1 `
 	sql += condition
 	_, err = o.Raw(sql, pars).QueryRows(&list)
@@ -122,7 +122,7 @@ func GetAllReportChapterTypeList(condition string, pars []interface{}) (list []*
 
 // GetEnableReportChapterTypeList 获取未暂停的章节类型列表
 func GetEnableReportChapterTypeList(researchType string) (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT
 				*
 			FROM
@@ -151,7 +151,7 @@ type DayWeekReportPauseTime struct {
 
 // GetDayWeekReportPauseTimeList 获取晨报周报暂停时间
 func GetDayWeekReportPauseTimeList() (list []*DayWeekReportPauseTime, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT research_type, MAX(a.pause_start_time) AS pause_start_time, MAX(a.pause_end_time) AS pause_end_time FROM report_chapter_type AS a WHERE a.is_set = 1 GROUP BY a.research_type`
 	_, err = o.Raw(sql).QueryRows(&list)
 	return
@@ -177,7 +177,7 @@ type SetDayWeekReportEnableUpdateRuleReq struct {
 
 // ResetDayWeekReportUpdateRule 重置章节类型的暂停时间
 func ResetDayWeekReportUpdateRule(researchType string) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` UPDATE report_chapter_type SET pause_start_time = null, pause_end_time = null, is_set = 0 WHERE research_type = ?`
 	_, err = o.Raw(sql, researchType).Exec()
 	return
@@ -185,7 +185,7 @@ func ResetDayWeekReportUpdateRule(researchType string) (err error) {
 
 // SetDayWeekReportUpdateRule 设置章节类型的暂停时间
 func SetDayWeekReportUpdateRule(researchType string, list []DayWeekReportUpdateRule) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	to, err := o.Begin()
 	if err != nil {
 		return
@@ -221,7 +221,7 @@ func SetDayWeekReportUpdateRule(researchType string, list []DayWeekReportUpdateR
 
 // SetDayWeekReportEnableUpdateRule 设置章节类型的禁用状态
 func SetDayWeekReportEnableUpdateRule(dayReportChapterTypeIdList, weekReportChapterTypeIdList []string) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	to, err := o.Begin()
 	if err != nil {
 		return
@@ -279,7 +279,7 @@ type StopUpdateReportChapterTypeResp struct {
 
 // GetStopUpdateReportChapterTypeListByResearchType 获取暂停更新章节类型列表
 func GetStopUpdateReportChapterTypeListByResearchType() (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE is_set = 1 AND pause_end_time >= ? AND enabled = 1 `
 	_, err = o.Raw(sql, time.Now().Format(utils.FormatDate)).QueryRows(&list)
 	return
@@ -287,7 +287,7 @@ func GetStopUpdateReportChapterTypeListByResearchType() (list []*ReportChapterTy
 
 // GetDisableUpdateReportChapterTypeListByResearchType 获取停止更新的章节类型列表
 func GetDisableUpdateReportChapterTypeListByResearchType() (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE enabled = 0`
 	_, err = o.Raw(sql).QueryRows(&list)
 	return
@@ -299,14 +299,13 @@ type UpdateReportChapterTypeResp struct {
 	Week []*ReportChapterType `description:"所有周报品种"`
 }
 
-type ReportChapterTypePageListResp struct {
-	List   []*ReportChapterTypeListItem
-	Paging *paging.PagingItem `description:"分页数据"`
+type ReportChapterTypeListResp struct {
+	List []*ReportChapterTypeListItem
 }
 
 // GetReportChapterTypeCount 获取章节类型总数
 func GetReportChapterTypeCount(condition string, pars []interface{}) (count int, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT COUNT(1) FROM report_chapter_type WHERE 1 = 1 `
 	sql += condition
 	err = o.Raw(sql, pars).QueryRow(&count)
@@ -314,13 +313,12 @@ func GetReportChapterTypeCount(condition string, pars []interface{}) (count int,
 }
 
 // GetReportChapterTypePageList 获取章节类型列表
-func GetReportChapterTypePageList(condition string, pars []interface{}, startSize, pageSize int) (list []*ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+func GetReportChapterTypePageList(condition string, pars []interface{}) (list []*ReportChapterType, err error) {
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE 1 = 1 `
 	sql += condition
 	sql += ` ORDER BY sort ASC, created_time DESC`
-	sql += ` LIMIT ?,?`
-	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&list)
+	_, err = o.Raw(sql, pars).QueryRows(&list)
 	return
 }
 
@@ -336,31 +334,33 @@ type ReportChapterTypeListItem struct {
 	WordsImage            string `description:"带字的icon"`
 	EditImgUrl            string `description:"管理后台编辑时选用的图"`
 	IsShow                int    `description:"显示隐藏: 1-显示; 0-隐藏"`
+	ChartPermissionIdList []int  `description:"权限id数组"`
+	Enabled               int    `description:"是否可用,1可用,0禁用"`
 }
 
 // ReportChapterTypeAddReq 新增章节类型请求体
 type ReportChapterTypeAddReq struct {
 	ReportChapterTypeName string `description:"报告章节类型名称"`
-	Sort                  int    `description:"排序字段"`
 	ResearchType          string `description:"研报类型"`
-	SelectedImage         string `description:"选中时的icon"`
+	ChartPermissionIdList []int  `description:"权限id数组"`
+	/*SelectedImage         string `description:"选中时的icon"`
 	UnselectedImage       string `description:"未选中时的icon"`
 	WordsImage            string `description:"带字的icon"`
 	EditImgUrl            string `description:"管理后台编辑时选用的图"`
-	IsShow                int    `description:"显示隐藏: 1-显示; 0-隐藏"`
+	IsShow                int    `description:"显示隐藏: 1-显示; 0-隐藏"`*/
 }
 
 // ReportChapterTypeEditReq 编辑章节类型请求体
 type ReportChapterTypeEditReq struct {
 	ReportChapterTypeId   int    `description:"报告章节类型id"`
 	ReportChapterTypeName string `description:"报告章节类型名称"`
-	Sort                  int    `description:"排序字段"`
 	ResearchType          string `description:"研报类型"`
-	SelectedImage         string `description:"选中时的icon"`
+	ChartPermissionIdList []int  `description:"权限id数组"`
+	/*SelectedImage         string `description:"选中时的icon"`
 	UnselectedImage       string `description:"未选中时的icon"`
 	WordsImage            string `description:"带字的icon"`
 	EditImgUrl            string `description:"管理后台编辑时选用的图"`
-	IsShow                int    `description:"显示隐藏: 1-显示; 0-隐藏"`
+	IsShow                int    `description:"显示隐藏: 1-显示; 0-隐藏"`*/
 }
 
 // ReportChapterTypeDelReq 删除章节类型请求体
@@ -374,12 +374,76 @@ type ReportChapterTypeAuthSettingReq struct {
 	ChartPermissionIdList []int `description:"权限id数组"`
 }
 
+type ReportChapterTypeMoveReq struct {
+	ReportChapterTypeId int `description:"报告章节类型id"`
+	//	ParentChartPermissionId int `description:"父级品种id"`
+	PrevReportChapterTypeId int `description:"上一个兄弟节点报告章节类型id"`
+	NextReportChapterTypeId int `description:"下一个兄弟节点报告章节类型id"`
+}
+
+type ReportChapterTypeEnabledReq struct {
+	ReportChapterTypeId int `description:"报告章节类型id"`
+	Enabled             int `description:"是否可用,1可用,0禁用"`
+}
+
 // GetReportChapterTypeByCondition 获取章节类型
 func GetReportChapterTypeByCondition(condition string, pars []interface{}) (item *ReportChapterType, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type WHERE 1 = 1 `
 	sql += condition
 	sql += ` LIMIT 1`
 	err = o.Raw(sql, pars).QueryRow(&item)
 	return
 }
+
+// GetMaxSort 获取最大的排序值
+func (r *ReportChapterType) GetMaxSort() (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT max(sort) AS sort FROM report_chapter_type`
+	err = o.Raw(sql).QueryRow(&maxSort)
+	return
+}
+
+// GetMaxSortByResearchType 获取最大的排序值
+func (r *ReportChapterType) GetMaxSortByResearchType(researchType string) (maxSort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT max(sort) AS sort FROM report_chapter_type WHERE research_type = ?`
+	err = o.Raw(sql, researchType).QueryRow(&maxSort)
+	return
+}
+
+// UpdateReportChapterTypeSortByResearchType 根据父类id更新排序
+func UpdateReportChapterTypeSortByResearchType(researchType string, reportChapterTypeId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` update report_chapter_type set sort = ` + updateSort + ` WHERE research_type=? AND sort > ?`
+	if reportChapterTypeId > 0 {
+		sql += ` or ( report_chapter_type_id > ` + fmt.Sprint(reportChapterTypeId) + ` and sort = ` + fmt.Sprint(nowSort) + `)`
+	}
+
+	_, err = o.Raw(sql, researchType, nowSort).Exec()
+	return
+}
+
+// GetFirstReportChapterTypeByParentId 获取当前父级分类下,且排序数相同 的排序第一条的数据
+func (r *ReportChapterType) GetFirstReportChapterTypeByResearchType(researchType string) (item *ReportChapterType, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter_type WHERE 1 = 1 AND research_type = ? ORDER BY sort ASC, report_chapter_type_id ASC LIMIT 1`
+	err = o.Raw(sql, researchType).QueryRow(&item)
+	return
+}
+
+// GetReportChapterTypeById 获取章节类型
+func (r *ReportChapterType) GetReportChapterTypeById(reportChapterTypeId int) (item *ReportChapterType, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter_type WHERE report_chapter_type_id = ?`
+	err = o.Raw(sql, reportChapterTypeId).QueryRow(&item)
+	return
+}
+
+// SetEnabled 更新启动禁用
+func (r *ReportChapterType) SetEnabled(id, enabled int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` update report_chapter_type set enabled = ? WHERE report_chapter_type_id = ?`
+	_, err = o.Raw(sql, enabled, id).Exec()
+	return
+}

+ 10 - 2
models/report_chapter_type_permission.go

@@ -18,7 +18,7 @@ type ReportChapterTypePermission struct {
 
 // GetChapterTypePermissionByTypeIdAndResearchType 根据章节类型ID及研报类型获取章节类型权限列表
 func GetChapterTypePermissionByTypeIdAndResearchType(typeId int, researchType string) (list []*ReportChapterTypePermission, err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT * FROM report_chapter_type_permission WHERE report_chapter_type_id = ? AND research_type = ? ORDER BY chart_permission_id ASC `
 	_, err = o.Raw(sql, typeId, researchType).QueryRows(&list)
 	return
@@ -26,7 +26,7 @@ func GetChapterTypePermissionByTypeIdAndResearchType(typeId int, researchType st
 
 // SetReportChapterTypePermission 设置报告章节类型权限
 func SetReportChapterTypePermission(chapterTypeId int, researchType string, newPermissions []*ReportChapterTypePermission, newWeekPermissions []*ChartPermissionChapterMapping) (err error) {
-	o := orm.NewOrmUsingDB("weekly")
+	o := orm.NewOrmUsingDB("rddp")
 	to, err := o.Begin()
 	if err != nil {
 		return
@@ -73,3 +73,11 @@ func SetReportChapterTypePermission(chapterTypeId int, researchType string, newP
 	}
 	return
 }
+
+// GetChapterTypePermissionByResearchType 根据章节类型ID及研报类型获取章节类型权限列表
+func GetChapterTypePermissionByResearchType(researchType string) (list []*ReportChapterTypePermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT * FROM report_chapter_type_permission WHERE research_type = ? ORDER BY chart_permission_id ASC `
+	_, err = o.Raw(sql, researchType).QueryRows(&list)
+	return
+}

+ 561 - 0
models/speech_recognition/speech_recognition.go

@@ -0,0 +1,561 @@
+package speech_recognition
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strings"
+	"time"
+)
+
+const (
+	SpeechRecognitionFileRemoveFlag = 1 // 文件删除标记
+
+	SpeechRecognitionStateWait    = 1
+	SpeechRecognitionStateSuccess = 2
+	SpeechRecognitionStateFail    = 3
+)
+
+// SpeechRecognition 语音识别主表
+type SpeechRecognition struct {
+	SpeechRecognitionId int       `orm:"column(speech_recognition_id);pk"`
+	UniqueCode          string    `description:"唯一编码"`
+	FileName            string    `description:"文件名称"`
+	ResourceUrl         string    `description:"文件路径"`
+	MenuId              int       `description:"目录ID"`
+	SysUserId           int       `description:"创建人ID"`
+	SysUserName         string    `description:"创建人姓名"`
+	State               int       `description:"状态:1-待转换;2-转换完成;3-转换失败"`
+	Abstract            string    `description:"摘要,取前几段内容"`
+	Sort                int       `description:"目录下的排序"`
+	FileState           int       `description:"文件(非语音识别)删除状态:0-正常;1-删除(该字段作为软删标识)"`
+	FileSecond          int       `description:"文件时长(秒)"`
+	FileSize            int       `description:"文件大小(byte)"`
+	ConvertRemark       string    `description:"转写备注-失败原因"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionCols = struct {
+	SpeechRecognitionId string
+	UniqueCode          string
+	FileName            string
+	ResourceUrl         string
+	MenuId              string
+	MenuPath            string
+	SysUserId           string
+	SysUserName         string
+	State               string
+	Abstract            string
+	Sort                string
+	FileState           string
+	FileSecond          string
+	FileSize            string
+	ConvertRemark       string
+	CreateTime          string
+	ModifyTime          string
+}{
+	SpeechRecognitionId: "speech_recognition_id",
+	UniqueCode:          "unique_code",
+	FileName:            "file_name",
+	ResourceUrl:         "resource_url",
+	MenuId:              "menu_id",
+	MenuPath:            "menu_path",
+	SysUserId:           "sys_user_id",
+	SysUserName:         "sys_user_name",
+	State:               "state",
+	Abstract:            "abstract",
+	Sort:                "sort",
+	FileState:           "file_state",
+	FileSecond:          "file_second",
+	FileSize:            "file_size",
+	ConvertRemark:       "convert_remark",
+	CreateTime:          "create_time",
+	ModifyTime:          "modify_time",
+}
+
+func (m *SpeechRecognition) TableName() string {
+	return "speech_recognition"
+}
+
+func (m *SpeechRecognition) PrimaryId() string {
+	return SpeechRecognitionCols.SpeechRecognitionId
+}
+
+func (m *SpeechRecognition) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionId = int(id)
+	return
+}
+
+func (m *SpeechRecognition) CreateMulti(items []*SpeechRecognition) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognition) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognition) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionId).Exec()
+	return
+}
+
+func (m *SpeechRecognition) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognition) GetItemById(id int) (item *SpeechRecognition, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognition) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognition, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognition) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognition) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognition, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognition) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognition, err error) {
+	o := orm.NewOrm()
+	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)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionItem 语音识别信息
+type SpeechRecognitionItem struct {
+	SpeechRecognitionId int
+	UniqueCode          string `description:"唯一编码"`
+	FileName            string `description:"文件名称"`
+	ResourceUrl         string `description:"文件路径"`
+	MenuId              int    `description:"目录ID"`
+	SysUserId           int    `description:"创建人ID"`
+	SysUserName         string `description:"创建人姓名"`
+	State               int    `description:"状态:1-待转换;2-转换完成;3-转换失败"`
+	Abstract            string `description:"摘要,取前几段内容"`
+	Sort                int    `description:"目录下的排序"`
+	ConvertRemark       string `description:"转写备注-失败原因"`
+	CreateTime          string `description:"创建时间"`
+	ModifyTime          string `description:"修改时间"`
+}
+
+func FormatSpeechRecognition2Item(origin *SpeechRecognition) (item *SpeechRecognitionItem) {
+	if origin == nil {
+		return
+	}
+	item = new(SpeechRecognitionItem)
+	item.SpeechRecognitionId = origin.SpeechRecognitionId
+	item.UniqueCode = origin.UniqueCode
+	item.FileName = origin.FileName
+	item.ResourceUrl = origin.ResourceUrl
+	if origin.FileState == SpeechRecognitionFileRemoveFlag {
+		item.ResourceUrl = ""
+	}
+	item.MenuId = origin.MenuId
+	item.SysUserId = origin.SysUserId
+	item.SysUserName = origin.SysUserName
+	item.State = origin.State
+	item.Abstract = origin.Abstract
+	item.Sort = origin.Sort
+	item.ConvertRemark = origin.ConvertRemark
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	return
+}
+
+// SpeechRecognitionSaveReq 保存请求体
+type SpeechRecognitionSaveReq struct {
+	SpeechRecognitionId int                               `description:"语音识别ID"`
+	FileName            string                            `description:"文件名称"`
+	TagIds              []int                             `description:"标签IDs"`
+	Contents            []SpeechRecognitionSaveContentReq `description:"保存内容"`
+}
+
+// SpeechRecognitionSaveContentReq 保存内容
+type SpeechRecognitionSaveContentReq struct {
+	SpeechRecognitionContentId int    `description:"语音识别内容ID"`
+	Content                    string `description:"段落内容"`
+}
+
+// SpeechRecognitionRenameReq 重命名
+type SpeechRecognitionRenameReq struct {
+	SpeechRecognitionId int    `description:"语音识别ID"`
+	FileName            string `description:"文件名称"`
+}
+
+// SpeechRecognitionRemoveReq 删除
+type SpeechRecognitionRemoveReq struct {
+	SpeechRecognitionId int `description:"语音识别ID"`
+}
+
+// SpeechRecognitionRemoveFileReq 删除文件
+type SpeechRecognitionRemoveFileReq struct {
+	SpeechRecognitionId int `description:"语音识别ID"`
+}
+
+// SpeechRecognitionSaveTagReq 保存标签
+type SpeechRecognitionSaveTagReq struct {
+	SpeechRecognitionId int   `description:"语音识别ID"`
+	TagIds              []int `description:"标签IDs"`
+}
+
+// SpeechRecognitionConvertReq 批量转写
+type SpeechRecognitionConvertReq struct {
+	MenuId int                             `description:"目录ID"`
+	Files  []SpeechRecognitionConvertFiles `description:"转写文件"`
+}
+
+// SpeechRecognitionConvertFiles 批量转写文件
+type SpeechRecognitionConvertFiles struct {
+	FileName    string `description:"文件名称"`
+	ResourceUrl string `description:"文件地址"`
+	FileSecond  int    `description:"文件时长(秒)"`
+	FileSize    int    `description:"文件大小(byte)"`
+}
+
+// UpdateSpeechAndApiLog 更新语音识别及API记录
+func UpdateSpeechAndApiLog(speechItem *SpeechRecognition, speechCols []string, apiLogItem *SpeechRecognitionApiLog, logCols []string) (err error) {
+	if speechItem == nil || apiLogItem == nil {
+		err = fmt.Errorf("speechItem nil or apiLogItem nil")
+		return
+	}
+	o := orm.NewOrm()
+	tx, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+		} else {
+			_ = tx.Commit()
+		}
+	}()
+
+	_, e := tx.Update(speechItem, speechCols...)
+	if e != nil {
+		err = fmt.Errorf("update speech err: %s", e.Error())
+		return
+	}
+	_, e = tx.Update(apiLogItem, logCols...)
+	if e != nil {
+		err = fmt.Errorf("update api log err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// CreateContentAndUpdateSpeechAndApiLog 新增语音识别内容并更新语音识别及API记录
+func CreateContentAndUpdateSpeechAndApiLog(contents []*SpeechRecognitionContent, speechItem *SpeechRecognition, speechCols []string, apiLogItem *SpeechRecognitionApiLog, logCols []string) (err error) {
+	if speechItem == nil || apiLogItem == nil {
+		err = fmt.Errorf("speechItem nil or apiLogItem nil")
+		return
+	}
+	o := orm.NewOrm()
+	tx, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+		} else {
+			_ = tx.Commit()
+		}
+	}()
+
+	_, e := tx.Update(speechItem, speechCols...)
+	if e != nil {
+		err = fmt.Errorf("update speech err: %s", e.Error())
+		return
+	}
+	_, e = tx.Update(apiLogItem, logCols...)
+	if e != nil {
+		err = fmt.Errorf("update api log err: %s", e.Error())
+		return
+	}
+	if len(contents) > 0 {
+		_, e = tx.InsertMulti(len(contents), contents)
+		if e != nil {
+			err = fmt.Errorf("insert multi contents err: %s", e.Error())
+			return
+		}
+	}
+	return
+}
+
+// SpeechRecognitionDetailItem 语音识别详情信息
+type SpeechRecognitionDetailItem struct {
+	SpeechRecognitionId int
+	UniqueCode          string                          `description:"唯一编码"`
+	FileName            string                          `description:"文件名称"`
+	FileExt             string                          `description:"文件后缀名"`
+	ResourceUrl         string                          `description:"文件地址"`
+	MenuId              int                             `description:"目录ID"`
+	MenuPath            []*SpeechRecognitionMenuItem    `description:"目录全路径, 多级并列为一个数组"`
+	SysUserId           int                             `description:"创建人ID"`
+	SysUserName         string                          `description:"创建人姓名"`
+	Abstract            string                          `description:"摘要,取前几段内容"`
+	Sort                int                             `description:"目录下的排序"`
+	FileSecond          string                          `description:"文件时长(HH:MM:SS/MM:SS)"`
+	FileSize            string                          `description:"文件大小(MB)"`
+	CreateTime          string                          `description:"创建时间"`
+	ModifyTime          string                          `description:"修改时间"`
+	Contents            []*SpeechRecognitionContentItem `description:"语音识别内容"`
+	Tags                []*SpeechRecognitionDetailTag   `description:"标签"`
+}
+
+func FormatSpeechRecognition2DetailItem(origin *SpeechRecognition, contents []*SpeechRecognitionContentItem, tags []*SpeechRecognitionDetailTag, menuPath []*SpeechRecognitionMenuItem) (item *SpeechRecognitionDetailItem) {
+	if origin == nil {
+		return
+	}
+	item = new(SpeechRecognitionDetailItem)
+	item.SpeechRecognitionId = origin.SpeechRecognitionId
+	item.UniqueCode = origin.UniqueCode
+	item.FileName = origin.FileName
+	item.ResourceUrl = origin.ResourceUrl
+	if item.ResourceUrl != "" {
+		pointArr := strings.Split(item.ResourceUrl, ".")
+		if len(pointArr) > 0 {
+			item.FileExt = pointArr[len(pointArr)-1]
+		}
+	}
+	item.ResourceUrl = origin.ResourceUrl
+	if origin.FileState == SpeechRecognitionFileRemoveFlag {
+		item.ResourceUrl = ""
+	}
+	item.MenuId = origin.MenuId
+	item.MenuPath = menuPath
+	item.SysUserId = origin.SysUserId
+	item.SysUserName = origin.SysUserName
+	item.Abstract = origin.Abstract
+	item.Sort = origin.Sort
+	item.FileSecond = utils.SecondsToHHMMSS(origin.FileSecond)
+	item.FileSize = fmt.Sprintf("%.2fM", utils.ByteToMB(origin.FileSize))
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	item.Contents = contents
+	item.Tags = tags
+	return
+}
+
+// SpeechRecognitionDetailTag 语音识别详情标签
+type SpeechRecognitionDetailTag struct {
+	TagId   int    `description:"标签ID"`
+	TagName string `description:"标签名称"`
+}
+
+// GetSpeechRecognitionTagBySpeechId 获取语音识别标签
+func GetSpeechRecognitionTagBySpeechId(speechId int) (items []*SpeechRecognitionDetailTag, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT a.speech_recognition_tag_id AS tag_id, a.tag_name FROM speech_recognition_tag AS a
+		JOIN speech_recognition_tag_mapping AS b ON a.speech_recognition_tag_id = b.tag_id
+		WHERE b.speech_recognition_id = ?`
+	_, err = o.Raw(sql, speechId).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionMappingTags 语音识别标签
+type SpeechRecognitionMappingTags struct {
+	SpeechRecognitionId int    `description:"语音识别ID"`
+	TagId               int    `description:"标签ID"`
+	TagName             string `description:"标签名称"`
+}
+
+// GetSpeechRecognitionTagsBySpeechIds 根据语音识别IDs获取标签
+func GetSpeechRecognitionTagsBySpeechIds(speechIds []int) (items []*SpeechRecognitionMappingTags, err error) {
+	if len(speechIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT a.speech_recognition_id, a.tag_id, b.tag_name FROM speech_recognition_tag_mapping AS a
+		JOIN speech_recognition_tag AS b ON a.tag_id = b.speech_recognition_tag_id
+		WHERE a.speech_recognition_id IN (%s)`, utils.GetOrmInReplace(len(speechIds)))
+	_, err = o.Raw(sql, speechIds).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionListReq 语音识别列表请求体
+type SpeechRecognitionListReq struct {
+	PageSize     int    `form:"PageSize"`
+	CurrentIndex int    `form:"CurrentIndex"`
+	FileName     string `form:"FileName" description:"文件名称"`
+	StartTime    string `form:"StartTime" description:"开始时间"`
+	EndTime      string `form:"EndTime" description:"结束时间"`
+	CreateUserId string `form:"CreateUserId" description:"创建人IDs"`
+	TagId        int    `form:"TagId" description:"标签ID"`
+	TagIds       string `form:"TagIds" description:"标签IDs, 英文逗号分隔"`
+	MenuId       int    `form:"MenuId" description:"目录ID"`
+	IsTagMenu    bool   `form:"IsTagMenu" description:"是否为标签目录"`
+}
+
+// SpeechRecognitionListResp 语音识别列表响应体
+type SpeechRecognitionListResp struct {
+	List   []*SpeechRecognitionDetailItem
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// SpeechRecognitionContentExportReq 导出内容
+type SpeechRecognitionContentExportReq struct {
+	SpeechRecognitionId int  `description:"语音识别ID"`
+	ExportType          int  `description:"导出类型:1-txt;2-doc;3-pdf"`
+	Timestamp           bool `description:"是否显示时间戳"`
+}
+
+// UpdateSortByMenuId 根据分类ID更新排序
+func (m *SpeechRecognition) UpdateSortByMenuId(menuId, nowSort int, prevSpeechId int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`UPDATE %s SET %s = %s WHERE %s = ? `, m.TableName(), SpeechRecognitionCols.Sort, updateSort, SpeechRecognitionCols.MenuId)
+	if prevSpeechId > 0 {
+		sql += fmt.Sprintf(` AND (%s > ? OR (%s > %d AND %s = %d))`, SpeechRecognitionCols.Sort, SpeechRecognitionCols.SpeechRecognitionId, prevSpeechId, SpeechRecognitionCols.Sort, nowSort)
+	} else {
+		sql += fmt.Sprintf(` AND %s > ?`, SpeechRecognitionCols.Sort)
+	}
+	_, err = o.Raw(sql, menuId, nowSort).Exec()
+	return
+}
+
+// GetMaxSortByMenuId 获取分类下最大Sort
+func (m *SpeechRecognition) GetMaxSortByMenuId(menuId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT MAX(sort) AS sort FROM %s WHERE %s = ?`, m.TableName(), SpeechRecognitionCols.MenuId)
+	err = o.Raw(sql, menuId).QueryRow(&sort)
+	return
+}
+
+// GetFirstByMenuId 获取目录下排序第一的数据
+func (m *SpeechRecognition) GetFirstByMenuId(menuId int) (item *SpeechRecognition, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? ORDER BY %s ASC, %s ASC LIMIT 1`, m.TableName(), SpeechRecognitionCols.MenuId, SpeechRecognitionCols.Sort, SpeechRecognitionCols.SpeechRecognitionId)
+	err = o.Raw(sql, menuId).QueryRow(&item)
+	return
+}
+
+// SpeechRecognitionConvertCheckNameReq 校验文件重名请求体
+type SpeechRecognitionConvertCheckNameReq struct {
+	FileName string `description:"文件名称"`
+}
+
+// SpeechSave 更新内容、摘要及标签
+func (m *SpeechRecognition) SpeechSave(speechItem *SpeechRecognition, speechCols []string, contents []SpeechRecognitionSaveContentReq, tagMappings []*SpeechRecognitionTagMapping) (err error) {
+	if speechItem == nil {
+		err = fmt.Errorf("speech nil")
+		return
+	}
+	o := orm.NewOrm()
+	tx, e := o.Begin()
+	if e != nil {
+		err = fmt.Errorf("transaction begin err: %s", e.Error())
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	// 转写文件
+	if len(speechCols) > 0 {
+		_, e = tx.Update(speechItem, speechCols...)
+		if e != nil {
+			err = fmt.Errorf("update speech err: %s", e.Error())
+			return
+		}
+	}
+
+	// 转写内容
+	if len(contents) > 0 {
+		sql := fmt.Sprintf(`UPDATE %s SET %s = ?, %s = 1, %s = NOW() WHERE %s = ?`, "speech_recognition_content", SpeechRecognitionContentCols.Content, SpeechRecognitionContentCols.IsUpdate, SpeechRecognitionContentCols.ModifyTime, SpeechRecognitionContentCols.SpeechRecognitionContentId)
+		p, e := tx.Raw(sql).Prepare()
+		if e != nil {
+			err = fmt.Errorf("update prepare err: %s", e.Error())
+			return
+		}
+		defer func() {
+			_ = p.Close()
+		}()
+		for _, v := range contents {
+			_, e = p.Exec(v.Content, v.SpeechRecognitionContentId)
+			if e != nil {
+				err = fmt.Errorf("update exec err: %s", e.Error())
+				return
+			}
+		}
+	}
+
+	// 标签
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ?`, "speech_recognition_tag_mapping", SpeechRecognitionTagMappingCols.SpeechRecognitionId)
+	_, e = tx.Raw(sql, speechItem.SpeechRecognitionId).Exec()
+	if e != nil {
+		err = fmt.Errorf("remove tag mappings err: %s", e.Error())
+		return
+	}
+	if len(tagMappings) > 0 {
+		_, e = tx.InsertMulti(len(tagMappings), tagMappings)
+		if e != nil {
+			err = fmt.Errorf("insert tag mappings err: %s", e.Error())
+			return
+		}
+	}
+	return
+}

+ 159 - 0
models/speech_recognition/speech_recognition_api_log.go

@@ -0,0 +1,159 @@
+package speech_recognition
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	ApiRequestCodeSuccess = 0 // API成功状态码
+)
+
+// ApiErrMsgMapping API请求结果状态码对应错误提示
+var ApiErrMsgMapping = map[int]string{
+	10000: "转码失败,请确认音频格式是否符合标准",
+	10001: "识别失败",
+	10002: "语音时长太短",
+	10003: "语音时长太长",
+	10004: "无效的语音文件",
+	10005: "其他失败",
+	10006: "音轨个数不匹配",
+	10007: "音频下载失败",
+}
+
+// SpeechRecognitionApiLog 语音识别-API请求日志
+type SpeechRecognitionApiLog struct {
+	Id                  int       `orm:"column(id);pk"`
+	SpeechRecognitionId int       `description:"报告类型:1-中文研报;2-英文研报;3-智能研报"`
+	RequestId           string    `description:"API请求的唯一标识TaskId"`
+	RequestCode         int       `description:"API请求结果状态码:-1-待请求;0-成功;其他-失败"`
+	RequestResult       string    `description:"API请求结果-JSON"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionApiLogCols = struct {
+	Id                  string
+	SpeechRecognitionId string
+	RequestId           string
+	RequestCode         string
+	RequestResult       string
+	CreateTime          string
+	ModifyTime          string
+}{
+	Id:                  "id",
+	SpeechRecognitionId: "speech_recognition_id",
+	RequestId:           "request_id",
+	RequestCode:         "request_code",
+	RequestResult:       "request_result",
+	CreateTime:          "create_time",
+	ModifyTime:          "modify_time",
+}
+
+func (m *SpeechRecognitionApiLog) TableName() string {
+	return "speech_recognition_api_log"
+}
+
+func (m *SpeechRecognitionApiLog) PrimaryId() string {
+	return SpeechRecognitionApiLogCols.Id
+}
+
+func (m *SpeechRecognitionApiLog) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.Id = int(id)
+	return
+}
+
+func (m *SpeechRecognitionApiLog) CreateMulti(items []*SpeechRecognitionApiLog) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionApiLog) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionApiLog) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.Id).Exec()
+	return
+}
+
+func (m *SpeechRecognitionApiLog) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionApiLog) GetItemById(id int) (item *SpeechRecognitionApiLog, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionApiLog) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionApiLog, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionApiLog) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionApiLog) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionApiLog, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionApiLog) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionApiLog, err error) {
+	o := orm.NewOrm()
+	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)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}

+ 211 - 0
models/speech_recognition/speech_recognition_content.go

@@ -0,0 +1,211 @@
+package speech_recognition
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// SpeechRecognitionContent 语音识别-内容表
+type SpeechRecognitionContent struct {
+	SpeechRecognitionContentId int       `orm:"column(speech_recognition_content_id);pk"`
+	SpeechRecognitionId        int       `description:"语音识别ID"`
+	Sort                       int       `description:"段落排序"`
+	Content                    string    `description:"段落内容"`
+	StartMs                    int       `description:"单句开始时间(毫秒)"`
+	EndMs                      int       `description:"单句结束时间(毫秒)"`
+	IsUpdate                   int       `description:"是否手动修改过:0-否;1-是"`
+	CreateTime                 time.Time `description:"创建时间"`
+	ModifyTime                 time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionContentCols = struct {
+	SpeechRecognitionContentId string
+	SpeechRecognitionId        string
+	Sort                       string
+	Content                    string
+	StartMs                    string
+	EndMs                      string
+	IsUpdate                   string
+	CreateTime                 string
+	ModifyTime                 string
+}{
+	SpeechRecognitionContentId: "speech_recognition_content_id",
+	SpeechRecognitionId:        "speech_recognition_id",
+	Sort:                       "sort",
+	Content:                    "content",
+	StartMs:                    "start_ms",
+	EndMs:                      "end_ms",
+	IsUpdate:                   "is_update",
+	CreateTime:                 "create_time",
+	ModifyTime:                 "modify_time",
+}
+
+func (m *SpeechRecognitionContent) TableName() string {
+	return "speech_recognition_content"
+}
+
+func (m *SpeechRecognitionContent) PrimaryId() string {
+	return SpeechRecognitionContentCols.SpeechRecognitionContentId
+}
+
+func (m *SpeechRecognitionContent) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionContentId = int(id)
+	return
+}
+
+func (m *SpeechRecognitionContent) CreateMulti(items []*SpeechRecognitionContent) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionContent) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionContent) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionContentId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionContent) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionContent) GetItemById(id int) (item *SpeechRecognitionContent, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionContent) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionContent, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionContent) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionContent) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionContent, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionContent) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionContent, err error) {
+	o := orm.NewOrm()
+	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)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+type SpeechRecognitionContentItem struct {
+	SpeechRecognitionContentId int
+	SpeechRecognitionId        int    `description:"语音识别ID"`
+	Sort                       int    `description:"段落排序"`
+	Content                    string `description:"段落内容"`
+	StartMs                    int    `description:"单句开始时间(毫秒)"`
+	EndMs                      int    `description:"单句结束时间(毫秒)"`
+	StartTime                  string `description:"开始时间, 格式HH:MM:SS"`
+	CreateTime                 string `description:"创建时间"`
+	ModifyTime                 string `description:"修改时间"`
+	HideTimestamp              bool   `description:"前端用的, 默认false就行"`
+	IsHover                    bool   `description:"前端用的, 默认false就行"`
+}
+
+func FormatSpeechRecognitionContent2Item(origin *SpeechRecognitionContent) (item *SpeechRecognitionContentItem) {
+	if origin == nil {
+		return
+	}
+	item = new(SpeechRecognitionContentItem)
+	item.SpeechRecognitionContentId = origin.SpeechRecognitionContentId
+	item.SpeechRecognitionId = origin.SpeechRecognitionId
+	item.Sort = origin.Sort
+	item.Content = origin.Content
+	item.StartMs = origin.StartMs
+	item.EndMs = origin.EndMs
+	item.StartTime = utils.MillisecondsToHHMMSS(origin.StartMs)
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	return
+}
+
+// BatchUpdateContents 批量更新语音识别内容
+func (m *SpeechRecognitionContent) BatchUpdateContents(contents []SpeechRecognitionSaveContentReq) (err error) {
+	if len(contents) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`UPDATE %s SET %s = ?, %s = 1, %s = NOW() WHERE %s = ?`, m.TableName(), SpeechRecognitionContentCols.Content, SpeechRecognitionContentCols.IsUpdate, SpeechRecognitionContentCols.ModifyTime, SpeechRecognitionContentCols.SpeechRecognitionContentId)
+	p, err := o.Raw(sql).Prepare()
+	if err != nil {
+		return
+	}
+	defer func() {
+		_ = p.Close()
+	}()
+	for _, v := range contents {
+		_, err = p.Exec(v.Content, v.SpeechRecognitionContentId)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+// ClearContentBySpeechId 清除转写文件内容
+func (m *SpeechRecognitionContent) ClearContentBySpeechId(speechId int) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ?`, m.TableName(), SpeechRecognitionContentCols.SpeechRecognitionId)
+	_, err = o.Raw(sql, speechId).Exec()
+	return
+}

+ 256 - 0
models/speech_recognition/speech_recognition_menu.go

@@ -0,0 +1,256 @@
+package speech_recognition
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	SpeechRecognitionMenuNodeTypeDefault = 0
+	SpeechRecognitionMenuNodeTypeSpeech  = 1
+)
+
+// SpeechRecognitionMenu 语音识别-目录表
+type SpeechRecognitionMenu struct {
+	SpeechRecognitionMenuId int       `orm:"column(speech_recognition_menu_id);pk"`
+	UniqueCode              string    `description:"唯一编码"`
+	MenuName                string    `description:"目录名称"`
+	ParentId                int       `description:"父级ID"`
+	Level                   int       `description:"目录层级"`
+	Sort                    int       `description:"排序"`
+	RootId                  int       `description:"顶级ID"`
+	CreateTime              time.Time `description:"创建时间"`
+	ModifyTime              time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionMenuCols = struct {
+	SpeechRecognitionMenuId string
+	UniqueCode              string
+	MenuName                string
+	ParentId                string
+	Level                   string
+	Sort                    string
+	RootId                  string
+	CreateTime              string
+	ModifyTime              string
+}{
+	SpeechRecognitionMenuId: "speech_recognition_menu_id",
+	UniqueCode:              "unique_code",
+	MenuName:                "menu_name",
+	ParentId:                "parent_id",
+	Level:                   "level",
+	Sort:                    "sort",
+	RootId:                  "root_id",
+	CreateTime:              "create_time",
+	ModifyTime:              "modify_time",
+}
+
+func (m *SpeechRecognitionMenu) TableName() string {
+	return "speech_recognition_menu"
+}
+
+func (m *SpeechRecognitionMenu) PrimaryId() string {
+	return SpeechRecognitionMenuCols.SpeechRecognitionMenuId
+}
+
+func (m *SpeechRecognitionMenu) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionMenuId = int(id)
+	return
+}
+
+func (m *SpeechRecognitionMenu) CreateMulti(items []*SpeechRecognitionMenu) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionMenu) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionMenu) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionMenuId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionMenu) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetItemById(id int) (item *SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionMenu) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	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)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionMenuItem 目录
+type SpeechRecognitionMenuItem struct {
+	UniqueCode string                       `description:"唯一编码"`
+	MenuId     int                          `description:"目录ID"`
+	MenuName   string                       `description:"目录名称"`
+	ParentId   int                          `description:"父级ID"`
+	Level      int                          `description:"目录层级"`
+	Sort       int                          `description:"排序"`
+	CreateTime string                       `description:"创建时间"`
+	Children   []*SpeechRecognitionMenuItem `description:"子目录"`
+}
+
+// SpeechRecognitionMenuNodeItem 语音识别目录节点
+type SpeechRecognitionMenuNodeItem struct {
+	UniqueCode            string                           `description:"唯一编码"`
+	NodeType              int                              `description:"节点类型:0-目录;1-语音识别"`
+	MenuId                int                              `description:"目录ID"`
+	MenuName              string                           `description:"目录名称"`
+	SpeechRecognitionId   int                              `description:"语音识别ID"`
+	SpeechRecognitionName string                           `description:"语音识别名称"`
+	ParentId              int                              `description:"父级ID"`
+	Level                 int                              `description:"目录层级"`
+	Sort                  int                              `description:"排序"`
+	CreateTime            string                           `description:"创建时间"`
+	Children              []*SpeechRecognitionMenuNodeItem `description:"子节点"`
+}
+
+// SpeechRecognitionMenuAddReq 新增语音识别目录
+type SpeechRecognitionMenuAddReq struct {
+	ParentId int    `description:"父级ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionMenuEditReq 编辑语音识别目录
+type SpeechRecognitionMenuEditReq struct {
+	MenuId   int    `description:"目录ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionMenuRemoveReq 删除语音识别目录
+type SpeechRecognitionMenuRemoveReq struct {
+	MenuId int `description:"目录ID"`
+}
+
+// SpeechRecognitionMenuRemoveCheckResp 删除语音识别目录-响应体
+type SpeechRecognitionMenuRemoveCheckResp struct {
+	CheckResult int    `description:"校验结果:0-可删除;1-关联内容;2-关联空目录"`
+	Tips        string `description:"提示信息"`
+}
+
+// SpeechRecognitionMenuMoveReq 移动目录请求体
+type SpeechRecognitionMenuMoveReq struct {
+	MenuId       int `description:"目录ID"`
+	ParentMenuId int `description:"父级目录ID"`
+	PrevMenuId   int `description:"上一个兄弟节点目录ID"`
+	NextMenuId   int `description:"下一个兄弟节点目录ID"`
+	SpeechId     int `description:"语音识别ID, 大于0则表示移动语音识别"`
+	PrevSpeechId int `description:"上一个语音识别ID"`
+	NextSpeechId int `description:"下一个语音识别ID"`
+}
+
+// UpdateSortByParentId 根据父级ID更新排序
+func (m *SpeechRecognitionMenu) UpdateSortByParentId(parentId, menuId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`UPDATE %s SET %s = %s WHERE %s = ? AND %s > ?`, m.TableName(), SpeechRecognitionMenuCols.Sort, updateSort, SpeechRecognitionMenuCols.ParentId, SpeechRecognitionMenuCols.Sort)
+	if menuId > 0 {
+		sql += fmt.Sprintf(` OR (%s > %d AND %s = %d)`, SpeechRecognitionMenuCols.SpeechRecognitionMenuId, menuId, SpeechRecognitionMenuCols.Sort, nowSort)
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// GetMaxSortByParentId 获取父级分类下最大Sort
+func (m *SpeechRecognitionMenu) GetMaxSortByParentId(parentId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT MAX(sort) AS sort FROM %s WHERE %s = ?`, m.TableName(), SpeechRecognitionMenuCols.ParentId)
+	err = o.Raw(sql, parentId).QueryRow(&sort)
+	return
+}
+
+// GetFirstByParentId 获取父级目录下排序第一的目录
+func (m *SpeechRecognitionMenu) GetFirstByParentId(parentId int) (item *SpeechRecognitionMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? ORDER BY %s ASC, %s ASC LIMIT 1`, m.TableName(), SpeechRecognitionMenuCols.ParentId, SpeechRecognitionMenuCols.Sort, SpeechRecognitionMenuCols.SpeechRecognitionMenuId)
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+// UpdateChildByParentMenuId 通过父级目录ID更新子目录
+func (m *SpeechRecognitionMenu) UpdateChildByParentMenuId(menuIds []int, rootId int, levelStep int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	var pars []interface{}
+	pars = append(pars, rootId, levelStep)
+	pars = append(pars, menuIds)
+	sql := fmt.Sprintf(`UPDATE %s SET %s = ?, %s = %s + ? WHERE %s IN (%s)`, m.TableName(), SpeechRecognitionMenuCols.RootId, SpeechRecognitionMenuCols.Level, SpeechRecognitionMenuCols.Level, SpeechRecognitionMenuCols.SpeechRecognitionMenuId, utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, pars).Exec()
+	return
+}

+ 225 - 0
models/speech_recognition/speech_recognition_tag.go

@@ -0,0 +1,225 @@
+package speech_recognition
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// SpeechRecognitionTag 语音识别-标签表
+type SpeechRecognitionTag struct {
+	SpeechRecognitionTagId int       `orm:"column(speech_recognition_tag_id);pk"`
+	UniqueCode             string    `description:"唯一编码"`
+	TagName                string    `description:"标签名称"`
+	MenuId                 int       `description:"目录ID"`
+	Sort                   int       `description:"排序"`
+	CreateTime             time.Time `description:"创建时间"`
+	ModifyTime             time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionTagCols = struct {
+	SpeechRecognitionTagId string
+	UniqueCode             string
+	TagName                string
+	MenuId                 string
+	MenuPath               string
+	Sort                   string
+	CreateTime             string
+	ModifyTime             string
+}{
+	SpeechRecognitionTagId: "speech_recognition_tag_id",
+	UniqueCode:             "unique_code",
+	TagName:                "tag_name",
+	MenuId:                 "menu_id",
+	MenuPath:               "menu_path",
+	Sort:                   "sort",
+	CreateTime:             "create_time",
+	ModifyTime:             "modify_time",
+}
+
+func (m *SpeechRecognitionTag) TableName() string {
+	return "speech_recognition_tag"
+}
+
+func (m *SpeechRecognitionTag) PrimaryId() string {
+	return SpeechRecognitionTagCols.SpeechRecognitionTagId
+}
+
+func (m *SpeechRecognitionTag) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionTagId = int(id)
+	return
+}
+
+func (m *SpeechRecognitionTag) CreateMulti(items []*SpeechRecognitionTag) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionTag) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionTag) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionTagId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTag) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTag) GetItemById(id int) (item *SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	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)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionTagItem 语音识别标签
+type SpeechRecognitionTagItem struct {
+	UniqueCode string `description:"唯一编码"`
+	TagId      int    `description:"标签ID"`
+	TagName    string `description:"标签名称"`
+	MenuId     int    `description:"目录ID"`
+	Sort       int    `description:"排序"`
+	CreateTime string `description:"创建时间"`
+}
+
+func FormatSpeechRecognitionTag2Item(origin *SpeechRecognitionTag) (item *SpeechRecognitionTagItem) {
+	if origin == nil {
+		return
+	}
+	item = new(SpeechRecognitionTagItem)
+	item.UniqueCode = origin.UniqueCode
+	item.TagId = origin.SpeechRecognitionTagId
+	item.TagName = origin.TagName
+	item.MenuId = origin.MenuId
+	item.Sort = origin.Sort
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	return
+}
+
+// SpeechRecognitionTagAddReq 新增标签
+type SpeechRecognitionTagAddReq struct {
+	MenuId  int    `description:"目录ID"`
+	TagName string `description:"标签名称"`
+}
+
+// SpeechRecognitionTagEditReq 编辑标签
+type SpeechRecognitionTagEditReq struct {
+	TagId   int    `description:"标签ID"`
+	TagName string `description:"标签名称"`
+}
+
+// SpeechRecognitionTagRemoveReq 删除标签
+type SpeechRecognitionTagRemoveReq struct {
+	TagId int `description:"标签ID"`
+}
+
+// UpdateSortByMenuId 根据分类ID更新排序
+func (m *SpeechRecognitionTag) UpdateSortByMenuId(menuId, nowSort int, prevTagId int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`UPDATE %s SET %s = %s WHERE %s = ? `, m.TableName(), SpeechRecognitionTagCols.Sort, updateSort, SpeechRecognitionTagCols.MenuId)
+	if prevTagId > 0 {
+		sql += fmt.Sprintf(` AND (%s > ? OR (%s > %d AND %s = %d))`, SpeechRecognitionTagCols.Sort, SpeechRecognitionTagCols.SpeechRecognitionTagId, prevTagId, SpeechRecognitionTagCols.Sort, nowSort)
+	} else {
+		sql += fmt.Sprintf(` AND %s > ?`, SpeechRecognitionTagCols.Sort)
+	}
+	_, err = o.Raw(sql, menuId, nowSort).Exec()
+	return
+}
+
+// GetMaxSortByMenuId 获取分类下最大Sort
+func (m *SpeechRecognitionTag) GetMaxSortByMenuId(menuId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT MAX(sort) AS sort FROM %s WHERE %s = ?`, m.TableName(), SpeechRecognitionTagCols.MenuId)
+	err = o.Raw(sql, menuId).QueryRow(&sort)
+	return
+}
+
+// GetFirstByMenuId 获取目录下排序第一的数据
+func (m *SpeechRecognitionTag) GetFirstByMenuId(menuId int) (item *SpeechRecognitionTag, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? ORDER BY %s ASC, %s ASC LIMIT 1`, m.TableName(), SpeechRecognitionTagCols.MenuId, SpeechRecognitionTagCols.Sort, SpeechRecognitionTagCols.SpeechRecognitionTagId)
+	err = o.Raw(sql, menuId).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTag) GetTagIdsByMenuIds(menuIds []int) (tagIds []int, err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE %s IN (%s) GROUP BY %s`, SpeechRecognitionTagCols.SpeechRecognitionTagId, m.TableName(), SpeechRecognitionTagCols.MenuId, utils.GetOrmInReplace(len(menuIds)), SpeechRecognitionTagCols.SpeechRecognitionTagId)
+	_, err = o.Raw(sql, menuIds).QueryRows(&tagIds)
+	return
+}

+ 148 - 0
models/speech_recognition/speech_recognition_tag_mapping.go

@@ -0,0 +1,148 @@
+package speech_recognition
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+)
+
+// SpeechRecognitionTagMapping 语音识别-标签关联表
+type SpeechRecognitionTagMapping struct {
+	Id                  int `orm:"column(id);pk"`
+	SpeechRecognitionId int `description:"语音识别ID"`
+	TagId               int `description:"标签ID"`
+}
+
+var SpeechRecognitionTagMappingCols = struct {
+	Id                  string
+	SpeechRecognitionId string
+	TagId               string
+}{
+	Id:                  "id",
+	SpeechRecognitionId: "speech_recognition_id",
+	TagId:               "tag_id",
+}
+
+func (m *SpeechRecognitionTagMapping) TableName() string {
+	return "speech_recognition_tag_mapping"
+}
+
+func (m *SpeechRecognitionTagMapping) PrimaryId() string {
+	return SpeechRecognitionTagMappingCols.Id
+}
+
+func (m *SpeechRecognitionTagMapping) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.Id = int(id)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) CreateMulti(items []*SpeechRecognitionTagMapping) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.Id).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetItemById(id int) (item *SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionTagMapping, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// ClearMappingBySpeechId 清除转写文件标签关联
+func (m *SpeechRecognitionTagMapping) ClearMappingBySpeechId(speechId int) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ?`, m.TableName(), SpeechRecognitionTagMappingCols.SpeechRecognitionId)
+	_, err = o.Raw(sql, speechId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMapping) GetSpeechIdsByTagIds(tagIds []int) (speechIds []int, err error) {
+	if len(tagIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE %s IN (%s) GROUP BY %s`, SpeechRecognitionTagMappingCols.SpeechRecognitionId, m.TableName(), SpeechRecognitionTagMappingCols.TagId, utils.GetOrmInReplace(len(tagIds)), SpeechRecognitionTagMappingCols.SpeechRecognitionId)
+	_, err = o.Raw(sql, tagIds).QueryRows(&speechIds)
+	return
+}

+ 250 - 0
models/speech_recognition/speech_recognition_tag_menu.go

@@ -0,0 +1,250 @@
+package speech_recognition
+
+import (
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+const (
+	SpeechRecognitionTagMenuNodeTypeDefault = 0
+	SpeechRecognitionTagMenuNodeTypeTag     = 1
+)
+
+// SpeechRecognitionTagMenu 标签目录表
+type SpeechRecognitionTagMenu struct {
+	SpeechRecognitionTagMenuId int       `orm:"column(speech_recognition_tag_menu_id);pk"`
+	UniqueCode                 string    `description:"唯一编码"`
+	MenuName                   string    `description:"目录名称"`
+	ParentId                   int       `description:"父级ID"`
+	Level                      int       `description:"目录层级"`
+	Sort                       int       `description:"排序"`
+	RootId                     int       `description:"顶级ID"`
+	CreateTime                 time.Time `description:"创建时间"`
+	ModifyTime                 time.Time `description:"修改时间"`
+}
+
+var SpeechRecognitionTagMenuCols = struct {
+	SpeechRecognitionTagMenuId string
+	UniqueCode                 string
+	MenuName                   string
+	ParentId                   string
+	Level                      string
+	Sort                       string
+	RootId                     string
+	CreateTime                 string
+	ModifyTime                 string
+}{
+	SpeechRecognitionTagMenuId: "speech_recognition_tag_menu_id",
+	UniqueCode:                 "unique_code",
+	MenuName:                   "menu_name",
+	ParentId:                   "parent_id",
+	Level:                      "level",
+	Sort:                       "sort",
+	RootId:                     "root_id",
+	CreateTime:                 "create_time",
+	ModifyTime:                 "modify_time",
+}
+
+func (m *SpeechRecognitionTagMenu) TableName() string {
+	return "speech_recognition_tag_menu"
+}
+
+func (m *SpeechRecognitionTagMenu) PrimaryId() string {
+	return SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId
+}
+
+func (m *SpeechRecognitionTagMenu) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.SpeechRecognitionTagMenuId = int(id)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) CreateMulti(items []*SpeechRecognitionTagMenu) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.SpeechRecognitionTagMenuId).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) MultiDel(menuIds []int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.PrimaryId(), utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, menuIds).Exec()
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetItemById(id int) (item *SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	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 = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *SpeechRecognitionTagMenu) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	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)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// SpeechRecognitionTagMenuItem 标签目录
+type SpeechRecognitionTagMenuItem struct {
+	UniqueCode string                          `description:"唯一编码"`
+	MenuId     int                             `description:"目录ID"`
+	MenuName   string                          `description:"目录名称"`
+	ParentId   int                             `description:"父级ID"`
+	Level      int                             `description:"目录层级"`
+	Sort       int                             `description:"排序"`
+	CreateTime string                          `description:"创建时间"`
+	Children   []*SpeechRecognitionTagMenuItem `description:"子目录"`
+}
+
+// SpeechRecognitionTagMenuNodeItem 标签目录树节点
+type SpeechRecognitionTagMenuNodeItem struct {
+	UniqueCode string                              `description:"唯一编码"`
+	NodeType   int                                 `description:"节点类型:0-目录;1-标签"`
+	MenuId     int                                 `description:"目录ID"`
+	MenuName   string                              `description:"目录名称"`
+	TagId      int                                 `description:"标签ID"`
+	TagName    string                              `description:"标签名称"`
+	ParentId   int                                 `description:"父级ID"`
+	Level      int                                 `description:"目录层级"`
+	Sort       int                                 `description:"排序"`
+	CreateTime string                              `description:"创建时间"`
+	Children   []*SpeechRecognitionTagMenuNodeItem `description:"子节点"`
+}
+
+// SpeechRecognitionTagMenuAddReq 新增标签目录
+type SpeechRecognitionTagMenuAddReq struct {
+	ParentId int    `description:"父级ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionTagMenuEditReq 编辑标签目录
+type SpeechRecognitionTagMenuEditReq struct {
+	MenuId   int    `description:"目录ID"`
+	MenuName string `description:"目录名称"`
+}
+
+// SpeechRecognitionTagMenuRemoveReq 删除标签目录
+type SpeechRecognitionTagMenuRemoveReq struct {
+	MenuId int `description:"目录ID"`
+}
+
+// SpeechRecognitionTagMenuMoveReq 移动目录请求体
+type SpeechRecognitionTagMenuMoveReq struct {
+	MenuId       int `description:"目录ID"`
+	ParentMenuId int `description:"父级目录ID"`
+	PrevMenuId   int `description:"上一个兄弟节点目录ID"`
+	NextMenuId   int `description:"下一个兄弟节点目录ID"`
+	TagId        int `description:"标签ID, 大于0则表示移动标签"`
+	PrevTagId    int `description:"上一个标签ID"`
+	NextTagId    int `description:"下一个标签ID"`
+}
+
+// UpdateSortByParentId 根据父级ID更新排序
+func (m *SpeechRecognitionTagMenu) UpdateSortByParentId(parentId, menuId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`UPDATE %s SET %s = %s WHERE %s = ? AND %s > ?`, m.TableName(), SpeechRecognitionTagMenuCols.Sort, updateSort, SpeechRecognitionTagMenuCols.ParentId, SpeechRecognitionTagMenuCols.Sort)
+	if menuId > 0 {
+		sql += fmt.Sprintf(` OR (%s > %d AND %s = %d)`, SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId, menuId, SpeechRecognitionTagMenuCols.Sort, nowSort)
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// GetMaxSortByParentId 获取父级分类下最大Sort
+func (m *SpeechRecognitionTagMenu) GetMaxSortByParentId(parentId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT MAX(sort) AS sort FROM %s WHERE %s = ?`, m.TableName(), SpeechRecognitionTagMenuCols.ParentId)
+	err = o.Raw(sql, parentId).QueryRow(&sort)
+	return
+}
+
+// GetFirstByParentId 获取父级目录下排序第一的目录
+func (m *SpeechRecognitionTagMenu) GetFirstByParentId(parentId int) (item *SpeechRecognitionTagMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? ORDER BY %s ASC, %s ASC LIMIT 1`, m.TableName(), SpeechRecognitionTagMenuCols.ParentId, SpeechRecognitionTagMenuCols.Sort, SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId)
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+// UpdateChildByParentMenuId 通过父级目录ID更新子目录
+func (m *SpeechRecognitionTagMenu) UpdateChildByParentMenuId(menuIds []int, rootId int, levelStep int) (err error) {
+	if len(menuIds) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	var pars []interface{}
+	pars = append(pars, rootId, levelStep)
+	pars = append(pars, menuIds)
+	sql := fmt.Sprintf(`UPDATE %s SET %s = ?, %s = %s + ? WHERE %s IN (%s)`, m.TableName(), SpeechRecognitionTagMenuCols.RootId, SpeechRecognitionTagMenuCols.Level, SpeechRecognitionTagMenuCols.Level, SpeechRecognitionTagMenuCols.SpeechRecognitionTagMenuId, utils.GetOrmInReplace(len(menuIds)))
+	_, err = o.Raw(sql, pars).Exec()
+	return
+}

+ 51 - 0
models/target.go

@@ -1433,6 +1433,38 @@ func GetEdbinfoListByCodeListGroupByUserId(edbCodeList []string) (items []*Edbin
 	return
 }
 
+// GetEdbinfoListByCodeListByCodeIdList
+// @Description: 根据指标code列表获取列表信息
+// @param edbCodeList
+// @return items
+// @return err
+func GetEdbinfoListByCodeListByCodeIdList(edbCodeList []string) (items []*Edbinfo, err error) {
+	num := len(edbCodeList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("edb")
+	sql := `SELECT * FROM edbinfo WHERE TRADE_CODE in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, edbCodeList).QueryRows(&items)
+	return
+}
+
+// GetEdbinfoListByCodeListByUserId
+// @Description: 根据用户id列表获取指标列表信息
+// @param userIdList
+// @return items
+// @return err
+func GetEdbinfoListByCodeListByUserId(userIdList []int) (items []*Edbinfo, err error) {
+	num := len(userIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("edb")
+	sql := `SELECT * FROM edbinfo WHERE user_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userIdList).QueryRows(&items)
+	return
+}
+
 // ModifyEdbinfoUserIdByCodeList 根据指标code列表修改创建人
 func ModifyEdbinfoUserIdByCodeList(edbCodeList []string, userId int) (err error) {
 	num := len(edbCodeList)
@@ -1445,6 +1477,25 @@ func ModifyEdbinfoUserIdByCodeList(edbCodeList []string, userId int) (err error)
 	return
 }
 
+// ModifyEdbinfoUserIdByOldUserId
+// @Description:  根据旧用户id修改新用户id
+// @author: Roc
+// @datetime 2024-03-25 17:59:32
+// @param oldUserId int
+// @param userId int
+// @return err error
+func ModifyEdbinfoUserIdByOldUserId(oldUserIdList []int, userId int) (err error) {
+	num := len(oldUserIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("edb")
+	sql := `UPDATE edbinfo SET user_id=? WHERE user_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userId, oldUserIdList).Exec()
+
+	return
+}
+
 func GetEdbInfoAdminList() (list []int, err error) {
 	sql := `SELECT user_id FROM edbinfo GROUP BY user_id `
 	o := orm.NewOrmUsingDB("edb")

+ 551 - 47
routers/commentsRouter.go

@@ -511,6 +511,141 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "MoveAllEdbChartUser",
+            Router: `/edb_chart/all/change_user`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "MoveEdbChartUser",
+            Router: `/edb_chart/change_user`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "EdbChartClassifyList",
+            Router: `/edb_chart/classify`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "SetPermissionEdbChartClassifyIsPermission",
+            Router: `/edb_chart/classify/permission/is_permission/set`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "SetEdbChartClassifyPermission",
+            Router: `/edb_chart/classify/permission/set`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "GetEdbChartClassifyPermission",
+            Router: `/edb_chart/classify/permission/show_by_user`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "SecretEdbChartClassifyList",
+            Router: `/edb_chart/classify/secret`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "MoveEdbChartCount",
+            Router: `/edb_chart/count`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "MoveEdbChartList",
+            Router: `/edb_chart/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "GetEdbChartNoPermission",
+            Router: `/edb_chart/no_classify_permission/show_by_data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "SetEdbChartPermission",
+            Router: `/edb_chart/permission/set`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "GetEdbChartPermission",
+            Router: `/edb_chart/permission/show_by_data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "MessageDetail",
+            Router: `/message/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "MessageList",
+            Router: `/message/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/data_manage_permission:DataMangePermissionController"],
+        beego.ControllerComments{
+            Method: "MessageRead",
+            Router: `/message/read`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage/excel:CustomAnalysisController"],
         beego.ControllerComments{
             Method: "Add",
@@ -2815,33 +2950,6 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
-        beego.ControllerComments{
-            Method: "MoveEdbChartUser",
-            Router: `/edb_chart/change_user`,
-            AllowHTTPMethods: []string{"post"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
-        beego.ControllerComments{
-            Method: "EdbChartClassifyList",
-            Router: `/edb_chart/classify`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
-        beego.ControllerComments{
-            Method: "MoveEdbChartList",
-            Router: `/edb_chart/list`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
             Method: "QueryEdbDataTable",
@@ -4192,24 +4300,6 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:PredictEdbClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:PredictEdbClassifyController"],
-        beego.ControllerComments{
-            Method: "List",
-            Router: `/predict_classify/list`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
-    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:PredictEdbClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:PredictEdbClassifyController"],
-        beego.ControllerComments{
-            Method: "ListV2",
-            Router: `/predict_classify/list/v2`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(),
-            Filters: nil,
-            Params: nil})
-
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:PredictEdbClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:PredictEdbClassifyController"],
         beego.ControllerComments{
             Method: "Move",
@@ -4615,6 +4705,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"],
+        beego.ControllerComments{
+            Method: "SetEnabled",
+            Router: `/enabled/set`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"],
         beego.ControllerComments{
             Method: "List",
@@ -4624,6 +4723,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnPermissionController"],
         beego.ControllerComments{
             Method: "ParentList",
@@ -4907,7 +5015,7 @@ func init() {
         beego.ControllerComments{
             Method: "AddClassify",
             Router: `/classify/add`,
-            AllowHTTPMethods: []string{"get"},
+            AllowHTTPMethods: []string{"post"},
             MethodParams: param.Make(),
             Filters: nil,
             Params: nil})
@@ -4925,7 +5033,16 @@ func init() {
         beego.ControllerComments{
             Method: "EditClassify",
             Router: `/classify/edit`,
-            AllowHTTPMethods: []string{"get"},
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnglishReportController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnglishReportController"],
+        beego.ControllerComments{
+            Method: "SetEnabled",
+            Router: `/classify/enabled/set`,
+            AllowHTTPMethods: []string{"post"},
             MethodParams: param.Make(),
             Filters: nil,
             Params: nil})
@@ -4948,6 +5065,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnglishReportController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnglishReportController"],
+        beego.ControllerComments{
+            Method: "MoveClassify",
+            Router: `/classify/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnglishReportController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/english_report:EnglishReportController"],
         beego.ControllerComments{
             Method: "ClassifyIdDetail",
@@ -6028,6 +6154,285 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionCommonController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionCommonController"],
+        beego.ControllerComments{
+            Method: "RecTaskCallback",
+            Router: `/rec_task/callback`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "Convert",
+            Router: `/convert`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "CheckFileName",
+            Router: `/convert/check_name`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "ConvertList",
+            Router: `/convert_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "Export",
+            Router: `/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "RemoveFile",
+            Router: `/remove_file`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "Rename",
+            Router: `/rename`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "Save",
+            Router: `/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionController"],
+        beego.ControllerComments{
+            Method: "SaveTag",
+            Router: `/save_tag`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/menu/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/menu/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/menu/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/menu/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/menu/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "RemoveCheck",
+            Router: `/menu/remove_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionMenuController"],
+        beego.ControllerComments{
+            Method: "Tree",
+            Router: `/menu/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/tag/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/tag/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/tag/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/tag/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagController"],
+        beego.ControllerComments{
+            Method: "RemoveCheck",
+            Router: `/tag/remove_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/tag/menu/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/tag/menu/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/tag/menu/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/tag/menu/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Remove",
+            Router: `/tag/menu/remove`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "RemoveCheck",
+            Router: `/tag/menu/remove_check`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/speech_recognition:SpeechRecognitionTagMenuController"],
+        beego.ControllerComments{
+            Method: "Tree",
+            Router: `/tag/menu/tree`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/trade_analysis:TradeAnalysisController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/trade_analysis:TradeAnalysisController"],
         beego.ControllerComments{
             Method: "GetClassifyName",
@@ -6082,6 +6487,51 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "SetEnabled",
+            Router: `/enabled/set`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"],
         beego.ControllerComments{
             Method: "Add",
@@ -6118,6 +6568,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"],
+        beego.ControllerComments{
+            Method: "SetEnabled",
+            Router: `/enabled/set`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"],
         beego.ControllerComments{
             Method: "FindByIdClassify",
@@ -6136,6 +6595,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ClassifyController"],
         beego.ControllerComments{
             Method: "ParentClassify",
@@ -6316,6 +6784,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers:MessageController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:MessageController"],
+        beego.ControllerComments{
+            Method: "UnReadMessageNum",
+            Router: `/unread/num`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers:OutLinkController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:OutLinkController"],
         beego.ControllerComments{
             Method: "AllList",
@@ -7036,6 +7513,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"],
+        beego.ControllerComments{
+            Method: "SetEnabled",
+            Router: `/chapter_type/enabled/set`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"],
         beego.ControllerComments{
             Method: "List",
@@ -7045,6 +7531,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"],
+        beego.ControllerComments{
+            Method: "Move",
+            Router: `/chapter_type/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ReportChapterTypeController"],
         beego.ControllerComments{
             Method: "PermissionList",
@@ -7432,6 +7927,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers:ResourceAuthController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ResourceAuthController"],
+        beego.ControllerComments{
+            Method: "FileDownload",
+            Router: `/file/download`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers:ResourceController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers:ResourceController"],
         beego.ControllerComments{
             Method: "Upload",

+ 23 - 0
routers/router.go

@@ -13,6 +13,7 @@ import (
 	"eta/eta_api/controllers/data_manage"
 	"eta/eta_api/controllers/data_manage/correlation"
 	"eta/eta_api/controllers/data_manage/cross_variety"
+	"eta/eta_api/controllers/data_manage/data_manage_permission"
 	"eta/eta_api/controllers/data_manage/excel"
 	future_good2 "eta/eta_api/controllers/data_manage/future_good"
 	"eta/eta_api/controllers/data_manage/line_equation"
@@ -27,6 +28,7 @@ import (
 	"eta/eta_api/controllers/sandbox"
 	"eta/eta_api/controllers/semantic_analysis"
 	"eta/eta_api/controllers/smart_report"
+	"eta/eta_api/controllers/speech_recognition"
 	"eta/eta_api/controllers/trade_analysis"
 	"github.com/beego/beego/v2/server/web"
 	"github.com/beego/beego/v2/server/web/filter/cors"
@@ -146,6 +148,7 @@ func init() {
 		web.NSNamespace("/resource",
 			web.NSInclude(
 				&controllers.ResourceController{},
+				&controllers.ResourceAuthController{},
 			),
 		),
 		web.NSNamespace("/datamanage",
@@ -163,6 +166,7 @@ func init() {
 				&data_manage.BaseFromNationalStatisticsController{},
 				&data_manage.JiaYueEdbSourceController{},
 				&data_manage.ChartThemeController{},
+				&data_manage_permission.DataMangePermissionController{},
 			),
 		),
 		web.NSNamespace("/my_chart",
@@ -343,6 +347,25 @@ func init() {
 				&data_source.DataSourceController{},
 			),
 		),
+		web.NSNamespace("/permission",
+			web.NSInclude(
+				&controllers.ChartPermissionController{},
+			),
+		),
+		web.NSNamespace("/speech_recognition",
+			web.NSInclude(
+				&speech_recognition.SpeechRecognitionCommonController{},
+				&speech_recognition.SpeechRecognitionController{},
+				&speech_recognition.SpeechRecognitionMenuController{},
+				&speech_recognition.SpeechRecognitionTagController{},
+				&speech_recognition.SpeechRecognitionTagMenuController{},
+			),
+		),
+		web.NSNamespace("/message",
+			web.NSInclude(
+				&controllers.MessageController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 478 - 0
services/chart_permission.go

@@ -0,0 +1,478 @@
+package services
+
+import (
+	"eta/eta_api/models"
+	"eta/eta_api/models/company"
+	"eta/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+// 获取权限列表
+func GetChartPermissionList(cond string, pars []interface{}) (permissionList []*models.ChartPermission, err error) {
+	ob := new(models.ChartPermission)
+	permissionList, err = ob.GetItemsByCondition(cond, pars)
+	if err != nil {
+		err = fmt.Errorf("获取权限列表失败, Err: %s", err.Error())
+		return
+	}
+
+	return
+}
+
+// 新增权限
+func AddChartPermission(req models.PermissionAddReq) (err error, errMsg string) {
+	// 重名校验
+	ob := new(models.ChartPermission)
+	existCond := ` AND permission_name = ? AND parent_id = ?`
+	existPars := make([]interface{}, 0)
+	existPars = append(existPars, req.PermissionName, req.ParentId)
+	exist, e := ob.GetItemByCondition(existCond, existPars)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		errMsg = "操作失败"
+		err = fmt.Errorf("获取重名品种权限失败, Err: " + e.Error())
+		return
+	}
+	if exist != nil && exist.ChartPermissionId > 0 {
+		errMsg = "品种名称已存在"
+		err = fmt.Errorf("品种名称已存在")
+		return
+	}
+
+	// 获取最大的排序值
+	maxSort, e := ob.GetMaxSort()
+	if e != nil {
+		errMsg = "查询品种排序失败"
+		err = fmt.Errorf("查询品种排序失败, Err: " + e.Error())
+		return
+	}
+	parentPermissionName := ""
+	if req.ParentId > 0 {
+		//查询父级是否存在
+		parent, e := ob.GetItemById(req.ParentId)
+		if e != nil {
+			errMsg = "查询父级品种失败"
+			err = fmt.Errorf("查询父级品种失败, Err: " + e.Error())
+			return
+		}
+		if parent.ChartPermissionId == 0 {
+			errMsg = "请选择正确的父级品种"
+			err = fmt.Errorf("请选择正确的父级品种")
+			return
+		}
+		if parent.ParentId != 0 {
+			errMsg = "只能选择一级品种作为父级品种"
+			err = fmt.Errorf("只能选择一级品种作为父级品种")
+			return
+		}
+		parentPermissionName = parent.PermissionName
+	} else {
+		parentPermissionName = req.PermissionName
+	}
+	// 新增
+	ob.ChartPermissionName = req.PermissionName
+	ob.PermissionName = req.PermissionName
+	ob.Remark = req.PermissionName
+	ob.ParentId = req.ParentId
+	ob.ProductId = 1
+	ob.IsPublic = req.IsPublic
+	ob.Enabled = req.Enabled
+	ob.Sort = maxSort + 1
+
+	ob.CreatedTime = time.Now()
+	ob.LastUpdatedTime = time.Now()
+	if ob.ProductId == 1 {
+		ob.ProductName = "ficc"
+	} else {
+		ob.ProductName = "权益"
+	}
+	ob.ProductPermissionName = ob.ProductName + ob.PermissionName
+	ob.ClassifyName = parentPermissionName
+	if e = ob.Create(); e != nil {
+		errMsg = "操作失败"
+		err = fmt.Errorf("新增品种权限失败, Err: " + e.Error())
+		return
+	}
+	if req.ParentId > 0 && req.Enabled == 1 {
+		//  更新父级品种的启用禁用
+		err = ob.SetEnabledByChartPermissionId(req.ParentId, req.Enabled)
+		if err != nil {
+			errMsg = "更新品种启用禁用状态失败"
+			err = fmt.Errorf("更新品种启用禁用状态失败, Err: " + err.Error())
+			return
+		}
+	}
+	// 同步本次变更的数据
+	go func() {
+		_, _ = ChartFiccPermissionSync()
+	}()
+	return
+}
+
+func EditChartPermission(req models.PermissionEditReq) (err error, errMsg string) {
+	//查询是否存在品种
+	ob := new(models.ChartPermission)
+	item, e := ob.GetItemById(req.PermissionId)
+	if e != nil {
+		errMsg = "查询品种信息失败"
+		err = fmt.Errorf("查询品种信息失败, Err: " + e.Error())
+		return
+	}
+	if item.ChartPermissionId == 0 {
+		errMsg = "请选择正确的品种"
+		err = fmt.Errorf("请选择正确的品种")
+		return
+	}
+	// 查询品种名称是否修改
+	if item.PermissionName != req.PermissionName {
+		existCond := ` AND permission_name = ? AND parent_id = ? AND chart_permission_id !=?`
+		existPars := make([]interface{}, 0)
+		existPars = append(existPars, req.PermissionName, item.ParentId, req.PermissionId)
+		exist, e := ob.GetItemByCondition(existCond, existPars)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			errMsg = "操作失败"
+			err = fmt.Errorf("获取重名品种权限失败, Err: " + e.Error())
+			return
+		}
+		if exist != nil && exist.ChartPermissionId > 0 {
+			errMsg = "品种名称已存在"
+			err = fmt.Errorf("品种名称已存在")
+			return
+		}
+	}
+
+	//判断父级品种是否存在
+	parentPermissionName := ""
+	if req.ParentId > 0 {
+		//查询父级是否存在
+		parent, e := ob.GetItemById(req.ParentId)
+		if e != nil {
+			errMsg = "查询父级品种失败"
+			err = fmt.Errorf("查询父级品种失败, Err: " + e.Error())
+			return
+		}
+		if parent.ChartPermissionId == 0 {
+			errMsg = "请选择正确的父级品种"
+			err = fmt.Errorf("请选择正确的父级品种")
+			return
+		}
+		if parent.ParentId != 0 {
+			errMsg = "只能选择一级品种作为父级品种"
+			err = fmt.Errorf("只能选择一级品种作为父级品种")
+			return
+		}
+		parentPermissionName = parent.PermissionName
+	} else {
+		parentPermissionName = req.PermissionName
+	}
+	updateCol := []string{"PermissionName", "IsPublic", "ParentId", "ClassifyName", "LastUpdatedTime", "ProductPermissionName"}
+	if item.ProductId == 1 {
+		item.Remark = req.PermissionName //remark 在权益品种中用来区分主客观
+		updateCol = append(updateCol, "Remark")
+	}
+	item.PermissionName = req.PermissionName
+	item.IsPublic = req.IsPublic
+	item.ParentId = req.ParentId
+	item.ClassifyName = parentPermissionName
+	item.ProductPermissionName = item.ProductName + item.PermissionName
+	item.LastUpdatedTime = time.Now()
+	err = item.Update(updateCol)
+	if err != nil {
+		errMsg = "更新失败"
+		err = fmt.Errorf("更新品种失败, Err: " + err.Error())
+		return
+	}
+
+	//判断是否是一级品种
+	if item.ParentId == 0 {
+		// 判断是否设置公有的二级品种
+		if len(req.PublicPermissionIds) > 0 {
+			// 更新二级品种的公有权限
+			err = ob.SetIsPublic(req.PublicPermissionIds, item.ChartPermissionId, 1)
+			if err != nil {
+				errMsg = "更新品种公有权限失败"
+				err = fmt.Errorf("更新品种公有权限失败, Err: " + err.Error())
+				return
+			}
+		}
+		// 更新二级的启动禁用
+		err = ob.UpdateClassifyNameByParentId(item.ChartPermissionId, req.PermissionName)
+		if err != nil {
+			errMsg = "更新品种启用禁用状态失败"
+			err = fmt.Errorf("更新品种启用禁用状态失败, Err: " + err.Error())
+			return
+		}
+	} else if item.ParentId > 0 {
+		if item.Enabled == 1 {
+			//  更新父级品种的启用禁用
+			err = ob.SetEnabledByChartPermissionId(item.ParentId, item.Enabled)
+			if err != nil {
+				errMsg = "更新品种启用禁用状态失败"
+				err = fmt.Errorf("更新品种启用禁用状态失败, Err: " + err.Error())
+				return
+			}
+		}
+	}
+	// 同步本次变更的数据
+	go func() {
+		_, _ = ChartFiccPermissionSync()
+	}()
+	return
+}
+
+// SetEnabledChartPermission  设置启用禁用
+func SetEnabledChartPermission(req models.PermissionEnabledReq) (err error, errMsg string) {
+	//查询是否存在品种
+	ob := new(models.ChartPermission)
+	item, e := ob.GetItemById(req.PermissionId)
+	if e != nil {
+		errMsg = "查询品种信息失败"
+		err = fmt.Errorf("查询品种信息失败, Err: " + e.Error())
+		return
+	}
+	if item.ChartPermissionId == 0 {
+		errMsg = "请选择正确的品种"
+		err = fmt.Errorf("请选择正确的品种")
+		return
+	}
+	// 查询品种名称是否修改
+	item.Enabled = req.Enabled
+	item.LastUpdatedTime = time.Now()
+	err = item.Update([]string{"Enabled", "LastUpdatedTime"})
+	if err != nil {
+		errMsg = "更新失败"
+		err = fmt.Errorf("更新品种失败, Err: " + err.Error())
+		return
+	}
+
+	//判断是否是一级品种
+	if item.ParentId == 0 {
+		// 判断是否设置公有的二级品种
+		// 更新二级的启动禁用
+		err = ob.SetEnabledByParentId(item.ChartPermissionId, req.Enabled)
+		if err != nil {
+			errMsg = "更新品种启用禁用状态失败"
+			err = fmt.Errorf("更新品种启用禁用状态失败, Err: " + err.Error())
+			return
+		}
+
+		//
+	} else if item.ParentId > 0 {
+		if req.Enabled == 1 {
+			//  更新父级品种的启用禁用
+			err = ob.SetEnabledByChartPermissionId(item.ParentId, req.Enabled)
+			if err != nil {
+				errMsg = "更新品种启用禁用状态失败"
+				err = fmt.Errorf("更新品种启用禁用状态失败, Err: " + err.Error())
+				return
+			}
+		}
+	}
+	// 同步本次变更的数据
+	go func() {
+		_, _ = ChartFiccPermissionSync()
+	}()
+	return
+}
+
+// MoveChartPermission 移动品种
+func MoveChartPermission(req models.PermissionMoveReq) (err error, errMsg string) {
+	ob := new(models.ChartPermission)
+	chartPermissionId := req.PermissionId
+	prevChartPermissionId := req.PrevPermissionId
+	nextChartPermissionId := req.NextPermissionId
+
+	//如果有传入 上一个兄弟节点分类id
+	var (
+		permissionInfo *models.ChartPermission
+		prevPermission *models.ChartPermission
+		nextPermission *models.ChartPermission
+
+		prevSort int
+		nextSort int
+	)
+
+	// 移动对象为分类, 判断权限
+	permissionInfo, err = ob.GetItemById(chartPermissionId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "当前品种不存在"
+			err = fmt.Errorf("获取品种信息失败,Err:" + err.Error())
+			return
+		}
+		errMsg = "移动失败"
+		err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
+		return
+	} else if permissionInfo.ChartPermissionId == 0 {
+		errMsg = "当前品种不存在"
+		err = fmt.Errorf("获取品种信息失败,Err:" + err.Error())
+		return
+	}
+
+	parentChartPermissionId := permissionInfo.ParentId
+	productId := permissionInfo.ProductId
+	if prevChartPermissionId > 0 {
+		prevPermission, err = ob.GetItemById(prevChartPermissionId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = fmt.Errorf("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
+			return
+		}
+		prevSort = prevPermission.Sort
+	}
+
+	if nextChartPermissionId > 0 {
+		//下一个兄弟节点
+		nextPermission, err = ob.GetItemById(nextChartPermissionId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
+			return
+		}
+		nextSort = nextPermission.Sort
+	}
+
+	err, errMsg = moveChartPermission(permissionInfo, prevPermission, nextPermission, parentChartPermissionId, prevSort, nextSort, productId)
+	return
+}
+
+// moveChartPermission 移动指标分类
+func moveChartPermission(permissionInfo, prevPermission, nextPermission *models.ChartPermission, parentId, prevSort, nextSort, productId int) (err error, errMsg string) {
+	ob := new(models.ChartPermission)
+	updateCol := make([]string, 0)
+
+	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
+	if permissionInfo.ParentId != parentId {
+		errMsg = "移动失败"
+		err = fmt.Errorf("不支持目录层级变更")
+		return
+	}
+
+	if prevSort > 0 {
+		//如果是移动在两个兄弟节点之间
+		if nextSort > 0 {
+			//下一个兄弟节点
+			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+			if prevSort == nextSort || prevSort == permissionInfo.Sort {
+				//变更兄弟节点的排序
+				updateSortStr := `sort + 2`
+
+				//变更分类
+				if prevPermission != nil {
+					_ = models.UpdateChartPermissionSortByParentId(parentId, prevPermission.ChartPermissionId, prevPermission.Sort, updateSortStr, productId)
+				} else {
+					_ = models.UpdateChartPermissionSortByParentId(parentId, 0, prevSort, updateSortStr, productId)
+				}
+
+			} else {
+				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+				if nextSort-prevSort == 1 {
+					//变更兄弟节点的排序
+					updateSortStr := `sort + 1`
+
+					//变更分类
+					if prevPermission != nil {
+						_ = models.UpdateChartPermissionSortByParentId(parentId, prevPermission.ChartPermissionId, prevSort, updateSortStr, productId)
+					} else {
+						_ = models.UpdateChartPermissionSortByParentId(parentId, 0, prevSort, updateSortStr, productId)
+					}
+
+				}
+			}
+		}
+
+		permissionInfo.Sort = prevSort + 1
+		permissionInfo.LastUpdatedTime = time.Now()
+		updateCol = append(updateCol, "Sort", "LastUpdatedTime")
+	} else if prevPermission == nil && nextPermission == nil && parentId > 0 {
+		//处理只拖动到目录里,默认放到目录底部的情况
+		var maxSort int
+		maxSort, err = ob.GetMaxSortByParentId(parentId)
+		if err != nil {
+			errMsg = "移动失败"
+			err = fmt.Errorf("查询组内排序信息失败,Err:" + err.Error())
+			return
+		}
+		permissionInfo.Sort = maxSort + 1 //那就是排在组内最后一位
+		permissionInfo.LastUpdatedTime = time.Now()
+		updateCol = append(updateCol, "Sort", "LastUpdatedTime")
+	} else {
+		// 拖动到父级分类的第一位
+		firstPermission, tmpErr := ob.GetFirstChartPermissionByParentId(parentId)
+		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+			errMsg = "移动失败"
+			err = fmt.Errorf("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error())
+			return
+		}
+
+		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+		if firstPermission != nil && firstPermission.ChartPermissionId != 0 && firstPermission.Sort == 0 {
+			updateSortStr := ` sort + 1 `
+			_ = models.UpdateChartPermissionSortByParentId(parentId, firstPermission.ChartPermissionId-1, 0, updateSortStr, productId)
+		}
+
+		permissionInfo.Sort = 0 //那就是排在第一位
+		permissionInfo.LastUpdatedTime = time.Now()
+		updateCol = append(updateCol, "Sort", "LastUpdatedTime")
+	}
+
+	//更新
+	if len(updateCol) > 0 {
+		err = permissionInfo.Update(updateCol)
+		if err != nil {
+			errMsg = "移动失败"
+			err = fmt.Errorf("修改失败,Err:" + err.Error())
+			return
+		}
+	}
+
+	// 同步本次变更的数据
+	go func() {
+		_, _ = ChartFiccPermissionSync()
+	}()
+	return
+}
+
+// GetChartPermissionEnabledList 查询已启用的FICC权限列表
+func GetChartPermissionEnabledList() (list []*company.PermissionSetList, err error) {
+	dataList, err := GetChartPermissionList(" AND enabled = 1", []interface{}{})
+	if err != nil {
+		return
+	}
+	//enabledList := make([]*models.ChartPermission, 0)
+	parentList := make([]*models.ChartPermission, 0)
+	enabledMap := make(map[int][]*company.PermissionSetItem)
+	listMap := make(map[int]*models.ChartPermission)
+	for _, v := range dataList {
+		listMap[v.ChartPermissionId] = v
+		if v.ParentId == 0 {
+			parentList = append(parentList, v)
+		}
+		if v.Enabled == 1 && v.ParentId > 0 && v.PermissionType == 0 {
+			//enabledList = append(enabledList, v)
+			item := &company.PermissionSetItem{
+				ChartPermissionId: v.ChartPermissionId,
+				PermissionName:    v.PermissionName,
+				PermissionType:    v.PermissionType,
+			}
+
+			enabledMap[v.ParentId] = append(enabledMap[v.ParentId], item)
+		}
+	}
+	for _, v := range parentList {
+		items, ok := enabledMap[v.ChartPermissionId]
+		if !ok {
+			continue
+		}
+		checkList := make([]int, 0)
+		p := new(company.PermissionSetList)
+		p.PermissionName = v.PermissionName
+		p.Child = items
+		if v.PermissionName == "宏观经济" {
+			checkList = append(checkList, 1)
+		}
+		p.CheckList = checkList
+		list = append(list, p)
+	}
+	return
+}

+ 206 - 0
services/chart_permission_sync.go

@@ -0,0 +1,206 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_api/services/alarm_msg"
+	"eta/eta_api/utils"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+)
+
+type ChartPermissionResp struct {
+	Code   int    `json:"code" description:"状态码"`
+	Msg    string `json:"msg" description:"提示信息"`
+	ErrMsg string `json:"-" description:"错误信息,不用返回给前端,只是做日志记录"`
+}
+
+func crmEtaPost(url string, pars interface{}) (respBody []byte, err error) {
+	params, e := json.Marshal(pars)
+	if e != nil {
+		err = fmt.Errorf("data json marshal err: %s", e.Error())
+		return
+	}
+
+	body := ioutil.NopCloser(strings.NewReader(string(params)))
+	client := &http.Client{}
+	req, e := http.NewRequest("POST", url, body)
+	if e != nil {
+		err = fmt.Errorf("http create request err: %s", e.Error())
+		return
+	}
+
+	contentType := "application/json;charset=utf-8"
+	req.Header.Set("Content-Type", contentType)
+	req.Header.Set("Authorization", utils.CrmEtaAuthorization)
+	resp, e := client.Do(req)
+	if e != nil {
+		err = fmt.Errorf("http client do err: %s", e.Error())
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	b, e := ioutil.ReadAll(resp.Body)
+	if e != nil {
+		err = fmt.Errorf("resp body read err: %s", e.Error())
+		return
+	}
+	if len(b) == 0 {
+		err = fmt.Errorf("resp body is empty")
+		return
+	}
+	// 生产环境解密, 注意有个坑前后的双引号
+	if utils.RunMode == "release" {
+		str := string(b)
+		str = strings.Trim(str, `"`)
+		b = utils.DesBase64Decrypt([]byte(str), utils.CrmEtaServerDes3Key)
+	}
+	respBody = b
+	return
+}
+
+func ChartFiccPermissionSync() (err error, errMsg string) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info("同步品种权限数据失败, Err: " + err.Error() + errMsg)
+			alarm_msg.SendAlarmMsg("同步品种权限数据失败,Err:"+err.Error(), 3)
+		}
+	}()
+	if utils.CrmEtaServerUrl == "" {
+		return
+	}
+	url := fmt.Sprint(utils.CrmEtaServerUrl, "/api/crm/chart_permission/sync")
+	pars := make(map[string]interface{})
+	b, err := crmEtaPost(url, pars)
+	if err != nil {
+		errMsg = "同步品种失败"
+		err = fmt.Errorf("url:%s err: %s", url, err.Error())
+		return
+	}
+	//result := new(models.ResultData)
+	result := new(ChartPermissionResp)
+	if e := json.Unmarshal(b, &result); e != nil {
+		errMsg = "同步品种失败"
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	utils.FileLog.Info("%s", string(b))
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s, err: %s", string(b), result.ErrMsg)
+		errMsg = result.Msg
+		return
+	}
+	return
+}
+
+type EditClassifyPermissionReq struct {
+	Keyword string
+}
+
+// EditClassifyChartPermissionSync 设置报告分类权限
+func EditClassifyChartPermissionSync(keyword string) (err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info("同步设置报告分类权限失败, Err: " + err.Error())
+			alarm_msg.SendAlarmMsg("同步设置报告分类权限失败,Err:"+err.Error(), 3)
+		}
+	}()
+	if utils.CrmEtaServerUrl == "" {
+		return
+	}
+	req := &EditClassifyPermissionReq{Keyword: keyword}
+	url := fmt.Sprint(utils.CrmEtaServerUrl, "/api/crm/chart_permission/classify/sync")
+	b, err := crmEtaPost(url, req)
+	if err != nil {
+		err = fmt.Errorf("url:%s err: %s", url, err.Error())
+		return
+	}
+	//result := new(models.ResultData)
+	result := new(ChartPermissionResp)
+	if e := json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	utils.FileLog.Info("%s", string(b))
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	return
+}
+
+type EditReportPermissionSyncReq struct {
+	ReportId           int64  `description:"报告id"`
+	ClassifyNameSecond string `description:"二级分类名称"`
+}
+
+// EditReportPermissionSync 设置报告权限
+func EditReportPermissionSync(reportId int64, classifyNameSecond string) (err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info("同步设置报告权限失败, Err: " + err.Error())
+			alarm_msg.SendAlarmMsg("同步设置报告权限失败,Err:"+err.Error(), 3)
+		}
+	}()
+	if utils.CrmEtaServerUrl == "" {
+		return
+	}
+	req := &EditReportPermissionSyncReq{ReportId: reportId, ClassifyNameSecond: classifyNameSecond}
+	url := fmt.Sprint(utils.CrmEtaServerUrl, "/api/crm/chart_permission/report/sync")
+	b, err := crmEtaPost(url, req)
+	if err != nil {
+		err = fmt.Errorf("url:%s err: %s", url, err.Error())
+		return
+	}
+	//result := new(models.ResultData)
+	result := new(ChartPermissionResp)
+	if e := json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	utils.FileLog.Info("%s", string(b))
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	return
+}
+
+type EditKeywordPermissionSyncReq struct {
+	NewKeyword string
+	Keyword    string
+}
+
+// EditKeywordPermissionSync 设置报告权限分类名称
+func EditKeywordPermissionSync(newKeyword, keyword string) (err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info("同步设置报告权限分类名称失败, Err: " + err.Error())
+			alarm_msg.SendAlarmMsg("同步设置报告权限分类名称失败,Err:"+err.Error(), 3)
+		}
+	}()
+	if utils.CrmEtaServerUrl == "" {
+		return
+	}
+	req := &EditKeywordPermissionSyncReq{NewKeyword: newKeyword, Keyword: keyword}
+	url := fmt.Sprint(utils.CrmEtaServerUrl, "/api/crm/chart_permission/keyword/sync")
+	b, err := crmEtaPost(url, req)
+	if err != nil {
+		err = fmt.Errorf("url:%s err: %s", url, err.Error())
+		return
+	}
+	//result := new(models.ResultData)
+	result := new(ChartPermissionResp)
+	if e := json.Unmarshal(b, &result); e != nil {
+		err = fmt.Errorf("result unmarshal err: %s\nresult: %s", e.Error(), string(b))
+		return
+	}
+	utils.FileLog.Info("%s", string(b))
+	if result.Code != 200 {
+		err = fmt.Errorf("result: %s", string(b))
+		return
+	}
+	return
+}

Some files were not shown because too many files changed in this diff