浏览代码

一期数据同步自由数据

kobe6258 2 月之前
父节点
当前提交
9302a03560

+ 172 - 0
controllers/eta_controller.go

@@ -0,0 +1,172 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_mini_crm_ht/models"
+	"eta/eta_mini_crm_ht/models/request"
+	"eta/eta_mini_crm_ht/models/response"
+	"eta/eta_mini_crm_ht/services"
+	"net/http"
+)
+
+type ETAController struct {
+	BaseAuthController
+}
+
+// GetDataList
+// @Title 数据列表
+// @Description  数据列表
+// @Success 200 {object} models.LoginResp
+// @router /business_data/data/list [get]
+func (this *ETAController) GetDataList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	etaRequest := new(request.IndexDataListReq)
+	// 绑定查询参数到结构体
+	if err := this.ParseForm(etaRequest); err != nil {
+		this.Ctx.Output.SetStatus(http.StatusBadRequest)
+		this.Data["json"] = map[string]string{"error": "Invalid request parameters"}
+		this.ServeJSON()
+		return
+	}
+	dataList, err := services.GetDataList(etaRequest.ToEtaDataRequest())
+	if err != nil {
+		br.Msg = "分类列表获取失败"
+		br.ErrMsg = "分类列表获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+	//var data = new(response.BaseFromBusinessIndexResponse)
+	br.Data = dataList
+	br.Ret = 200
+	br.Msg = "指标信息获取成功"
+	br.Success = true
+}
+
+// GetList
+// @Title 数据列表
+// @Description  数据列表
+// @Success 200 {object} models.LoginResp
+// @router /business_data/list [get]
+func (this *ETAController) GetList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	etaRequest := new(request.IndexListReq)
+	// 绑定查询参数到结构体
+	if err := this.ParseForm(etaRequest); err != nil {
+		this.Ctx.Output.SetStatus(http.StatusBadRequest)
+		this.Data["json"] = map[string]string{"error": "Invalid request parameters"}
+		this.ServeJSON()
+		return
+	}
+	if etaRequest.SortColumn == "" {
+		etaRequest.SortColumn = "create_time"
+	}
+	if etaRequest.SortOrder == "" {
+		etaRequest.SortOrder = "desc"
+	}
+	indexList, err := services.GetList(etaRequest.ToEtaRequest())
+	if err != nil {
+		br.Msg = "分类列表获取失败"
+		br.ErrMsg = "分类列表获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+	var data = new(response.BaseFromBusinessIndexResponse)
+	br.Data = data.ToCrmRequest(indexList)
+	br.Ret = 200
+	br.Msg = "指标信息获取成功"
+	br.Success = true
+}
+
+// GetSourceList
+// @Title 渠道列表
+// @Description  获取一期指标信息
+// @Success 200 {object} models.LoginResp
+// @router /business_data/source/list [get]
+func (this *ETAController) GetSourceList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sourceList, err := services.GetSourceList()
+	if err != nil {
+		br.Msg = "分类列表获取失败"
+		br.ErrMsg = "分类列表获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+	//过滤包含一期的来源
+	br.Data = sourceList
+	br.Ret = 200
+	br.Msg = "指标信息获取成功"
+	br.Success = true
+}
+
+// DeleteIndex
+// @Title 删除自有数据指标
+// @Description  删除自有数据指标
+// @Success 200 {object} models.LoginResp
+// @router /business_data/del [post]
+func (this *ETAController) DeleteIndex() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.IndexesDeleteReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.DeleteAll {
+		req.DeleteList = []string{}
+		undeleteMap := make(map[string]int, len(req.UnDeleteList))
+		if len(req.UnDeleteList) > 0 {
+			for _, v := range req.UnDeleteList {
+				undeleteMap[v] = 1
+			}
+		}
+		list, fetchErr := services.GetIndexList()
+		if fetchErr != nil {
+			br.Msg = "指标列表获取失败"
+			br.ErrMsg = "指标列表获取失败:" + fetchErr.Error()
+			return
+		}
+		for _, v := range list {
+			if _, ok := undeleteMap[v]; !ok {
+				req.DeleteList = append(req.DeleteList, v)
+			}
+		}
+	} else {
+		if len(req.DeleteList) == 0 {
+			br.Msg = "指标编码不能为空"
+			br.ErrMsg = "指标编码不能为空"
+			return
+		}
+	}
+	err = services.DeleteSyncTask(req.DeleteList)
+	if err != nil {
+		br.Msg = "删除指标失败"
+		br.ErrMsg = "删除指标失败,系统错误,Err:" + err.Error()
+		return
+	}
+	respList, err := services.DeleteIndexes(req.DeleteList)
+	if err != nil {
+		br.Msg = "分类列表获取失败"
+		br.ErrMsg = "分类列表获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Data = respList
+	br.Ret = 200
+	br.Msg = "删除指标成功"
+	br.Success = true
+}

+ 0 - 35
controllers/htController.go

