Browse Source

上传图表至社区

xyxie 1 year ago
parent
commit
773b49cda6

+ 91 - 0
controllers/base_common.go

@@ -0,0 +1,91 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_forum_hub/services/alarm_msg"
+	"net/http"
+	"net/url"
+
+	"github.com/beego/beego/v2/server/web"
+
+	"eta/eta_forum_hub/models"
+	"eta/eta_forum_hub/utils"
+)
+
+type BaseCommonController struct {
+	web.Controller
+}
+
+func (c *BaseCommonController) ServeJSON(encoding ...bool) {
+	// 方法处理完后,需要后置处理的业务逻辑
+	//if handlerList, ok := AfterHandlerUrlMap[c.Ctx.Request.URL.Path]; ok {
+	//	for _, handler := range handlerList {
+	//		handler(c.Ctx.Input.RequestBody)
+	//	}
+	//}
+
+	var (
+		hasIndent   = false
+		hasEncoding = false
+	)
+	if web.BConfig.RunMode == web.PROD {
+		hasIndent = false
+	}
+	if len(encoding) > 0 && encoding[0] == true {
+		hasEncoding = true
+	}
+	if c.Data["json"] == nil {
+		go alarm_msg.SendAlarmMsg("接口:URI:"+c.Ctx.Input.URI()+";无返回值", 3)
+		return
+	}
+
+	baseRes := c.Data["json"].(*models.BaseResponse)
+	if baseRes != nil && baseRes.Ret != 408 {
+		body, _ := json.Marshal(baseRes)
+		var requestBody string
+		method := c.Ctx.Input.Method()
+		if method == "GET" {
+			requestBody = c.Ctx.Request.RequestURI
+		} else {
+			requestBody, _ = url.QueryUnescape(string(c.Ctx.Input.RequestBody))
+		}
+		if baseRes.Ret != 200 && baseRes.IsSendEmail {
+			//go utils.SendEmail(utils.APP_NAME_CN+"【"+utils.RunMode+"】"+"失败提醒", "URI:"+c.Ctx.Input.URI()+"<br/> "+"Params"+requestBody+" <br/>"+"ErrMsg:"+baseRes.ErrMsg+";<br/>Msg:"+baseRes.Msg+";<br/> Body:"+string(body)+"<br/>", utils.EmailSendToUsers)
+			go alarm_msg.SendAlarmMsg("失败提醒:URI:"+c.Ctx.Input.URI()+";请求入参:Params"+requestBody+" ErrMsg:"+baseRes.ErrMsg+";Msg"+baseRes.Msg+"; Body:"+string(body), 3)
+		}
+	}
+	c.JSON(c.Data["json"], hasIndent, hasEncoding)
+}
+
+func (c *BaseCommonController) JSON(data interface{}, hasIndent bool, coding bool) error {
+	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
+	var content []byte
+	var err error
+	if hasIndent {
+		content, err = json.MarshalIndent(data, "", "  ")
+	} else {
+		content, err = json.Marshal(data)
+	}
+	if err != nil {
+		http.Error(c.Ctx.Output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
+		return err
+	}
+	ip := c.Ctx.Input.IP()
+	requestBody, err := url.QueryUnescape(string(c.Ctx.Input.RequestBody))
+	if err != nil {
+		requestBody = string(c.Ctx.Input.RequestBody)
+	}
+	if requestBody == "" {
+		requestBody = c.Ctx.Input.URI()
+	}
+	authorization := c.Ctx.Input.Header("authorization")
+	if authorization == "" {
+		authorization = c.Ctx.Input.Header("Authorization")
+	}
+
+	utils.ApiLog.Info("uri:%s, authorization:%s, requestBody:%s, responseBody:%s, ip:%s", c.Ctx.Input.URI(), authorization, requestBody, content, ip)
+	if coding {
+		content = []byte(utils.StringsToJSON(string(content)))
+	}
+	return c.Ctx.Output.Body(content)
+}

+ 211 - 0
controllers/chart_info.go

@@ -0,0 +1,211 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_forum_hub/models"
+	"eta/eta_forum_hub/services"
+	"strings"
+)
+
+type ChartInfoController struct {
+	BaseCommonController
+}
+
+// Update
+// @Title 图表-更新
+// @Description 图表-更新
+// @Param	request	body data_manage.AddChartReq true "type json string"
+// @Success 200 {object} data_manage.AddChartInfoResp
+// @router /update [post]
+func (this *ChartInfoController) Update() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	/*deleteCache := true
+	cacheKey := "CACHE_CHART_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}*/
+	var req models.AddChartReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartInfo == nil {
+		br.Msg = "请选择图表"
+		return
+	}
+	if req.ChartInfo.ChartInfoId <= 0 {
+		br.Msg = "请选择图表"
+		return
+	}
+	//校验图表名称是否重复
+	req.ChartInfo.ChartName = strings.Trim(req.ChartInfo.ChartName, " ")
+	if req.ChartInfo.ChartName == "" {
+		br.Msg = "请填写图表名称!"
+		return
+	}
+
+	if len(req.EdbInfoList) <= 0 {
+		br.Msg = "指标信息不能为空"
+		return
+	}
+	for _, edbInfo := range req.EdbInfoList {
+		if edbInfo.EdbName == "" {
+			br.Msg = "指标名称不能为空"
+			return
+		}
+	}
+
+	if len(req.ChartEdbMapping) <= 0 {
+		br.Msg = "图表指标映射不能为空"
+		return
+	}
+
+	chartInfo, err, errMsg, _ := services.UpdateChartInfoAndEdbInfo(&req, 0, "")
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = models.AddChartInfoResp{
+		ChartInfoId: chartInfo.ChartInfoId,
+		UniqueCode:  chartInfo.UniqueCode,
+		ChartType:   chartInfo.ChartType,
+	}
+	return
+}
+
+// Save
+// @Title 图表-保存
+// @Description 图表-保存
+// @Param	request	body data_manage.AddChartReq true "type json string"
+// @Success 200 {object} data_manage.AddChartInfoResp
+// @router /save [post]
+func (this *ChartInfoController) Save() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	/*deleteCache := true
+	cacheKey := "CACHE_CHART_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
+	defer func() {
+		if deleteCache {
+			utils.Rc.Delete(cacheKey)
+		}
+	}()
+	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
+		deleteCache = false
+		br.Msg = "系统处理中,请稍后重试!"
+		br.ErrMsg = "系统处理中,请稍后重试!" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
+		return
+	}*/
+	var req models.AddChartReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ChartInfo == nil {
+		br.Msg = "请选择图表"
+		return
+	}
+	//校验图表名称是否重复
+	req.ChartInfo.ChartName = strings.Trim(req.ChartInfo.ChartName, " ")
+	if req.ChartInfo.ChartName == "" {
+		br.Msg = "请填写图表名称!"
+		return
+	}
+
+	if len(req.EdbInfoList) <= 0 {
+		br.Msg = "指标信息不能为空"
+		return
+	}
+	for _, edbInfo := range req.EdbInfoList {
+		if edbInfo.EdbName == "" {
+			br.Msg = "指标名称不能为空"
+			return
+		}
+	}
+
+	if len(req.ChartEdbMapping) <= 0 {
+		br.Msg = "图表指标映射不能为空"
+		return
+	}
+
+	chartInfo, err, errMsg, _ := services.AddChartInfo(&req, 0, "")
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = models.AddChartInfoResp{
+		ChartInfoId: chartInfo.ChartInfoId,
+		UniqueCode:  chartInfo.UniqueCode,
+		ChartType:   chartInfo.ChartType,
+	}
+	return
+}
+
+// Delete
+// @Title 图表-删除
+// @Description 图表-删除
+// @Param	request	body data_manage.DeleteChartReq true "type json string"
+// @Success 200 {object}
+// @router /delete [post]
+func (this *ChartInfoController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req models.DeleteChartReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ChartInfoId <= 0 {
+		br.Msg = "请选择图表"
+		return
+	}
+
+	err, errMsg := services.DeleteChart(req.ChartInfoId)
+	if err != nil {
+		br.Msg = errMsg
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}

+ 9 - 0
go.mod

@@ -9,6 +9,7 @@ require (
 	github.com/go-sql-driver/mysql v1.7.0
 	github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b
 	github.com/shopspring/decimal v1.3.1
+	go.mongodb.org/mongo-driver v1.15.0
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 )
 
@@ -16,6 +17,7 @@ require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/golang/snappy v0.0.1 // indirect
 	github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac // indirect
 	github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 // indirect
 	github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2 // indirect
@@ -23,10 +25,12 @@ require (
 	github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9 // indirect
 	github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
+	github.com/klauspost/compress v1.13.6 // indirect
 	github.com/kr/text v0.2.0 // indirect
 	github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.15.1 // indirect
 	github.com/prometheus/client_model v0.3.0 // indirect
@@ -34,8 +38,13 @@ require (
 	github.com/prometheus/procfs v0.9.0 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
 	github.com/stretchr/testify v1.8.4 // indirect
+	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
+	github.com/xdg-go/scram v1.1.2 // indirect
+	github.com/xdg-go/stringprep v1.0.4 // indirect
+	github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
 	golang.org/x/crypto v0.19.0 // indirect
 	golang.org/x/net v0.21.0 // indirect
+	golang.org/x/sync v0.1.0 // indirect
 	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	google.golang.org/protobuf v1.30.0 // indirect

+ 42 - 0
go.sum

@@ -20,6 +20,8 @@ github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgj
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac h1:Q0Jsdxl5jbxouNs1TQYt0gxesYMU4VXRbsTlgDloZ50=
 github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
 github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 h1:EvokxLQsaaQjcWVWSV38221VAK7qc2zhaO17bKys/18=
@@ -39,6 +41,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -51,6 +55,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -71,15 +77,51 @@ github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5g
 github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
+github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
+github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
+github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc=
+go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
 golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=

+ 1 - 0
main.go

@@ -10,5 +10,6 @@ func main() {
 		beego.BConfig.WebConfig.DirectoryIndex = true
 		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
 	}
+
 	beego.Run()
 }

+ 200 - 0
models/admin.go

@@ -0,0 +1,200 @@
+package models
+
+import (
+	"eta/eta_forum_hub/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+type LoginReq struct {
+	Username   string `description:"账号"`
+	Password   string `description:"密码"`
+	IsRemember bool   `description:"是否属于受信设备"`
+}
+
+type LoginResp struct {
+	Authorization   string
+	AdminName       string `description:"系统用户名称"`
+	RealName        string `description:"系统用户姓名"`
+	RoleName        string `description:"角色名称"`
+	RoleTypeCode    string `description:"角色类型编码"`
+	SysRoleTypeCode string `description:"角色类型编码"`
+	AdminId         int    `description:"系统用户id"`
+	ProductName     string `description:"产品名称:admin,ficc,权益"`
+	Authority       int    `description:"管理权限,0:无,1:部门负责人,2:小组负责人,或者ficc销售主管,4:ficc销售组长"`
+}
+
+type Admin struct {
+	AdminId                   int    `orm:"column(admin_id);pk" description:"系统用户id"`
+	AdminName                 string `description:"系统用户名称"`
+	AdminAvatar               string `description:"用户头像"`
+	RealName                  string `description:"系统用户姓名"`
+	Password                  string `json:"-"`
+	LastUpdatedPasswordTime   string `json:"-"`
+	Enabled                   int
+	Email                     string `description:"系统用户邮箱"`
+	LastLoginTime             string
+	CreatedTime               time.Time
+	LastUpdatedTime           string
+	Role                      string    `description:"系统用户角色"`
+	Mobile                    string    `description:"手机号"`
+	RoleType                  int       `description:"角色类型:1需要录入指标,0:不需要"`
+	RoleId                    int       `description:"角色ID"`
+	RoleName                  string    `description:"角色名称"`
+	RoleTypeCode              string    `description:"角色类型编码"`
+	DepartmentId              int       `description:"部门id"`
+	DepartmentName            string    `description:"部门名称"`
+	GroupId                   int       `description:"分组id"`
+	GroupName                 string    `description:"分组名称"`
+	Authority                 int       `description:"管理权限,0:无,1:部门负责人,2:小组负责人,或者ficc销售主管,3:超级管理员,4:ficc销售组长"`
+	Position                  string    `description:"职位"`
+	DisableTime               time.Time `description:"禁用时间"`
+	ChartPermission           int8      `description:"图表权限id"`
+	OpenId                    string    `description:"弘则部门公众号的openid"`
+	UnionId                   string    `description:"微信公众平台唯一标识"`
+	EdbPermission             int8      `description:"指标库操作权限,0:只能操作 自己的,1:所有指标可操作"`
+	MysteelChemicalPermission int8      `description:"钢联化工指标操作权限,0:只能操作 自己的,1:所有指标可操作"`
+	PredictEdbPermission      int8      `description:"预测指标库操作权限,0:只能操作 自己的,1:所有预测指标可操作"`
+	Province                  string    `description:"省"`
+	ProvinceCode              string    `description:"省编码"`
+	City                      string    `description:"市"`
+	CityCode                  string    `description:"市编码"`
+	EmployeeId                string    `description:"员工工号(钉钉/每刻报销)"`
+	TelAreaCode               string    `description:"手机区号"`
+	IsLdap                    int       `description:"是否为域用户:0-系统账户;1-域用户"`
+}
+
+// Update 更新用户基础信息
+func (item *Admin) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(item, cols...)
+	return
+}
+
+func CheckSysUser(userName, password string) (item *Admin, err error) {
+	sql := ` SELECT a.*,b.role_type_code FROM admin AS a
+			 INNER JOIN sys_role AS b ON a.role_id=b.role_id WHERE a.admin_name=? AND a.password=? LIMIT 1`
+	o := orm.NewOrm()
+	err = o.Raw(sql, userName, password).QueryRow(&item)
+	return
+}
+
+func GetSysUserById(sysUserId int) (item *Admin, err error) {
+	sql := `SELECT * FROM admin WHERE admin_id=? LIMIT 1`
+	o := orm.NewOrm()
+	err = o.Raw(sql, sysUserId).QueryRow(&item)
+	return
+}
+
+func ModifyPwd(sysUserId int, newPwd string) (err error) {
+	sql := `UPDATE admin SET password=?,last_updated_time=NOW() WHERE admin_id=? `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, newPwd, sysUserId).Exec()
+	return
+}
+
+type ModifyPwdReq struct {
+	OldPwd string `description:"旧密码"`
+	NewPwd string `description:"新密码"`
+}
+
+// AdminWxUserRelation 管理员-微信用户关联
+type AdminWxUserRelation struct {
+	AdminId   int    `json:"admin_id"`
+	AdminName string `json:"admin_name"`
+	RealName  string `json:"real_name"`
+	UserId    int    `json:"user_id"`
+}
+
+// GetAdminListByIdList 根据用户id列表获取系统用户列表
+func GetAdminListByIdList(idList []int) (items []*Admin, err error) {
+	lenNum := len(idList)
+	if lenNum <= 0 {
+		return
+	}
+	sql := `SELECT * FROM admin WHERE admin_id in (` + utils.GetOrmInReplace(lenNum) + `) and enabled=1 `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, idList).QueryRows(&items)
+	return
+}
+
+// GetAdminListByIdList 根据用户id列表获取系统用户列表
+func GetAdminListByIdListWithoutEnable(idList []int) (items []*Admin, err error) {
+	lenNum := len(idList)
+	if lenNum <= 0 {
+		return
+	}
+	sql := `SELECT * FROM admin WHERE admin_id in (` + utils.GetOrmInReplace(lenNum) + `) `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, idList).QueryRows(&items)
+	return
+}
+
+func (item *Admin) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM admin WHERE 1=1 %s`, condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (item *Admin) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*Admin, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY created_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM admin WHERE 1=1 %s %s`, fields, condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// GetSysUserByMobile 手机号获取用户
+func GetSysUserByMobile(mobile string) (item *Admin, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+				a.*, b.role_type_code
+			FROM
+				admin AS a
+			INNER JOIN sys_role AS b ON a.role_id = b.role_id
+			WHERE
+				a.mobile = ?
+			LIMIT 1`
+	err = o.Raw(sql, mobile).QueryRow(&item)
+	return
+}
+
+// GetSysUserByEmail 邮箱获取用户
+func GetSysUserByEmail(email string) (item *Admin, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+				a.*, b.role_type_code
+			FROM
+				admin AS a
+			INNER JOIN sys_role AS b ON a.role_id = b.role_id
+			WHERE
+				a.email = ?
+			LIMIT 1`
+	err = o.Raw(sql, email).QueryRow(&item)
+	return
+}
+
+// GetSysUserByAdminName 账号获取用户
+func GetSysUserByAdminName(adminName string) (item *Admin, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+				a.*, b.role_type_code
+			FROM
+				admin AS a
+			INNER JOIN sys_role AS b ON a.role_id = b.role_id
+			WHERE
+				a.admin_name = ?
+			LIMIT 1`
+	err = o.Raw(sql, adminName).QueryRow(&item)
+	return
+}

+ 350 - 0
models/chart_classify.go

@@ -0,0 +1,350 @@
+package models
+
+import (
+	"eta/eta_forum_hub/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type ChartClassify struct {
+	ChartClassifyId   int       `orm:"column(chart_classify_id);pk"`
+	ChartClassifyName string    `description:"分类名称"`
+	ParentId          int       `description:"父级id"`
+	HasData           int       `description:"是否含有指标数据"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+	SysUserId         int       `description:"创建人id"`
+	SysUserRealName   string    `description:"创建人姓名"`
+	Level             int       `description:"层级"`
+	UniqueCode        string    `description:"唯一编码"`
+	Sort              int       `description:"排序字段,越小越靠前,默认值:10"`
+	Source            int       `description:"1:ETA图库;2:商品价格曲线"`
+	IsJoinPermission  int       `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+}
+
+func AddChartClassify(item *ChartClassify) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type AddChartClassifyReq struct {
+	ChartClassifyName string `description:"分类名称"`
+	ParentId          int    `description:"父级id,第一级传0"`
+	Level             int    `description:"层级,第一级传0,其余传上一级的层级"`
+}
+
+func GetChartClassifyCount(chartClassifyName string, parentId, source int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM chart_classify WHERE parent_id=? AND source = ? AND chart_classify_name=? `
+	err = o.Raw(sql, parentId, source, chartClassifyName).QueryRow(&count)
+	return
+}
+
+type EditChartClassifyReq struct {
+	ChartClassifyName string `description:"分类名称"`
+	ChartClassifyId   int    `description:"分类id"`
+}
+
+func GetChartClassifyById(classifyId int) (item *ChartClassify, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_classify WHERE chart_classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+func GetChartClassifyCountById(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT count(1) AS count FROM chart_classify WHERE chart_classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+func EditChartClassify(classifyId, source int, chartClassifyName string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE chart_classify SET chart_classify_name=?,modify_time=NOW() WHERE chart_classify_id=? AND source = ? `
+	_, err = o.Raw(sql, chartClassifyName, classifyId, source).Exec()
+	return
+}
+
+type DeleteChartClassifyReq struct {
+	ChartClassifyId int `description:"分类id"`
+	ChartInfoId     int `description:"指标id"`
+}
+
+func GetChartInfoCountByClassifyId(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM chart_info AS a
+				WHERE a.chart_classify_id IN(
+				SELECT t.chart_classify_id FROM 
+				(
+				SELECT rd.*
+				FROM (SELECT * FROM chart_classify WHERE parent_id IS NOT NULL) rd,
+					 (SELECT @pid := ?) pd 
+				WHERE FIND_IN_SET(parent_id, @pid) > 0 
+				  AND @pid := CONCAT(@pid, ',', chart_classify_id) 
+				UNION SELECT * FROM chart_classify WHERE chart_classify_id = @pid
+				)AS t
+				) `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+func DeleteChartClassify(classifyId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` DELETE FROM chart_classify
+				WHERE chart_classify_id IN(
+				SELECT t.chart_classify_id FROM
+				(
+				SELECT rd.*
+				FROM (SELECT * FROM chart_classify WHERE parent_id IS NOT NULL) rd,
+				(SELECT @pid := ?) pd
+				WHERE FIND_IN_SET(parent_id, @pid) > 0
+				AND @pid := CONCAT(@pid, ',', chart_classify_id)
+				UNION SELECT * FROM chart_classify WHERE chart_classify_id = @pid
+				)AS t
+				) `
+	_, err = o.Raw(sql, classifyId).Exec()
+	return
+}
+
+// GetChartClassifyByParentId
+// @param source int 1:ETA图库;2:商品价格曲线;3:相关性图表
+func GetChartClassifyByParentId(parentId, source int) (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE parent_id=? AND source = ? order by sort asc,chart_classify_id asc`
+	_, err = o.Raw(sql, parentId, source).QueryRows(&items)
+	return
+}
+
+// GetChartClassifyAll
+// @param source int 1:ETA图库;2:商品价格曲线;3:相关性图表
+func GetChartClassifyAll(source int) (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE parent_id<>0 AND source = ? order by sort asc,chart_classify_id asc`
+	_, err = o.Raw(sql, source).QueryRows(&items)
+	return
+}
+
+type ChartClassifyItems struct {
+	ChartClassifyId     int `description:"分类id"`
+	ChartInfoId         int `description:"指标id"`
+	ChartClassifyName   string
+	ChartClassifyNameEn string
+	ParentId            int
+	Level               int    `description:"层级"`
+	Sort                int    `description:"排序字段,越小越靠前,默认值:10"`
+	UniqueCode          string `description:"唯一编码"`
+	Source              int    `description:"来源id"`
+	SourceName          string `description:"来源名称"`
+	SysUserId           int    `description:"创建人id"`
+	SysUserRealName     string `description:"创建人姓名"`
+	DateType            int    `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间"`
+	StartDate           string `description:"自定义开始日期"`
+	EndDate             string `description:"自定义结束日期"`
+	ChartType           int    `description:"生成样式:1:曲线图,2:季节性图"`
+	Calendar            string `description:"公历/农历"`
+	SeasonStartDate     string `description:"季节性图开始日期"`
+	SeasonEndDate       string `description:"季节性图开始日期"`
+	Children            []*ChartClassifyItems
+	Button              ChartClassifyItemsButton `description:"按钮权限"`
+	IsJoinPermission    int                      `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth       bool                     `description:"是否有数据权限,默认:false"`
+}
+
+// ChartClassifyItemsButton 操作按钮
+type ChartClassifyItemsButton struct {
+	AddButton    bool `description:"是否可添加"`
+	OpButton     bool `description:"是否可编辑"`
+	DeleteButton bool `description:"是否可删除"`
+	MoveButton   bool `description:"是否可移动"`
+}
+
+type ChartClassifyListResp struct {
+	AllNodes      []*ChartClassifyItems
+	Language      string `description:"指标的展示语言,CN:中文,EN:英文"`
+	CanOpClassify bool   `description:"是否允许操作分类"`
+}
+
+type ChartClassifyDeleteCheckResp struct {
+	DeleteStatus int    `description:"检测状态:0:默认值,如果为0,继续走其他校验,1:该分类下关联图表不可删除,2:确认删除当前目录及包含的子目录吗"`
+	TipsMsg      string `description:"提示信息"`
+}
+
+type ChartClassifyDeleteCheckReq struct {
+	ChartClassifyId int `description:"分类id"`
+	ChartInfoId     int `description:"指标id"`
+}
+
+func GetChartClassifyCountByClassifyId(chartClassifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM (
+			SELECT rd.*
+			FROM (SELECT * FROM chart_classify WHERE parent_id IS NOT NULL) rd,
+				 (SELECT @pid := ?) pd 
+			WHERE FIND_IN_SET(parent_id, @pid) > 0 
+			  AND @pid := CONCAT(@pid, ',', chart_classify_id) 
+			UNION SELECT * FROM chart_classify WHERE chart_classify_id = @pid
+			)AS t
+			WHERE t.chart_classify_id<>? `
+	err = o.Raw(sql, chartClassifyId, chartClassifyId).QueryRow(&count)
+	return
+}
+
+func GetChartClassifyByCondition(condition string, pars []interface{}) (item *ChartClassify, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+// MoveChartClassifyReq 移动图表分类请求参数
+type MoveChartClassifyReq struct {
+	ClassifyId       int `description:"分类id"`
+	ParentClassifyId int `description:"父级分类id"`
+	PrevClassifyId   int `description:"上一个兄弟节点分类id"`
+	NextClassifyId   int `description:"下一个兄弟节点分类id"`
+}
+
+// GetFirstChartClassifyByParentId 获取当前父级图表分类下的排序第一条的数据
+func GetFirstChartClassifyByParentId(parentId int) (item *ChartClassify, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE parent_id=? order by sort asc,chart_classify_id asc limit 1`
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+// GetFirstChartClassifyByParentIdAndSource 获取当前父级图表分类下的排序第一条的数据
+func GetFirstChartClassifyByParentIdAndSource(parentId, source int) (item *ChartClassify, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE parent_id=?  and source = ? order by sort asc,chart_classify_id asc limit 1`
+	err = o.Raw(sql, parentId, source).QueryRow(&item)
+	return
+}
+
+// UpdateChartClassifySortByParentId 根据图表父类id更新排序
+func UpdateChartClassifySortByParentId(parentId, classifyId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := ` update chart_classify set sort = ` + updateSort + ` WHERE parent_id=? and sort > ? `
+	if classifyId > 0 {
+		sql += ` or ( chart_classify_id > ` + fmt.Sprint(classifyId) + ` and sort= ` + fmt.Sprint(nowSort) + `)`
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// Update 更新图表分类基础信息
+func (chartClassify *ChartClassify) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(chartClassify, cols...)
+	return
+}
+
+// GetChartClassifyMaxSort 获取图表分类下最大的排序数
+func GetChartClassifyMaxSort(parentId, source int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT Max(sort) AS sort FROM chart_classify WHERE parent_id=? AND source = ? `
+	err = o.Raw(sql, parentId, source).QueryRow(&sort)
+	return
+}
+
+type ChartClassifyView struct {
+	ChartClassifyId   int    `orm:"column(chart_classify_id);pk"`
+	ChartClassifyName string `description:"分类名称"`
+	ParentId          int    `description:"父级id"`
+}
+
+func GetChartClassifyViewById(classifyId int) (item *ChartClassifyView, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_classify WHERE chart_classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+func GetChartClassifyByParentIdFromETA(parentId int) (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE parent_id=? AND source = 1 order by sort asc,chart_classify_id asc`
+	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	return
+}
+
+func GetChartClassifyAllFromETA() (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE parent_id<>0 AND source = 1 order by sort asc,chart_classify_id asc`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+func GetChartClassifyTwo(source int) (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE level=3 AND source = ? order by sort asc,chart_classify_id asc`
+	_, err = o.Raw(sql, source).QueryRows(&items)
+	return
+}
+
+func GetChartClassifyByLevel(level, source int) (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE level=? AND source = ? order by sort asc,chart_classify_id asc`
+	_, err = o.Raw(sql, level, source).QueryRows(&items)
+	return
+}
+
+func EditChartClassifySysUser(classifyId, sysUserId int, chartClassifyName string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE chart_classify SET sys_user_id=?,sys_user_real_name=?,modify_time=NOW() WHERE parent_id=?  AND level=3 `
+	_, err = o.Raw(sql, sysUserId, chartClassifyName, classifyId).Exec()
+	return
+}
+
+func GetAllChartClassifyItemsBySource(source int) (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_classify WHERE source = ? order by sort ASC,chart_classify_id ASC`
+	_, err = o.Raw(sql, source).QueryRows(&items)
+	return
+}
+
+// GetChartClassifyByParentIdAndName 根据父级ID和名称获取分类
+func GetChartClassifyByParentIdAndName(parentId int, classifyName string, classifyId int) (item *ChartClassify, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_classify WHERE parent_id = ? AND chart_classify_name = ? AND chart_classify_id <> ? LIMIT 1`
+	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.NewOrm()
+	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.NewOrm()
+	sql := `SELECT * FROM chart_classify WHERE source = ? AND is_join_permission = ? `
+	_, err = o.Raw(sql, source, isJoinPermission).QueryRows(&items)
+	return
+}

+ 318 - 0
models/chart_edb_mapping.go

@@ -0,0 +1,318 @@
+package models
+
+import (
+	"eta/eta_forum_hub/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type ChartEdbMapping struct {
+	ChartEdbMappingId int       `orm:"column(chart_edb_mapping_id);pk"`
+	ChartInfoId       int       `description:"图表id"`
+	EdbInfoId         int       `description:"指标id"`
+	CreateTime        time.Time `description:"创建时间"`
+	ModifyTime        time.Time `description:"修改时间"`
+	UniqueCode        string    `description:"唯一编码"`
+	MaxData           float64   `description:"上限"`
+	MinData           float64   `description:"下限"`
+	IsOrder           bool      `description:"true:正序,false:逆序"`
+	IsAxis            int       `description:"true:左轴,false:右轴"`
+	EdbInfoType       int       `description:"true:标准指标,false:领先指标"`
+	LeadValue         int       `description:"领先值"`
+	LeadUnit          string    `description:"领先单位"`
+	ChartStyle        string    `description:"图表类型"`
+	ChartColor        string    `description:"颜色"`
+	PredictChartColor string    `description:"预测数据的颜色"`
+	ChartWidth        float64   `description:"线条大小"`
+	Source            int       `description:"1:ETA图库;2:商品价格曲线"`
+	EdbAliasName      string    `description:"中文别名"`
+	IsConvert         int       `description:"是否数据转换 0不转 1转"`
+	ConvertType       int       `description:"数据转换类型 1乘 2除 3对数"`
+	ConvertValue      float64   `description:"数据转换值"`
+	ConvertUnit       string    `description:"数据转换单位"`
+	ConvertEnUnit     string    `description:"数据转换单位"`
+	EdbCode           string    `description:"指标编码"`
+}
+
+func AddChartEdbMapping(items []*ChartEdbMapping) (err error) {
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func GetChartEdbMappingList(chartInfoId int) (list []*ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	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.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
+			 WHERE chart_info_id=? 
+             ORDER BY chart_edb_mapping_id ASC `
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&list)
+	return
+}
+
+func GetChartEdbMappingListByChartInfoIds(chartInfoIds string) (list []*ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	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 + `) 
+             ORDER BY chart_edb_mapping_id ASC `
+	_, err = o.Raw(sql).QueryRows(&list)
+	return
+}
+
+// GetChartEdbMappingListByEdbInfoIdList 根据指标id列表获取关联关系
+func GetChartEdbMappingListByEdbInfoIdList(edbIdList []int) (list []*ChartEdbInfoMapping, err error) {
+	num := len(edbIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	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) + `)
+              `
+	_, err = o.Raw(sql, edbIdList, edbIdList).QueryRows(&list)
+	return
+}
+
+// GetChartEdbMappingListByIdList 通过图表id列表获取
+func GetChartEdbMappingListByIdList(chartInfoIdList []int) (list []*ChartEdbInfoMapping, err error) {
+	num := len(chartInfoIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	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) + `) 
+             ORDER BY chart_edb_mapping_id ASC `
+	_, err = o.Raw(sql, chartInfoIdList).QueryRows(&list)
+	return
+}
+
+func GetRelationEdbInfoListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT a.* FROM edb_info AS a 
+	JOIN edb_info_calculate_mapping AS b on a.edb_info_id = b.edb_info_id WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	//sql += " ORDER BY sort ASC,chart_info_id DESC LIMIT ?,? "
+	sql += " ORDER BY a.create_time DESC LIMIT ?,? "
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&item)
+	return
+}
+
+func GetRelationEdbInfoListCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM edb_info AS a 
+	JOIN edb_info_calculate_mapping AS b on a.edb_info_id = b.edb_info_id WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+// GetEtaEdbChartEdbMapping       商品曲线图查询对应的普通指标
+func GetEtaEdbChartEdbMapping(chartInfoId int) (item *ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	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,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 = ?
+             ORDER BY chart_edb_mapping_id ASC `
+	err = o.Raw(sql, chartInfoId, utils.CHART_SOURCE_DEFAULT).QueryRow(&item)
+	return
+}
+
+// GetFutureGoodEdbChartEdbMapping       商品曲线图查询对应的商品指标
+func GetFutureGoodEdbChartEdbMapping(chartInfoId int) (item *ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	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.future_good_edb_info_id,b.future_good_edb_code as edb_code,b.future_good_edb_name as edb_name,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value
+             FROM chart_edb_mapping AS a
+			 INNER JOIN future_good_edb_info AS b ON a.edb_info_id=b.future_good_edb_info_id
+			 WHERE a.chart_info_id=? AND a.source = ?
+             ORDER BY chart_edb_mapping_id ASC `
+	err = o.Raw(sql, chartInfoId, utils.CHART_SOURCE_FUTURE_GOOD).QueryRow(&item)
+	return
+}
+
+// GetFutureGoodEdbChartEdbMappingList       商品曲线图查询对应的商品指标
+func GetFutureGoodEdbChartEdbMappingList(chartInfoId int) (items []*ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	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.future_good_edb_info_id,b.future_good_edb_code as edb_code,b.future_good_edb_name as edb_name,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value
+             FROM chart_edb_mapping AS a
+			 INNER JOIN future_good_edb_info AS b ON a.edb_info_id=b.future_good_edb_info_id
+			 WHERE a.chart_info_id=? AND a.source = ?
+             ORDER BY chart_edb_mapping_id ASC `
+	_, err = o.Raw(sql, chartInfoId, utils.CHART_SOURCE_FUTURE_GOOD).QueryRows(&items)
+	return
+}
+
+// GetChartEdbMappingListV2 根据图表id获取指标信息,不连表查询指标表
+func GetChartEdbMappingListV2(chartInfoId int) (list []*ChartEdbMapping, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT a.* FROM chart_edb_mapping AS a
+			 WHERE chart_info_id=? 
+             ORDER BY chart_edb_mapping_id ASC `
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&list)
+	return
+}
+
+// GetChartEdbMappingByEdbInfoId 根据指标id获取edb_mapping
+func GetChartEdbMappingByEdbInfoId(edbInfoId int) (item *ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	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)
+	return
+}
+
+// GetChartEdbMappingByFutureGoodEdbInfoId 根据指标id获取edb_mapping
+func GetChartEdbMappingByFutureGoodEdbInfoId(edbInfoId int) (item *ChartEdbInfoMapping, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT future_good_edb_info_id as edb_info_id,future_good_edb_code as edb_code,b.future_good_edb_name as edb_name,b.start_date,b.end_date,b.modify_time,b.latest_date,b.latest_value,b.region_type
+             FROM future_good_edb_info b
+			 WHERE future_good_edb_info_id = ?  limit 1 `
+	err = o.Raw(sql, edbInfoId).QueryRow(&item)
+	return
+}
+
+// ModifyChartEdbMapping
+// @Description: 修改图表的关系表
+// @author: Roc
+// @datetime 2023-12-11 17:23:32
+// @param chartInfoId int
+// @param edbInfoList []*EdbInfo
+// @return err error
+func ModifyChartEdbMapping(chartInfoId int, edbInfoList []*EdbInfo) (err error) {
+	o, err := orm.NewOrm().Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			fmt.Println("AddCalculateHcz,Err:" + err.Error())
+			_ = o.Rollback()
+		} else {
+			_ = o.Commit()
+		}
+	}()
+	list := make([]*ChartEdbMapping, 0)
+	sql := ` SELECT a.*
+             FROM chart_edb_mapping AS a
+			 WHERE chart_info_id=? 
+             ORDER BY chart_edb_mapping_id ASC `
+	_, err = o.Raw(sql, chartInfoId).QueryRows(&list)
+
+	if err != nil {
+		return
+	}
+
+	mappingIdMap := make(map[int]*ChartEdbMapping)
+	removeMapping := make(map[int]int)
+	for _, v := range list {
+		mappingIdMap[v.EdbInfoId] = v
+		removeMapping[v.EdbInfoId] = v.ChartEdbMappingId
+	}
+
+	addList := make([]*ChartEdbMapping, 0)
+	for _, v := range edbInfoList {
+		_, ok := mappingIdMap[v.EdbInfoId]
+		// 存在该指标关系就不处理了
+		if ok {
+			delete(removeMapping, v.EdbInfoId)
+			continue
+		}
+		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+		// 不存在就添加
+		addList = append(addList, &ChartEdbMapping{
+			//ChartEdbMappingId: 0,
+			ChartInfoId: chartInfoId,
+			EdbInfoId:   v.EdbInfoId,
+			CreateTime:  time.Now(),
+			ModifyTime:  time.Now(),
+			UniqueCode:  utils.MD5(utils.CHART_PREFIX + "_" + fmt.Sprint(chartInfoId) + "_" + fmt.Sprint(v.EdbInfoId) + "_" + timestamp),
+			MaxData:     v.MaxValue,
+			MinData:     v.MinValue,
+			//IsOrder:     v.IsOrder,
+			//IsAxis:      v.IsAxis,
+			EdbInfoType: v.EdbInfoType,
+			//LeadValue:   v.LeadValue,
+			//LeadUnit:    v.LeadUnit,
+			//ChartStyle:  v.ChartStyle,
+			//ChartColor:  v.ChartColor,
+			//ChartWidth:  v.ChartWidth,
+			Source: v.Source,
+		})
+	}
+
+	// 需要添加的话,那就添加吧
+	if len(addList) > 0 {
+		_, err = o.InsertMulti(len(addList), addList)
+		if err != nil {
+			return
+		}
+	}
+
+	// 移除不必要的mapping
+	if len(removeMapping) > 0 {
+		removeIdList := make([]string, 0) //需要移除的日期
+		for _, v := range removeMapping {
+			removeIdList = append(removeIdList, fmt.Sprint(v))
+		}
+		removeIdStr := strings.Join(removeIdList, `","`)
+		removeIdStr = `"` + removeIdStr + `"`
+		//如果拼接指标变更了,那么需要删除所有的指标数据
+		sql := fmt.Sprintf(` DELETE FROM chart_edb_mapping WHERE chart_edb_mapping_id in (%s) `, removeIdStr)
+
+		_, err = o.Raw(sql).Exec()
+		if err != nil {
+			err = fmt.Errorf("移除不必要的mapping失败,Err:" + err.Error())
+			return
+		}
+	}
+
+	return
+}
+
+func DeleteChartEdbMappingByChartEdbMappingId(removeIdStr string) (err error) {
+	// 删除映射关系
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(` DELETE FROM chart_edb_mapping WHERE chart_edb_mapping_id in (%s) `, removeIdStr)
+	_, err = o.Raw(sql).Exec()
+	if err != nil {
+		err = fmt.Errorf("删除映射关系失败,Err:" + err.Error())
+		return
+	}
+	return
+}
+
+func (c *ChartEdbMapping) Update(col []string) (err error) {
+	// 删除映射关系
+	o := orm.NewOrm()
+	_, err = o.Update(c, col...)
+	return
+}
+
+func GetChartEdbMappingCount(edbInfoId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM chart_edb_mapping WHERE edb_info_id=? `
+	err = o.Raw(sql, edbInfoId).QueryRow(&count)
+	return
+}

+ 1928 - 0
models/chart_info.go

@@ -0,0 +1,1928 @@
+package models
+
+import (
+	"eta/eta_forum_hub/models/mgodb"
+	"eta/eta_forum_hub/utils"
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type ChartInfo struct {
+	ChartInfoId       int    `orm:"column(chart_info_id);pk"`
+	ChartName         string `description:"来源名称"`
+	ChartNameEn       string `description:"英文图表名称"`
+	ChartClassifyId   int    `description:"图表分类id"`
+	SysUserId         int
+	SysUserRealName   string
+	UniqueCode        string `description:"图表唯一编码"`
+	CreateTime        time.Time
+	ModifyTime        time.Time
+	DateType          int    `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间"`
+	StartDate         string `description:"自定义开始日期"`
+	EndDate           string `description:"自定义结束日期"`
+	IsSetName         int    `description:"设置名称"`
+	EdbInfoIds        string `description:"指标id"`
+	ChartType         int    `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图,8:商品价格曲线图,9:相关性图,10:截面散点图, 11:雷达图"`
+	Calendar          string `description:"公历/农历"`
+	SeasonStartDate   string `description:"季节性图开始日期"`
+	SeasonEndDate     string `description:"季节性图开始日期"`
+	ChartImage        string `description:"图表图片"`
+	Sort              int    `description:"排序字段,数字越小越排前面"`
+	XMin              string `description:"图表X轴最小值"`
+	XMax              string `description:"图表X轴最大值"`
+	LeftMin           string `description:"图表左侧最小值"`
+	LeftMax           string `description:"图表左侧最大值"`
+	RightMin          string `description:"图表右侧最小值"`
+	RightMax          string `description:"图表右侧最大值"`
+	Right2Min         string `description:"图表右侧2最小值"`
+	Right2Max         string `description:"图表右侧2最大值"`
+	MinMaxSave        int    `description:"是否手动保存过上下限:0-否;1-是"`
+	Disabled          int    `description:"是否禁用,0:启用,1:禁用,默认:0"`
+	BarConfig         string `description:"柱方图的配置,json数据"`
+	Source            int    `description:"1:ETA图库;2:商品价格曲线"`
+	ExtraConfig       string `description:"图表额外配置,json数据"`
+	SeasonExtraConfig string `description:"季节性图表中的配置,json数据"`
+	StartYear         int    `description:"当选择的日期类型为最近N年类型时,即date_type=20, 用start_year表示N"`
+	ChartThemeId      int    `description:"图表应用主题ID"`
+	SourcesFrom       string `description:"图表来源"`
+	Instructions      string `description:"图表说明"`
+	MarkersLines      string `description:"标识线"`
+	MarkersAreas      string `description:"标识区"`
+	Unit              string `description:"中文单位名称"`
+	UnitEn            string `description:"英文单位名称"`
+	IsJoinPermission  int    `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+}
+
+type ChartInfoMore struct {
+	ChartInfo
+	IsEnChart     bool `description:"是否展示英文标识"`
+	HaveOperaAuth bool `description:"是否有数据权限,默认:false"`
+}
+
+func AddChartInfo(item *ChartInfo) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+func UpdateChartInfo(item *ChartInfo) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(&item)
+	return
+}
+
+type ChartInfoItem struct {
+	ChartInfoId     int    `description:"图表id"`
+	ChartName       string `description:"图表名称"`
+	ChartClassifyId int    `description:"图表分类"`
+}
+
+// GetChartInfoAll 用于分类展示
+// @param source int 1:ETA图库;2:商品价格曲线
+func GetChartInfoAll(sourceList []int) (items []*ChartClassifyItems, err error) {
+	num := len(sourceList)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrm()
+	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,source
+            FROM chart_info WHERE source in (` + utils.GetOrmInReplace(num) + `)  ORDER BY sort asc,chart_info_id ASC `
+	_, err = o.Raw(sql, sourceList).QueryRows(&items)
+	return
+}
+
+// GetChartInfoByAdminId 获取所有我创建的图表,用于分类展示
+func GetChartInfoByAdminId(sourceList []int, adminId int) (items []*ChartClassifyItems, err error) {
+	num := len(sourceList)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrm()
+	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
+            FROM chart_info where source in (` + utils.GetOrmInReplace(num) + `)  AND sys_user_id = ? ORDER BY sort asc,create_time ASC `
+	_, err = o.Raw(sql, sourceList, adminId).QueryRows(&items)
+	return
+}
+
+// 用于分类展示
+func GetChartInfoAllList() (items []*ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT *
+            FROM chart_info ORDER BY create_time ASC `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// 图表检索数据
+type ChartInfoSearch struct {
+	EdbCode   string `description:"图表编码"`
+	StartDate string `description:"起始日期"`
+	EndDate   string `description:"终止日期"`
+	DataList  []*EdbInfoSearchData
+}
+
+type ChartInfoSearchData struct {
+	DataTime string  `description:"数据日期"`
+	Value    float64 `description:"数据"`
+}
+
+type ChartInfoSearchResp struct {
+	SearchItem *EdbInfoSearch `description:"图表分类"`
+	Status     int            `description:"1:数据已存在于弘则数据库,2:新数据"`
+}
+
+func GetChartInfoById(chartInfoId int) (item *ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE chart_info_id=? `
+	err = o.Raw(sql, chartInfoId).QueryRow(&item)
+	return
+}
+
+func GetChartInfoViewById(chartInfoId int) (item *ChartInfoView, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE chart_info_id=? `
+	err = o.Raw(sql, chartInfoId).QueryRow(&item)
+	return
+}
+
+func GetChartInfoViewByIds(chartInfoIds []string) (list []*ChartInfoView, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE chart_info_id in ("` + strings.Join(chartInfoIds, `","`) + `") `
+	_, err = o.Raw(sql).QueryRows(&list)
+	return
+}
+
+type SaveChartInfoReq struct {
+	ChartEdbInfoList []*ChartSaveItem `description:"指标及配置信息"`
+	ChartInfoId      int              `description:"图表id,新增时传0"`
+	DateType         int              `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间,6:起始日期至今"`
+	StartDate        string           `description:"自定义开始日期"`
+	EndDate          string           `description:"自定义结束日期"`
+	Calendar         string           `description:"公历/农历"`
+	LeftMin          string           `description:"图表左侧最小值"`
+	LeftMax          string           `description:"图表左侧最大值"`
+	RightMin         string           `description:"图表右侧最小值"`
+	RightMax         string           `description:"图表右侧最大值"`
+	Right2Min        string           `description:"图表右侧最小值"`
+	Right2Max        string           `description:"图表右侧最大值"`
+	MinMaxSave       int              `description:"是否手动保存过上下限:0-否;1-是"`
+	ExtraConfig      string           `description:"图表额外配置,json数据"`
+	StartYear        int              `description:"当选择的日期类型为最近N年类型时,即date_type=20, 用start_year表示N"`
+}
+
+type ChartSaveItem struct {
+	EdbInfoId         int     `description:"指标id"`
+	MaxData           float64 `description:"上限"`
+	MinData           float64 `description:"下限"`
+	IsOrder           bool    `description:"true:正序,false:逆序"`
+	IsAxis            int     `description:"1:左轴,0:右轴"`
+	EdbInfoType       int     `description:"1:标准指标,0:领先指标"`
+	LeadValue         int     `description:"领先值"`
+	LeadUnit          string  `description:"领先单位"`
+	ChartStyle        string  `description:"图表类型"`
+	ChartColor        string  `description:"颜色"`
+	PredictChartColor string  `description:"预测数据的颜色"`
+	ChartWidth        float64 `description:"线条大小"`
+	Source            int     `description:"1:ETA图库;2:商品价格曲线"`
+	EdbAliasName      string  `description:"中文别名"`
+	IsConvert         int     `description:"是否数据转换 0不转 1转"`
+	ConvertType       int     `description:"数据转换类型 1乘 2除 3对数"`
+	ConvertValue      float64 `description:"数据转换值"`
+	ConvertUnit       string  `description:"数据转换单位"`
+	ConvertEnUnit     string  `description:"数据转换单位"`
+}
+
+func DeleteChartInfoAndData(chartInfoId int) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	sql := ` DELETE FROM chart_info WHERE chart_info_id=? `
+	_, err = to.Raw(sql, chartInfoId).Exec()
+	if err != nil {
+		return
+	}
+	sql = ` DELETE FROM  chart_edb_mapping WHERE chart_info_id=? `
+	_, err = to.Raw(sql, chartInfoId).Exec()
+	return
+}
+
+func GetChartInfoCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM chart_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+type EditChartInfoReq struct {
+	ChartInfoId          int                     `description:"图表ID"`
+	ChartName            string                  `description:"图表名称"`
+	ChartClassifyId      int                     `description:"分类id"`
+	ChartEdbInfoList     []*ChartSaveItem        `description:"指标及配置信息"`
+	ChartType            int                     `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图,8:商品价格曲线图,9:相关性图,10:截面散点图"`
+	DateType             int                     `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间,6:起始日期至今,20:N年至今"`
+	StartDate            string                  `description:"自定义开始日期"`
+	EndDate              string                  `description:"自定义结束日期"`
+	Calendar             string                  `description:"公历/农历"`
+	LeftMin              string                  `description:"图表左侧最小值"`
+	LeftMax              string                  `description:"图表左侧最大值"`
+	RightMin             string                  `description:"图表右侧最小值"`
+	RightMax             string                  `description:"图表右侧最大值"`
+	Right2Min            string                  `description:"图表右侧最小值"`
+	Right2Max            string                  `description:"图表右侧最大值"`
+	MinMaxSave           int                     `description:"是否手动保存过上下限:0-否;1-是"`
+	BarChartInfo         BarChartInfoReq         `description:"柱方图的配置"`
+	CorrelationChartInfo CorrelationChartInfoReq `description:"相关性图表配置"`
+	ExtraConfig          string                  `description:"图表额外配置信息,json字符串"`
+	SeasonExtraConfig    SeasonExtraItem         `description:"季节性图表中的配置,json数据"`
+	StartYear            int                     `description:"当选择的日期类型为最近N年类型时,即date_type=20, 用start_year表示N"`
+	ChartThemeId         int                     `description:"图表应用主题ID"`
+	SourcesFrom          string                  `description:"图表来源"`
+	Instructions         string                  `description:"图表说明"`
+	MarkersLines         string                  `description:"标识线"`
+	MarkersAreas         string                  `description:"标识区"`
+	Unit                 string                  `description:"中文单位名称"`
+	UnitEn               string                  `description:"英文单位名称"`
+}
+
+type EditChartEnInfoReq struct {
+	ChartInfoId      int                       `description:"图表ID"`
+	ChartNameEn      string                    `description:"英文图表名称"`
+	ChartEdbInfoList []*EditChartEnInfoEdbItem `description:"指标及配置信息"`
+	ExtraConfig      string                    `description:"图表额外配置信息,json字符串"`
+}
+type EditChartEnInfoEdbItem struct {
+	EdbInfoId int    `description:"指标ID"`
+	EdbNameEn string `description:"英文指标名称"`
+	UnitEn    string `description:"英文单位"`
+}
+
+func ModifyChartInfo(item *EditChartInfoReq) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE  chart_info
+			SET
+			  chart_name =?,
+			  chart_classify_id = ?,
+              is_set_name=1,
+			  modify_time = NOW()
+			WHERE chart_info_id = ?`
+	_, err = o.Raw(sql, item.ChartName, item.ChartClassifyId, item.ChartInfoId).Exec()
+	return
+}
+
+type ChartInfoList struct {
+	ChartInfoId          int    `orm:"column(chart_info_id);pk"`
+	ChartName            string `description:"来源名称"`
+	ChartChartClassifyId int    `description:"图表分类id"`
+	SysUserId            int
+	SysUserRealName      string
+	UniqueCode           string `description:"图表唯一编码"`
+	CreateTime           time.Time
+	ModifyTime           time.Time
+	EdbInfoList          []*EdbInfoList
+}
+
+type ChartInfoListResp struct {
+	Item *ChartInfoList
+}
+
+func GetChartInfoByCondition(condition string, pars []interface{}) (item *ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func GetChartInfoByNewest(source int) (item *ChartInfoList, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE 1=1 AND source = ? ORDER BY modify_time DESC LIMIT 1 `
+	err = o.Raw(sql, source).QueryRow(&item)
+	return
+}
+
+func ModifyChartInfoModifyTime(chartInfoId int64) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE  chart_info SET modify_time = NOW() WHERE chart_info_id = ? `
+	_, err = o.Raw(sql, chartInfoId).Exec()
+	return
+}
+
+type MoveChartInfoReq struct {
+	ChartInfoId     int `description:"图表ID"`
+	PrevChartInfoId int `description:"上一个图表ID"`
+	NextChartInfoId int `description:"下一个图表ID"`
+	ChartClassifyId int `description:"分类id"`
+}
+
+func MoveChartInfo(chartInfoId, classifyId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE  chart_info
+			SET
+			  chart_classify_id = ?
+			WHERE chart_info_id = ?`
+	_, err = o.Raw(sql, classifyId, chartInfoId).Exec()
+	return
+}
+
+type DeleteChartInfoReq struct {
+	ChartInfoId int `description:"图表ID"`
+}
+
+type EdbDataList struct {
+	EdbDataId     int     `description:" 指标数据ID"`
+	EdbInfoId     int     `description:"指标ID"`
+	DataTime      string  //`json:"-" description:"数据日期"`
+	DataTimestamp int64   `description:"数据日期"`
+	Value         float64 `description:"数据值"`
+}
+
+type EdbDataListByUniqueCode struct {
+	EdbDataId     int     `description:" 指标数据ID" json:"-"`
+	EdbInfoId     int     `description:"指标ID" json:"-"`
+	DataTime      string  //`json:"-" description:"数据日期"`
+	DataTimestamp int64   `description:"数据日期"`
+	Value         float64 `description:"数据值"`
+}
+
+func GetEdbDataLunarList(endInfoId int, startDate, endDate string) (list []*EdbDataList, err error) {
+	tableName := "edb_data_quarter"
+	sql := `SELECT edb_data_id,edb_info_id,data_time,TRUNCATE(value,2) AS value,data_timestamp FROM %s WHERE edb_info_id=? AND data_time>=? AND data_time<=? ORDER BY data_time ASC `
+	sql = fmt.Sprintf(sql, tableName)
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, endInfoId, startDate, endDate).QueryRows(&list)
+	return
+}
+
+type ChartEdbInfoMapping struct {
+	EdbInfoId           int     `description:"指标id"`
+	SourceName          string  `description:"来源名称"`
+	Source              int     `description:"来源id"`
+	SubSource           int     `description:"来源id"`
+	EdbCode             string  `description:"指标编码"`
+	EdbName             string  `description:"指标名称"`
+	EdbAliasName        string  `description:"指标名称(别名)"`
+	EdbNameEn           string  `description:"英文指标名称"`
+	EdbAliasNameEn      string  `description:"英文指标名称(别名)"`
+	EdbType             int     `description:"指标类型:1:基础指标,2:计算指标"`
+	Frequency           string  `description:"频率"`
+	FrequencyEn         string  `description:"英文频率"`
+	Unit                string  `description:"单位"`
+	UnitEn              string  `description:"英文单位"`
+	StartDate           string  `description:"起始日期"`
+	EndDate             string  `description:"终止日期"`
+	ModifyTime          string  `description:"指标最后更新时间"`
+	ChartEdbMappingId   int     `description:"图表指标id"`
+	ChartInfoId         int     `description:"图表id"`
+	MaxData             float64 `description:"上限"`
+	MinData             float64 `description:"下限"`
+	IsOrder             bool    `description:"true:正序,false:逆序"`
+	IsAxis              int     `description:"1:左轴,0:右轴"`
+	EdbInfoType         int     `description:"1:标准指标,0:领先指标"`
+	EdbInfoCategoryType int     `description:"0:普通指标,1:预测指标"`
+	LeadValue           int     `description:"领先值"`
+	LeadUnit            string  `description:"领先单位"`
+	LeadUnitEn          string  `description:"领先英文单位"`
+	ChartStyle          string  `description:"图表类型"`
+	ChartColor          string  `description:"颜色"`
+	PredictChartColor   string  `description:"预测数据的颜色"`
+	ChartWidth          float64 `description:"线条大小"`
+	ChartType           int     `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图,8:商品价格曲线图,9:相关性图"`
+	LatestDate          string  `description:"数据最新日期"`
+	LatestValue         float64 `description:"数据最新值"`
+	MoveLatestDate      string  `description:"移动后的数据最新日期"`
+	UniqueCode          string  `description:"指标唯一编码"`
+	MinValue            float64 `json:"-" description:"最小值"`
+	MaxValue            float64 `json:"-" description:"最大值"`
+	DataList            interface{}
+	IsNullData          bool    `json:"-" description:"是否空数据"`
+	MappingSource       int     `description:"1:ETA图库;2:商品价格曲线"`
+	RegionType          string  `description:"交易所来源,海外还是国内" json:"-"`
+	ClassifyId          int     `description:"分类id"`
+	IsConvert           int     `description:"是否数据转换 0不转 1转"`
+	ConvertType         int     `description:"数据转换类型 1乘 2除 3对数"`
+	ConvertValue        float64 `description:"数据转换值"`
+	ConvertUnit         string  `description:"数据转换单位"`
+	ConvertEnUnit       string  `description:"数据转换单位"`
+	IsJoinPermission    int     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth       bool    `description:"是否有数据权限,默认:false"`
+}
+
+type QuarterData struct {
+	Year                 int
+	DataList             []*EdbDataList
+	CuttingDataTimestamp int64 `description:"切割的时间戳"`
+	ChartLegend          string
+	Years                string
+}
+
+type QuarterXDateItem struct {
+	StartDate            time.Time
+	EndDate              time.Time
+	ShowName             string
+	ChartLegend          string
+	CuttingDataTimestamp int64 `description:"切割的时间戳"`
+}
+
+type QuarterDataByUniqueCode struct {
+	Year     int
+	DataList []*EdbDataListByUniqueCode
+}
+
+type ChartEdbInfoDetailResp struct {
+	EdbInfo *ChartEdbInfoMapping
+}
+
+type ChartInfoDetailResp struct {
+	ChartInfo    *ChartInfoView
+	EdbInfoList  []*ChartEdbInfoMapping
+	XEdbIdValue  []int           `description:"柱方图的x轴数据,指标id"`
+	YDataList    []YData         `description:"柱方图的y轴数据"`
+	XDataList    []XData         `description:"商品价格曲线的X轴数据"`
+	BarChartInfo BarChartInfoReq `description:"柱方图的配置"`
+	//CorrelationChartInfo *CorrelationInfo `description:"相关性图表信息"`
+	DataResp interface{} `description:"图表数据,根据图的类型而定的,没有确定的数据格式"`
+}
+
+// XData 商品价格曲线的的x轴数据
+type XData struct {
+	Name   string `description:"别名"`
+	NameEn string `description:"英文别名"`
+}
+
+// YData 柱方图的y轴数据
+type YData struct {
+	Date           string          `description:"数据日期"`
+	ConfigDate     time.Time       `description:"配置的日期" json:"-"`
+	Color          string          `description:"数据颜色"`
+	Name           string          `description:"别名"`
+	NameEn         string          `description:"英文别名"`
+	Value          []float64       `description:"每个指标的值"`
+	NoDataEdbList  []int           `description:"没有数据的指标列表"`
+	XEdbInfoIdList []int           `description:"对应X轴的指标id列表"`
+	NameList       []string        `description:"每个值对应的名称"`
+	EnNameList     []string        `description:"每个值对应的英文名称"`
+	EdbValMap      map[int]float64 `description:"指标与值的对应" json:"-"`
+	M              []int           `description:"对应开始日期的间隔值" json:"-"`
+	Unit           string          `description:"中文单位名称"`
+	UnitEn         string          `description:"英文单位名称"`
+}
+
+func ModifyChartInfoAndMapping(edbInfoIdStr string, req *SaveChartInfoReq, chartType int) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	//非季节图
+	if chartType != 2 {
+		updateStr := `edb_info_ids=?,
+			  modify_time = NOW(),
+              date_type=?,
+			  start_date=?,
+			  end_date=?,
+ 			  left_min=?,
+			  left_max=?,
+			  right_min=?,
+			  right_max=?,
+			  right2_min=?,
+			  right2_max=?,
+			  min_max_save=?,
+              start_year=?`
+		pars := []interface{}{edbInfoIdStr, req.DateType, req.StartDate, req.EndDate, req.LeftMin, req.LeftMax, req.RightMin, req.RightMax, req.Right2Min, req.Right2Max, req.MinMaxSave, req.StartYear}
+		if req.ExtraConfig != `` {
+			updateStr += `,extra_config=? `
+			pars = append(pars, req.ExtraConfig)
+		}
+		pars = append(pars, req.ChartInfoId)
+
+		sql := ` UPDATE  chart_info SET ` + updateStr + ` WHERE chart_info_id = ?`
+		_, err = to.Raw(sql, pars).Exec()
+		if err != nil {
+			fmt.Println("UPDATE  chart_info Err:", err.Error())
+			return err
+		}
+	} else {
+		sql := ` UPDATE  chart_info
+			SET
+              edb_info_ids=?,
+			  modify_time = NOW(),
+			  calendar=?,
+			  date_type=?,
+			  start_date=?,
+			  end_date=?,
+			  season_start_date=?,
+			  season_end_date=?,
+			  left_min=?,
+			  left_max=?,
+			  right_min=?,
+			  right_max=?,
+			  right2_min=?,
+			  right2_max=?,
+			  min_max_save=?,
+			  start_year=?
+			WHERE chart_info_id = ?`
+		_, err = to.Raw(sql, edbInfoIdStr, req.Calendar, req.DateType, req.StartDate, req.EndDate, req.StartDate, req.EndDate, req.LeftMin, req.LeftMax, req.RightMin, req.RightMax, req.Right2Min, req.Right2Max, req.MinMaxSave, req.StartYear, req.ChartInfoId).Exec()
+		if err != nil {
+			fmt.Println("UPDATE  chart_info Err:", err.Error())
+			return err
+		}
+	}
+
+	var edbInfoIdArr []string
+	mapList := make([]*ChartEdbMapping, 0)
+	for _, v := range req.ChartEdbInfoList {
+		edbInfoIdArr = append(edbInfoIdArr, strconv.Itoa(v.EdbInfoId))
+		var count int
+		csql := `SELECT COUNT(1) AS count FROM chart_edb_mapping WHERE chart_info_id=? AND edb_info_id=? `
+		err = to.Raw(csql, req.ChartInfoId, v.EdbInfoId).QueryRow(&count)
+		if err != nil {
+			fmt.Println("QueryRow Err:", err.Error())
+			return err
+		}
+		if count > 0 {
+			msql := `UPDATE  chart_edb_mapping
+				SET
+                 modify_time = NOW(),
+				 max_data = ?,
+				 min_data = ?,
+				 is_order = ?,
+				 is_axis = ?,
+				 edb_info_type = ?,
+				 lead_value = ?,
+				 lead_unit = ?,
+				 chart_style = ?,
+				 chart_color = ?,
+				 predict_chart_color = ?,
+				 chart_width = ?
+				WHERE chart_info_id =? AND edb_info_id=? `
+			_, err = to.Raw(msql, v.MaxData, v.MinData, v.IsOrder, v.IsAxis, v.EdbInfoType, v.LeadValue, v.LeadUnit, v.ChartStyle, v.ChartColor, v.PredictChartColor, v.ChartWidth, req.ChartInfoId, v.EdbInfoId).Exec()
+			if err != nil {
+				fmt.Println("chart_edb_mapping Err:" + err.Error())
+				return err
+			}
+		} else {
+			mapItem := new(ChartEdbMapping)
+			mapItem.ChartInfoId = req.ChartInfoId
+			mapItem.EdbInfoId = v.EdbInfoId
+			mapItem.CreateTime = time.Now()
+			mapItem.ModifyTime = time.Now()
+			timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+			mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
+			mapItem.MaxData = v.MaxData
+			mapItem.MinData = v.MinData
+			mapItem.IsOrder = v.IsOrder
+			mapItem.IsAxis = v.IsAxis
+			mapItem.EdbInfoType = v.EdbInfoType
+			mapItem.LeadValue = v.LeadValue
+			mapItem.LeadUnit = v.LeadUnit
+			mapItem.ChartStyle = v.ChartStyle
+			mapItem.ChartColor = v.ChartColor
+			mapItem.PredictChartColor = v.PredictChartColor
+			mapItem.ChartWidth = v.ChartWidth
+			mapList = append(mapList, mapItem)
+		}
+	}
+	if len(mapList) > 0 {
+		_, err = to.InsertMulti(1, mapList)
+		if err != nil {
+			fmt.Println("AddChartEdbMapping Err:" + err.Error())
+			return err
+		}
+	}
+	if len(edbInfoIdArr) > 0 {
+		edbInfoIdStr := strings.Join(edbInfoIdArr, ",")
+		if edbInfoIdStr != "" {
+			dsql := `DELETE FROM chart_edb_mapping WHERE chart_info_id=? AND edb_info_id NOT IN(` + edbInfoIdStr + `)`
+			_, err = to.Raw(dsql, req.ChartInfoId).Exec()
+			if err != nil {
+				fmt.Println("delete err:" + err.Error())
+				return err
+			}
+		}
+	}
+	return
+}
+
+// EditChartInfoAndMapping 修改 ETA图库 的 图表与指标 的关系
+func EditChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr string, calendar string, dateType, disabled int, barChartConf string, chartEdbInfoList []*ChartSaveItem, seasonExtra string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	var pars []interface{}
+	pars = append(pars, req.ChartName)
+	pars = append(pars, edbInfoIdStr)
+	pars = append(pars, req.ChartType)
+	pars = append(pars, req.ChartClassifyId)
+	pars = append(pars, disabled)
+	pars = append(pars, barChartConf)
+	pars = append(pars, req.ExtraConfig)
+	pars = append(pars, seasonExtra)
+	pars = append(pars, req.StartYear)
+	pars = append(pars, req.ChartThemeId)
+	pars = append(pars, req.SourcesFrom)
+	pars = append(pars, req.Instructions)
+	pars = append(pars, req.MarkersLines)
+	pars = append(pars, req.MarkersAreas)
+	pars = append(pars, req.Unit)
+	pars = append(pars, req.UnitEn)
+
+	sql := ` UPDATE  chart_info
+			SET
+			  chart_name =?,
+              edb_info_ids=?,
+			  chart_type=?,
+			  chart_classify_id = ?,
+			  modify_time = NOW(),
+              disabled = ?,
+              bar_config = ?,
+              extra_config = ?, 
+              season_extra_config = ?,
+ 			  start_year = ?,
+ 			  chart_theme_id = ?,
+ 			  sources_from = ?,
+ 			  instructions = ?,
+ 			  markers_lines = ?,
+ 			  markers_areas = ?,
+ 			  unit = ?,
+ 			  unit_en = ?
+			`
+	if calendar != "" {
+		sql += `,calendar = ? `
+		pars = append(pars, calendar)
+	}
+	if dateType > 0 {
+		sql += `,date_type = ? `
+		pars = append(pars, dateType)
+	}
+
+	sql += `,start_date = ? `
+	pars = append(pars, req.StartDate)
+
+	sql += `,end_date = ? `
+	pars = append(pars, req.EndDate)
+
+	sql += `,season_start_date = ? `
+	pars = append(pars, req.StartDate)
+
+	sql += `,season_end_date = ? `
+	pars = append(pars, req.EndDate)
+
+	sql += `,left_min = ? `
+	pars = append(pars, req.LeftMin)
+
+	sql += `,left_max = ? `
+	pars = append(pars, req.LeftMax)
+
+	sql += `,right_min = ? `
+	pars = append(pars, req.RightMin)
+
+	sql += `,right_max = ? `
+	pars = append(pars, req.RightMax)
+
+	sql += `,right2_min = ? `
+	pars = append(pars, req.Right2Min)
+
+	sql += `,right2_max = ? `
+	pars = append(pars, req.Right2Max)
+
+	sql += `,min_max_save = ? `
+	pars = append(pars, req.MinMaxSave)
+
+	sql += `WHERE chart_info_id = ?`
+
+	pars = append(pars, req.ChartInfoId)
+	_, err = to.Raw(sql, pars).Exec()
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+	chartEdbMappingIdList := make([]string, 0)
+
+	for _, v := range chartEdbInfoList {
+		// 查询该指标是否存在,如果存在的话,那么就去修改,否则新增
+		var tmpChartEdbMapping *ChartEdbMapping
+		csql := `SELECT *  FROM chart_edb_mapping WHERE chart_info_id=? AND edb_info_id=? AND source = ? `
+		err = to.Raw(csql, req.ChartInfoId, v.EdbInfoId, utils.CHART_SOURCE_DEFAULT).QueryRow(&tmpChartEdbMapping)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			fmt.Println("QueryRow Err:", err.Error())
+			return err
+		}
+		if tmpChartEdbMapping != nil {
+			chartEdbMappingIdList = append(chartEdbMappingIdList, strconv.Itoa(tmpChartEdbMapping.ChartEdbMappingId))
+			tmpChartEdbMapping.ModifyTime = time.Now()
+			tmpChartEdbMapping.MaxData = v.MaxData
+			tmpChartEdbMapping.MinData = v.MinData
+			tmpChartEdbMapping.IsOrder = v.IsOrder
+			tmpChartEdbMapping.IsAxis = v.IsAxis
+			tmpChartEdbMapping.EdbInfoType = v.EdbInfoType
+			tmpChartEdbMapping.LeadValue = v.LeadValue
+			tmpChartEdbMapping.LeadUnit = v.LeadUnit
+			tmpChartEdbMapping.ChartStyle = v.ChartStyle
+			tmpChartEdbMapping.ChartColor = v.ChartColor
+			tmpChartEdbMapping.PredictChartColor = v.PredictChartColor
+			tmpChartEdbMapping.ChartWidth = v.ChartWidth
+			tmpChartEdbMapping.EdbAliasName = v.EdbAliasName
+			tmpChartEdbMapping.IsConvert = v.IsConvert
+			tmpChartEdbMapping.ConvertType = v.ConvertType
+			tmpChartEdbMapping.ConvertValue = v.ConvertValue
+			tmpChartEdbMapping.ConvertUnit = v.ConvertUnit
+			tmpChartEdbMapping.ConvertEnUnit = v.ConvertEnUnit
+			_, err = to.Update(tmpChartEdbMapping, "ModifyTime", "MaxData", "MinData", "IsOrder", "IsAxis", "EdbInfoType", "LeadValue", "LeadUnit", "ChartStyle", "ChartColor", "PredictChartColor", "ChartWidth", "EdbAliasName",
+				"IsConvert", "ConvertType", "ConvertValue", "ConvertUnit", "ConvertEnUnit")
+			if err != nil {
+				fmt.Println("chart_edb_mapping Err:" + err.Error())
+				return err
+			}
+		} else {
+			mapItem := new(ChartEdbMapping)
+			mapItem.ChartInfoId = req.ChartInfoId
+			mapItem.EdbInfoId = v.EdbInfoId
+			mapItem.CreateTime = time.Now()
+			mapItem.ModifyTime = time.Now()
+			timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+			mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp + "_" + strconv.Itoa(v.EdbInfoId))
+			mapItem.MaxData = v.MaxData
+			mapItem.MinData = v.MinData
+			mapItem.IsOrder = v.IsOrder
+			mapItem.IsAxis = v.IsAxis
+			mapItem.EdbInfoType = v.EdbInfoType
+			mapItem.LeadValue = v.LeadValue
+			mapItem.LeadUnit = v.LeadUnit
+			mapItem.ChartStyle = v.ChartStyle
+			mapItem.ChartColor = v.ChartColor
+			mapItem.PredictChartColor = v.PredictChartColor
+			mapItem.ChartWidth = v.ChartWidth
+			mapItem.Source = utils.CHART_SOURCE_DEFAULT
+			mapItem.EdbAliasName = v.EdbAliasName
+			mapItem.IsConvert = v.IsConvert
+			mapItem.ConvertType = v.ConvertType
+			mapItem.ConvertValue = v.ConvertValue
+			mapItem.ConvertUnit = v.ConvertUnit
+			mapItem.ConvertEnUnit = v.ConvertEnUnit
+			tmpId, err := to.Insert(mapItem)
+			if err != nil {
+				fmt.Println("AddChartEdbMapping Err:" + err.Error())
+				return err
+			}
+			mapItem.ChartEdbMappingId = int(tmpId)
+			chartEdbMappingIdList = append(chartEdbMappingIdList, strconv.Itoa(mapItem.ChartEdbMappingId))
+		}
+	}
+	if len(chartEdbMappingIdList) > 0 {
+		chartEdbMappingIdStr := strings.Join(chartEdbMappingIdList, ",")
+		dsql := `DELETE FROM chart_edb_mapping WHERE chart_info_id=? AND chart_edb_mapping_id NOT IN(` + chartEdbMappingIdStr + `)`
+		_, err = to.Raw(dsql, req.ChartInfoId).Exec()
+		if err != nil {
+			fmt.Println("delete err:" + err.Error())
+			return err
+		}
+	}
+	return
+}
+
+// EditFutureGoodChartInfoAndMapping 修改商品价格曲线的 图表与指标 的关系
+func EditFutureGoodChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr string, calendar string, dateType, disabled int, barChartConf string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	var pars []interface{}
+	pars = append(pars, req.ChartName)
+	pars = append(pars, edbInfoIdStr)
+	pars = append(pars, req.ChartType)
+	pars = append(pars, req.ChartClassifyId)
+	pars = append(pars, disabled)
+	pars = append(pars, barChartConf)
+
+	sql := ` UPDATE  chart_info
+			SET
+			  chart_name =?,
+              edb_info_ids=?,
+			  chart_type=?,
+			  chart_classify_id = ?,
+			  modify_time = NOW(),
+              disabled = ?,
+              bar_config = ?
+			`
+	if calendar != "" {
+		sql += `,calendar = ? `
+		pars = append(pars, calendar)
+	}
+	if dateType > 0 {
+		sql += `,date_type = ? `
+		pars = append(pars, dateType)
+	}
+
+	sql += `,start_date = ? `
+	pars = append(pars, req.StartDate)
+
+	sql += `,end_date = ? `
+	pars = append(pars, req.EndDate)
+
+	sql += `,season_start_date = ? `
+	pars = append(pars, req.StartDate)
+
+	sql += `,season_end_date = ? `
+	pars = append(pars, req.EndDate)
+
+	sql += `,left_min = ? `
+	pars = append(pars, req.LeftMin)
+
+	sql += `,left_max = ? `
+	pars = append(pars, req.LeftMax)
+
+	sql += `,right_min = ? `
+	pars = append(pars, req.RightMin)
+
+	sql += `,right_max = ? `
+	pars = append(pars, req.RightMax)
+
+	sql += `,right2_min = ? `
+	pars = append(pars, req.Right2Min)
+
+	sql += `,right2_max = ? `
+	pars = append(pars, req.Right2Max)
+
+	sql += `WHERE chart_info_id = ?`
+
+	pars = append(pars, req.ChartInfoId)
+	_, err = to.Raw(sql, pars).Exec()
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+	chartEdbMappingIdList := make([]string, 0)
+	for _, v := range req.BarChartInfo.EdbInfoIdList {
+		// 查询该指标是否存在,如果存在的话,那么就去修改,否则新增
+		var tmpChartEdbMapping *ChartEdbMapping
+		csql := `SELECT *  FROM chart_edb_mapping WHERE chart_info_id=? AND edb_info_id=? AND source = ? `
+		err = to.Raw(csql, req.ChartInfoId, v.EdbInfoId, v.Source).QueryRow(&tmpChartEdbMapping)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			fmt.Println("QueryRow Err:", err.Error())
+			return err
+		}
+		if tmpChartEdbMapping != nil {
+			chartEdbMappingIdList = append(chartEdbMappingIdList, strconv.Itoa(tmpChartEdbMapping.ChartEdbMappingId))
+			//tmpChartEdbMapping.ModifyTime = time.Now()
+			//tmpChartEdbMapping.MaxData = v.MaxData
+			//tmpChartEdbMapping.MinData = v.MinData
+			//tmpChartEdbMapping.IsOrder = v.IsOrder
+			//tmpChartEdbMapping.IsAxis = v.IsAxis
+			//tmpChartEdbMapping.EdbInfoType = v.EdbInfoType
+			//tmpChartEdbMapping.LeadValue = v.LeadValue
+			//tmpChartEdbMapping.LeadUnit = v.LeadUnit
+			//tmpChartEdbMapping.ChartStyle = v.ChartStyle
+			//tmpChartEdbMapping.ChartColor = v.ChartColor
+			//tmpChartEdbMapping.PredictChartColor = v.PredictChartColor
+			//tmpChartEdbMapping.ChartWidth = v.ChartWidth
+			//_, err = to.Update(tmpChartEdbMapping, "ModifyTime", "MaxData", "MinData", "IsOrder", "IsAxis", "EdbInfoType", "LeadValue", "LeadUnit", "ChartStyle", "ChartColor", "PredictChartColor", "ChartWidth")
+			//if err != nil {
+			//	fmt.Println("chart_edb_mapping Err:" + err.Error())
+			//	return err
+			//}
+		} else {
+			mapItem := new(ChartEdbMapping)
+			mapItem.ChartInfoId = req.ChartInfoId
+			mapItem.EdbInfoId = v.EdbInfoId
+			mapItem.CreateTime = time.Now()
+			mapItem.ModifyTime = time.Now()
+			timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+			mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp + "_" + strconv.Itoa(v.EdbInfoId))
+			//mapItem.MaxData = v.MaxData
+			//mapItem.MinData = v.MinData
+			mapItem.IsOrder = true
+			mapItem.IsAxis = 1
+			mapItem.EdbInfoType = 1
+			//mapItem.LeadValue = v.LeadValue
+			//mapItem.LeadUnit = v.LeadUnit
+			//mapItem.ChartStyle = v.ChartStyle
+			//mapItem.ChartColor = v.ChartColor
+			//mapItem.PredictChartColor = v.PredictChartColor
+			//mapItem.ChartWidth = v.ChartWidth
+			mapItem.Source = v.Source
+			tmpId, err := to.Insert(mapItem)
+			if err != nil {
+				fmt.Println("AddChartEdbMapping Err:" + err.Error())
+				return err
+			}
+			mapItem.ChartEdbMappingId = int(tmpId)
+			chartEdbMappingIdList = append(chartEdbMappingIdList, strconv.Itoa(mapItem.ChartEdbMappingId))
+		}
+	}
+	if len(chartEdbMappingIdList) > 0 {
+		chartEdbMappingIdStr := strings.Join(chartEdbMappingIdList, ",")
+		dsql := `DELETE FROM chart_edb_mapping WHERE chart_info_id=? AND chart_edb_mapping_id NOT IN(` + chartEdbMappingIdStr + `)`
+		_, err = to.Raw(dsql, req.ChartInfoId).Exec()
+		if err != nil {
+			fmt.Println("delete err:" + err.Error())
+			return err
+		}
+	}
+	return
+}
+
+func EditChartEnInfoAndEdbEnInfo(req *EditChartEnInfoReq) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	var pars []interface{}
+	updateField := ` chart_name_en =?, `
+	pars = append(pars, req.ChartNameEn)
+
+	if req.ExtraConfig != `` {
+		updateField += ` extra_config =?, `
+		pars = append(pars, req.ExtraConfig)
+	}
+
+	sql := ` UPDATE  chart_info
+			SET ` + updateField + ` modify_time = NOW()
+			WHERE chart_info_id = ?`
+
+	pars = append(pars, req.ChartInfoId)
+	_, err = to.Raw(sql, pars).Exec()
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+	var edbInfoIdArr []string
+	for _, v := range req.ChartEdbInfoList {
+		edbInfoIdArr = append(edbInfoIdArr, strconv.Itoa(v.EdbInfoId))
+		var count int
+		csql := `SELECT COUNT(1) AS count FROM chart_edb_mapping WHERE chart_info_id=? AND edb_info_id=? `
+		err = to.Raw(csql, req.ChartInfoId, v.EdbInfoId).QueryRow(&count)
+		if err != nil {
+			fmt.Println("QueryRow Err:", err.Error())
+			return err
+		}
+		if count > 0 {
+			msql := ` UPDATE  edb_info
+			SET
+			  edb_name_en =?,
+			  unit_en = ?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ? `
+			_, err = to.Raw(msql, v.EdbNameEn, v.UnitEn, v.EdbInfoId).Exec()
+			if err != nil {
+				fmt.Println("edb_info Err:" + err.Error())
+				return err
+			}
+		}
+	}
+	return
+}
+
+type AddChartInfoReq struct {
+	ChartEdbInfoList []*ChartSaveItem `description:"指标及配置信息"`
+	//ChartClassifyId      int                     `description:"分类id"`
+	ChartName            string                  `description:"图表名称"`
+	ChartType            int                     `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图"`
+	DateType             int                     `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间,6:起始日期至今"`
+	StartDate            string                  `description:"自定义开始日期"`
+	EndDate              string                  `description:"自定义结束日期"`
+	Calendar             string                  `description:"公历/农历"`
+	LeftMin              string                  `description:"图表左侧最小值"`
+	LeftMax              string                  `description:"图表左侧最大值"`
+	RightMin             string                  `description:"图表右侧最小值"`
+	RightMax             string                  `description:"图表右侧最大值"`
+	Right2Min            string                  `description:"图表右侧2最小值"`
+	Right2Max            string                  `description:"图表右侧2最大值"`
+	MinMaxSave           int                     `description:"是否手动保存过上下限:0-否;1-是"`
+	Disabled             int                     `description:"是否禁用,0:启用,1:禁用,默认:0"`
+	BarConfig            string                  `description:"柱方图的配置,json数据"`
+	CorrelationChartInfo CorrelationChartInfoReq `description:"相关性图表配置"`
+	ExtraConfig          string                  `description:"图表额外配置信息,json字符串"`
+	ChartImage           string                  `description:"封面图" json:"-"`
+	SeasonExtraConfig    string                  `description:"季节性图表中的配置,json数据"`
+	StartYear            int                     `description:"当选择的日期类型为最近N年类型时,即date_type=20, 用start_year表示N"`
+	Source               int                     `description:"1:ETA图库;2:商品价格曲线"`
+	ChartThemeId         int                     `description:"图表应用主题ID"`
+	SourcesFrom          string                  `description:"图表来源"`
+	Instructions         string                  `description:"图表说明"`
+	MarkersLines         string                  `description:"标识线"`
+	MarkersAreas         string                  `description:"标识区"`
+	Unit                 string                  `description:"中文单位名称"`
+	UnitEn               string                  `description:"英文单位名称"`
+}
+
+type AddChartReq struct {
+	ChartInfo               *ChartInfo
+	Description             string `description:"逻辑简述"`
+	EdbInfoList             []*EdbInfo
+	ChartThemeList          []*ChartTheme
+	EdbInfoDataList         []*AddEdbDataReq
+	ChartEdbMapping         []*ChartEdbMapping
+	EdbInfoCalculateMapping []*EdbInfoCalculateMapping
+}
+
+type AddEdbDataReq struct {
+	EdbCode  string
+	DataList []*mgodb.EdbDataBase
+}
+
+type DeleteChartReq struct {
+	ChartInfoId int `description:"图表id"`
+}
+
+type PreviewChartInfoReq struct {
+	ChartEdbInfoList  []*ChartSaveItem `description:"指标及配置信息"`
+	DateType          int              `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间,6:起始日期至今 20:最近N年"`
+	ChartType         int              `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图"`
+	StartDate         string           `description:"自定义开始日期"`
+	EndDate           string           `description:"自定义结束日期"`
+	Calendar          string           `description:"公历/农历"`
+	SeasonExtraConfig SeasonExtraItem  `description:"季节性图表中的配置,json数据"`
+	StartYear         int              `description:"当选择的日期类型为最近N年类型时,即date_type=20, 用start_year表示N"`
+}
+
+type SeasonExtraItem struct {
+	ChartLegend []SeasonChartLegend `description:"自定义的图例名称"`
+	XStartDate  string              `description:"横坐标显示的起始日"`
+	XEndDate    string              `description:"横坐标显示的截止日"`
+	JumpYear    int                 `description:"横坐标日期是否跨年,1跨年,0不跨年"`
+}
+
+type SeasonChartLegend struct {
+	Name  string
+	Value string
+}
+type AddChartInfoResp struct {
+	ChartInfoId int    `description:"图表id"`
+	UniqueCode  string `description:"图表唯一编码"`
+	ChartType   int    `description:"生成样式:1:曲线图,2:季节性图"`
+}
+
+type QuarterDataList []*QuarterData
+
+func (m QuarterDataList) Len() int {
+	return len(m)
+}
+
+func (m QuarterDataList) Less(i, j int) bool {
+	return m[i].Years < m[j].Years
+}
+
+func (m QuarterDataList) Swap(i, j int) {
+	m[i], m[j] = m[j], m[i]
+}
+
+// 判断图表指标是否已经存在
+func ChartInfoExist(condition, edbInfoIdStr string) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM (
+		SELECT GROUP_CONCAT(edb_info_id ORDER BY edb_info_id ASC  SEPARATOR ',') AS edb_info_id_str 
+		 FROM chart_edb_mapping AS a
+         WHERE 1=1`
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` GROUP BY chart_info_id 
+		)AS t
+		WHERE t.edb_info_id_str=? 
+        GROUP BY t.edb_info_id_str `
+	o := orm.NewOrm()
+	err = o.Raw(sql, edbInfoIdStr).QueryRow(&count)
+	return
+}
+
+func ChartInfoSearchByKeyWord(keyword string, showSysId int) (searchList []*ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE 1=1 `
+
+	var pars []interface{}
+
+	if keyword != "" {
+		sql += `AND chart_name LIKE ?  `
+		pars = append(pars, utils.GetLikeKeyword(keyword))
+	}
+
+	if showSysId > 0 {
+		sql += ` AND sys_user_id = ? `
+		pars = append(pars, showSysId)
+	}
+	sql += ` ORDER BY create_time DESC `
+	if keyword == "" {
+		sql += ` LIMIT 100 `
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&searchList)
+	return
+}
+
+// ChartInfoSearchByEmptyKeyWord 没有关键字的时候获取默认100条数据
+func ChartInfoSearchByEmptyKeyWord(showSysId int, sourceList []int, noPermissionChartIdList []int, startSize, pageSize int) (total int64, searchList []*ChartInfo, err error) {
+	num := len(sourceList)
+	o := orm.NewOrm()
+
+	baseSql := `  FROM chart_info WHERE 1=1 AND source in (` + utils.GetOrmInReplace(num) + `)`
+
+	var basePars []interface{}
+	basePars = append(basePars, sourceList)
+
+	if showSysId > 0 {
+		baseSql += ` AND sys_user_id = ? `
+		basePars = append(basePars, showSysId)
+	}
+
+	lenNoPermissionChartIdList := len(noPermissionChartIdList)
+	if lenNoPermissionChartIdList > 0 {
+		baseSql += ` AND chart_info_id not in (` + utils.GetOrmInReplace(lenNoPermissionChartIdList) + `) `
+		basePars = append(basePars, noPermissionChartIdList)
+	}
+
+	// 查找数量
+	totalSql := " SELECT count(1) as total " + baseSql
+	err = o.Raw(totalSql, basePars).QueryRow(&total)
+	if err != nil {
+		return
+	}
+
+	// 查找列表数据
+	sql := " SELECT *  " + baseSql + ` ORDER BY create_time DESC LIMIT ?,? `
+	basePars = append(basePars, startSize, pageSize)
+
+	_, err = o.Raw(sql, basePars).QueryRows(&searchList)
+
+	return
+}
+
+func GetNextChartInfo(classifyId int) (item *ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT b.* FROM chart_classify AS a
+			INNER JOIN chart_info AS b ON a.chart_classify_id=b.chart_classify_id
+			WHERE a.chart_classify_id>?
+			ORDER BY a.chart_classify_id ASC
+			LIMIT 1 `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+type SetChartInfoImageReq struct {
+	ChartInfoId int    `description:"图表ID"`
+	ImageUrl    string `description:"图表图片地址"`
+}
+
+func EditChartInfoImage(req *SetChartInfoImageReq) (err error) {
+	o := orm.NewOrm()
+
+	sql := ` UPDATE  chart_info SET chart_image=?, modify_time = NOW() WHERE chart_info_id = ? `
+	_, err = o.Raw(sql, req.ImageUrl, req.ChartInfoId).Exec()
+	if err != nil {
+		fmt.Println("EditChartInfoImage Err:", err.Error())
+		return err
+	}
+
+	return
+}
+
+type ChartInfoDetailFromUniqueCodeResp struct {
+	ChartInfo    *ChartInfoView
+	Status       bool `description:"true:图表存在,false:图表不存在"`
+	EdbInfoList  []*ChartEdbInfoMapping
+	XEdbIdValue  []int           `description:"柱方图的x轴数据,指标id"`
+	YDataList    []YData         `description:"柱方图的y轴数据"`
+	XDataList    []XData         `description:"商品价格曲线的X轴数据"`
+	BarChartInfo BarChartInfoReq `description:"柱方图的配置"`
+	//CorrelationChartInfo *CorrelationInfo `description:"相关性图表信息"`
+	DataResp interface{} `description:"图表数据,根据图的类型而定的,没有确定的数据格式"`
+}
+
+func GetChartInfoByUniqueCode(uniqueCode string) (item *ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE unique_code=? `
+	err = o.Raw(sql, uniqueCode).QueryRow(&item)
+	return
+}
+
+func GetChartInfoViewByUniqueCode(uniqueCode string) (item *ChartInfoView, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE unique_code=? `
+	err = o.Raw(sql, uniqueCode).QueryRow(&item)
+	return
+}
+
+// GetFirstChartInfoByClassifyId 获取当前分类下,且排序数相同 的排序第一条的数据
+func GetFirstChartInfoByClassifyId(classifyId int) (item *ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE chart_classify_id=? order by sort asc,chart_info_id asc limit 1`
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+// UpdateChartInfoSortByClassifyId 根据图表id更新排序
+func UpdateChartInfoSortByClassifyId(classifyId, nowSort, prevChartInfoId int, sourceList []int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	num := len(sourceList)
+	if num <= 0 {
+		return
+	}
+	sql := ` update chart_info set sort = ` + updateSort + ` WHERE chart_classify_id=? AND source in (` + utils.GetOrmInReplace(num) + `) AND `
+	if prevChartInfoId > 0 {
+		sql += ` (sort > ? or (chart_info_id > ` + fmt.Sprint(prevChartInfoId) + ` and sort = ` + fmt.Sprint(nowSort) + `))`
+	}
+	_, err = o.Raw(sql, classifyId, sourceList, nowSort).Exec()
+	return
+}
+
+// Update 更新图表基础信息
+func (chartInfo *ChartInfo) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(chartInfo, cols...)
+	return
+}
+
+type ChartInfoView struct {
+	ChartInfoId       int    `orm:"column(chart_info_id);pk"`
+	ChartName         string `description:"来源名称"`
+	ChartNameEn       string `description:"英文图表名称"`
+	Unit              string `description:"中文单位名称"`
+	UnitEn            string `description:"英文单位名称"`
+	ChartClassifyId   int    `description:"图表分类id"`
+	ChartClassifyName string `description:"图表名称"`
+	SysUserId         int
+	SysUserRealName   string
+	UniqueCode        string `description:"图表唯一编码"`
+	CreateTime        time.Time
+	ModifyTime        time.Time
+	DateType          int    `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间"`
+	StartDate         string `description:"自定义开始日期"`
+	EndDate           string `description:"自定义结束日期"`
+	IsSetName         int    `description:"设置名称"`
+	EdbInfoIds        string `description:"指标id"`
+	ChartType         int    `description:"生成样式:1:曲线图,2:季节性图"`
+	Calendar          string `description:"公历/农历"`
+	SeasonStartDate   string `description:"季节性图开始日期"`
+	SeasonEndDate     string `description:"季节性图开始日期"`
+	ChartImage        string `description:"图表图片"`
+	Sort              int    `description:"排序字段,数字越小越排前面"`
+	IsAdd             bool   `description:"true:已加入我的图库,false:未加入我的图库"`
+	MyChartId         int
+	MyChartClassifyId string `description:"我的图表分类,多个用逗号隔开"`
+	ChartClassify     []*ChartClassifyView
+	EdbEndDate        string `description:"指标最新更新日期"`
+	XMin              string `description:"图表X轴最小值"`
+	XMax              string `description:"图表X轴最大值"`
+	LeftMin           string `description:"图表左侧最小值"`
+	LeftMax           string `description:"图表左侧最大值"`
+	RightMin          string `description:"图表右侧最小值"`
+	RightMax          string `description:"图表右侧最大值"`
+	Right2Min         string `description:"图表右侧最小值"`
+	Right2Max         string `description:"图表右侧最大值"`
+	MinMaxSave        int    `description:"是否手动保存过上下限:0-否;1-是"`
+	IsEdit            bool   `description:"是否有编辑权限"`
+	IsEnChart         bool   `description:"是否展示英文标识"`
+	WarnMsg           string `description:"错误信息"`
+	Disabled          int    `description:"是否禁用,0:启用,1:禁用,默认:0"`
+	BarConfig         string `description:"柱方图的配置,json数据" json:"-"`
+	Source            int    `description:"1:ETA图库;2:商品价格曲线;3:相关性图表"`
+	//CorrelationLeadUnit string `description:"相关性图表-领先单位"`
+	ExtraConfig       string          `description:"图表额外配置,json数据"`
+	ChartSource       string          `description:"图表来源str"`
+	ChartSourceEn     string          `description:"图表来源(英文)"`
+	Button            ChartViewButton `description:"操作按钮"`
+	SeasonExtraConfig string          `description:"季节性图表中的配置,json数据"`
+	StartYear         int             `description:"当选择的日期类型为最近N年类型时,即date_type=20, 用start_year表示N"`
+	ChartThemeId      int             `description:"图表应用主题ID"`
+	ChartThemeStyle   string          `description:"图表应用主题样式"`
+	SourcesFrom       string          `description:"图表来源"`
+	Instructions      string          `description:"图表说明"`
+	MarkersLines      string          `description:"标识线"`
+	MarkersAreas      string          `description:"标识区"`
+	IsJoinPermission  int             `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth     bool            `description:"是否有数据权限,默认:false"`
+}
+
+type ChartViewButton struct {
+	IsEdit    bool `description:"是否有编辑权限"`
+	IsEnChart bool `description:"是否展示英文标识"`
+	IsAdd     bool `description:"true:已加入我的图库,false:未加入我的图库"`
+	IsCopy    bool `description:"是否有另存为按钮"`
+	IsSetName int  `description:"设置名称"`
+}
+
+type ImageSvgToPngResp struct {
+	Data struct {
+		ResourceURL string `json:"ResourceUrl"`
+	} `json:"Data"`
+	ErrCode     string `json:"ErrCode"`
+	ErrMsg      string `json:"ErrMsg"`
+	IsSendEmail bool   `json:"IsSendEmail"`
+	Msg         string `json:"Msg"`
+	Ret         int64  `json:"Ret"`
+	Success     bool   `json:"Success"`
+}
+
+// GetChartInfoByClassifyIdAndName 根据分类id和图表名获取图表信息
+func GetChartInfoByClassifyIdAndName(classifyId int, chartName string) (item *ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE chart_classify_id = ? and chart_name=? `
+	err = o.Raw(sql, classifyId, chartName).QueryRow(&item)
+	return
+}
+
+// BatchChartRefreshReq 批量刷新图表请求
+type BatchChartRefreshReq struct {
+	ChartInfoCode   []string `description:"图表编码数组"`
+	ReportId        int      `description:"报告id"`
+	ReportChapterId int      `description:"报告章节id"`
+	Source          string   `description:"来源,枚举值:report、english_report、smart_report"`
+}
+
+// GetChartInfoListByUniqueCodeSlice 根据图表编码获取图表列表数据
+func GetChartInfoListByUniqueCodeSlice(uniqueCodeSlice []string) (total int64, items []*ChartInfo, err error) {
+	if len(uniqueCodeSlice) <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE unique_code in ("` + strings.Join(uniqueCodeSlice, `","`) + `") `
+	total, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// CopyAddChartInfoReq 复制并新增图表
+type CopyAddChartInfoReq struct {
+	ChartInfoId     int    `description:"待复制的图表id"`
+	ChartClassifyId int    `description:"分类id"`
+	ChartName       string `description:"图表名称"`
+}
+
+// GetChartInfoListByCondition 根据条件获取图表数据了列表
+func GetChartInfoListByCondition(condition string, pars []interface{}, startSize, pageSize int) (items []*ChartInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY chart_info_id DESC LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// GetChartInfoListGroupByUserId 根据指标id列表、用户分组获取指标信息
+func GetChartInfoListGroupByUserId(edbIdList []string) (items []*ChartInfo, err error) {
+	num := len(edbIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	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.NewOrm()
+	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.NewOrm()
+	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)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := `UPDATE chart_info SET sys_user_id=?,sys_user_real_name=? WHERE chart_info_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, userId, userName, edbIdList).Exec()
+	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.NewOrm()
+	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:"指标信息"`
+	DateList      []BarChartInfoDateReq    `description:"日期配置"`
+	Sort          BarChartInfoSortReq      `description:"排序"`
+	XEdbList      []BarChartInfoEdbItemReq `description:"X轴选择的指标列表"`
+	YEdbList      []BarChartInfoEdbItemReq `description:"Y轴选择的指标列表"`
+	Unit          string                   `description:"中文单位"`
+	UnitEn        string                   `description:"英文单位"`
+}
+
+// BarChartInfoEdbItemReq 柱方图预览请求数据(指标相关)
+type BarChartInfoEdbItemReq struct {
+	EdbInfoId     int     `description:"指标ID"`
+	Name          string  `description:"别名"`
+	NameEn        string  `description:"英文别名"`
+	Source        int     `description:"1:ETA图库;2:商品价格"`
+	IsConvert     int     `description:"是否数据转换 0不转 1转"`
+	ConvertType   int     `description:"数据转换类型 1乘 2除 3对数"`
+	ConvertValue  float64 `description:"数据转换值"`
+	ConvertUnit   string  `description:"数据转换单位"`
+	ConvertEnUnit string  `description:"数据转换单位"`
+}
+
+// BarChartInfoDateReq 柱方图预览请求数据(日期相关)
+type BarChartInfoDateReq struct {
+	Type  int    `description:"配置类型"`
+	Date  string `description:"固定日期"`
+	Value int    `description:"N天的值"`
+	Color string `description:"颜色"`
+	Name  string `description:"别名"`
+}
+
+// BarChartInfoSortReq 柱方图预览请求数据(排序相关)
+type BarChartInfoSortReq struct {
+	Sort      int `description:"排序类型,0:默认,1:升序,2:降序"`
+	DateIndex int `description:"日期数据的下标,从0开始"`
+}
+
+// CorrelationChartInfoReq 相关性图表请求体
+type CorrelationChartInfoReq struct {
+	LeadValue          int                              `description:"领先期数"`
+	LeadUnit           string                           `description:"频度"`
+	CalculateValue     int                              `description:"计算窗口"`
+	CalculateUnit      string                           `description:"计算频度"`
+	BaseCalculateValue int                              `description:"基础计算窗口(滚动相关性的时候用到)"`
+	BaseCalculateUnit  string                           `description:"基础计算频度(滚动相关性的时候用到)"`
+	DateType           int                              `description:"日期类型:1:00年至今,2:10年至今,3:15年至今,4:年初至今,5:自定义时间,6:起始日期至今"`
+	StartDate          string                           `description:"开始日期"`
+	EndDate            string                           `description:"结束日期"`
+	EdbInfoIdList      []CorrelationChartInfoEdbItemReq `description:"指标信息"`
+}
+
+// CorrelationChartInfoEdbItemReq 相关性图表请求指标
+type CorrelationChartInfoEdbItemReq struct {
+	EdbInfoId int    `description:"指标ID"`
+	Name      string `description:"别名"`
+	NameEn    string `description:"英文别名"`
+	//Source    int    `description:"1:ETA图库;2:商品价格"`
+}
+
+/*
+// EditCorrelationChartInfoAndMapping 修改相关性图表的 图表与指标 的关系
+func EditCorrelationChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr string, calendar string, dateType, disabled int, barChartConf string, correlationChart *ChartInfoCorrelation, correlationUpdateCols []string) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+	var pars []interface{}
+	pars = append(pars, req.ChartName)
+	pars = append(pars, edbInfoIdStr)
+	pars = append(pars, req.ChartType)
+	pars = append(pars, req.ChartClassifyId)
+	pars = append(pars, disabled)
+	pars = append(pars, barChartConf)
+
+	sql := ` UPDATE  chart_info
+			SET
+			  chart_name =?,
+              edb_info_ids=?,
+			  chart_type=?,
+			  chart_classify_id = ?,
+			  modify_time = NOW(),
+              disabled = ?,
+              bar_config = ?
+			`
+	if calendar != "" {
+		sql += `,calendar = ? `
+		pars = append(pars, calendar)
+	}
+	if dateType > 0 {
+		sql += `,date_type = ? `
+		pars = append(pars, dateType)
+	}
+
+	sql += `,start_date = ? `
+	pars = append(pars, req.StartDate)
+
+	sql += `,end_date = ? `
+	pars = append(pars, req.EndDate)
+
+	sql += `,season_start_date = ? `
+	pars = append(pars, req.StartDate)
+
+	sql += `,season_end_date = ? `
+	pars = append(pars, req.EndDate)
+
+	sql += `,left_min = ? `
+	pars = append(pars, req.LeftMin)
+
+	sql += `,left_max = ? `
+	pars = append(pars, req.LeftMax)
+
+	sql += `,right_min = ? `
+	pars = append(pars, req.RightMin)
+
+	sql += `,right_max = ? `
+	pars = append(pars, req.RightMax)
+
+	sql += `WHERE chart_info_id = ?`
+
+	pars = append(pars, req.ChartInfoId)
+	_, err = to.Raw(sql, pars).Exec()
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+	chartEdbMappingIdList := make([]string, 0)
+	for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
+		// 查询该指标是否存在,如果存在的话,那么就去修改,否则新增
+		var tmpChartEdbMapping *ChartEdbMapping
+		csql := `SELECT *  FROM chart_edb_mapping WHERE chart_info_id=? AND edb_info_id=? AND source = ? `
+		err = to.Raw(csql, req.ChartInfoId, v.EdbInfoId, utils.CHART_SOURCE_CORRELATION).QueryRow(&tmpChartEdbMapping)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			fmt.Println("QueryRow Err:", err.Error())
+			return err
+		}
+		if tmpChartEdbMapping != nil {
+			chartEdbMappingIdList = append(chartEdbMappingIdList, strconv.Itoa(tmpChartEdbMapping.ChartEdbMappingId))
+			//tmpChartEdbMapping.ModifyTime = time.Now()
+			//tmpChartEdbMapping.MaxData = v.MaxData
+			//tmpChartEdbMapping.MinData = v.MinData
+			//tmpChartEdbMapping.IsOrder = v.IsOrder
+			//tmpChartEdbMapping.IsAxis = v.IsAxis
+			//tmpChartEdbMapping.EdbInfoType = v.EdbInfoType
+			//tmpChartEdbMapping.LeadValue = v.LeadValue
+			//tmpChartEdbMapping.LeadUnit = v.LeadUnit
+			//tmpChartEdbMapping.ChartStyle = v.ChartStyle
+			//tmpChartEdbMapping.ChartColor = v.ChartColor
+			//tmpChartEdbMapping.PredictChartColor = v.PredictChartColor
+			//tmpChartEdbMapping.ChartWidth = v.ChartWidth
+			//_, err = to.Update(tmpChartEdbMapping, "ModifyTime", "MaxData", "MinData", "IsOrder", "IsAxis", "EdbInfoType", "LeadValue", "LeadUnit", "ChartStyle", "ChartColor", "PredictChartColor", "ChartWidth")
+			//if err != nil {
+			//	fmt.Println("chart_edb_mapping Err:" + err.Error())
+			//	return err
+			//}
+		} else {
+			mapItem := new(ChartEdbMapping)
+			mapItem.ChartInfoId = req.ChartInfoId
+			mapItem.EdbInfoId = v.EdbInfoId
+			mapItem.CreateTime = time.Now()
+			mapItem.ModifyTime = time.Now()
+			timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+			mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp + "_" + strconv.Itoa(v.EdbInfoId))
+			//mapItem.MaxData = v.MaxData
+			//mapItem.MinData = v.MinData
+			mapItem.IsOrder = true
+			mapItem.IsAxis = 1
+			mapItem.EdbInfoType = 1
+			//mapItem.LeadValue = v.LeadValue
+			//mapItem.LeadUnit = v.LeadUnit
+			//mapItem.ChartStyle = v.ChartStyle
+			//mapItem.ChartColor = v.ChartColor
+			//mapItem.PredictChartColor = v.PredictChartColor
+			//mapItem.ChartWidth = v.ChartWidth
+			mapItem.Source = utils.CHART_SOURCE_CORRELATION
+			tmpId, err := to.Insert(mapItem)
+			if err != nil {
+				fmt.Println("AddChartEdbMapping Err:" + err.Error())
+				return err
+			}
+			mapItem.ChartEdbMappingId = int(tmpId)
+			chartEdbMappingIdList = append(chartEdbMappingIdList, strconv.Itoa(mapItem.ChartEdbMappingId))
+		}
+	}
+	if len(chartEdbMappingIdList) > 0 {
+		chartEdbMappingIdStr := strings.Join(chartEdbMappingIdList, ",")
+		dsql := `DELETE FROM chart_edb_mapping WHERE chart_info_id=? AND chart_edb_mapping_id NOT IN(` + chartEdbMappingIdStr + `)`
+		_, err = to.Raw(dsql, req.ChartInfoId).Exec()
+		if err != nil {
+			fmt.Println("delete err:" + err.Error())
+			return err
+		}
+	}
+
+	// 相关性图表
+	_, err = to.Update(correlationChart, correlationUpdateCols...)
+	return
+}*/
+
+// PreviewSectionScatterChartReq 预览截面散点图的请求
+type PreviewSectionScatterChartReq struct {
+	ChartName       string `description:"图表名称"`
+	ChartClassifyId int    `description:"分类id"`
+	ExtraConfig     string `description:"图表额外配置信息,json字符串"`
+}
+
+// SectionScatterReq 截面散点请求
+type SectionScatterReq struct {
+	XName       string `description:"x轴名称"`
+	XNameEn     string `description:"x轴名称(英文)"`
+	XUnitName   string `description:"x轴单位名称"`
+	XUnitNameEn string `description:"x轴单位名称(英文)"`
+	YName       string `description:"y轴名称"`
+	YNameEn     string `description:"y轴名称(英文)"`
+	YUnitName   string `description:"y轴单位名称"`
+	YUnitNameEn string `description:"y轴单位名称(英文)"`
+	XMinValue   string `description:"X轴的最小值"`
+	XMaxValue   string `description:"X轴的最大值"`
+	YMinValue   string `description:"Y轴的最小值"`
+	YMaxValue   string `description:"Y轴的最大值"`
+	//EdbList     []SectionScatterEdbItemReq    `description:"指标数据"`
+	SeriesList []SectionScatterSeriesItemReq `description:"系列数据"`
+}
+
+// SectionScatterSeriesItemReq 系列的请求
+type SectionScatterSeriesItemReq struct {
+	Name            string `description:"系列名"`
+	NameEn          string `description:"系列名(英文名)"`
+	IsNameDefault   bool   `description:"是否使用默认的系列名 false修改过 true默认  影响自动更新"`
+	Color           string `description:"颜色"`
+	EdbInfoList     []SectionScatterEdbItemReq
+	ShowTrendLine   bool `description:"是否展示趋势线"`
+	ShowFitEquation bool `description:"是否展示方程式"`
+	ShowRSquare     bool `description:"是否展示R平方"`
+}
+
+// SectionScatterEdbItemReq 截面散点请求的指标
+type SectionScatterEdbItemReq struct {
+	XEdbInfoId int    `description:"X轴的指标ID"`
+	YEdbInfoId int    `description:"Y轴的指标ID"`
+	Name       string `description:"别名"`
+	NameEn     string `description:"英文别名"`
+	XDateType  int    `description:"X轴的日期配置类型"`
+	XDate      string `description:"X轴的日期固定日期"`
+	XDateValue int    `description:"X轴的日期N天的值"`
+	YDateType  int    `description:"Y轴的日期配置类型"`
+	YDate      string `description:"Y轴的日期固定日期"`
+	YDateValue int    `description:"Y轴的日期N天的值"`
+	IsShow     bool   `description:"是否展示"`
+}
+
+// SectionScatterInfoResp 截面散点图数据
+type SectionScatterInfoResp struct {
+	XName       string                         `description:"x轴名称"`
+	XNameEn     string                         `description:"x轴名称(英文)"`
+	XUnitName   string                         `description:"x轴单位名称"`
+	XUnitNameEn string                         `description:"x轴单位名称(英文)"`
+	YName       string                         `description:"y轴名称"`
+	YNameEn     string                         `description:"y轴名称(英文)"`
+	YUnitName   string                         `description:"y轴单位名称"`
+	YUnitNameEn string                         `description:"y轴单位名称(英文)"`
+	XMinValue   string                         `description:"X轴的最小值"`
+	XMaxValue   string                         `description:"X轴的最大值"`
+	YMinValue   string                         `description:"Y轴的最小值"`
+	YMaxValue   string                         `description:"Y轴的最大值"`
+	DataList    []SectionScatterSeriesItemResp `description:"数据列"`
+}
+
+// SectionScatterSeriesItemResp 系列的返回
+type SectionScatterSeriesItemResp struct {
+	Name            string `description:"系列名"`
+	NameEn          string `description:"系列名(英文)"`
+	IsNameDefault   bool   `description:"是否使用默认的系列名 false修改过 true默认  影响自动更新"`
+	Color           string `description:"颜色"`
+	EdbInfoList     []SectionScatterEdbItemResp
+	ShowTrendLine   bool              `description:"是否展示趋势线"`
+	ShowFitEquation bool              `description:"是否展示方程式"`
+	ShowRSquare     bool              `description:"是否展示R平方"`
+	TrendLine       string            `description:"方程式"`
+	RSquare         string            `description:"R平方的值(决定系数R2)"`
+	TrendLimitData  []CoordinatePoint `description:"趋势线的前后坐标点"`
+}
+
+// SectionScatterEdbItemResp 截面散点的返回参数
+type SectionScatterEdbItemResp struct {
+	XEdbInfoId int     `description:"X轴指标id"`
+	XDate      string  `description:"X轴指标实际日期"`
+	XName      string  `description:"X轴指标名称"`
+	XNameEn    string  `description:"X轴指标英文名称"`
+	XValue     float64 `description:"X轴实际值"`
+	YEdbInfoId int     `description:"Y轴指标id"`
+	YDate      string  `description:"Y轴指标实际日期"`
+	YName      string  `description:"Y轴指标名称"`
+	YNameEn    string  `description:"Y轴指标英文名称"`
+	YValue     float64 `description:"Y轴实际值"`
+	IsShow     bool    `description:"是否展示"`
+	Name       string  `description:"标签名称"`
+	NameEn     string  `description:"英文标签名称"`
+}
+
+// CoordinatePoint 坐标点
+type CoordinatePoint struct {
+	X float64
+	Y float64
+}
+
+// RollingCorrelationChartDataResp 滚动相关性图
+type RollingCorrelationChartDataResp struct {
+	XDateTimeValue []string `description:"滚动相关性图的x轴数据,日期数据"`
+	YDataList      []YData  `description:"滚动相关性图的y轴数据"`
+}
+
+// GetChartInfoAll 用于分类展示
+// @param source int 1:ETA图库;2:商品价格曲线
+func GetChartInfoAllByClassifyId(source, classifyId int) (items []*ChartClassifyItems, err error) {
+	o := orm.NewOrm()
+	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,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
+}
+
+// ProfitFutureGoodChartResp 商品利润图
+type ProfitFutureGoodChartResp struct {
+	XDataList    []XData
+	YDataList    []YData
+	ProfitName   string `description:"利润的名称"`
+	ProfitNameEn string `description:"利润的英文名称"`
+}
+
+func FIXChartClassifyId(newId, oldId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE chart_info SET chart_classify_id=? WHERE chart_classify_id=? `
+	_, err = o.Raw(sql, newId, oldId).Exec()
+	return
+}
+
+// GetChartInfoByAdminIdAndClassify 获取所有我创建的图表,用于分类展示
+func GetChartInfoByAdminIdAndClassify(sourceList []int, adminId, classifyId int) (items []*ChartClassifyItems, err error) {
+	num := len(sourceList)
+	if num <= 0 {
+		return
+	}
+
+	o := orm.NewOrm()
+	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,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
+}
+
+// GetChartInfoAdminList 根据条件获取图表数据了列表
+func GetChartInfoAdminList() (items []int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT sys_user_id FROM chart_info GROUP BY sys_user_id `
+
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// EditChartInfoExtraConfig 修改 ETA图库 的 图表额外配置
+func EditChartInfoExtraConfig(chartId int, extraConfig string) (err error) {
+	o := orm.NewOrm()
+	var pars []interface{}
+	pars = append(pars, extraConfig)
+
+	sql := ` UPDATE  chart_info
+			SET
+			  modify_time = NOW(),
+              extra_config = ?
+			`
+	sql += `WHERE chart_info_id = ?`
+
+	pars = append(pars, chartId)
+	_, err = o.Raw(sql, pars).Exec()
+	if err != nil {
+		fmt.Println("UPDATE  chart_info Err:", err.Error())
+		return err
+	}
+
+	return
+}
+
+// PreviewRadarChartReq 预览雷达图的请求入参
+type PreviewRadarChartReq struct {
+	ChartEdbInfoList []*ChartSaveItem `description:"指标及配置信息"`
+	ExtraConfig      string           `description:"图表额外配置信息,json字符串"`
+}
+
+// RadarChartInfoReq 雷达图预览请求数据
+type RadarChartInfoReq struct {
+	DateList []RadarChartInfoDateReq `description:"日期配置"`
+}
+
+// RadarChartInfoEdbItemReq 雷达图预览请求数据(指标相关)
+type RadarChartInfoEdbItemReq struct {
+	EdbInfoId int    `description:"指标ID"`
+	Name      string `description:"别名"`
+	//NameEn    string `description:"英文别名"`
+	//Source    int    `description:"1:ETA图库;2:商品价格"`
+}
+
+// RadarChartInfoDateReq 雷达图预览请求数据(日期相关)
+type RadarChartInfoDateReq struct {
+	Type  int    `description:"配置类型"`
+	Date  string `description:"固定日期"`
+	Value int    `description:"N天的值"`
+	Color string `description:"颜色"`
+	Name  string `description:"别名"`
+}
+
+// RadarChartInfoResp 雷达图数据
+type RadarChartInfoResp struct {
+	YDataList   []RadarYData `description:"数据列"`
+	XEdbIdValue []int
+}
+
+// RadarYData 雷达图的y轴数据
+type RadarYData struct {
+	Date  string    `description:"数据日期"`
+	Color string    `description:"数据颜色"`
+	Name  string    `description:"别名"`
+	Value []float64 `description:"每个指标的值"`
+}

+ 151 - 0
models/chart_theme.go

@@ -0,0 +1,151 @@
+package models
+
+import (
+	"errors"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartTheme
+// @Description: 图表主题表
+type ChartTheme struct {
+	ChartThemeId     int       `description:"图表主题类型ID" orm:"column(chart_theme_id);pk"`
+	ChartThemeName   string    `description:"图表主题名称"`
+	ChartThemeTypeId int       `description:"图表主题类型ID"`
+	ChartImage       string    `description:"缩略图"`
+	Config           string    `description:"配置"`
+	IsDelete         int       `description:"是否删除,0:未删除;1:已删除"`
+	SysUserId        int       `description:"操作人"`
+	SysUserRealName  string    `description:"操作人的真实名称"`
+	IsSystemTheme    int       `description:"是否是系统主题,0:不是;1:是"`
+	ModifyTime       time.Time `description:"修改时间"`
+	CreateTime       time.Time `description:"创建时间"`
+}
+
+// GetChartThemeId
+// @Description: 根据id获取主题
+// @author: Roc
+// @datetime 2023-12-14 16:05:36
+// @param chartThemeId int
+// @return item *ChartTheme
+// @return err error
+func GetChartThemeId(chartThemeId int) (item *ChartTheme, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_theme where chart_theme_id = ? AND is_delete = 0`
+	err = o.Raw(sql, chartThemeId).QueryRow(&item)
+
+	return
+}
+
+// Add
+// @Description: 添加
+// @author: Roc
+// @receiver m
+// @datetime 2023-12-14 16:11:10
+// @param cols []string
+// @return err error
+func (m *ChartTheme) Add() (err error) {
+	if m.ChartThemeId > 0 {
+		err = errors.New("该配置已存在")
+		return
+	}
+	o := orm.NewOrm()
+	lastId, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.ChartThemeId = int(lastId)
+
+	return
+}
+
+// Update
+// @Description: 更新
+// @author: Roc
+// @receiver m
+// @datetime 2023-12-14 16:11:10
+// @param cols []string
+// @return err error
+func (m *ChartTheme) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+// GetChartThemeListByTypeId
+// @Description: 根据图表类型获取关联的图表主题列表
+// @author: Roc
+// @datetime 2023-12-13 17:39:48
+// @return list []*ChartTheme
+// @return err error
+func GetChartThemeListByTypeId(chartThemeTypeId int) (list []*ChartTheme, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_theme WHERE chart_theme_type_id = ? AND  is_delete=0 ORDER BY chart_theme_id ASC `
+	_, err = o.Raw(sql, chartThemeTypeId).QueryRows(&list)
+
+	return
+}
+
+// GetAllChartThemeList
+// @Description: 获取所有图表主题列表
+// @author: Roc
+// @datetime 2023-12-13 17:39:48
+// @return list []*ChartTheme
+// @return err error
+func GetAllChartThemeList() (list []*ChartTheme, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_theme WHERE  is_delete=0 ORDER BY chart_theme_id ASC `
+	_, err = o.Raw(sql).QueryRows(&list)
+
+	return
+}
+
+// ChartThemeItem
+// @Description: 图表主题配置
+type ChartThemeItem struct {
+	ChartThemeId     int    `description:"图表主题类型ID" orm:"column(chart_theme_id);pk"`
+	ChartThemeName   string `description:"图表主题名称"`
+	ChartThemeTypeId int    `description:"图表主题类型ID"`
+	Config           string `description:"配置"`
+	ChartImage       string `description:"缩略图"`
+	//IsDelete            int       `description:"是否删除,0:未删除;1:已删除"`
+	IsSystemTheme       int       `description:"是否是系统主题,0:不是;1:是"`
+	SysUserId           int       `description:"操作人"`
+	SysUserRealName     string    `description:"操作人的真实名称"`
+	ModifyTime          time.Time `description:"修改时间"`
+	CreateTime          time.Time `description:"创建时间"`
+	DefaultChartThemeId int       `description:"默认使用的图表主题ID"`
+}
+
+// GetChartThemeItemList
+// @Description: 根据图表类型id获取配置列表
+// @author: Roc
+// @datetime 2023-12-14 14:26:35
+// @param chartThemeTypeId int
+// @return list []*ChartThemeConfig
+// @return err error
+func GetChartThemeItemList(chartThemeTypeId int) (list []*ChartThemeItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT a.*,b.default_chart_theme_id FROM chart_theme a 
+         JOIN chart_theme_type b on a.chart_theme_type_id =b.chart_theme_type_id 
+         WHERE a.chart_theme_type_id = ? AND a.is_delete=0 ORDER BY a.chart_theme_id ASC `
+	_, err = o.Raw(sql, chartThemeTypeId).QueryRows(&list)
+
+	return
+}
+
+// GetSystemChartTheme
+// @Description: 根据图表类型id获取系统配置
+// @author: Roc
+// @datetime 2023-12-14 14:26:35
+// @param chartThemeTypeId int
+// @return item *ChartTheme
+// @return err error
+func GetSystemChartTheme(chartThemeTypeId int) (item *ChartTheme, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT a.* FROM chart_theme a
+         WHERE a.chart_theme_type_id = ? AND a.is_system_theme=1 ORDER BY a.chart_theme_id ASC `
+	err = o.Raw(sql, chartThemeTypeId).QueryRow(&item)
+
+	return
+}

+ 30 - 0
models/chart_theme/request/theme.go

@@ -0,0 +1,30 @@
+package request
+
+// AddThemeReq
+// @Description: 新增主题请求参数
+type AddThemeReq struct {
+	ChartThemeName   string `description:"主题名称"`
+	ChartThemeTypeId int    `description:"图表类型id"`
+}
+
+// EditThemeReq
+// @Description: 编辑主题请求参数
+type EditThemeReq struct {
+	ChartThemeId   int    `description:"主题id"`
+	ChartThemeName string `description:"主题名称"`
+	Config         string `description:"配置的值"`
+	ChartImage     string `description:"缩略图"`
+}
+
+// DeleteThemeReq
+// @Description: 删除主题请求参数
+type DeleteThemeReq struct {
+	ChartThemeId int `description:"配置id"`
+}
+
+// SetDefaultThemeReq
+// @Description: 配置默认主题请求参数
+type SetDefaultThemeReq struct {
+	ChartThemeId     int `description:"主题id"`
+	ChartThemeTypeId int `description:"主题类型id"`
+}

+ 91 - 0
models/chart_theme_default_data.go

@@ -0,0 +1,91 @@
+package models
+
+import (
+	"eta/eta_forum_hub/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartThemeDefaultData
+// @Description: 图表默认数据
+type ChartThemeDefaultData struct {
+	EdbDataId     int       `description:"指标数据ID" orm:"column(edb_data_id);pk"`
+	EdbInfoId     int       `description:"指标ID"`
+	EdbCode       string    `description:"指标编码"`
+	DataTime      string    //`json:"-" description:"数据日期"`
+	DataTimestamp int64     `description:"数据日期"`
+	Value         float64   `description:"数据值"`
+	ModifyTime    time.Time `description:"修改时间"`
+	CreateTime    time.Time `description:"创建时间"`
+}
+
+// GetChartThemeDefaultDataList
+// @Description: 获取指标的数据(日期正序返回)
+// @author: Roc
+// @datetime 2023-12-13 16:40:14
+// @param endInfoId int
+// @return list []*ChartThemeDefaultData
+// @return err error
+func GetChartThemeDefaultDataList(endInfoId int) (list []*ChartThemeDefaultData, err error) {
+	sql := `SELECT * FROM chart_theme_default_data WHERE edb_info_id=? `
+
+	sql += ` ORDER BY data_time ASC `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, endInfoId).QueryRows(&list)
+	return
+}
+
+// Update
+// @Description: 更新
+// @author: Roc
+// @receiver m
+// @datetime 2023-12-13 16:40:04
+// @param cols []string
+// @return err error
+func (m *ChartThemeDefaultData) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+
+	return
+}
+
+// GetChartThemeDefaultDataItemList
+// @Description: 获取指标的数据(日期正序返回)
+// @author: Roc
+// @datetime 2023-12-13 16:40:22
+// @param endInfoId int
+// @return list []*ChartThemeDefaultDataItem
+// @return err error
+func GetChartThemeDefaultDataItemList(endInfoId int, startDate string) (list []*EdbDataList, err error) {
+	sql := `SELECT edb_data_id,edb_info_id,data_time,value,data_timestamp FROM chart_theme_default_data WHERE edb_info_id=? `
+	var pars []interface{}
+	if startDate != "" {
+		sql += ` AND data_time>=? `
+		pars = append(pars, startDate)
+	}
+
+	sql += ` ORDER BY data_time ASC `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, endInfoId, pars).QueryRows(&list)
+	return
+}
+
+// GetChartEdbMappingListByEdbInfoId
+// @Description: 返回模拟的mapping假数据
+// @author: Roc
+// @datetime 2023-12-14 10:03:20
+// @param edbInfoIdList []int
+// @return list []*models.ChartEdbInfoMapping
+// @return err error
+func GetChartEdbMappingListByEdbInfoId(edbInfoIdList []int) (list []*ChartEdbInfoMapping, err error) {
+	num := len(edbInfoIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM chart_theme_default_edb_info WHERE edb_info_id IN(` + utils.GetOrmInReplace(num) + `)
+              `
+	_, err = o.Raw(sql, edbInfoIdList).QueryRows(&list)
+
+	return
+}

+ 90 - 0
models/chart_theme_type.go

@@ -0,0 +1,90 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// ChartThemeType
+// @Description: 图表主题类型表
+type ChartThemeType struct {
+	ChartThemeTypeId    int       `description:"图表主题类型ID" orm:"column(chart_theme_type_id);pk"`
+	ChartTypeName       string    `description:"类型名称"`
+	ChartType           int       `description:"图表类型"`
+	ChartSource         int       `description:"图表来源"`
+	DefaultChartThemeId int       `description:"默认使用的主题id"`
+	ModifyTime          time.Time `description:"修改时间"`
+	CreateTime          time.Time `description:"创建时间"`
+}
+
+// Update
+// @Description: 更新
+// @author: Roc
+// @receiver m
+// @datetime 2023-12-14 16:11:10
+// @param cols []string
+// @return err error
+func (m *ChartThemeType) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+// GetAllChartThemeTypeList
+// @Description: 获取所有图表主题类型列表
+// @author: Roc
+// @datetime 2023-12-13 17:31:03
+// @return list []*ChartThemeType
+// @return err error
+func GetAllChartThemeTypeList() (list []*ChartThemeType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_theme_type ORDER BY chart_theme_type_id ASC `
+	_, err = o.Raw(sql).QueryRows(&list)
+
+	return
+}
+
+// GetChartThemeTypeListBySource
+// @Description: 根据来源获取图表主题类型列表
+// @author: Roc
+// @datetime 2023-12-13 17:31:03
+// @param source int
+// @return list []*ChartThemeType
+// @return err error
+func GetChartThemeTypeListBySource(source int) (list []*ChartThemeType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_theme_type WHERE chart_source = ?  ORDER BY chart_theme_type_id ASC `
+	_, err = o.Raw(sql, source).QueryRows(&list)
+
+	return
+}
+
+// GetChartThemeTypeById
+// @Description: 通过类型id获取类型
+// @author: Roc
+// @datetime 2023-12-14 09:53:58
+// @param chartThemeTypeId int
+// @return item *ChartThemeType
+// @return err error
+func GetChartThemeTypeById(chartThemeTypeId int) (item *ChartThemeType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_theme_type where chart_theme_type_id = ? `
+	err = o.Raw(sql, chartThemeTypeId).QueryRow(&item)
+
+	return
+}
+
+// GetChartThemeTypeByChartTypeAndSource
+// @Description: 通过图表类型和来源获取类型
+// @author: Roc
+// @datetime 2023-12-14 09:53:58
+// @param chartThemeTypeId int
+// @return item *ChartThemeType
+// @return err error
+func GetChartThemeTypeByChartTypeAndSource(chartType, source int) (item *ChartThemeType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_theme_type where chart_type = ? AND chart_source = ? `
+	err = o.Raw(sql, chartType, source).QueryRow(&item)
+
+	return
+}

+ 29 - 18
models/db.go

@@ -8,24 +8,35 @@ import (
 )
 
 func init() {
-	if utils.MYSQL_URL_ETA != "" {
-		_ = orm.RegisterDataBase("eta", "mysql", utils.MYSQL_URL_ETA)
-		orm.SetMaxIdleConns("eta", 50)
-		orm.SetMaxOpenConns("eta", 100)
-		etaDb, _ := orm.GetDB("eta")
-		etaDb.SetConnMaxLifetime(10 * time.Minute)
+	_ = orm.RegisterDataBase("default", "mysql", utils.MYSQL_URL)
+	orm.SetMaxIdleConns("default", 50)
+	orm.SetMaxOpenConns("default", 100)
 
-		orm.Debug = true
-		orm.DebugLog = orm.NewLog(utils.Binlog)
-	}
-	if utils.MYSQL_URL_DATA != "" {
-		_ = orm.RegisterDataBase("data", "mysql", utils.MYSQL_URL_DATA)
-		orm.SetMaxIdleConns("data", 50)
-		orm.SetMaxOpenConns("data", 100)
-		etaDb, _ := orm.GetDB("data")
-		etaDb.SetConnMaxLifetime(10 * time.Minute)
+	db, _ := orm.GetDB("default")
+	db.SetConnMaxLifetime(10 * time.Minute)
 
-		orm.Debug = true
-		orm.DebugLog = orm.NewLog(utils.Binlog)
-	}
+	orm.Debug = true
+	orm.DebugLog = orm.NewLog(utils.Binlog)
+	
+	initChart()
+	initEdbData()
+}
+
+// initChart 图表 数据表
+func initChart() {
+	orm.RegisterModel(
+		new(ChartClassify),
+		new(ChartInfo),
+		new(ChartEdbMapping),
+		new(ChartTheme),
+		new(ChartThemeType),
+	)
+}
+
+// initEdbData 指标服务 数据表
+func initEdbData() {
+	orm.RegisterModel(
+		new(EdbInfoCalculateMapping),
+		new(EdbInfo),
+	)
 }

+ 309 - 0
models/edb_info.go

@@ -0,0 +1,309 @@
+package models
+
+import (
+	"eta/eta_forum_hub/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type EdbInfo struct {
+	EdbInfoId        int    `orm:"column(edb_info_id);pk"`
+	EdbInfoType      int    `description:"指标类型,0:普通指标,1:预测指标"`
+	SourceName       string `description:"来源名称"`
+	Source           int    `description:"来源id"`
+	EdbCode          string `description:"指标编码"`
+	EdbName          string `description:"指标名称"`
+	EdbNameEn        string `description:"英文指标名称"`
+	EdbNameSource    string `description:"指标名称来源"`
+	Frequency        string `description:"频率"`
+	Unit             string `description:"单位"`
+	UnitEn           string `description:"英文单位"`
+	StartDate        string `description:"起始日期"`
+	EndDate          string `description:"终止日期"`
+	ClassifyId       int    `description:"分类id"`
+	SysUserId        int
+	SysUserRealName  string
+	UniqueCode       string `description:"指标唯一编码"`
+	CreateTime       time.Time
+	ModifyTime       time.Time
+	MinValue         float64 `description:"指标最小值"`
+	MaxValue         float64 `description:"指标最大值"`
+	CalculateFormula string  `description:"计算公式"`
+	EdbType          int     `description:"指标类型:1:基础指标,2:计算指标"`
+	Sort             int     `description:"排序字段"`
+	LatestDate       string  `description:"数据最新日期(实际日期)"`
+	LatestValue      float64 `description:"数据最新值(实际值)"`
+	EndValue         float64 `description:"数据的最新值(预测日期的最新值)"`
+	MoveType         int     `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency    string  `description:"移动频度"`
+	NoUpdate         int8    `description:"是否停止更新,0:继续更新;1:停止更新"`
+	ServerUrl        string  `description:"服务器地址"`
+	ChartImage       string  `description:"图表图片"`
+	Calendar         string  `description:"公历/农历" orm:"default(公历);"`
+	DataDateType     string  `orm:"column(data_date_type);size(255);null;default(交易日)"`
+	ManualSave       int     `description:"是否有手动保存过上下限: 0-否; 1-是"`
+	EmptyType        int     `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
+	MaxEmptyType     int     `description:"MAX、MIN公式空值处理类型(1、等于0;2、跳过空值)"`
+	TerminalCode     string  `description:"终端编码,用于配置在机器上"`
+	DataUpdateTime   string  `description:"最近一次数据发生变化的时间"`
+	ErDataUpdateDate string  `description:"本次更新,数据发生变化的最早日期"`
+	SourceIndexName  string  `description:"数据源中的指标名称"`
+	SubSource        int     `description:"子数据来源:0:经济数据库,1:日期序列"`
+	SubSourceName    string  `description:"子数据来源名称"`
+	IndicatorCode    string  `description:"指标代码"`
+	StockCode        string  `description:"证券代码"`
+	Extra            string  `description:"指标额外配置"`
+	IsJoinPermission int     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+}
+
+type EdbInfoFullClassify struct {
+	*EdbInfo
+	CorrelationStr string `description:"相关性系数字符串"`
+	HaveOperaAuth  bool   `description:"是否有数据权限,默认:false"`
+}
+
+func AddEdbInfo(item *EdbInfo) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+// 更新指标信息
+func (e *EdbInfo) Update(col []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(e, col...)
+	return
+}
+
+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:"单位"`
+	HaveOperaAuth bool   `description:"是否有数据权限,默认:false"`
+}
+
+type BaseEdbInfoResp struct {
+	List []*BaseEdbNameItem
+}
+
+// 指标检索数据
+type EdbInfoSearch struct {
+	EdbCode   string `description:"指标编码"`
+	StartDate string `description:"起始日期"`
+	EndDate   string `description:"终止日期"`
+	EdbName   string `description:"指标名称"`
+	Unit      string `description:"单位"`
+	Frequency string `description:"频率"`
+	DataList  []*EdbInfoSearchData
+	StockList []*StockInfo `description:"时序数据"`
+}
+
+type StockInfo struct {
+	StockCode string
+	EdbCode   string
+	DataList  []*EdbInfoSearchData
+}
+
+type EdbInfoSearchData struct {
+	DataTime string  `description:"数据日期"`
+	Value    float64 `description:"数据"`
+}
+
+type BaseIndexInfo struct {
+	IndexName string `description:"数据日期"`
+	Unit      string `description:"单位"`
+	Frequency string `description:"频率"`
+}
+
+type EdbInfoSearchResp struct {
+	SearchItem      *EdbInfoSearch `description:"指标分类"`
+	Status          int            `description:"1:数据已存在于弘则数据库,2:新数据,3:数据已存在于弘则数据库,但是当前账号无权限"`
+	StockSearchList []*EdbInfoSearch
+}
+
+func GetEdbInfoByEdbCode(source int, edbCode string) (item *EdbInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM edb_info WHERE source=? AND edb_code=? `
+	err = o.Raw(sql, source, edbCode).QueryRow(&item)
+	return
+}
+
+func GetEdbInfoById(edbInfoId int) (item *EdbInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM edb_info WHERE edb_info_id=? `
+	err = o.Raw(sql, edbInfoId).QueryRow(&item)
+	return
+}
+
+// GetEdbInfoByUniqueCode
+// @Description: 根据uniqueCode获取指标详情
+// @author: Roc
+// @datetime 2024-01-18 13:40:01
+// @param uniqueCode string
+// @return item *EdbInfo
+// @return err error
+func GetEdbInfoByUniqueCode(uniqueCode string) (item *EdbInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM edb_info WHERE unique_code=? `
+	err = o.Raw(sql, uniqueCode).QueryRow(&item)
+	return
+}
+
+// GetEdbInfoByIdList 根据指标id集合 获取 指标列表
+func GetEdbInfoByIdList(edbInfoIdList []int) (items []*EdbInfo, err error) {
+	num := len(edbInfoIdList)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM edb_info WHERE edb_info_id in (` + utils.GetOrmInReplace(num) + `) `
+	_, err = o.Raw(sql, edbInfoIdList).QueryRows(&items)
+	return
+}
+
+func DeleteEdbInfo(edbInfoId int) (err error) {
+	o := orm.NewOrm()
+	to, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = to.Rollback()
+		} else {
+			_ = to.Commit()
+		}
+	}()
+
+	// 删除指标信息
+	sql := ` DELETE FROM edb_info WHERE edb_info_id=? `
+	_, err = to.Raw(sql, edbInfoId).Exec()
+	if err != nil {
+		return
+	}
+
+	// 删除计算指标的关系
+	sql = ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id=? `
+	_, err = to.Raw(sql, edbInfoId).Exec()
+
+	return
+}
+
+func GetEdbInfoCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM edb_info WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+type EditEdbInfoReq struct {
+	EdbInfoId        int    `description:"指标ID"`
+	EdbName          string `description:"指标名称"`
+	Frequency        string `description:"频率"`
+	Unit             string `description:"单位"`
+	ClassifyId       int    `description:"分类id"`
+	CalculateFormula string `description:"计算公式"`
+}
+
+type EditEdbEnInfoReq struct {
+	EdbInfoId int    `description:"指标ID"`
+	EdbNameEn string `description:"英文指标名称"`
+	UnitEn    string `description:"英文单位"`
+}
+
+func ModifyEdbInfo(item *EditEdbInfoReq) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name =?,
+			  edb_name_source =?,
+			  frequency = ?,
+			  unit = ?,
+			  classify_id = ?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ?`
+	_, err = o.Raw(sql, item.EdbName, item.EdbName, item.Frequency, item.Unit, item.ClassifyId, item.EdbInfoId).Exec()
+	return
+}
+
+// ModifyEdbEnInfo 修改指标英文信息
+func ModifyEdbEnInfo(item *EditEdbEnInfoReq) (err error) {
+	o := orm.NewOrm()
+	sql := ` UPDATE  edb_info
+			SET
+			  edb_name_en =?,
+			  unit_en = ?,
+			  modify_time = NOW()
+			WHERE edb_info_id = ?`
+	_, err = o.Raw(sql, item.EdbNameEn, item.UnitEn, item.EdbInfoId).Exec()
+	return
+}
+
+type EdbInfoList struct {
+	EdbInfoId        int                     `orm:"column(edb_info_id);pk"`
+	EdbInfoType      int                     `description:"指标类型,0:普通指标,1:预测指标"`
+	SourceName       string                  `description:"来源名称"`
+	Source           int                     `description:"来源id"`
+	EdbCode          string                  `description:"指标编码"`
+	EdbNameEn        string                  `description:"英文指标名称"`
+	EdbName          string                  `description:"指标名称"`
+	Frequency        string                  `description:"频率"`
+	FrequencyEn      string                  `description:"英文频率"`
+	Unit             string                  `description:"单位"`
+	UnitEn           string                  `description:"英文单位"`
+	StartDate        string                  `description:"起始日期"`
+	EndDate          string                  `description:"终止日期"`
+	LatestDate       string                  `description:"数据最新日期(实际日期)"`
+	LatestValue      float64                 `description:"数据最新值(实际值)"`
+	EndValue         float64                 `description:"数据的最新值(预测日期的最新值)"`
+	ClassifyId       int                     `description:"分类id"`
+	UniqueCode       string                  `description:"指标唯一编码"`
+	SysUserId        int                     `description:"创建人id"`
+	SysUserRealName  string                  `description:"创建人姓名"`
+	ModifyTime       string                  `description:"最新修改时间"`
+	CreateTime       string                  `description:"创建时间"`
+	EdbNameAlias     string                  `json:"-" description:"指标名称,别名"`
+	EdbType          int                     `description:"指标类型:1:基础指标,2:计算指标"`
+	ChartImage       string                  `description:"图表图片"`
+	RuleType         int                     `description:"预测规则,1:最新,2:固定值"`
+	FixedValue       float64                 `description:"固定值"`
+	DataList         []*EdbData              `description:"实际指标数据"`
+	PredictDataList  []*EdbData              `description:"预测指标数据"`
+	IsEnEdb          bool                    `description:"是否展示英文标识"`
+	DataInsertConfig EdbDataInsertConfigItem `description:"指标数据插入配置"`
+	DataDateType     string                  `description:"数据日期类型,枚举值:交易日、自然日"`
+	EmptyType        int                     `description:"空值处理类型(0查找前后35天,1不计算,2前值填充,3后值填充,4等于0)"`
+	MaxEmptyType     int                     `description:"MAX、MIN公式空值处理类型(1、等于0;2、跳过空值)"`
+	SubSource        int                     `description:"子数据来源:0:经济数据库,1:日期序列"`
+	SubSourceName    string                  `description:"子数据来源名称"`
+	IndicatorCode    string                  `description:"指标代码"`
+	StockCode        string                  `description:"证券代码"`
+	NoUpdate         int8                    `description:"是否停止更新,0:继续更新;1:停止更新"`
+	IsJoinPermission int                     `description:"是否加入权限管控,0:不加入;1:加入;默认:0"`
+	HaveOperaAuth    bool                    `description:"是否有数据权限,默认:false"`
+}
+
+type EdbDataInsertConfigItem struct {
+	Date     string `description:"插入的日期"`
+	RealDate string `description:"实际最晚的日期"`
+	Value    string `description:"插入的值"`
+}
+
+type EdbData struct {
+	EdbDataId int `orm:"column(edb_data_id);pk"`
+	EdbInfoId int
+	DataTime  string
+	Value     float64
+}
+
+type EdbInfoListResp struct {
+	Item *EdbInfoList
+}