@@ -1,35 +0,0 @@
-package controllers
-
-import (
-	"eta/eta_mini_crm_ht/models"
-	"eta/eta_mini_crm_ht/services"
-)
-
-type HTController struct {
-	BaseAuthController
-}
-
-// GetIndexInfo
-// @Title 获取一期指标信息
-// @Description  获取一期指标信息
-// @Success 200 {object} models.LoginResp
-// @router /getIndexInfo [get]
-func (this *HTController) GetIndexInfo(IndexCode string) {
-	br := new(models.BaseResponse).Init()
-	defer func() {
-		this.Data["json"] = br
-		this.ServeJSON()
-	}()
-
-	IndexInfo, err := services.GetIndexInfo(IndexCode)
-	if err != nil {
-		br.Msg = "分类列表获取失败"
-		br.ErrMsg = "分类列表获取失败,系统错误,Err:" + err.Error()
-		return
-	}
-
-	br.Data = IndexInfo
-	br.Ret = 200
-	br.Msg = "指标信息获取成功"
-	br.Success = true
-}

+ 61 - 0
controllers/ht_controller.go

@@ -0,0 +1,61 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_mini_crm_ht/models"
+	"eta/eta_mini_crm_ht/models/request"
+	"eta/eta_mini_crm_ht/services"
+)
+
+type HTController struct {
+	BaseAuthController
+}
+
+// GetIndexInfo
+// @Title 获取一期指标信息
+// @Description  获取一期指标信息
+// @Success 200 {object} models.LoginResp
+// @router /getIndexInfo [get]
+func (this *HTController) GetIndexInfo(IndexCode string) {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	IndexInfo, err := services.GetIndexInfo(IndexCode)
+	if err != nil {
+		br.Msg = "指标详情信息获取失败"
+		br.ErrMsg = "指标详情信息获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+	br.Data = IndexInfo
+	br.Ret = 200
+	br.Msg = "指标详情信息获取成功"
+	br.Success = true
+}
+
+// PushIndexInfo
+// @Title 添加指标信息
+// @Description  添加指标信息
+// @Success 200 {object} models.LoginResp
+// @router /push [post]
+func (this *HTController) PushIndexInfo() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.IndexPushReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	err = services.PushIndexInfo(req.IndexCode)
+	if err != nil {
+		br.Msg = "同步指标失败"
+		br.ErrMsg = "同步指标失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "同步指标成功"
+	br.Success = true
+}

+ 27 - 0
controllers/video.go

@@ -572,3 +572,30 @@ var chunksMap = make(map[string][]Chunk)
 func getFourccType(boxHeader BoxHeader) (fourccType string) {
 	return string(boxHeader.FourccType[:])
 }
+
+// MinIOSign @Title 上传图片
+// @Description 上传视频
+// @Param   File   query   file  true       "文件"
+// @Success 200 {object} models.ReportAuthorResp
+// @router /minioSign [get]
+func (this *VideoController) MinIOSign() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	ossClient := oss.NewOssClient()
+	token, err := ossClient.GetUploadToken()
+	if err != nil {
+		utils.FileLog.Error(err.Error())
+		br.Msg = "获取minio上传签名失败"
+		br.ErrMsg = "获取minio配置失败:" + err.Error()
+		return
+	}
+	resp := new(response.MinioSignResp)
+	resp.OssToken = token
+	br.Ret = 200
+	br.Data = resp
+	br.Msg = "获取minio配置成功"
+	return
+}

+ 47 - 0
models/request/eta_hub.go

@@ -0,0 +1,47 @@
+package request
+
+import (
+	"eta/eta_mini_crm_ht/services"
+)
+
+type IndexListReq struct {
+	PageSize     int
+	CurrentIndex int
+	SortColumn   string
+	SortOrder    string
+	KeyWord      string
+	SourceName   string
+	Unit         string
+	Frequency    string
+}
+type IndexDataListReq struct {
+	PageSize     int
+	CurrentIndex int
+	IndexCode    string
+}
+type IndexesDeleteReq struct {
+	DeleteAll    bool
+	UnDeleteList []string
+	DeleteList   []string
+}
+
+func (idr *IndexListReq) ToEtaRequest() (req services.IndexListRequest) {
+	return services.IndexListRequest{
+		PageSize:     idr.PageSize,
+		CurrentIndex: idr.CurrentIndex,
+		KeyWord:      idr.KeyWord,
+		SortColumn:   idr.SortColumn,
+		SortOrder:    idr.SortOrder,
+		SourceName:   idr.SourceName,
+		Frequency:    idr.Frequency,
+		SysSource:    "ht_mini_crm",
+	}
+}
+
+func (idr *IndexDataListReq) ToEtaDataRequest() (req services.IndexDataListRequest) {
+	return services.IndexDataListRequest{
+		PageSize:     idr.PageSize,
+		CurrentIndex: idr.CurrentIndex,
+		IndexCode:    idr.IndexCode,
+	}
+}