+ 112 - 0
models/edb_info_calculate_mapping.go

@@ -0,0 +1,112 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// EdbInfoCalculateMapping 计算指标于基础指标,关系表
+type EdbInfoCalculateMapping struct {
+	EdbInfoCalculateMappingId int       `orm:"column(edb_info_calculate_mapping_id);pk"`
+	EdbInfoId                 int       `description:"计算指标id"`
+	Source                    int       `description:"计算指标来源"`
+	SourceName                string    `description:"计算指标来源名称"`
+	EdbCode                   string    `description:"计算指标编码"`
+	FromEdbInfoId             int       `description:"基础指标id"`
+	FromEdbCode               string    `description:"基础指标编码"`
+	FromEdbName               string    `description:"基础指标名称"`
+	FromSource                int       `description:"基础指标来源"`
+	FromSourceName            string    `description:"基础指标来源名称"`
+	FromTag                   string    `description:"来源指标标签"`
+	Sort                      int       `description:"计算指标名称排序"`
+	CreateTime                time.Time `description:"创建时间"`
+	ModifyTime                time.Time `description:"修改时间"`
+	FromSubSource             int       `description:"渠道子数据库来源"`
+}
+
+func AddEdbInfoCalculateMappingMulti(items []*EdbInfoCalculateMapping) (err error) {
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(1, items)
+	return
+}
+
+func DeleteEdbInfoMapping(edbInfoId int64) (err error) {
+	o := orm.NewOrm()
+	// 删除计算指标的关系
+	sql := ` DELETE FROM edb_info_calculate_mapping WHERE edb_info_id=? `
+	_, err = o.Raw(sql, edbInfoId).Exec()
+	return
+}
+
+func GetEdbInfoCalculateMappingCount(edbInfoId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT COUNT(1) AS count FROM edb_info_calculate_mapping WHERE from_edb_info_id=? `
+	err = o.Raw(sql, edbInfoId).QueryRow(&count)
+	return
+}
+
+type EdbInfoCalculateMappingView struct {
+	EdbInfoCalculateMappingId int       `orm:"column(edb_info_calculate_mapping_id);pk"`
+	EdbInfoId                 int       `description:"计算指标id"`
+	Source                    int       `description:"计算指标来源"`
+	SourceName                string    `description:"计算指标来源名称"`
+	EdbCode                   string    `description:"计算指标编码"`
+	FromEdbInfoId             int       `description:"基础指标id"`
+	FromEdbCode               string    `description:"基础指标编码"`
+	FromEdbName               string    `description:"基础指标名称"`
+	FromSource                int       `description:"基础指标来源"`
+	FromSourceName            string    `description:"基础指标来源名称"`
+	FromTag                   string    `description:"来源指标标签"`
+	Sort                      int       `description:"计算指标名称排序"`
+	CreateTime                time.Time `description:"创建时间"`
+	ModifyTime                time.Time `description:"修改时间"`
+	StartDate                 string    `description:"开始日期"`
+	EndDate                   string    `description:"结束日期"`
+	CalculateFormula          string    `description:"N值"`
+	MoveType                  int       `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency             string    `description:"移动频度"`
+}
+
+func GetEdbInfoCalculateMappingDetail(edbInfoId int) (item *EdbInfoCalculateMappingView, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT a.*,b.start_date,b.end_date,b.calculate_formula,b.move_type,b.move_frequency FROM edb_info_calculate_mapping AS a
+			INNER JOIN edb_info AS b ON a.edb_info_id=b.edb_info_id
+			WHERE a.edb_info_id=? `
+	err = o.Raw(sql, edbInfoId).QueryRow(&item)
+	return
+}
+
+// EdbInfoCalculateMappingInfo
+// @Description: 计算指标与基础指标关系表
+type EdbInfoCalculateMappingInfo struct {
+	EdbInfoCalculateMappingId int       `orm:"column(edb_info_calculate_mapping_id);pk"`
+	EdbInfoId                 int       `description:"计算指标id"`
+	Source                    int       `description:"计算指标来源"`
+	SourceName                string    `description:"计算指标来源名称"`
+	EdbCode                   string    `description:"计算指标编码"`
+	FromEdbInfoId             int       `description:"基础指标id"`
+	FromEdbCode               string    `description:"基础指标编码"`
+	FromEdbName               string    `description:"基础指标名称"`
+	FromSource                int       `description:"基础指标来源"`
+	FromSourceName            string    `description:"基础指标来源名称"`
+	MoveValue                 int       `description:"领先值"`
+	FromTag                   string    `description:"来源指标标签"`
+	Sort                      int       `description:"计算指标名称排序"`
+	CreateTime                time.Time `description:"创建时间"`
+	ModifyTime                time.Time `description:"修改时间"`
+	FromEdbType               int       `description:"来源指标类型:1:基础指标,2:计算指标"`
+	FromEdbInfoType           int       `description:"来源指标类型: 0-基础指标; 1-预测指标"`
+	FromClassifyId            int       `description:"来源指标分类ID"`
+	FromUniqueCode            string    `description:"来源指标唯一编码"`
+	NoUpdate                  int8      `description:"是否停止更新,0:继续更新;1:停止更新"`
+}
+
+// GetEdbInfoCalculateMappingListByEdbInfoId 根据生成的指标id获取来源的指标id列表
+func GetEdbInfoCalculateMappingListByEdbInfoId(edbInfoId int) (items []*EdbInfoCalculateMappingInfo, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT a.*,b.edb_type as from_edb_type,b.edb_info_type as from_edb_info_type, b.unique_code AS from_unique_code, b.classify_id AS from_classify_id,b.no_update FROM edb_info_calculate_mapping AS a
+			INNER JOIN edb_info AS b ON a.from_edb_info_id=b.edb_info_id
+			WHERE a.edb_info_id=? `
+	_, err = o.Raw(sql, edbInfoId).QueryRows(&items)
+	return
+}

+ 39 - 0
models/mgodb/db.go

@@ -0,0 +1,39 @@
+package mgodb
+
+import (
+	"context"
+	"eta/eta_forum_hub/utils"
+	"fmt"
+	"go.mongodb.org/mongo-driver/mongo"
+	"go.mongodb.org/mongo-driver/mongo/options"
+	"go.mongodb.org/mongo-driver/mongo/readpref"
+	"time"
+)
+
+var MgoClient *mongo.Client
+
+func init() {
+	var err error
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	defer cancel()
+	credential := options.Credential{
+		AuthMechanism: utils.MONGODB_CREDENTIAL,
+		Username:      "hzeta",
+		Password:      "hzeta2023",
+	}
+	clientOpts := options.Client().ApplyURI(utils.MONGODB_URL).SetAuth(credential)
+	clientOpts.SetMinPoolSize(0)
+	clientOpts.SetMaxPoolSize(100)
+	clientOpts.SetConnectTimeout(10 * time.Second)
+
+	MgoClient, err = mongo.Connect(context.TODO(), clientOpts)
+	if err != nil {
+		panic(err)
+	}
+
+	if err = MgoClient.Ping(ctx, readpref.Primary()); err != nil {
+		panic(err)
+	}
+
+	fmt.Println("Connected to MongoDB!")
+}