+ 5 - 0
models/request/ht_futures.go

@@ -0,0 +1,5 @@
+package request
+
+type IndexPushReq struct {
+	IndexCode string
+}

+ 44 - 0
models/response/eta.go

@@ -0,0 +1,44 @@
+package response
+
+import (
+	"eta/eta_mini_crm_ht/services"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+type BaseFromBusinessIndex struct {
+	IndexCode  string `description:"指标编码"`
+	IndexName  string `description:"指标名称"`
+	Unit       string `description:"单位"`
+	Frequency  string `description:"频度"`
+	SourceName string `description:"数据来源名称"`
+	StartDate  string `description:"指标开始时间"`
+	EndDate    string `description:"指标最新时间"`
+	CreateTime string `description:"入库时间"`
+}
+type BaseFromBusinessIndexResponse struct {
+	Paging         *paging.PagingItem
+	List           []*BaseFromBusinessIndex
+	LastUpdateTime string
+}
+
+func (idr *BaseFromBusinessIndexResponse) ToCrmRequest(resp *services.BaseFromBusinessIndexResp) (req BaseFromBusinessIndexResponse) {
+	var crmList []*BaseFromBusinessIndex
+	for _, item := range resp.List {
+		crmList = append(crmList, &BaseFromBusinessIndex{
+			IndexCode:  item.IndexCode,
+			IndexName:  item.IndexName,
+			Unit:       item.Unit,
+			Frequency:  item.Frequency,
+			SourceName: item.SourceName,
+			StartDate:  item.StartDate.Format(time.DateOnly),
+			EndDate:    item.EndDate.Format(time.DateOnly),
+			CreateTime: item.CreateTime.Format(time.DateTime),
+		})
+	}
+	return BaseFromBusinessIndexResponse{
+		Paging:         resp.Paging,
+		List:           crmList,
+		LastUpdateTime: resp.LastUpdateTime,
+	}
+}

+ 5 - 0
models/response/media.go

@@ -2,6 +2,7 @@ package response
 
 import (
 	"eta/eta_mini_crm_ht/models"
+	"eta/eta_mini_crm_ht/utils/oss"
 	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
@@ -19,3 +20,7 @@ type MediaUploadResp struct {
 	Url                 string `description:"上传文件URL"`
 	DurationMillisecond int    `description:"时长"`
 }
+type MinioSignResp struct {
+	oss.OssToken
+	//Sign string `description:"上传签名"`
+}

+ 54 - 0
routers/commentsRouter.go

@@ -153,6 +153,42 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"],
+        beego.ControllerComments{
+            Method: "GetDataList",
+            Router: `/business_data/data/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"],
+        beego.ControllerComments{
+            Method: "DeleteIndex",
+            Router: `/business_data/del`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"],
+        beego.ControllerComments{
+            Method: "GetList",
+            Router: `/business_data/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ETAController"],
+        beego.ControllerComments{
+            Method: "GetSourceList",
+            Router: `/business_data/source/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:FeedBackController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:FeedBackController"],
         beego.ControllerComments{
             Method: "FeedBackList",
@@ -173,6 +209,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:HTController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:HTController"],
+        beego.ControllerComments{
+            Method: "PushIndexInfo",
+            Router: `/push`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ImageController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:ImageController"],
         beego.ControllerComments{
             Method: "AddImage",
@@ -821,6 +866,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:VideoController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:VideoController"],
+        beego.ControllerComments{
+            Method: "MinIOSign",
+            Router: `/minioSign`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:VideoController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm_ht/controllers:VideoController"],
         beego.ControllerComments{
             Method: "UploadFile",

+ 4 - 0
routers/router.go

@@ -106,6 +106,10 @@ func init() {
 			beego.NSInclude(
 				&controllers.HTController{},
 			),
+		), beego.NSNamespace("/eta/v1",
+			beego.NSInclude(
+				&controllers.ETAController{},
+			),
 		),
 	)
 	beego.AddNamespace(ns)

+ 304 - 0
services/eta_service.go

@@ -0,0 +1,304 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_mini_crm_ht/utils"
+	httpClient "eta/eta_mini_crm_ht/utils/http"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"io"
+	"strings"
+	"time"
+)
+
+const (
+	SourceListUrl = "/v1/edb/business/edb/source/list"
+	DataListUrl   = "/v1/edb/business/edb/list"
+	DataDetailUrl = "/v1/edb/business/edb/data/list"
+
+	DeleteIndexesUrl = "/v1/edb/business/edb/del"
+)
+
+//type IndexInfo struct {
+//	IndexCode      string        `json:"indexCode"`
+//	IndexName      string        `json:"indexName"`
+//	Frequency      string        `json:"frequency"`
+//	SourceName     string        `json:"sourceName"`
+//	LatestDataDate string        `json:"latestDataDate"`
+//	LastPushTime   string        `json:"lastPushTime"`
+//	Remark         string        `json:"remark"`
+//	Unit           string        `json:"unit"`
+//	DataList       []interface{} `json:"dataList"`
+//}
+
+type ETAResponse struct {
+	Ret     int
+	Msg     string
+	ErrMsg  string
+	ErrCode string
+	Data    json.RawMessage
+}
+
+func createETARequest() (client *httpClient.HttpClient, err error) {
+	client = httpClient.DefaultClient()
+	signHeader, signErr := utils.GenerateSignatureAndHeaders()
+	if signErr != nil {
+		err = signErr
+		utils.FileLog.Error("创建eta请求接口失败,生成签名失败:%v", signErr)
+		return
+	}
+	structMap, err := client.StructToMap(signHeader)
+	if err != nil {
+		utils.FileLog.Error("创建eta请求接口失败,生成签名请求头失败:%v", err)
+		return
+	}
+	client.AddHeader(structMap)
+	return
+}
+func GetDataList(request IndexDataListRequest) (baseFromBusinessIndexDataResp *BaseFromBusinessIndexDataResp, err error) {
+	if utils.ETA_ADDRESS == "" {
+		err = errors.New("未配置ETA_API地址")
+		return
+	}
+	url := fmt.Sprintf("%s%s?%s", utils.ETA_ADDRESS, DataDetailUrl, request.ToString())
+	client, err := createETARequest()
+	if err != nil {
+		utils.FileLog.Error("创建eta请求接口失败:%v", err)
+		return
+	}
+	resp, err := client.Get(url)
+	if err != nil {
+		utils.FileLog.Error("获取来源列表信息失败", err.Error())
+		return
+	}
+	defer func(Body io.ReadCloser) {
+		closeErr := Body.Close()
+		if closeErr != nil {
+			utils.FileLog.Error("关闭Response失败:%v", closeErr)
+		}
+	}(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
+	var htRes ETAResponse
+	err = json.Unmarshal(body, &htRes)
+	if err != nil {
+		utils.FileLog.Error("解析应答信息失败:%v", err)
+		return
+	}
+	if htRes.Ret == 200 {
+		err = json.Unmarshal(htRes.Data, &baseFromBusinessIndexDataResp)
+	} else {
+		err = errors.New(htRes.ErrMsg)
+	}
+	return
+}
+func GetSourceList() (businessSourceList []*EdbBusinessSource, err error) {
+	if utils.ETA_ADDRESS == "" {
+		err = errors.New("未配置ETA_API地址")
+		return
+	}
+	url := fmt.Sprintf("%s%s", utils.ETA_ADDRESS, SourceListUrl)
+	client, err := createETARequest()
+	if err != nil {
+		utils.FileLog.Error("创建eta请求接口失败:%v", err)
+		return
+	}
+	resp, err := client.Get(url)
+	if err != nil {
+		utils.FileLog.Error("获取来源列表信息失败", err.Error())
+		return
+	}
+	defer func(Body io.ReadCloser) {
+		closeErr := Body.Close()
+		if closeErr != nil {
+			utils.FileLog.Error("关闭Response失败:%v", closeErr)
+		}
+	}(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
+	var htRes ETAResponse
+	err = json.Unmarshal(body, &htRes)
+	if err != nil {
+		utils.FileLog.Error("解析应答信息失败:%v", err)
+		return
+	}
+	if htRes.Ret == 200 {
+		err = json.Unmarshal(htRes.Data, &businessSourceList)
+	} else {
+		err = errors.New(htRes.ErrMsg)
+	}
+	if err == nil {
+		var filterList []*EdbBusinessSource
+		for _, v := range businessSourceList {
+			if strings.HasPrefix(v.SourceName, "一期-") {
+				filterList = append(filterList, v)
+			}
+		}
+		businessSourceList = filterList
+	}
+	return
+}
+
+type IndexListRequest struct {
+	PageSize     int
+	CurrentIndex int
+	SourceName   string
+	Frequency    string
+	SortColumn   string
+	SortOrder    string
+	KeyWord      string
+	SysSource    string
+}
+type IndexDataListRequest struct {
+	PageSize     int
+	CurrentIndex int
+	IndexCode    string
+}
+
+func (ilr *IndexListRequest) ToString() string {
+	return fmt.Sprintf("PageSize=%d&CurrentIndex=%d&SortColumn=%s&SortOrder=%s&SourceName=%s&KeyWord=%s&Frequency=%s&SysSource=%s",
+		ilr.PageSize, ilr.CurrentIndex, ilr.SortColumn, ilr.SortOrder, ilr.SourceName, ilr.KeyWord, ilr.Frequency, ilr.SysSource)
+}
+func (ilr *IndexDataListRequest) ToString() string {
+	return fmt.Sprintf("PageSize=%d&CurrentIndex=%d&IndexCode=%s",
+		ilr.PageSize, ilr.CurrentIndex, ilr.IndexCode)
+}
+
+func GetIndexList() (list []string, err error) {
+	indexReq := IndexListRequest{
+		PageSize:     500,
+		CurrentIndex: 1,
+		SysSource:    "ht_mini_crm",
+	}
+	for {
+		resp, fetchErr := GetList(indexReq)
+		if fetchErr != nil {
+			utils.FileLog.Error("获取指标列表信息失败", fetchErr.Error())
+			err = errors.New("获取指标列表信息失败:" + fetchErr.Error())
+			return
+		}
+		for _, v := range resp.List {
+			list = append(list, v.IndexCode)
+		}
+		if indexReq.CurrentIndex*indexReq.PageSize >= resp.Paging.Totals {
+			return
+		}
+		indexReq.CurrentIndex += 1
+	}
+}
+func GetList(indexRequest IndexListRequest) (businessIndexResp *BaseFromBusinessIndexResp, err error) {
+	if utils.ETA_ADDRESS == "" {
+		err = errors.New("未配置ETA_API地址")
+		return
+	}
+	url := fmt.Sprintf("%s%s?%s", utils.ETA_ADDRESS, DataListUrl, indexRequest.ToString())
+	client, err := createETARequest()
+	if err != nil {
+		utils.FileLog.Error("创建eta请求接口失败:%v", err)
+		return
+	}
+	resp, err := client.Get(url)
+	if err != nil {
+		utils.FileLog.Error("获取指标列表信息失败", err.Error())
+		return
+	}
+	defer func(Body io.ReadCloser) {
+		closeErr := Body.Close()
+		if closeErr != nil {
+			utils.FileLog.Error("关闭Response失败:%v", closeErr)
+		}
+	}(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
+	var htRes ETAResponse
+	err = json.Unmarshal(body, &htRes)
+	if err != nil {
+		utils.FileLog.Error("解析应答信息失败:%v", err)
+		return
+	}
+	if htRes.Ret == 200 {
+		err = json.Unmarshal(htRes.Data, &businessIndexResp)
+	} else {
+		err = errors.New(htRes.ErrMsg)
+	}
+	return
+}
+
+type EdbBusinessSource struct {
+	EdbBusinessSourceId int64     `orm:"column(edb_business_source_id);pk"`
+	SourceName          string    `description:"来源名称"` // 来源名称
+	CreateTime          time.Time `description:"创建时间"` // 创建时间
+}
+type BaseFromBusinessIndexItem struct {
+	IndexCode  string    `description:"指标编码"`
+	IndexName  string    `description:"指标名称"`
+	Unit       string    `description:"单位"`
+	Frequency  string    `description:"频度"`
+	SourceName string    `description:"数据来源名称"`
+	StartDate  time.Time `description:"指标开始时间"`
+	EndDate    time.Time `description:"指标最新时间"`
+	CreateTime time.Time `description:"入库时间"`
+}
+
+type BaseFromBusinessIndexDataItem struct {
+	ID        string
+	EdbDataId int `orm:"column(edb_data_id);pk"`
+	IndexCode string
+	DataTime  string
+	Value     float64
+}
+type BaseFromBusinessIndexResp struct {
+	Paging         *paging.PagingItem
+	List           []*BaseFromBusinessIndexItem
+	LastUpdateTime string
+}
+type BaseFromBusinessIndexDataResp struct {
+	Paging         *paging.PagingItem
+	List           []*BaseFromBusinessIndexDataItem
+	LastUpdateTime string
+}
+type DelBusinessIndexResp struct {
+	IsDeleteEdbCodeList []string `description:"已经删除了的指标编码"`
+	NoDeleteEdbCodeList []string `description:"未删除的指标编码"`
+}
+
+type DelBusinessIndexReq struct {
+	IndexCodeList []string `description:"已经删除了的指标编码"`
+}
+
+func DeleteIndexes(indexCodes []string) (deleteBusinessIndexResp *DelBusinessIndexResp, err error) {
+	if utils.ETA_ADDRESS == "" {
+		err = errors.New("未配置ETA_API地址")
+		return
+	}
+	url := fmt.Sprintf("%s%s", utils.ETA_ADDRESS, DeleteIndexesUrl)
+	client, err := createETARequest()
+	if err != nil {
+		utils.FileLog.Error("创建eta请求接口失败:%v", err)
+		return
+	}
+	resp, err := client.Post(url, &DelBusinessIndexReq{
+		IndexCodeList: indexCodes,
+	})
+	if err != nil {
+		utils.FileLog.Error("获取来源列表信息失败", err.Error())
+		return
+	}
+	defer func(Body io.ReadCloser) {
+		closeErr := Body.Close()
+		if closeErr != nil {
+			utils.FileLog.Error("关闭Response失败:%v", closeErr)
+		}
+	}(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
+	var htRes ETAResponse
+	err = json.Unmarshal(body, &htRes)
+	if err != nil {
+		utils.FileLog.Error("解析应答信息失败:%v", err)
+		return
+	}
+	if htRes.Ret == 200 {
+		err = json.Unmarshal(htRes.Data, &deleteBusinessIndexResp)
+	} else {
+		err = errors.New(htRes.ErrMsg)
+	}
+	return
+}

+ 0 - 66
services/htService.go

@@ -1,66 +0,0 @@
-package services
-
-import (
-	"encoding/json"
-	"errors"
-	"eta/eta_mini_crm_ht/utils"
-	httpClient "eta/eta_mini_crm_ht/utils/http"
-	"fmt"
-	"io"
-)
-
-const (
-	GetIndexInfoUrl = "/htApi/v1/index/getIndexInfo"
-)
-
-type IndexInfo struct {
-	IndexCode      string        `json:"indexCode"`
-	IndexName      string        `json:"indexName"`
-	Frequency      string        `json:"frequency"`
-	SourceName     string        `json:"sourceName"`
-	LatestDataDate string        `json:"latestDataDate"`
-	LastPushTime   string        `json:"lastPushTime"`
-	Remark         string        `json:"remark"`
-	Unit           string        `json:"unit"`
-	DataList       []interface{} `json:"dataList"`
-}
-
-type HTResponse struct {
-	Code    string          `json:"code"`
-	Success bool            `json:"success"`
-	Message string          `json:"message"`
-	Data    json.RawMessage `json:"data"`
-}
-
-func GetIndexInfo(indexCode string) (indexInfo *IndexInfo, err error) {
-	client := httpClient.DefaultClient()
-	if utils.HT_ADDRESS == "" {
-		err = errors.New("未配置海通钢联地址")
-		return
-	}
-	url := fmt.Sprintf("%s%s?indexCode=%s", utils.HT_ADDRESS, GetIndexInfoUrl, indexCode)
-	resp, err := client.Get(url)
-	if err != nil {
-		utils.FileLog.Error("获取钢联指标信息失败", err.Error())
-		return
-	}
-	defer func(Body io.ReadCloser) {
-		closeErr := Body.Close()
-		if closeErr != nil {
-			utils.FileLog.Error("关闭Response失败:%v", closeErr)
-		}
-	}(resp.Body)
-	body, _ := io.ReadAll(resp.Body)
-	var htRes HTResponse
-	err = json.Unmarshal(body, &htRes)
-	if err != nil {
-		utils.FileLog.Error("解析应答信息失败:%v", err)
-		return
-	}
-	if htRes.Success {
-		err = json.Unmarshal(htRes.Data, &indexInfo)
-	} else {
-		err = errors.New(htRes.Message)
-	}
-	return
-}

+ 142 - 0
services/ht_service.go

@@ -0,0 +1,142 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_mini_crm_ht/utils"
+	httpClient "eta/eta_mini_crm_ht/utils/http"
+	"fmt"
+	"io"
+)
+
+const (
+	GetIndexInfoUrl        = "/htApi/v1/index/getIndexInfo"
+	PushIndexInfoUrl       = "/htApi/v1/index/push"
+	DeleteIndexSyncTaskUrl = "/htApi/v1/index/deleteTask"
+)
+
+type IndexInfo struct {
+	IndexCode      string
+	IndexName      string
+	Frequency      string
+	SourceName     string
+	LatestDataDate string
+	StartDate      string
+	EndDate        string
+	LastPushTime   string
+	Remark         string
+	Unit           string
+	DataList       []interface{}
+}
+type PushIndex struct {
+	IndexCode string `json:"indexCode"`
+}
+
+type DeleteIndexSyncTask struct {
+	IndexCode []string `json:"indexCode"`
+}
+type HTResponse struct {
+	Code    string          `json:"code"`
+	Success bool            `json:"success"`
+	Message string          `json:"message"`
+	Data    json.RawMessage `json:"data"`
+}
+
+func GetIndexInfo(indexCode string) (indexInfo *IndexInfo, err error) {
+	client := httpClient.DefaultClient()
+	if utils.HT_ADDRESS == "" {
+		err = errors.New("未配置海通钢联地址")
+		return
+	}
+	url := fmt.Sprintf("%s%s?indexCode=%s", utils.HT_ADDRESS, GetIndexInfoUrl, indexCode)
+	resp, err := client.Get(url)
+	if err != nil {
+		utils.FileLog.Error("获取钢联指标信息失败", err.Error())
+		return
+	}
+	defer func(Body io.ReadCloser) {
+		closeErr := Body.Close()
+		if closeErr != nil {
+			utils.FileLog.Error("关闭Response失败:%v", closeErr)
+		}
+	}(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
+	var htRes HTResponse
+	err = json.Unmarshal(body, &htRes)
+	if err != nil {
+		utils.FileLog.Error("解析应答信息失败:%v", err)
+		return
+	}
+	if htRes.Success {
+		err = json.Unmarshal(htRes.Data, &indexInfo)
+	} else {
+		err = errors.New(htRes.Message)
+	}
+	return
+}
+
+func PushIndexInfo(indexCode string) (err error) {
+	client := httpClient.DefaultClient()
+	if utils.HT_ADDRESS == "" {
+		err = errors.New("未配置海通钢联地址")
+		return
+	}
+	url := fmt.Sprintf("%s%s?indexCode=%s", utils.HT_ADDRESS, PushIndexInfoUrl, indexCode)
+	resp, err := client.Post(url, &PushIndex{
+		IndexCode: indexCode,
+	})
+	if err != nil {
+		utils.FileLog.Error("获取钢联指标信息失败", err.Error())
+		return
+	}
+	defer func(Body io.ReadCloser) {
+		closeErr := Body.Close()
+		if closeErr != nil {
+			utils.FileLog.Error("关闭Response失败:%v", closeErr)
+		}
+	}(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
+	var htRes HTResponse
+	err = json.Unmarshal(body, &htRes)
+	if err != nil {
+		utils.FileLog.Error("解析应答信息失败:%v", err)
+		return
+	}
+	if !htRes.Success {
+		err = errors.New(htRes.Message)
+	}
+	return
+}
+
+func DeleteSyncTask(indexCodes []string) (err error) {
+	client := httpClient.DefaultClient()
+	if utils.HT_ADDRESS == "" {
+		err = errors.New("未配置海通钢联地址")
+		return
+	}
+	url := fmt.Sprintf("%s%s", utils.HT_ADDRESS, DeleteIndexSyncTaskUrl)
+	resp, err := client.Post(url, &DeleteIndexSyncTask{
+		IndexCode: indexCodes,
+	})
+	if err != nil {
+		utils.FileLog.Error("停止钢联指标失败", err.Error())
+		return
+	}
+	defer func(Body io.ReadCloser) {
+		closeErr := Body.Close()
+		if closeErr != nil {
+			utils.FileLog.Error("关闭Response失败:%v", closeErr)
+		}
+	}(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
+	var htRes HTResponse
+	err = json.Unmarshal(body, &htRes)
+	if err != nil {
+		utils.FileLog.Error("解析应答信息失败:%v", err)
+		return
+	}
+	if !htRes.Success {
+		err = errors.New(htRes.Message)
+	}
+	return
+}

+ 13 - 1
utils/config.go

@@ -106,7 +106,14 @@ var (
 
 // 钢联一期地址
 var (
-	HT_ADDRESS string
+	HT_ADDRESS  string
+	ETA_ADDRESS string
+)
+
+// etahub 签名
+var (
+	APP_ID string
+	SECRET string
 )
 
 // SSO登录
@@ -219,6 +226,11 @@ func init() {
 	}
 	{
 		HT_ADDRESS = config["ht_address"]
+		ETA_ADDRESS = config["eta_address"]
+	}
+	{
+		APP_ID = config["app_id"]
+		SECRET = config["secret"]
 	}
 	// 初始化ES
 	initEs()

+ 27 - 2
utils/http/http_client.go

@@ -6,6 +6,7 @@ import (
 	"errors"
 	"eta/eta_mini_crm_ht/utils"
 	"fmt"
+	"github.com/mitchellh/mapstructure"
 	"io"
 	"net/http"
 	"strings"
@@ -16,6 +17,23 @@ type HttpClient struct {
 	*http.Client
 	maxRetries     int
 	retryDelayFunc RetryDelayFunc
+	header         map[string]string
+}
+
+func (hc *HttpClient) AddHeader(header map[string]string) {
+	hc.header = header
+}
+func (hc *HttpClient) StructToMap(data interface{}) (dataMap map[string]string, err error) {
+	if data == nil {
+		utils.FileLog.Warn("请求data为空")
+		return
+	}
+	err = mapstructure.Decode(data, &dataMap)
+	if err != nil {
+		utils.FileLog.Error("结构体转Map失败", err.Error())
+		return
+	}
+	return
 }
 
 // NewClient 构造函数,其中 delayFunc 参数是可选的
@@ -68,7 +86,11 @@ func (hc *HttpClient) DoWithRetry(ctx context.Context, req *http.Request) (resp
 		return
 	}
 }
-
+func (hc *HttpClient) buildHeader(header *http.Header) {
+	for k, v := range hc.header {
+		header.Add(k, v)
+	}
+}
 func (hc *HttpClient) Post(url string, data interface{}) (resp *http.Response, err error) {
 	dataStr, err := json.Marshal(data)
 	if err != nil {
@@ -76,6 +98,7 @@ func (hc *HttpClient) Post(url string, data interface{}) (resp *http.Response, e
 	}
 	body := io.NopCloser(strings.NewReader(string(dataStr)))
 	req, err := http.NewRequest(http.MethodPost, url, body)
+	hc.buildHeader(&req.Header)
 	req.Header.Set("Content-Type", "application/json")
 	if err != nil {
 		utils.FileLog.Error("创建POST请求失败: %v", err)
@@ -109,6 +132,7 @@ func (hc *HttpClient) PostWithAuth(url string, data interface{}, token string) (
 	}
 	body := io.NopCloser(strings.NewReader(string(dataStr)))
 	req, err := http.NewRequest(http.MethodPost, url, body)
+	hc.buildHeader(&req.Header)
 	req.Header.Set("Content-Type", "application/json")
 	req.Header.Set("Authorization", token)
 	if err != nil {
@@ -133,7 +157,8 @@ func (hc *HttpClient) PostWithAuth(url string, data interface{}, token string) (
 	return
 }
 func (hc *HttpClient) Get(url string) (resp *http.Response, err error) {
-	req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil)
+	req, err := http.NewRequest(http.MethodGet, url, nil)
+	hc.buildHeader(&req.Header)
 	if err != nil {
 		utils.FileLog.Error("创建请求失败: %v", err)
 	}

+ 1 - 0
utils/oss/oss.go

@@ -23,6 +23,7 @@ type STSToken struct {
 	Bucketname      string
 	Endpoint        string
 	Imghost         string
+	Sign            string
 }
 
 type OssClient interface {

+ 95 - 0
utils/rsa.go

@@ -1,13 +1,25 @@
 package utils
 
 import (
+	"crypto/hmac"
 	"crypto/rand"
 	"crypto/rsa"
 	"crypto/sha256"
 	"crypto/x509"
+	"encoding/base64"
 	"encoding/pem"
 	"errors"
+	"fmt"
+	mathRand "math/rand"
 	"os"
+	"strings"
+	"time"
+)
+
+const (
+	RSAAlgorithm       = "RSA"
+	SignatureAlgorithm = "SHA1WithRSA"
+	letters            = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
 )
 
 // EncryptWithRSA 使用 RSA 公钥加密数据
@@ -43,3 +55,86 @@ func ParsePublicKeyFromPEM() (publicKey *rsa.PublicKey, err error) {
 	publicKey = key.(*rsa.PublicKey)
 	return
 }
+
+// 解析RSA私钥
+func ParsePrivateKeyFromPEM() (privateKey *rsa.PrivateKey, err error) {
+	pemBlock, err := os.ReadFile("./conf/rsa_private_key.pem")
+	block, _ := pem.Decode(pemBlock)
+	if block == nil {
+		FileLog.Error("私钥解析失败")
+		return nil, errors.New("公钥解析失败")
+	}
+	key, err := x509.ParsePKIXPublicKey(block.Bytes)
+	if err != nil {
+		return nil, err
+	}
+	privateKey = key.(*rsa.PrivateKey)
+	return
+}
+
+type SignatureParam struct {
+	Nonce     string `json:"nonce"`
+	TimeStamp string `json:"timestamp"`
+	AppId     string `json:"appId"`
+}
+
+func (sp *SignatureParam) ToString() string {
+	return fmt.Sprintf("appid=%s&nonce=%s&timestamp=%s", sp.AppId, sp.Nonce, sp.TimeStamp)
+}
+
+type HeaderParam struct {
+	Signature string `json:"signature"`
+	Nonce     string `json:"nonce"`
+	TimeStamp string `json:"timestamp"`
+	AppId     string `json:"appId"`
+}
+
+func GenerateSignatureAndHeaders() (headerParam HeaderParam, err error) {
+	if APP_ID == "" {
+		FileLog.Error("APP_ID为空")
+		err = errors.New("生成签名头失败,APP_ID未配置")
+		return
+	}
+	if SECRET == "" {
+		FileLog.Error("SECRET为空")
+		err = errors.New("生成签名头失败,SECRET未配置")
+		return
+	}
+	signParam := SignatureParam{
+		AppId:     APP_ID,
+		Nonce:     randomString(32),
+		TimeStamp: fmt.Sprintf("%d", time.Now().Unix()),
+	}
+
+	signature, err := generateHMACSHA256(SECRET, signParam.ToString())
+	if err != nil {
+		FileLog.Error("生成签名失败", err)
+		return
+	}
+	headerParam.Nonce = signParam.Nonce
+	headerParam.TimeStamp = signParam.TimeStamp
+	headerParam.AppId = signParam.AppId
+	headerParam.Signature = signature
+	return
+}
+
+func generateHMACSHA256(secret, data string) (encoded string, err error) {
+	h := hmac.New(sha256.New, []byte(secret))
+	h.Write([]byte(data))
+	signature := h.Sum(nil)
+	// Base64 编码
+	encoded = base64.StdEncoding.EncodeToString(signature)
+	// 替换 + 和 / 为 - 和 _
+	encoded = strings.ReplaceAll(encoded, "+", "-")
+	encoded = strings.ReplaceAll(encoded, "/", "_")
+	return
+}
+
+func randomString(size int) string {
+
+	ret := make([]byte, size)
+	for i := range ret {
+		ret[i] = letters[mathRand.Intn(len(letters))]
+	}
+	return string(ret)
+}