+ 119 - 0
models/mgodb/edb_data_base.go

@@ -0,0 +1,119 @@
+package mgodb
+
+import (
+	"context"
+	"eta/eta_forum_hub/utils"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo/options"
+	"time"
+)
+
+type EdbDataBase struct {
+	EdbInfoId     int    `bson:"edb_info_id"`
+	EdbCode       string `bson:"edb_code"`
+	DataTime      string `bson:"data_time"`
+	Value         string `bson:"value"`
+	Status        int    `bson:"status"`
+	CreateTime    string `bson:"create_time"`
+	ModifyTime    string `bson:"modify_time"`
+	DataTimestamp int64  `bson:"data_timestamp"`
+}
+
+type EdbInfoSearchData struct {
+	DataTime string  `description:"数据日期" bson:"data_time"`
+	Value    float64 `description:"数据" bson:"value"`
+	EdbCode  string  `description:"指标编码" bson:"edb_code"`
+}
+
+func GetEdbDataBaseByEdbInfoId(edbInfoId int) (items []*EdbDataBase, err error) {
+	findOptions := options.Find()
+	db := NewMgo(utils.MONGODB_COMMUNITY, "edb_data_base", MgoClient)
+	filter := bson.D{{"edb_info_id", edbInfoId}}
+	ctx := context.TODO()
+	cur, err := db.Find(filter, findOptions)
+	if err != nil {
+		return
+	}
+	// Close the cursor once finished
+	defer cur.Close(ctx)
+	for cur.Next(ctx) {
+		// create a value into which the single document can be decoded
+		var elem EdbDataBase
+		err = cur.Decode(&elem)
+		if err != nil {
+			return
+		}
+
+		items = append(items, &elem)
+	}
+
+	if err = cur.Err(); err != nil {
+		return
+	}
+	return
+}
+
+func GetEdbDataBaseByEdbCode(edbCode string) (items []*EdbDataBase, err error) {
+	findOptions := options.Find()
+	db := NewMgo(utils.MONGODB_COMMUNITY, "edb_data_base", MgoClient)
+	filter := bson.D{{"edb_code", edbCode}}
+	ctx := context.TODO()
+	cur, err := db.Find(filter, findOptions)
+	if err != nil {
+		return
+	}
+	// Close the cursor once finished
+	defer cur.Close(ctx)
+	for cur.Next(ctx) {
+		// create a value into which the single document can be decoded
+		var elem EdbDataBase
+		err = cur.Decode(&elem)
+		if err != nil {
+			return
+		}
+
+		items = append(items, &elem)
+	}
+
+	if err = cur.Err(); err != nil {
+		return
+	}
+	return
+}
+
+func InsertBatch(items []interface{}) (err error) {
+	db := NewMgo(utils.MONGODB_COMMUNITY, "edb_data_base", MgoClient)
+	_, err = db.InsertMany(items)
+	if err != nil {
+		return
+	}
+	return
+}
+
+func ModifyEdbInfoDataStatus(edbInfoId int64, edbCode string) (err error) {
+	filter := bson.D{{"edb_code", edbCode}}
+	update := bson.D{{"$set", bson.D{{"edb_info_id", edbInfoId}, {"modify_time", time.Now().Format("2006-01-02 15:04:05")}}}}
+	db := NewMgo(utils.MONGODB_COMMUNITY, "edb_data_base", MgoClient)
+	_, err = db.UpdateMany(filter, update)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// 删除
+func DeleteEdbInfoDataByEdbInfoId(edbInfoId int) (err error) {
+	filter := bson.D{{"edb_info_id", edbInfoId}}
+	db := NewMgo(utils.MONGODB_COMMUNITY, "edb_data_base", MgoClient)
+	_, err = db.DeleteMany(filter)
+	return
+}
+
+// 更新指标的值
+func ModifyValueEdbInfoDataStatus(edbCode string, dataTime string, value string) (err error) {
+	filter := bson.D{{"edb_code", edbCode}, {"data_time", dataTime}}
+	update := bson.D{{"$set", bson.D{{"value", value}, {"modify_time", time.Now().Format("2006-01-02 15:04:05")}}}}
+	db := NewMgo(utils.MONGODB_COMMUNITY, "edb_data_base", MgoClient)
+	_, err = db.UpdateOne(filter, update)
+	return
+}

+ 156 - 0
models/mgodb/mgo.go

@@ -0,0 +1,156 @@
+package mgodb
+
+import (
+	"context"
+	"fmt"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo"
+	"go.mongodb.org/mongo-driver/mongo/options"
+	"strconv"
+	"time"
+)
+
+type mgo struct {
+	database   string
+	collection string
+	client     *mongo.Client
+}
+
+func NewMgo(database, collection string, client *mongo.Client) *mgo {
+	return &mgo{
+		database,
+		collection,
+		client,
+	}
+}
+
+// 查询单个
+func (m *mgo) FindOne(key string, value interface{}) *mongo.SingleResult {
+	collection, _ := m.client.Database(m.database).Collection(m.collection).Clone()
+	filter := bson.D{{key, value}}
+	singleResult := collection.FindOne(context.TODO(), filter)
+	return singleResult
+}
+
+// 查询单个
+func (m *mgo) Find(filter bson.D, findOptions *options.FindOptions) (cur *mongo.Cursor, err error) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+
+	cur, err = collection.Find(context.TODO(), filter, findOptions)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// 插入单个
+func (m *mgo) InsertOne(value interface{}) (insertResult *mongo.InsertOneResult, err error) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	insertResult, err = collection.InsertOne(context.TODO(), value)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	return
+}
+
+func (m *mgo) InsertMany(value []interface{}) (insertManyResult *mongo.InsertManyResult, err error) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	insertManyResult, err = collection.InsertMany(context.TODO(), value)
+	if err != nil {
+		return
+	}
+
+	fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)
+	return
+}
+
+// 查询集合里有多少数据
+func (m *mgo) CollectionCount() (string, int64) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	name := collection.Name()
+	size, _ := collection.EstimatedDocumentCount(context.TODO())
+	return name, size
+}
+
+// 按选项查询集合 Skip 跳过 Limit 读取数量 sort 1 ,-1 . 1 为最初时间读取 , -1 为最新时间读取
+func (m *mgo) CollectionDocuments(Skip, Limit int64, sort int) *mongo.Cursor {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	SORT := bson.D{{"_id", sort}} //filter := bson.D{{key,value}}
+	filter := bson.D{{}}
+	findOptions := options.Find().SetSort(SORT).SetLimit(Limit).SetSkip(Skip)
+	//findOptions.SetLimit(i)
+	temp, _ := collection.Find(context.Background(), filter, findOptions)
+	return temp
+}
+
+// 获取集合创建时间和编号
+func (m *mgo) ParsingId(result string) (time.Time, uint64) {
+	temp1 := result[:8]
+	timestamp, _ := strconv.ParseInt(temp1, 16, 64)
+	dateTime := time.Unix(timestamp, 0) //这是截获情报时间 时间格式 2019-04-24 09:23:39 +0800 CST
+	temp2 := result[18:]
+	count, _ := strconv.ParseUint(temp2, 16, 64) //截获情报的编号
+	return dateTime, count
+}
+
+// 删除文章和查询文章
+func (m *mgo) DeleteAndFind(key string, value interface{}) (int64, *mongo.SingleResult) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	filter := bson.D{{key, value}}
+	singleResult := collection.FindOne(context.TODO(), filter)
+	DeleteResult, err := collection.DeleteOne(context.TODO(), filter, nil)
+	if err != nil {
+		fmt.Println("删除时出现错误,你删不掉的~")
+	}
+	return DeleteResult.DeletedCount, singleResult
+}
+
+// 删除文章
+func (m *mgo) Delete(key string, value interface{}) int64 {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	filter := bson.D{{key, value}}
+	count, err := collection.DeleteOne(context.TODO(), filter, nil)
+	if err != nil {
+		fmt.Println(err)
+	}
+	return count.DeletedCount
+
+}
+
+// 删除多个
+func (m *mgo) DeleteMany(filter bson.D) (num int64, err error) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	//filter := bson.D{{key, value}}
+
+	count, err := collection.DeleteMany(context.TODO(), filter)
+	if err != nil {
+		return
+	}
+	num = count.DeletedCount
+	return
+}
+
+func (m *mgo) UpdateMany(filter, update bson.D) (result *mongo.UpdateResult, err error) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	//filter := bson.D{{"name", "123456"}}
+	//update := bson.D{{"$set", bson.D{{"name", "张三"}}}}
+	result, err = collection.UpdateMany(context.TODO(), filter, update)
+	if err != nil {
+		return
+	}
+	fmt.Println(result)
+	return
+}
+
+func (m *mgo) UpdateOne(filter, update bson.D) (result *mongo.UpdateResult, err error) {
+	collection := m.client.Database(m.database).Collection(m.collection)
+	//filter := bson.D{{"name", "123456"}}
+	//update := bson.D{{"$set", bson.D{{"name", "张三"}}}}
+	result, err = collection.UpdateOne(context.TODO(), filter, update)
+	if err != nil {
+		return
+	}
+	fmt.Println(result)
+	return
+}

+ 26 - 98
routers/commentsRouter.go

@@ -7,103 +7,31 @@ import (
 
 func init() {
 
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers/xiangyu:XyController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers/xiangyu:XyController"],
-		beego.ControllerComments{
-			Method:           "SyncClassifyList",
-			Router:           `/sync/classify`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers/xiangyu:XyController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers/xiangyu:XyController"],
-		beego.ControllerComments{
-			Method:           "SyncIndexList",
-			Router:           `/sync/index`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers/xiangyu:XyController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers/xiangyu:XyController"],
-		beego.ControllerComments{
-			Method:           "SyncUser",
-			Router:           `/sync/user`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataFixController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataFixController"],
-		beego.ControllerComments{
-			Method:           "FixTableV1",
-			Router:           `/fix/v1`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"],
-		beego.ControllerComments{
-			Method:           "Base",
-			Router:           `/base`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"],
-		beego.ControllerComments{
-			Method:           "AddToEdbInfo",
-			Router:           `/base/edb_info/add`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"],
-		beego.ControllerComments{
-			Method:           "BaseJiaYue",
-			Router:           `/base_jiayue`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"],
-		beego.ControllerComments{
-			Method:           "MySteelChemicalToSource",
-			Router:           `/mysteel_chemical`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"],
-		beego.ControllerComments{
-			Method:           "MySteelChemicalBase",
-			Router:           `/mysteel_chemical/base`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"],
-		beego.ControllerComments{
-			Method:           "SmmToIndexLib",
-			Router:           `/smm/add/to_index_lib`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
-
-	beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:DataInitController"],
-		beego.ControllerComments{
-			Method:           "SmmToDataSource",
-			Router:           `/smm/to_data_source`,
-			AllowHTTPMethods: []string{"get"},
-			MethodParams:     param.Make(),
-			Filters:          nil,
-			Params:           nil})
+    beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Delete",
+            Router: `/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Save",
+            Router: `/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_forum_hub/controllers:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "Update",
+            Router: `/update`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
 
 }

+ 9 - 3
routers/router.go

@@ -8,11 +8,17 @@
 package routers
 
 import (
-	beego "github.com/beego/beego/v2/server/web"
+	"eta/eta_forum_hub/controllers"
+	"github.com/beego/beego/v2/server/web"
 )
 
 func init() {
-	ns := beego.NewNamespace("/v1",
+	ns := web.NewNamespace("/v1",
+		web.NSNamespace("/chart",
+			web.NSInclude(
+				&controllers.ChartInfoController{},
+			),
+		),
 	)
-	beego.AddNamespace(ns)
+	web.AddNamespace(ns)
 }

+ 91 - 0
services/alarm_msg/alarm_msg.go

@@ -0,0 +1,91 @@
+package alarm_msg
+
+import (
+	"crypto/tls"
+	"encoding/json"
+	"eta/eta_forum_hub/utils"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+	"time"
+)
+
+// SendAlarmMsg
+// projectName-项目名称
+// runMode-运行模式
+// msgBody-消息内容
+// level:消息基本,1:提示消息,2:警告消息,3:严重错误信息,默认为1 提示消息
+func SendAlarmMsg(msgBody string, level int) {
+	if utils.AlarmMsgUrl == `` {
+		return
+	}
+	params := make(map[string]interface{})
+	params["ProjectName"] = utils.APP_NAME_CN
+	params["RunMode"] = utils.RunMode
+	params["MsgBody"] = msgBody
+	params["Level"] = level
+	param, err := json.Marshal(params)
+	if err != nil {
+		utils.FileLog.Info("SendAlarmMsg json.Marshal Err:" + err.Error())
+		return
+	}
+	_, _ = Post(utils.AlarmMsgUrl, string(param), "application/json")
+}
+
+func HttpPost(url, postData string, params ...string) ([]byte, error) {
+	contentType := "application/x-www-form-urlencoded;charset=utf-8"
+	if len(params) > 0 && params[0] != "" {
+		contentType = params[0]
+	}
+	sTime := time.Now()
+	resp, err := http.Post(url,
+		contentType,
+		strings.NewReader(postData))
+	eTime := time.Now()
+	t := eTime.Sub(sTime).Nanoseconds() / 1000000
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	b, err := ioutil.ReadAll(resp.Body)
+	fmt.Println(t, "ms", "POST", "URL", url, "DATA", postData, "RESPONSE", string(b))
+	return b, err
+}
+
+func Post(url, postData string, params ...string) ([]byte, error) {
+	if strings.HasPrefix(url, "https://") {
+		return HttpsPost(url, postData, params...)
+	} else {
+		return HttpPost(url, postData, params...)
+	}
+}
+
+func HttpsPost(url, postData string, params ...string) ([]byte, error) {
+	body := ioutil.NopCloser(strings.NewReader(postData))
+	tr := &http.Transport{
+		TLSClientConfig:    &tls.Config{InsecureSkipVerify: true},
+		DisableCompression: true,
+	}
+	client := &http.Client{Transport: tr}
+	req, err := http.NewRequest("POST", url, body)
+	if err != nil {
+		return nil, err
+	}
+	contentType := "application/x-www-form-urlencoded;charset=utf-8"
+	if len(params) > 0 && params[0] != "" {
+		contentType = params[0]
+	}
+	req.Header.Set("Content-Type", contentType)
+	sTime := time.Now()
+	resp, err := client.Do(req)
+	eTime := time.Now()
+	t := eTime.Sub(sTime).Nanoseconds() / 1000000
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	b, err := ioutil.ReadAll(resp.Body)
+	fmt.Println(t, "ms", "POST", "URL", url, "DATA", postData, "RESPONSE", string(b))
+	return b, err
+}

+ 476 - 0
services/chart_info.go

@@ -0,0 +1,476 @@
+package services
+
+import (
+	"errors"
+	"eta/eta_forum_hub/models"
+	"eta/eta_forum_hub/utils"
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// AddChartInfo 添加图表
+func AddChartInfo(req *models.AddChartReq, sysUserId int, sysUserRealName string) (chartInfo *models.ChartInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true // 默认错误的时候要发送邮件
+
+	req.ChartInfo.ChartName = strings.Trim(req.ChartInfo.ChartName, " ")
+	if req.ChartInfo.ChartName == "" {
+		errMsg = "请填写图表名称!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	//判断图表是否存在
+	var condition string
+	var pars []interface{}
+
+	// todo 判断同一个平台上的图表是否重复
+	condition += " AND chart_name=? AND source = ? "
+	pars = append(pars, req.ChartInfo.ChartName, req.ChartInfo.Source)
+
+	count, err := models.GetChartInfoCountByCondition(condition, pars)
+	if err != nil {
+		errMsg = "判断图表名称是否存在失败"
+		err = errors.New("判断图表名称是否存在失败,Err:" + err.Error())
+		return
+	}
+
+	if count > 0 {
+		errMsg = "图表已存在"
+		err = errors.New("图表已存在")
+		isSendEmail = false
+		return
+	}
+
+	// 添加指标数据
+	err = BatchAddOrUpdateEdbData(req.EdbInfoDataList)
+	if err != nil {
+		errMsg = "添加指标数据失败"
+		err = errors.New("添加指标数据失败,Err:" + err.Error())
+		return
+	}
+	// 查询指标ID和指标编码之间的关系
+	originEdbInfoIdMap := make(map[int]string)
+	for _, v := range req.EdbInfoList {
+		originEdbInfoIdMap[v.EdbInfoId] = v.EdbCode
+	}
+	// 添加关联指标
+	var edbInfoIdArr []int
+	edbInfoList := make([]*models.EdbInfo, 0)
+	edbInfoList, err, errMsg, isSendEmail = BatchAddOrUpdateEdbInfo(req.EdbInfoList, req.EdbInfoCalculateMapping, sysUserId, sysUserRealName)
+	if err != nil {
+		errMsg = "添加关联指标失败"
+		err = errors.New("添加关联指标失败,Err:" + err.Error())
+		return
+	}
+	edbCodeMap := make(map[string]*models.EdbInfo, 0)
+	for _, v := range edbInfoList {
+		edbCodeMap[v.EdbCode] = v
+		edbInfoIdArr = append(edbInfoIdArr, v.EdbInfoId)
+	}
+
+	// todo 批量新增指标
+	sort.Ints(edbInfoIdArr)
+	var edbInfoIdArrStr []string
+	for _, v := range edbInfoIdArr {
+		edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
+	}
+	edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
+
+	chartInfo = new(models.ChartInfo)
+	chartInfo.ChartName = req.ChartInfo.ChartName
+	chartInfo.EdbInfoIds = edbInfoIdStr
+	chartInfo.SysUserId = req.ChartInfo.SysUserId
+	chartInfo.SysUserRealName = req.ChartInfo.SysUserRealName
+	chartInfo.CreateTime = time.Now()
+	chartInfo.ModifyTime = time.Now()
+	chartInfo.IsSetName = req.ChartInfo.IsSetName
+	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+
+	// todo 是否需要单独生成一个指标图表序列ID
+	chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
+	chartInfo.DateType = req.ChartInfo.DateType
+	chartInfo.ChartType = req.ChartInfo.ChartType
+
+	calendar := req.ChartInfo.Calendar
+	chartInfo.Calendar = calendar
+	chartInfo.StartDate = req.ChartInfo.StartDate
+	chartInfo.EndDate = req.ChartInfo.EndDate
+	chartInfo.SeasonStartDate = req.ChartInfo.StartDate
+	chartInfo.SeasonEndDate = req.ChartInfo.EndDate
+	chartInfo.LeftMin = req.ChartInfo.LeftMin
+	chartInfo.LeftMax = req.ChartInfo.LeftMax
+	chartInfo.RightMin = req.ChartInfo.RightMin
+	chartInfo.RightMax = req.ChartInfo.RightMax
+	chartInfo.Right2Min = req.ChartInfo.Right2Min
+	chartInfo.Right2Max = req.ChartInfo.Right2Max
+	chartInfo.MinMaxSave = req.ChartInfo.MinMaxSave
+	chartInfo.Disabled = req.ChartInfo.Disabled
+	chartInfo.BarConfig = req.ChartInfo.BarConfig
+	chartInfo.ExtraConfig = req.ChartInfo.ExtraConfig
+	chartInfo.SeasonExtraConfig = req.ChartInfo.SeasonExtraConfig
+	chartInfo.StartYear = req.ChartInfo.StartYear
+	chartInfo.Source = req.ChartInfo.Source
+	chartInfo.ChartThemeId = req.ChartInfo.ChartThemeId
+	chartInfo.SourcesFrom = req.ChartInfo.SourcesFrom
+	chartInfo.Instructions = req.ChartInfo.Instructions
+	chartInfo.MarkersLines = req.ChartInfo.MarkersLines
+	chartInfo.MarkersAreas = req.ChartInfo.MarkersAreas
+	chartInfo.Unit = req.ChartInfo.Unit
+	chartInfo.UnitEn = req.ChartInfo.UnitEn
+	newId, err := models.AddChartInfo(chartInfo)
+	if err != nil {
+		errMsg = `保存失败`
+		err = errors.New("保存失败,Err:" + err.Error())
+		return
+	}
+	chartInfo.ChartInfoId = int(newId)
+
+	// todo 先整理好指标信息,生成指标ID,再将图表和指标ID进行绑定
+	chartEdbInfoList := req.ChartEdbMapping
+	mapList := make([]*models.ChartEdbMapping, 0)
+	for _, v := range chartEdbInfoList {
+		mapItem := new(models.ChartEdbMapping)
+		mapItem.ChartInfoId = int(newId)
+		edbCode, ok := originEdbInfoIdMap[v.EdbInfoId]
+		if !ok {
+			err = fmt.Errorf("指标代码不存在,EdbCode:%s", v.EdbCode)
+			errMsg = "指标代码不存在"
+			return
+		}
+		edbBase, ok := edbCodeMap[edbCode]
+		if !ok {
+			err = fmt.Errorf("指标代码不存在,EdbCode:%s", v.EdbCode)
+			errMsg = "指标代码不存在"
+			return
+		}
+		mapItem.EdbInfoId = edbBase.EdbInfoId
+		mapItem.CreateTime = time.Now()
+		mapItem.ModifyTime = time.Now()
+		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+		mapItem.UniqueCode = utils.MD5(fmt.Sprint(utils.CHART_PREFIX, "_", edbBase.EdbInfoId, "_", timestamp))
+		mapItem.MaxData = v.MaxData
+		mapItem.MinData = v.MinData
+		mapItem.IsOrder = v.IsOrder
+		mapItem.IsAxis = v.IsAxis
+		mapItem.EdbInfoType = v.EdbInfoType
+		mapItem.LeadValue = v.LeadValue
+		mapItem.LeadUnit = v.LeadUnit
+		mapItem.ChartStyle = v.ChartStyle
+		mapItem.ChartColor = v.ChartColor
+		mapItem.PredictChartColor = v.PredictChartColor
+		mapItem.ChartWidth = v.ChartWidth
+		mapItem.Source = v.Source
+		mapItem.EdbAliasName = v.EdbAliasName
+		mapItem.IsConvert = v.IsConvert
+		mapItem.ConvertType = v.ConvertType
+		mapItem.ConvertValue = v.ConvertValue
+		mapItem.ConvertUnit = v.ConvertUnit
+		mapItem.ConvertEnUnit = v.ConvertEnUnit
+		mapItem.EdbCode = edbCode
+		mapList = append(mapList, mapItem)
+	}
+	if len(mapList) <= 0 {
+		errMsg = `图表指标映射不能为空`
+		err = errors.New("图表指标映射不能为空")
+		return
+	}
+	err = models.AddChartEdbMapping(mapList)
+	if err != nil {
+		errMsg = `保存失败`
+		err = errors.New("保存失败,Err:" + err.Error())
+		return
+	}
+	return
+}
+
+// UpdateChartInfoAndEdbInfo 刷新图表信息和指标信息
+func UpdateChartInfoAndEdbInfo(req *models.AddChartReq, sysUserId int, sysUserRealName string) (chartInfo *models.ChartInfo, err error, errMsg string, isSendEmail bool) {
+
+	isSendEmail = true // 默认错误的时候要发送邮件
+
+	req.ChartInfo.ChartName = strings.Trim(req.ChartInfo.ChartName, " ")
+	if req.ChartInfo.ChartName == "" {
+		errMsg = "请填写图表名称!"
+		err = errors.New(errMsg)
+		isSendEmail = false
+		return
+	}
+
+	chartInfo, err = models.GetChartInfoById(req.ChartInfo.ChartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "图表已被删除,请刷新页面"
+			err = errors.New(errMsg)
+			isSendEmail = false
+			return
+		}
+		errMsg = "获取图表信息失败"
+		err = errors.New("获取图表信息失败,Err:" + err.Error())
+		return
+	}
+
+	//判断图表是否存在
+	var condition string
+	var pars []interface{}
+
+	// todo 判断同一个平台上的图表是否重复
+	condition += " AND chart_name=? AND source = ? AND chart_info_id<>? "
+	pars = append(pars, req.ChartInfo.ChartName, req.ChartInfo.Source, req.ChartInfo.ChartInfoId)
+
+	count, err := models.GetChartInfoCountByCondition(condition, pars)
+	if err != nil {
+		errMsg = "判断图表名称是否存在失败"
+		err = errors.New("判断图表名称是否存在失败,Err:" + err.Error())
+		return
+	}
+
+	if count > 0 {
+		errMsg = "图表已存在"
+		err = errors.New("图表已存在")
+		isSendEmail = false
+		return
+	}
+
+	// 添加指标数据
+	err = BatchAddOrUpdateEdbData(req.EdbInfoDataList)
+	if err != nil {
+		errMsg = "添加指标数据失败"
+		err = errors.New("添加指标数据失败,Err:" + err.Error())
+		return
+	}
+	// 查询指标ID和指标编码之间的关系
+	originEdbInfoIdMap := make(map[int]string)
+	for _, v := range req.EdbInfoList {
+		originEdbInfoIdMap[v.EdbInfoId] = v.EdbCode
+	}
+	// 添加关联指标
+	var edbInfoIdArr []int
+	edbInfoList := make([]*models.EdbInfo, 0)
+	edbInfoList, err, errMsg, isSendEmail = BatchAddOrUpdateEdbInfo(req.EdbInfoList, req.EdbInfoCalculateMapping, sysUserId, sysUserRealName)
+	if err != nil {
+		errMsg = "添加关联指标失败"
+		err = errors.New("添加关联指标失败,Err:" + err.Error())
+		return
+	}
+	edbCodeMap := make(map[string]*models.EdbInfo, 0)
+	for _, v := range edbInfoList {
+		edbCodeMap[v.EdbCode] = v
+		edbInfoIdArr = append(edbInfoIdArr, v.EdbInfoId)
+	}
+
+	// todo 批量新增指标
+	sort.Ints(edbInfoIdArr)
+	var edbInfoIdArrStr []string
+	for _, v := range edbInfoIdArr {
+		edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
+	}
+	edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
+
+	chartInfo.ChartName = req.ChartInfo.ChartName
+	chartInfo.EdbInfoIds = edbInfoIdStr
+	chartInfo.SysUserId = req.ChartInfo.SysUserId
+	chartInfo.SysUserRealName = req.ChartInfo.SysUserRealName
+	chartInfo.ModifyTime = time.Now()
+	chartInfo.IsSetName = req.ChartInfo.IsSetName
+	chartInfo.DateType = req.ChartInfo.DateType
+	chartInfo.ChartType = req.ChartInfo.ChartType
+
+	calendar := req.ChartInfo.Calendar
+	chartInfo.Calendar = calendar
+	chartInfo.StartDate = req.ChartInfo.StartDate
+	chartInfo.EndDate = req.ChartInfo.EndDate
+	chartInfo.SeasonStartDate = req.ChartInfo.StartDate
+	chartInfo.SeasonEndDate = req.ChartInfo.EndDate
+	chartInfo.LeftMin = req.ChartInfo.LeftMin
+	chartInfo.LeftMax = req.ChartInfo.LeftMax
+	chartInfo.RightMin = req.ChartInfo.RightMin
+	chartInfo.RightMax = req.ChartInfo.RightMax
+	chartInfo.Right2Min = req.ChartInfo.Right2Min
+	chartInfo.Right2Max = req.ChartInfo.Right2Max
+	chartInfo.MinMaxSave = req.ChartInfo.MinMaxSave
+	chartInfo.Disabled = req.ChartInfo.Disabled
+	chartInfo.BarConfig = req.ChartInfo.BarConfig
+	chartInfo.ExtraConfig = req.ChartInfo.ExtraConfig
+	chartInfo.SeasonExtraConfig = req.ChartInfo.SeasonExtraConfig
+	chartInfo.StartYear = req.ChartInfo.StartYear
+	chartInfo.Source = req.ChartInfo.Source
+	chartInfo.ChartThemeId = req.ChartInfo.ChartThemeId
+	chartInfo.SourcesFrom = req.ChartInfo.SourcesFrom
+	chartInfo.Instructions = req.ChartInfo.Instructions
+	chartInfo.MarkersLines = req.ChartInfo.MarkersLines
+	chartInfo.MarkersAreas = req.ChartInfo.MarkersAreas
+	chartInfo.Unit = req.ChartInfo.Unit
+	chartInfo.UnitEn = req.ChartInfo.UnitEn
+	err = chartInfo.Update([]string{})
+	if err != nil {
+		errMsg = `更新失败`
+		err = errors.New("更新失败,Err:" + err.Error())
+		return
+	}
+
+	// 处理映射,已存在的映射直接更新,不存在的映射再新增,同时删除旧的映射关系
+	oldChartEdbMappingList, err := models.GetChartEdbMappingListV2(chartInfo.ChartInfoId)
+
+	oldMappingIdMap := make(map[string]*models.ChartEdbMapping)
+	removeMapping := make(map[int]struct{})
+	for _, v := range oldChartEdbMappingList {
+		name := fmt.Sprintf("%s-%s", v.EdbCode, v.Source)
+		oldMappingIdMap[name] = v
+		removeMapping[v.ChartEdbMappingId] = struct{}{}
+	}
+	// todo 先整理好指标信息,生成指标ID,再将图表和指标ID进行绑定
+	chartEdbInfoList := req.ChartEdbMapping
+	addMappingList := make([]*models.ChartEdbMapping, 0)
+	for _, v := range chartEdbInfoList {
+		mapItem := new(models.ChartEdbMapping)
+		mapItem.ChartInfoId = chartInfo.ChartInfoId
+		edbCode, ok := originEdbInfoIdMap[v.EdbInfoId]
+		if !ok {
+			err = fmt.Errorf("指标代码不存在,EdbCode:%s", v.EdbCode)
+			errMsg = "指标代码不存在"
+			return
+		}
+		edbBase, ok := edbCodeMap[edbCode]
+		if !ok {
+			err = fmt.Errorf("指标代码不存在,EdbCode:%s", v.EdbCode)
+			errMsg = "指标代码不存在"
+			return
+		}
+		// 判断是否已经存在映射关系
+		existName := fmt.Sprintf("%s-%s", edbCode, v.Source)
+		if oldMapping, ok1 := oldMappingIdMap[existName]; ok1 {
+			//更新映射关系
+			mapItem = oldMapping
+			mapItem.ModifyTime = time.Now()
+			mapItem.MaxData = v.MaxData
+			mapItem.MinData = v.MinData
+			mapItem.IsOrder = v.IsOrder
+			mapItem.IsAxis = v.IsAxis
+			mapItem.EdbInfoType = v.EdbInfoType
+			mapItem.LeadValue = v.LeadValue
+			mapItem.LeadUnit = v.LeadUnit
+			mapItem.ChartStyle = v.ChartStyle
+			mapItem.ChartColor = v.ChartColor
+			mapItem.PredictChartColor = v.PredictChartColor
+			mapItem.ChartWidth = v.ChartWidth
+			mapItem.Source = v.Source
+			mapItem.EdbAliasName = v.EdbAliasName
+			mapItem.IsConvert = v.IsConvert
+			mapItem.ConvertType = v.ConvertType
+			mapItem.ConvertValue = v.ConvertValue
+			mapItem.ConvertUnit = v.ConvertUnit
+			mapItem.ConvertEnUnit = v.ConvertEnUnit
+			mapItem.EdbCode = edbCode
+
+			err = mapItem.Update([]string{})
+			if err != nil {
+				errMsg = `更新失败`
+				err = errors.New("更新图表指标映射关系失败,Err:" + err.Error())
+				return
+			}
+			delete(removeMapping, mapItem.ChartEdbMappingId)
+		} else {
+			mapItem.EdbInfoId = edbBase.EdbInfoId
+			mapItem.CreateTime = time.Now()
+			mapItem.ModifyTime = time.Now()
+			timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+			mapItem.UniqueCode = utils.MD5(fmt.Sprint(utils.CHART_PREFIX, "_", edbBase.EdbInfoId, "_", timestamp))
+			mapItem.MaxData = v.MaxData
+			mapItem.MinData = v.MinData
+			mapItem.IsOrder = v.IsOrder
+			mapItem.IsAxis = v.IsAxis
+			mapItem.EdbInfoType = v.EdbInfoType
+			mapItem.LeadValue = v.LeadValue
+			mapItem.LeadUnit = v.LeadUnit
+			mapItem.ChartStyle = v.ChartStyle
+			mapItem.ChartColor = v.ChartColor
+			mapItem.PredictChartColor = v.PredictChartColor
+			mapItem.ChartWidth = v.ChartWidth
+			mapItem.Source = v.Source
+			mapItem.EdbAliasName = v.EdbAliasName
+			mapItem.IsConvert = v.IsConvert
+			mapItem.ConvertType = v.ConvertType
+			mapItem.ConvertValue = v.ConvertValue
+			mapItem.ConvertUnit = v.ConvertUnit
+			mapItem.ConvertEnUnit = v.ConvertEnUnit
+			mapItem.EdbCode = edbCode
+			addMappingList = append(addMappingList, mapItem)
+		}
+
+	}
+	if len(addMappingList) > 0 {
+		err = models.AddChartEdbMapping(addMappingList)
+		if err != nil {
+			errMsg = `保存失败`
+			err = errors.New("保存失败,Err:" + err.Error())
+			return
+		}
+	}
+
+	// 删除原先的绑定关系
+	if len(removeMapping) > 0 {
+		removeIdList := make([]string, 0) //需要移除的日期
+		for _, v := range removeMapping {
+			removeIdList = append(removeIdList, fmt.Sprint(v))
+		}
+		removeIdStr := strings.Join(removeIdList, `","`)
+		removeIdStr = `"` + removeIdStr + `"`
+		err = models.DeleteChartEdbMappingByChartEdbMappingId(removeIdStr)
+		if err != nil {
+			errMsg = `删除失败`
+			err = errors.New("删除失败,Err:" + err.Error())
+			return
+		}
+	}
+
+	return
+}
+
+// 删除图表信息
+func DeleteChart(chartInfoId int) (err error, errMsg string) {
+	//删除图表
+	chartInfo, err := models.GetChartInfoById(chartInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			errMsg = "图表已删除,请刷新页面"
+			err = fmt.Errorf("图表不存在,Err:" + err.Error())
+			return
+		} else {
+			errMsg = "删除失败"
+			err = fmt.Errorf("删除失败, 获取图表信息失败Err:" + err.Error())
+			return
+		}
+	}
+	if chartInfo == nil {
+		errMsg = "图表已删除,请刷新页面"
+		err = fmt.Errorf(errMsg)
+		return
+	}
+	// 处理映射,已存在的映射直接更新,不存在的映射再新增,同时删除旧的映射关系
+	oldChartEdbMappingList, err := models.GetChartEdbMappingListV2(chartInfo.ChartInfoId)
+
+	edbInfoIds := make([]int, 0)
+	for _, v := range oldChartEdbMappingList {
+		edbInfoIds = append(edbInfoIds, v.EdbInfoId)
+	}
+
+	//删除图表及关联指标
+	err = models.DeleteChartInfoAndData(chartInfo.ChartInfoId)
+	if err != nil {
+		errMsg = "删除失败"
+		err = fmt.Errorf("删除图表数据失败, Err:" + err.Error())
+		return
+	}
+
+	err, errMsg = BatchDeleteEdbInfo(edbInfoIds)
+	if err != nil {
+		errMsg = "删除失败"
+		err = fmt.Errorf("删除指标数据失败, Err:" + err.Error())
+		return
+	}
+	return
+}

+ 48 - 0
services/edb_data.go

@@ -0,0 +1,48 @@
+package services
+
+import (
+	"eta/eta_forum_hub/models"
+	"eta/eta_forum_hub/models/mgodb"
+	"fmt"
+)
+
+func BatchAddOrUpdateEdbData(req []*models.AddEdbDataReq) (err error) {
+	for _, reqData := range req {
+		err = AddOrUpdateEdbData(reqData.EdbCode, reqData.DataList)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+func AddOrUpdateEdbData(edbCode string, dataList []*mgodb.EdbDataBase) (err error) {
+	addList := make([]interface{}, 0)
+	existList, err := mgodb.GetEdbDataBaseByEdbCode(edbCode)
+	if err != nil {
+		err = fmt.Errorf("查询指标数据出错 error, %v", err)
+		return
+	}
+	existMap := make(map[string]string, len(existList))
+	for _, exist := range existList {
+		existMap[exist.DataTime] = exist.Value
+	}
+	for _, v := range dataList {
+		if oldVal, ok := existMap[v.DataTime]; !ok {
+			v.EdbInfoId = 0
+			addList = append(addList, v)
+		} else {
+			if v.Value != oldVal {
+				err = mgodb.ModifyValueEdbInfoDataStatus(v.EdbCode, v.DataTime, v.Value)
+				if err != nil {
+					err = fmt.Errorf("更新指标数据出错 error, %v", err)
+					return
+				}
+			}
+		}
+	}
+	if len(addList) > 0 {
+		err = mgodb.InsertBatch(addList)
+	}
+	return
+}

+ 231 - 0
services/edb_info.go

@@ -0,0 +1,231 @@
+package services
+
+import (
+	"errors"
+	"eta/eta_forum_hub/models"
+	"eta/eta_forum_hub/models/mgodb"
+	"eta/eta_forum_hub/utils"
+	"strconv"
+	"time"
+)
+
+// BatchAddOrUpdateEdbInfo 添加批量添加指标到指标库
+func BatchAddOrUpdateEdbInfo(edbList []*models.EdbInfo, edbMapping []*models.EdbInfoCalculateMapping, sysUserId int, sysUserRealName string) (newList []*models.EdbInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+	edbCodeMap := make(map[string]*models.EdbInfo)
+	for _, v := range edbList {
+		tmp, e, msg, _ := AddOrUpdateEdbInfo(v, sysUserId, sysUserRealName)
+		if e != nil {
+			err = e
+			errMsg = msg
+			return
+		}
+		newList = append(newList, tmp)
+		edbCodeMap[tmp.EdbCode] = tmp
+	}
+	//批量添加指标的mapping信息
+	calculateMappingItemList := make([]*models.EdbInfoCalculateMapping, 0)
+	for _, v := range edbMapping {
+		edbInfo, ok := edbCodeMap[v.EdbCode]
+		if !ok {
+			continue
+		}
+		fromEdbInfo, ok := edbCodeMap[v.FromEdbCode]
+		if !ok {
+			continue
+		}
+
+		calculateMappingItem := new(models.EdbInfoCalculateMapping)
+		calculateMappingItem.CreateTime = time.Now()
+		calculateMappingItem.ModifyTime = time.Now()
+		calculateMappingItem.Sort = v.Sort
+		calculateMappingItem.EdbCode = edbInfo.EdbCode
+		calculateMappingItem.EdbInfoId = edbInfo.EdbInfoId
+		calculateMappingItem.FromEdbInfoId = fromEdbInfo.EdbInfoId
+		calculateMappingItem.FromEdbCode = fromEdbInfo.EdbCode
+		calculateMappingItem.FromEdbName = fromEdbInfo.EdbName
+		calculateMappingItem.FromSource = fromEdbInfo.Source
+		calculateMappingItem.FromSourceName = fromEdbInfo.SourceName
+		calculateMappingItem.FromTag = v.FromTag
+		calculateMappingItem.Source = edbInfo.Source
+		calculateMappingItem.SourceName = edbInfo.SourceName
+		calculateMappingItem.FromSubSource = edbInfo.SubSource
+		calculateMappingItemList = append(calculateMappingItemList, calculateMappingItem)
+	}
+	err = models.AddEdbInfoCalculateMappingMulti(calculateMappingItemList)
+	if err != nil {
+		errMsg = "指标映射关系添加失败"
+		return
+	}
+	return
+}
+
+// AddOrUpdateEdbInfo 添加指标到指标库
+func AddOrUpdateEdbInfo(edbItem *models.EdbInfo, sysUserId int, sysUserRealName string) (edbInfo *models.EdbInfo, err error, errMsg string, isSendEmail bool) {
+	isSendEmail = true
+	//判断指标是否存在
+	edbInfo, err = models.GetEdbInfoByEdbCode(edbItem.Source, edbItem.EdbCode)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			err = nil
+		} else {
+			errMsg = "判断指标名称是否存在失败"
+			err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
+			return
+		}
+	}
+	var edbInfoId int64
+	// 指标已存在
+	if edbInfo != nil && edbInfo.EdbInfoId > 0 {
+		edbInfoId = int64(edbInfo.EdbInfoId)
+		// 更新指标信息
+		edbInfo.Source = edbItem.Source
+		edbInfo.SourceName = edbItem.SourceName
+		edbInfo.EdbType = edbItem.EdbType
+		edbInfo.EdbCode = edbItem.EdbCode
+		edbInfo.EdbName = edbItem.EdbName
+		edbInfo.EdbNameSource = edbItem.EdbNameSource
+		edbInfo.Frequency = edbItem.Frequency
+		edbInfo.Unit = edbItem.Unit
+		edbInfo.StartDate = edbItem.StartDate
+		edbInfo.EndDate = edbItem.EndDate
+		edbInfo.ClassifyId = edbItem.ClassifyId
+		edbInfo.SysUserId = sysUserId
+		edbInfo.SysUserRealName = sysUserRealName
+		edbInfo.ModifyTime = time.Now()
+		edbInfo.ServerUrl = edbItem.ServerUrl
+		edbInfo.Sort = edbItem.Sort
+		edbInfo.DataDateType = edbItem.DataDateType
+		edbInfo.TerminalCode = edbItem.TerminalCode
+		edbInfo.SourceIndexName = edbItem.SourceIndexName
+
+		edbInfo.MaxValue = edbItem.MaxValue
+		edbInfo.MinValue = edbItem.MinValue
+		edbInfo.EdbType = edbItem.EdbType
+		err = edbInfo.Update([]string{})
+		if err != nil {
+			errMsg = "保存失败"
+			err = errors.New("保存失败,Err:" + err.Error())
+			return
+		}
+		//同时删除指标的映射信息
+		err = models.DeleteEdbInfoMapping(edbInfoId)
+		if err != nil {
+			errMsg = "删除指标映射信息失败"
+			err = errors.New("删除指标映射信息失败,Err:" + err.Error())
+			return
+		}
+	} else {
+		edbInfo = new(models.EdbInfo)
+		edbInfo.Source = edbItem.Source
+		edbInfo.SourceName = edbItem.SourceName
+		edbInfo.EdbType = edbItem.EdbType
+		edbInfo.EdbCode = edbItem.EdbCode
+		edbInfo.EdbName = edbItem.EdbName
+		edbInfo.EdbNameSource = edbItem.EdbNameSource
+		edbInfo.Frequency = edbItem.Frequency
+		edbInfo.Unit = edbItem.Unit
+		edbInfo.StartDate = edbItem.StartDate
+		edbInfo.EndDate = edbItem.EndDate
+		edbInfo.ClassifyId = edbItem.ClassifyId
+		edbInfo.SysUserId = sysUserId
+		edbInfo.SysUserRealName = sysUserRealName
+		edbInfo.CreateTime = time.Now()
+		edbInfo.ModifyTime = time.Now()
+		edbInfo.ServerUrl = edbItem.ServerUrl
+		edbInfo.Sort = edbItem.Sort
+		edbInfo.DataDateType = edbItem.DataDateType
+		edbInfo.TerminalCode = edbItem.TerminalCode
+		edbInfo.SourceIndexName = edbItem.SourceIndexName
+		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
+		edbInfo.UniqueCode = utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
+
+		edbInfo.MaxValue = edbItem.MaxValue
+		edbInfo.MinValue = edbItem.MinValue
+		edbInfo.EdbType = edbItem.EdbType
+		edbInfoId, err = models.AddEdbInfo(edbInfo)
+		if err != nil {
+			errMsg = "保存失败"
+			err = errors.New("保存失败,Err:" + err.Error())
+			return
+		}
+		edbInfo.EdbInfoId = int(edbInfoId)
+	}
+
+	err = mgodb.ModifyEdbInfoDataStatus(edbInfoId, edbInfo.EdbCode)
+	if err != nil {
+		errMsg = "保存失败"
+		err = errors.New("更新指标数据失败,Err:" + err.Error())
+		return
+	}
+
+	return
+}
+
+// 批量删除指标,
+func BatchDeleteEdbInfo(edbInfoIds []int) (err error, errMsg string) {
+	for _, v := range edbInfoIds {
+		//查询单个指标是否允许删除
+		err, errMsg = DeleteEdbInfo(v)
+		if err != nil {
+			errMsg = "删除指标失败"
+			return
+		}
+	}
+	return
+}
+
+// 删除单个指标
+func DeleteEdbInfo(edbInfoId int) (err error, errMsg string) {
+	//判断指标是否存在
+	_, err = models.GetEdbInfoById(edbInfoId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			err = nil
+			return
+		} else {
+			errMsg = "判断指标名称是否存在失败"
+			err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
+			return
+		}
+	}
+	//判断指标是否用于作图,如果用于作图,则不可删除
+	chartCount, tmpErr := models.GetChartEdbMappingCount(edbInfoId)
+	if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
+		errMsg = "删除失败"
+		err = errors.New("判断指标是否被用于作图失败,Err:" + tmpErr.Error())
+		return
+	}
+	if chartCount > 0 {
+		errMsg = "当前指标已用作画图,不可删除"
+		return
+	}
+
+	//判断指标是否用作其他指标的计算
+	calculateCount, tmpErr := models.GetEdbInfoCalculateMappingCount(edbInfoId)
+	if tmpErr != nil {
+		errMsg = "删除失败"
+		err = errors.New("判断指标是否被用于计算失败,GetEdbInfoCalculateCount Err:" + tmpErr.Error())
+		return
+	}
+	if calculateCount > 0 {
+		errMsg = "当前指标已用作,指标运算,不可删除"
+		return
+	}
+
+	// 删除指标,删除映射关系,删除指标数据
+	err = models.DeleteEdbInfo(edbInfoId)
+	if err != nil {
+		errMsg = "删除失败"
+		err = errors.New("删除指标失败,Err:" + err.Error())
+		return
+	}
+
+	err = mgodb.DeleteEdbInfoDataByEdbInfoId(edbInfoId)
+	if err != nil {
+		errMsg = "删除失败"
+		err = errors.New("删除指标数据失败,Err:" + err.Error())
+		return
+	}
+	return
+}

+ 11 - 0
utils/common.go

@@ -1189,3 +1189,14 @@ func CheckFrequency(leftFrequency, rightFrequency string) int {
 
 	return frequencyMap[leftFrequency] - frequencyMap[rightFrequency]
 }
+
+// GetLikeKeyword
+//
+//	@Description: 获取sql查询中的like查询字段
+//	@author: Roc
+//	@datetime2023-10-23 14:46:32
+//	@param keyword string
+//	@return string
+func GetLikeKeyword(keyword string) string {
+	return `%` + keyword + `%`
+}

+ 35 - 19
utils/config.go

@@ -8,9 +8,12 @@ import (
 )
 
 var (
-	RunMode        string //运行模式
-	MYSQL_URL_ETA  string //数据库连接
-	MYSQL_URL_DATA string // 指标库数据库连接
+	RunMode            string //运行模式
+	APP_NAME_CN        string
+	MYSQL_URL          string //数据库连接
+	MONGODB_URL        string //mongodb连接
+	MONGODB_COMMUNITY  string //mongodb库名
+	MONGODB_CREDENTIAL string
 )
 
 // 公共api内部服务调用
@@ -31,11 +34,15 @@ const (
 
 // 日志配置
 var (
-	LogPath    string //调用过程中的日志存放地址
-	LogFile    string
-	BinLogPath string //数据库相关的日志存放地址
-	BinLogFile string
-	LogMaxDays int //日志最大保留天数
+	LogPath     string //调用过程中的日志存放地址
+	LogFile     string
+	LogDataPath string //调用过程中图表相关的日志存放地址
+	LogDataFile string
+	BinLogPath  string //数据库相关的日志存放地址
+	BinLogFile  string
+	ApiLogPath  string //接口请求地址和接口返回值日志存放地址
+	ApiLogFile  string
+	LogMaxDays  int //日志最大保留天数
 )
 
 var (
@@ -47,6 +54,9 @@ var (
 	SyncIndexPath      string // 桥接服务-指标同步服务地址
 )
 
+// AlarmMsgUrl 报警服务地址
+var AlarmMsgUrl string
+
 func init() {
 	tmpRunMode, err := web.AppConfig.String("run_mode")
 	if err != nil {
@@ -59,10 +69,16 @@ func init() {
 		panic("配置文件读取错误 " + err.Error())
 	}
 	beeLogger.Log.Info(RunMode + " 模式")
-
-	MYSQL_URL_ETA = config["mysql_url_eta"]
-	MYSQL_URL_DATA = config["mysql_url_data"]
-
+	// 项目中文名称
+	appNameCn, err := web.AppConfig.String("app_name_cn")
+	if err != nil {
+		panic(any("配置文件读取app_name_cn错误 " + err.Error()))
+	}
+	APP_NAME_CN = appNameCn
+	MYSQL_URL = config["mysql_url"]
+	MONGODB_URL = config["mongodb_url"]
+	MONGODB_COMMUNITY = config["mongodb_community"]
+	MONGODB_CREDENTIAL = config["mongodb_credential"]
 	// 公共api内部服务调用
 	{
 		// 公共指标库相关
@@ -82,20 +98,20 @@ func init() {
 	{
 		LogPath = config["log_path"]
 		LogFile = config["log_file"]
+		LogDataPath = config["log_data_path"]
+		LogDataFile = config["log_data_file"]
 		BinLogPath = config["binlog_path"]
 		BinLogFile = config["binlog_file"]
+		ApiLogPath = config["apilog_path"]
+		ApiLogFile = config["apilog_file"]
 		logMaxDaysStr := config["log_max_day"]
 		LogMaxDays, _ = strconv.Atoi(logMaxDaysStr)
 	}
 
-	// 桥接服务
 	{
-		EtaBridgeUrl = config["eta_bridge_url"]               // 桥接服务地址
-		EtaBridgeAppNameEn = config["eta_bridge_app_name_en"] // 桥接服务英文名称-鉴权用
-		EtaBridgeMd5Key = config["eta_bridge_md5_key"]        // 桥接服务Md5密钥-鉴权用
-		EtaBridgeDesKey = config["eta_bridge_des_key"]        // 桥接服务Des密钥-解密数据用
-		SyncUserPath = config["sync_user_path"]               // 桥接服务-用户同步服务地址
-		SyncIndexPath = config["sync_index_path"]             // 桥接服务-指标同步服务地址
+		// 报警服务地址
+		AlarmMsgUrl = config["alarm_msg_url"]
+
 	}
 }
 

+ 50 - 0
utils/logs.go

@@ -10,9 +10,13 @@ import (
 const (
 	DefaultLogPath    = "./etalogs/filelog"
 	DefaultBinlogPath = "./etalogs/binlog"
+	DefaultDataPath   = "./etalogs/datalog"
+	DefaultApiLogPath = "./etalogs/apilog"
 )
 
 var FileLog *logs.BeeLogger
+var ApiLog *logs.BeeLogger
+var FileLogData *logs.BeeLogger
 var Binlog *logs.BeeLogger
 
 func init() {
@@ -40,6 +44,8 @@ func init() {
 	FileLog.EnableFuncCallDepth(true)
 
 	initBinlog()
+	initApiLog()
+	initFileLogData()
 }
 
 type logConfig struct {
@@ -78,6 +84,50 @@ func initBinlog() {
 	Binlog.EnableFuncCallDepth(true)
 }
 
+func initApiLog() {
+	logPath := ApiLogPath
+	if logPath == "" {
+		logPath = DefaultApiLogPath
+	}
+	logFile := ApiLogFile
+	if logFile == "" {
+		logFile = "apilog.log"
+	}
+	os.MkdirAll(logPath, os.ModePerm)
+
+	// 打开文件
+	logFileName := path.Join(logPath, logFile)
+	ApiLog = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
+
+	logConf.FileName = logFileName
+	b, _ := json.Marshal(logConf)
+	ApiLog.SetLogger(logs.AdapterFile, string(b))
+	ApiLog.EnableFuncCallDepth(true)
+}
+
+func initFileLogData() {
+	logPath := LogDataPath
+	if logPath == "" {
+		logPath = DefaultDataPath
+	}
+	logFile := LogDataFile
+	if logFile == "" {
+		logFile = "datalog.log"
+	}
+	os.MkdirAll(logPath, os.ModePerm)
+
+	// 打开文件
+	logFileName := path.Join(logPath, logFile)
+	FileLogData = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
+
+	logConf.FileName = logFileName
+	b, _ := json.Marshal(logConf)
+	FileLogData.SetLogger(logs.AdapterFile, string(b))
+	FileLogData.EnableFuncCallDepth(true)
+}
+
 func getDefaultLogConfig() logConfig {
 	return logConfig{
 		FileName: "",