Browse Source

Merge branch 'master' into feature/nh_idap_0111

hsun 1 year ago
parent
commit
324aacbe95
42 changed files with 3354 additions and 770 deletions
  1. 36 15
      controllers/banner.go
  2. 28 14
      controllers/cloud_disk.go
  3. 148 36
      controllers/data_manage/chart_info.go
  4. 6 0
      controllers/data_manage/chart_theme.go
  5. 47 0
      controllers/data_manage/edb_info.go
  6. 13 3
      controllers/data_manage/excel/excel_info.go
  7. 492 0
      controllers/data_manage/fenwei_data.go
  8. 32 19
      controllers/data_manage/future_good/future_good_chart_info.go
  9. 416 0
      controllers/data_source/guagnzhouqihuo.go
  10. 28 16
      controllers/ppt_english.go
  11. 28 16
      controllers/ppt_v2.go
  12. 46 24
      controllers/report.go
  13. 183 104
      controllers/resource.go
  14. 27 15
      controllers/smart_report/smart_report.go
  15. 26 14
      controllers/voice.go
  16. 1 0
      go.mod
  17. 1 0
      go.sum
  18. 144 0
      models/data_manage/base_from_fenwei.go
  19. 55 0
      models/data_manage/base_from_fenwei_classify.go
  20. 54 2
      models/data_manage/chart_info.go
  21. 4 2
      models/data_manage/edb_data_base.go
  22. 39 0
      models/data_manage/edb_data_gz.go
  23. 134 0
      models/data_source/guagnzhouqihuo.go
  24. 1 1
      models/english_report_email.go
  25. 4 3
      models/roadshow/calendar.go
  26. 108 0
      routers/commentsRouter.go
  27. 6 0
      routers/router.go
  28. 130 0
      services/aws_s3.go
  29. 4 0
      services/data/base_edb_lib.go
  30. 162 21
      services/data/chart_info.go
  31. 19 3
      services/data/chart_theme.go
  32. 1 0
      services/data/edb_info.go
  33. 15 4
      services/data/excel/excel_op.go
  34. 219 0
      services/email.go
  35. 1 1
      services/excel_info.go
  36. 23 12
      services/file.go
  37. 399 290
      services/minio.go
  38. 149 104
      services/oss.go
  39. 45 26
      services/report.go
  40. 44 25
      services/video.go
  41. 28 0
      utils/config.go
  42. 8 0
      utils/constants.go

+ 36 - 15
controllers/banner.go

@@ -51,22 +51,43 @@ func (this *BannerController) Upload() {
 		return
 	}
 	resourceUrl := ``
-	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-	} else {
-		resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
+
+	//resourceUrl, err = services.UploadImgToMinIoTest(fileName, fpath)
+	//if err != nil {
+	//	br.Msg = "文件上传失败"
+	//	br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//	return
+	//}
+
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
 	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+
+	////上传到阿里云 和 minio
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//}
 
 	defer func() {
 		os.Remove(fpath)

+ 28 - 14
controllers/cloud_disk.go

@@ -584,21 +584,35 @@ func (this *CloudDiskController) ResourceUpload() {
 
 	resourceUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, e = services.UploadMinIoToDir(ossFileName, filePath, ossDir, "")
-		if e != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败, Err:" + e.Error()
-			return
-		}
-	} else {
-		resourceUrl, e = services.UploadAliyunToDir(ossFileName, filePath, ossDir, "")
-		if e != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败, Err:" + e.Error()
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, e = services.UploadMinIoToDir(ossFileName, filePath, ossDir, "")
+	//	if e != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败, Err:" + e.Error()
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, e = services.UploadAliyunToDir(ossFileName, filePath, ossDir, "")
+	//	if e != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败, Err:" + e.Error()
+	//		return
+	//	}
+	//}
+	savePath := ossDir + time.Now().Format("200601/20060102/") + ossFileName
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, e = ossClient.UploadFile(ossFileName, filePath, savePath)
+	if e != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + e.Error()
+		return
 	}
+
 	// 新增云盘资源
 	extMap := services.GetCloudDiskResourceFileTypeExtMap()
 	resourceIcon := extMap[ext]

+ 148 - 36
controllers/data_manage/chart_info.go

@@ -910,7 +910,7 @@ func (this *ChartInfoController) ChartInfoDetail() {
 			}
 		}
 	}
-	
+
 	// 图表的指标来源
 	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
 	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
@@ -2233,7 +2233,7 @@ func (this *ChartInfoController) ChartInfoBase64Upload() {
 		}
 	}
 
-	var saveToOssPath string
+	//var saveToOssPath string
 	randStr := utils.GetRandStringNoSpecialChar(28)
 	var fileName, outFileName string
 	fileName = randStr + ".txt"
@@ -2279,27 +2279,39 @@ func (this *ChartInfoController) ChartInfoBase64Upload() {
 		os.Remove(fileName)
 	}()
 
-	saveToOssPath = uploadDir + time.Now().Format("200601/20060102/")
-	saveToOssPath += outFileName
+	//saveToOssPath = uploadDir + time.Now().Format("200601/20060102/")
+	//saveToOssPath += outFileName
 
 	//上传到阿里云 和 minio
 	resourceUrl := ``
-	if utils.ObjectStorageClient == "minio" {
-		err = services.UploadFileToMinIo("", outFileName, saveToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.MinIoImghost + saveToOssPath
-	} else {
-		err = services.UploadFileToAliyun("", outFileName, saveToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.Imghost + saveToOssPath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = services.UploadFileToMinIo("", outFileName, saveToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.MinIoImghost + saveToOssPath
+	//} else {
+	//	err = services.UploadFileToAliyun("", outFileName, saveToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.Imghost + saveToOssPath
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(outFileName, outFileName, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 
 	resp.ResourceUrl = resourceUrl
@@ -2512,6 +2524,8 @@ func (this *ChartInfoController) CopyChartInfo() {
 		ExtraConfig:       oldChartInfo.ExtraConfig,
 		SeasonExtraConfig: oldChartInfo.SeasonExtraConfig,
 		StartYear:         oldChartInfo.StartYear,
+		Unit:              oldChartInfo.Unit,
+		UnitEn:            oldChartInfo.UnitEn,
 		ChartThemeId:      oldChartInfo.ChartThemeId,
 		SourcesFrom:       oldChartInfo.SourcesFrom,
 		Instructions:      oldChartInfo.Instructions,
@@ -2533,22 +2547,23 @@ func (this *ChartInfoController) CopyChartInfo() {
 			timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
 			mapItem := &data_manage.ChartEdbMapping{
 				//ChartEdbMappingId: 0,
-				ChartInfoId: chartInfo.ChartInfoId,
-				EdbInfoId:   v.EdbInfoId,
-				CreateTime:  time.Now(),
-				ModifyTime:  time.Now(),
-				UniqueCode:  utils.MD5(utils.CHART_PREFIX + "_" + timestamp),
-				MaxData:     v.MaxData,
-				MinData:     v.MinData,
-				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,
+				ChartInfoId:  chartInfo.ChartInfoId,
+				EdbInfoId:    v.EdbInfoId,
+				CreateTime:   time.Now(),
+				ModifyTime:   time.Now(),
+				UniqueCode:   utils.MD5(utils.CHART_PREFIX + "_" + timestamp),
+				MaxData:      v.MaxData,
+				MinData:      v.MinData,
+				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,
+				EdbAliasName: v.EdbAliasName,
 			}
 			mapList = append(mapList, mapItem)
 		}
@@ -3122,3 +3137,100 @@ func (this *EdbInfoController) GetBatchChartRefreshResult() {
 //		data.EsAddOrEditMyChartInfoByChartInfoId(v.ChartInfoId)
 //	}
 //}
+
+// PreviewRadarChartInfo
+// @Title 图表-获取预览的雷达图
+// @Description 图表-获取预览的雷达图
+// @Param	ExtraConfig	body data_manage.PreviewRadarChartReq true "type json string"
+// @Success 200 {object} data_manage.ChartEdbInfoDetailResp
+// @router /chart_info/preview/radar [post]
+func (this *ChartInfoController) PreviewRadarChartInfo() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req data_manage.PreviewRadarChartReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	chartInfo := new(data_manage.ChartInfoView)
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	chartType := utils.CHART_TYPE_RADAR
+	if len(req.ChartEdbInfoList) <= 0 {
+		br.Msg = "请选择指标"
+		return
+	}
+
+	edbInfoIdArr := make([]int, 0)
+	edbInfoNameMap := make(map[int]string)
+	for _, v := range req.ChartEdbInfoList {
+		edbInfoIdArr = append(edbInfoIdArr, v.EdbInfoId)
+		edbInfoNameMap[v.EdbInfoId] = v.EdbAliasName
+	}
+	mappingList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdArr)
+	for _, v := range mappingList {
+		if name, ok := edbInfoNameMap[v.EdbInfoId]; ok {
+			v.EdbAliasName = name
+		}
+	}
+	// 获取图表中的指标数据
+	edbList, xEdbIdValue, yDataList, dataResp, err, errMsg := data.GetChartEdbData(0, chartType, "", "", "", mappingList, req.ExtraConfig, "")
+	if err != nil {
+		br.Msg = "获取失败"
+		if errMsg != `` {
+			br.Msg = errMsg
+		}
+		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
+		return
+	}
+	warnEdbList := make([]string, 0)
+	for _, v := range edbList {
+		if v.IsNullData {
+			warnEdbList = append(warnEdbList, v.EdbName+"("+v.EdbCode+")")
+		}
+	}
+	if len(warnEdbList) > 0 {
+		chartInfo.WarnMsg = `图表引用指标异常,异常指标:` + strings.Join(warnEdbList, ",")
+	}
+
+	//图表操作权限
+	chartInfo.IsEdit = data.CheckOpChartPermission(sysUser, chartInfo.SysUserId)
+	//判断是否需要展示英文标识
+	chartInfo.IsEnChart = data.CheckIsEnChart(chartInfo.ChartNameEn, edbList, utils.CHART_SOURCE_DEFAULT, chartType)
+	chartInfo.Button = data_manage.ChartViewButton{
+		IsEdit:    chartInfo.IsEdit,
+		IsEnChart: chartInfo.IsEnChart,
+		IsAdd:     chartInfo.IsAdd,
+		IsCopy:    true,
+		IsSetName: chartInfo.IsSetName,
+	}
+	// 图表的指标来源
+	sourceNameList, sourceNameEnList := data.GetEdbSourceByEdbInfoIdList(edbList)
+	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
+	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")
+
+	resp := new(data_manage.ChartInfoDetailResp)
+	resp.ChartInfo = chartInfo
+	resp.EdbInfoList = edbList
+	resp.XEdbIdValue = xEdbIdValue
+	resp.YDataList = yDataList
+	resp.DataResp = dataResp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 6 - 0
controllers/data_manage/chart_theme.go

@@ -166,6 +166,12 @@ func (c *ChartThemeController) GetThemePreviewData() {
 		edbInfoIdList = []int{9, 10, 11, 12, 13, 14, 15, 16, 17, 18}
 		extraConfigStr = `{"XName":"123","XNameEn":"123","XUnitName":"无","XUnitNameEn":"none","YName":"321","YNameEn":"321","YUnitName":"无","YUnitNameEn":"none","XMinValue":"230","XMaxValue":"395","YMinValue":"380","YMaxValue":"850","SeriesList":[{"Name":"2021-11-21","NameEn":"2021-11-21","IsNameDefault":true,"Color":"","EdbInfoList":[{"XEdbInfoId":9,"YEdbInfoId":14,"Name":"指标1","NameEn":"","XDateType":1,"XDate":"","XDateValue":0,"YDateType":1,"YDate":"","YDateValue":0,"IsShow":false},{"XEdbInfoId":10,"YEdbInfoId":15,"Name":"指标2","NameEn":"指标2","XDateType":1,"XDate":"","XDateValue":0,"YDateType":1,"YDate":"","YDateValue":0,"IsShow":false},{"XEdbInfoId":11,"YEdbInfoId":16,"Name":"指标3","NameEn":"","XDateType":1,"XDate":"","XDateValue":0,"YDateType":1,"YDate":"","YDateValue":0,"IsShow":false},{"XEdbInfoId":12,"YEdbInfoId":17,"Name":"指标4","NameEn":"指标4","XDateType":1,"XDate":"","XDateValue":0,"YDateType":1,"YDate":"","YDateValue":0,"IsShow":false},{"XEdbInfoId":13,"YEdbInfoId":18,"Name":"指标5","NameEn":"","XDateType":1,"XDate":"","XDateValue":0,"YDateType":1,"YDate":"","YDateValue":0,"IsShow":false}],"ShowTrendLine":false,"ShowFitEquation":false,"ShowRSquare":false}]}`
 		chartInfo.ChartName = "截面散点图"
+	case utils.CHART_TYPE_RADAR:
+		edbInfoIdList = []int{19, 20, 21, 22, 23, 24}
+		chartInfo.LeftMin = "10000"
+		chartInfo.LeftMax = "60000"
+		extraConfigStr = `{"DateList":[{"Type":3,"Date":"2023-11-01","Value":0,"Color":"#00f","Name":""},{"Type":1,"Date":"","Value":0,"Color":"#f00","Name":""}]}`
+		chartInfo.ChartName = "雷达图"
 	default:
 		br.Msg = "暂不支持该类型"
 		br.IsSendEmail = false

+ 47 - 0
controllers/data_manage/edb_info.go

@@ -1623,6 +1623,53 @@ func (this *EdbInfoController) EdbInfoSearch() {
 				}
 				isAdd = true
 			}
+		} else if source == utils.DATA_SOURCE_GFEX { //广州期货交易所
+			dataItems, err := data_manage.GetEdbDataAllByEdbCode(edbCode, source, subSource, utils.EDB_DATA_LIMIT)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取上期所已存在信息失败,Err:" + err.Error()
+				return
+			}
+
+			if len(dataItems) > 0 {
+				searchItem.EdbCode = edbCode
+				minDate, maxDate, err := data_manage.GetEdbDataGzMaxOrMinDate(edbCode)
+				if err != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取上期所日期信息失败,Err:" + err.Error()
+					return
+				}
+				searchItem.DataList = dataItems
+				searchItem.StartDate = minDate
+				searchItem.EndDate = maxDate
+			} else {
+				respItem, err := data.AddEdbData(source, edbCode)
+				if err != nil {
+					br.Msg = "获取失败"
+					br.ErrMsg = "获取失败,Err:" + err.Error()
+					return
+				}
+				if respItem.Ret != 200 {
+					br.Msg = "未搜索到该指标"
+					br.ErrMsg = respItem.ErrMsg + ";EdbCode:" + edbCode
+					return
+				}
+				isAdd = true
+			}
+
+			//获取指标信息
+			indexInfo, err := data_manage.GetBaseInfoFromGzByIndexCode(edbCode)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取失败"
+				br.ErrMsg = "获取上期所指标详情失败,Err:" + err.Error()
+				return
+			}
+
+			if indexInfo != nil {
+				searchItem.Frequency = indexInfo.Frequency
+				searchItem.Unit = indexInfo.Unit
+				searchItem.EdbName = indexInfo.IndexName
+			}
 		} else {
 			// 代码中没有的来源那么从edb_source中找是否有对应的
 			sourceItem := data_manage.EdbSourceIdMap[source]

+ 13 - 3
controllers/data_manage/excel/excel_info.go

@@ -511,13 +511,18 @@ func (c *ExcelInfoController) Edit() {
 	}
 
 	// 标记编辑状态
-	_, err = services.UpdateExcelEditMark(req.ExcelInfoId, sysUser.AdminId, 1, sysUser.RealName)
+	markRet, err := services.UpdateExcelEditMark(req.ExcelInfoId, sysUser.AdminId, 1, sysUser.RealName)
 	if err != nil {
 		br.Msg = "查询标记状态失败"
 		br.ErrMsg = "查询标记状态失败,Err:" + err.Error()
 		return
 	}
-
+	if markRet.Status == 1 {
+		br.Ret = 200
+		br.Success = true
+		br.Data = markRet
+		return
+	}
 	excelClassify, err := excel3.GetExcelClassifyById(req.ExcelClassifyId)
 	if err != nil {
 		if err.Error() == utils.ErrNoRow() {
@@ -2276,8 +2281,13 @@ func (this *ExcelInfoController) MarkEditStatus() {
 		br.Msg = "标记状态异常"
 		return
 	}
+
+	status := 1
+	if req.Status == 2 {
+		status = 0
+	}
 	//更新标记key
-	data, err := services.UpdateExcelEditMark(req.ExcelInfoId, sysUser.AdminId, req.Status, sysUser.RealName)
+	data, err := services.UpdateExcelEditMark(req.ExcelInfoId, sysUser.AdminId, status, sysUser.RealName)
 	if err != nil {
 		br.Msg = err.Error()
 		return

+ 492 - 0
controllers/data_manage/fenwei_data.go

@@ -0,0 +1,492 @@
+package data_manage
+
+import (
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_manage"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"github.com/tealeg/xlsx"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+)
+
+// FenweiClassify
+// @Title 汾渭数据分类
+// @Description 汾渭数据分类接口
+// @Success 200 {object} data_manage.BaseFromFenweiClassifyItem
+// @router /fenwei/classify [get]
+func (this *EdbInfoController) FenweiClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	classifies, e := data_manage.GetBaseFromFenweiClassify()
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取汾渭数据分类失败, Err: " + e.Error()
+		return
+	}
+
+	classifyOb := new(data_manage.BaseFromFenweiClassify)
+	resp := make([]*data_manage.BaseFromFenweiClassifyItem, 0)
+	parentMap := make(map[int][]*data_manage.BaseFromFenweiClassifyItem)
+	for _, v := range classifies {
+		t := classifyOb.Format2Item(v)
+		if v.ParentId == 0 {
+			resp = append(resp, t)
+		}
+		if v.ParentId > 0 {
+			if parentMap[v.ParentId] == nil {
+				parentMap[v.ParentId] = make([]*data_manage.BaseFromFenweiClassifyItem, 0)
+			}
+			parentMap[v.ParentId] = append(parentMap[v.ParentId], t)
+		}
+	}
+	for _, v := range resp {
+		v.Child = parentMap[v.ClassifyId]
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// FenweiIndexData
+// @Title 获取汾渭数据
+// @Description 获取汾渭数据接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyId   query   string  true       "分类id"
+// @Success 200 {object} data_manage.LzFrequency
+// @router /fenwei/index/data [get]
+func (this *EdbInfoController) FenweiIndexData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	classifyId, _ := this.GetInt("ClassifyId")
+	if classifyId < 0 {
+		br.Msg = "请选择分类"
+		br.ErrMsg = "请选择分类"
+		return
+	}
+
+	// 获取指标
+	var condition string
+	var pars []interface{}
+	if classifyId >= 0 {
+		condition += ` AND classify_id=? `
+		pars = append(pars, classifyId)
+	}
+
+	indexes, err := data_manage.GetFenweiIndex(condition, pars)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	indexCodes := make([]string, 0)
+	for _, v := range indexes {
+		indexCodes = append(indexCodes, v.IndexCode)
+	}
+	indexCounts, e := data_manage.GetFenweiIndexDataCountGroup(indexCodes)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取指标数据总量失败, Err:" + err.Error()
+		return
+	}
+	countMap := make(map[string]int)
+	for _, v := range indexCounts {
+		countMap[v.IndexCode] = v.Count
+	}
+
+	resultList := make([]*data_manage.BaseFromFenweiIndexList, 0)
+	for _, v := range indexes {
+		product := new(data_manage.BaseFromFenweiIndexList)
+		product.FenweiIndexId = v.FenweiIndexId
+		product.ClassifyId = v.ClassifyId
+		product.Unit = v.Unit
+		product.IndexCode = v.IndexCode
+		product.IndexName = v.IndexName
+		product.Frequency = v.Frequency
+		product.CreateTime = v.CreateTime
+		product.ModifyTime = v.ModifyTime
+
+		total := countMap[v.IndexCode]
+		page := paging.GetPaging(currentIndex, pageSize, total)
+		dataList, e := data_manage.GetFenweiIndexData(v.IndexCode, startSize, pageSize)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取指标数据失败,Err:" + e.Error()
+			return
+		}
+		if dataList == nil {
+			dataList = make([]*data_manage.BaseFromFenweiData, 0)
+		}
+		product.DataList = dataList
+		product.Paging = page
+		resultList = append(resultList, product)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resultList
+}
+
+// FenweiSearchList
+// @Title Fenwei模糊搜索
+// @Description Fenwei模糊搜索
+// @Param   Keyword   query   string  ture       "关键字搜索"
+// @Success 200 {object} data_manage.BaseFromFenweiIndexSearchItem
+// @router /fenwei/search_list [get]
+func (this *EdbInfoController) FenweiSearchList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	list := make([]*data_manage.BaseFromFenweiIndexSearchItem, 0)
+	var err error
+	// 关键字
+	keyword := this.GetString("Keyword")
+	if keyword != "" {
+		keyWordArr := strings.Split(keyword, " ")
+
+		if len(keyWordArr) > 0 {
+			condition := ""
+			for _, v := range keyWordArr {
+				condition += ` AND CONCAT(index_name,index_code) LIKE '%` + v + `%'`
+			}
+			list, err = data_manage.GetFenweiItemList(condition)
+			if err != nil {
+				br.ErrMsg = "获取失败,Err:" + err.Error()
+				br.Msg = "获取失败"
+				return
+			}
+		}
+	} else {
+		list, err = data_manage.GetFenweiItemList("")
+		if err != nil {
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			br.Msg = "获取失败"
+			return
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// FenweiSingleData
+// @Title 获取Fenwei数据
+// @Description 获取Fenwei单条数据接口
+// @Param   IndexCode   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.BaseResponse
+// @router /fenwei/single_data [get]
+func (this *EdbInfoController) FenweiSingleData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	indexCode := this.GetString("IndexCode")
+	indexInfo, err := data_manage.GetBaseFromFenweiIndexByIndexCode(indexCode)
+	if err != nil {
+		br.Msg = "获取指标信息失败"
+		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
+		return
+	}
+	dataTmpList, err := data_manage.GetFenweiIndexDataByCode(indexCode)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	var ret data_manage.FenweiSingleDataResp
+	var dataList []*data_manage.FenweiSingleData
+
+	ret.ClassifyId = indexInfo.ClassifyId
+	ret.FenweiIndexId = indexInfo.FenweiIndexId
+	ret.IndexCode = indexInfo.IndexCode
+	ret.IndexName = indexInfo.IndexName
+	ret.Frequency = indexInfo.Frequency
+	ret.CreateTime = indexInfo.CreateTime.Format(utils.FormatDateTime)
+	ret.ModifyTime = indexInfo.ModifyTime.Format(utils.FormatDateTime)
+	ret.Unit = indexInfo.Unit
+	for _, v := range dataTmpList {
+		tmp := &data_manage.FenweiSingleData{
+			Value:    v.Value,
+			DataTime: v.DataTime,
+		}
+		dataList = append(dataList, tmp)
+	}
+	ret.Data = dataList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = ret
+}
+
+// ExportFenweiList
+// @Title 导出Fenwei数据
+// @Description 导出Fenwei数据
+// @Param   IndexName   query   string  false       "名称关键词"
+// @Param   IndexCode   query   string  false       "指标唯一编码"
+// @Param   ClassifyId   query   string  true       "分类"
+// @Success 200  导出成功
+// @router /fenwei/export [get]
+func (this *EdbInfoController) ExportFenweiList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	indexCode := this.GetString("IndexCode") //指标唯一编码
+	classifyId, _ := this.GetInt("ClassifyId")
+	//secNameList := make([]*models.EdbdataExportList, 0)
+
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+
+	var pars []interface{}
+	condition := ""
+	if classifyId > 0 {
+		//获取指标
+		condition += " AND classify_id=?"
+		pars = append(pars, classifyId)
+	}
+	if indexCode != "" {
+		//获取指标
+		condition += " AND index_code=?"
+		pars = append(pars, indexCode)
+	}
+	indexList, err := data_manage.GetFenweiIndex(condition, pars)
+	if err != nil {
+		fmt.Println("获取数据失败,Err:" + err.Error())
+		return
+	}
+	if len(indexList) <= 0 {
+		fmt.Println("indexList 为空")
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "success"
+		return
+	}
+	sheetNew := new(xlsx.Sheet)
+	// todo 分类名称
+	sheetNew, err = xlsxFile.AddSheet("汾渭数据")
+	//sheetNew.SetColWidth()
+	//获取指标数据
+	windRow := sheetNew.AddRow()
+	secNameRow := sheetNew.AddRow()
+	indexCodeRow := sheetNew.AddRow()
+	frequencyRow := sheetNew.AddRow()
+	unitRow := sheetNew.AddRow()
+	lastModifyDateRow := sheetNew.AddRow()
+	//获取分类下指标最大数据量
+	var dataMax int
+	setRowIndex := 6
+	indexCodeList := make([]string, 0)
+	for _, v := range indexList {
+		indexCodeList = append(indexCodeList, v.IndexCode)
+	}
+	dataListMap := make(map[string][]*data_manage.BaseFromFenweiData)
+	if len(indexList) > 0 {
+		allDataList, e := data_manage.GetFenweiIndexDataByCodes(indexCodeList)
+		if e != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + e.Error()
+			return
+		}
+		for _, v := range allDataList {
+			dataListMap[v.IndexCode] = append(dataListMap[v.IndexCode], v)
+		}
+		for _, v := range dataListMap {
+			if len(v) > dataMax {
+				dataMax = len(v)
+			}
+		}
+	}
+
+	for k, sv := range indexList {
+		//获取数据
+		dataList, ok := dataListMap[sv.IndexCode]
+		if !ok {
+			continue
+		}
+		if len(dataList) > 0 {
+			windRow.AddCell().SetValue("汾渭数据")
+			secNameRow.AddCell().SetValue("指标名称")
+			indexCodeRow.AddCell().SetValue("指标ID")
+			frequencyRow.AddCell().SetValue("频率")
+			unitRow.AddCell().SetValue("单位")
+			lastModifyDateRow.AddCell().SetValue("更新时间")
+
+			secNameRow.AddCell().SetValue(sv.IndexName)
+			indexCodeRow.AddCell().SetValue(sv.IndexCode)
+			frequencyRow.AddCell().SetValue(sv.Frequency)
+
+			unitRow.AddCell().SetValue(sv.Unit)
+			lastModifyDateRow.AddCell().SetValue(sv.ModifyTime)
+
+			windRow.AddCell()
+			windRow.AddCell()
+			secNameRow.AddCell()
+			indexCodeRow.AddCell()
+			frequencyRow.AddCell()
+			unitRow.AddCell()
+			lastModifyDateRow.AddCell()
+			min := k * 3
+			sheetNew.SetColWidth(min, min, 15)
+
+			if len(dataList) <= 0 {
+				for n := 0; n < dataMax; n++ {
+					rowIndex := setRowIndex + n
+					row := sheetNew.Row(rowIndex)
+					row.AddCell()
+					row.AddCell()
+					row.AddCell()
+				}
+			} else {
+				endRowIndex := 0
+				for rk, dv := range dataList {
+					rowIndex := setRowIndex + rk
+					row := sheetNew.Row(rowIndex)
+					displayDate, _ := time.Parse(utils.FormatDate, dv.DataTime)
+					displayDateCell := row.AddCell()
+					style := new(xlsx.Style)
+					style.ApplyAlignment = true
+					style.Alignment.WrapText = true
+					displayDateCell.SetStyle(style)
+					displayDateCell.SetDate(displayDate)
+
+					row.AddCell().SetValue(dv.Value)
+					row.AddCell()
+					endRowIndex = rowIndex
+				}
+				if len(dataList) < dataMax {
+					dataLen := dataMax - len(dataList)
+					for n := 0; n < dataLen; n++ {
+						rowIndex := (endRowIndex + 1) + n
+						row := sheetNew.Row(rowIndex)
+						row.AddCell()
+						row.AddCell()
+						row.AddCell()
+					}
+				}
+			}
+		}
+	}
+
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		err = xlsxFile.Save(downLoadnFilePath)
+		if err != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+	fileName := `汾渭数据`
+	if len(indexList) > 0 {
+		fileName = indexList[0].IndexName
+	}
+	fileName += time.Now().Format("06.01.02") + `.xlsx` //文件名称
+	this.Ctx.Output.Download(downLoadnFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadnFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+
+}

+ 32 - 19
controllers/data_manage/future_good/future_good_chart_info.go

@@ -2388,7 +2388,7 @@ func (this *FutureGoodChartInfoController) ChartInfoBase64Upload() {
 		}
 	}
 
-	var saveToOssPath string
+	//var saveToOssPath string
 	randStr := utils.GetRandStringNoSpecialChar(28)
 	var fileName, outFileName string
 	fileName = randStr + ".txt"
@@ -2434,27 +2434,40 @@ func (this *FutureGoodChartInfoController) ChartInfoBase64Upload() {
 		os.Remove(fileName)
 	}()
 
-	saveToOssPath = uploadDir + time.Now().Format("200601/20060102/")
-	saveToOssPath += outFileName
+	//saveToOssPath = uploadDir + time.Now().Format("200601/20060102/")
+	//saveToOssPath += outFileName
 	//上传到阿里云 和 minio
 	resourceUrl := ``
-	if utils.ObjectStorageClient == "minio" {
-		err = services.UploadFileToMinIo("", outFileName, saveToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.MinIoImghost + saveToOssPath
-	} else {
-		err = services.UploadFileToAliyun("", outFileName, saveToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.Imghost + saveToOssPath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = services.UploadFileToMinIo("", outFileName, saveToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.MinIoImghost + saveToOssPath
+	//} else {
+	//	err = services.UploadFileToAliyun("", outFileName, saveToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.Imghost + saveToOssPath
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
 	}
+	resourceUrl, err = ossClient.UploadFile(outFileName, outFileName, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+
 	resp.ResourceUrl = resourceUrl
 	resp.Source = "convert"
 	//resp.CacheKey = imgDataKey

+ 416 - 0
controllers/data_source/guagnzhouqihuo.go

@@ -0,0 +1,416 @@
+package data_source
+
+import (
+	"eta/eta_api/controllers"
+	"eta/eta_api/models"
+	"eta/eta_api/models/data_source"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/tealeg/xlsx"
+	"os"
+	"path/filepath"
+	"strconv"
+	"time"
+)
+
+// 广州期货交易所
+type DataSourceController struct {
+	controllers.BaseAuthController
+}
+
+// ComTradeCountryList
+// @Title 获取广州期货交易所分类
+// @Description 获取广州期货交易所分类
+// @Success 200 {object} []data_manage.ComTradeCountryItem
+// @router /gfex/classify/list [get]
+func (this *DataSourceController) GfexClassifyList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	gzqhObj := new(data_source.BaseFromTradeGuangzhouIndex)
+	classifyList, err := gzqhObj.GetBaseFromTradeGuangzhouClassifyAll()
+	if err != nil {
+		br.Msg = "获取分类失败"
+		br.ErrMsg = "获取分类失败,Err:" + err.Error()
+		return
+	}
+
+	classifyMap := make(map[int][]*data_source.BaseFromTradeGuangzhouClassifyView)
+	for _, v := range classifyList {
+		if v.ParentId == 0 {
+			continue
+		}
+		if items, ok := classifyMap[v.ParentId]; !ok {
+			list := make([]*data_source.BaseFromTradeGuangzhouClassifyView, 0)
+			list = append(list, v)
+			classifyMap[v.ParentId] = list
+		} else {
+			items = append(items, v)
+			classifyMap[v.ParentId] = items
+		}
+	}
+
+	classifyItems := make([]*data_source.BaseFromTradeGuangzhouClassifyView, 0)
+	for _, v := range classifyList {
+		if v.ParentId == 0 {
+			v.Children = classifyMap[v.BaseFromTradeGuangzhouClassifyId]
+			classifyItems = append(classifyItems, v)
+		}
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = classifyItems
+}
+
+// ComTradeCountryList
+// @Title 获取广州期货交易所数据最大日期
+// @Description 获取广州期货交易所数据最大日期
+// @Success 200 {object} []data_source.ComTradeCountryItem
+// @router /gfex/max/date [get]
+func (this *DataSourceController) GfexMaxDate() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	gzqhObj := new(data_source.BaseFromTradeGuangzhouIndex)
+	maxDate, err := gzqhObj.GetBaseFromTradeGuangzhouMaxDate()
+	if err != nil {
+		br.ErrMsg = "获取最新日期失败,Err:" + err.Error()
+		br.Msg = "获取最新日期失败"
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = maxDate
+}
+
+// ComTradeCountryList
+// @Title 获取广州期货交易所-分类下合约
+// @Description 获取广州期货交易所-分类下合约
+// @Param   BaseFromTradeGuangzhouClassifyId   query   int  true       "分类id"
+// @Param   TradeDate   query   string  true       "日期"
+// @Success 200 {object} []data_source.BaseFromTradeGuangzhouContract
+// @router /gfex/contract [get]
+func (this *DataSourceController) GfexContract() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	baseFromTradeGuangzhouClassifyId, _ := this.GetInt("BaseFromTradeGuangzhouClassifyId", 0)
+	if baseFromTradeGuangzhouClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.Msg = "分类id错误"
+		return
+	}
+	tradeDate := this.GetString("TradeDate")
+	if tradeDate == "" {
+		br.Msg = "参数错误"
+		br.Msg = "交易日期不能为空"
+		return
+	}
+	gzqhObj := new(data_source.BaseFromTradeGuangzhouIndex)
+	list, err := gzqhObj.GetBaseFromTradeGuangzhouContract(baseFromTradeGuangzhouClassifyId, tradeDate)
+	if err != nil {
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		br.Msg = "获取数据失败"
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// ComTradeCountryList
+// @Title 获取广州期货交易所-分类下指标信息
+// @Description 获取广州期货交易所-分类下指标信息
+// @Param   BaseFromTradeGuangzhouClassifyId   query   int  true       "分类id"
+// @Param   BaseFromTradeGuangzhouContractId   query   int  true       "合约id"
+// @Param   TradeDate   query   string  true       "日期"
+// @Success 200 {object} []data_source.BaseFromTradeGuangzhouIndexView
+// @router /gfex/index_data [get]
+func (this *DataSourceController) GfexIndexData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	baseFromTradeGuangzhouClassifyId, _ := this.GetInt("BaseFromTradeGuangzhouClassifyId", 0)
+	if baseFromTradeGuangzhouClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "分类id错误"
+		return
+	}
+	tradeDate := this.GetString("TradeDate")
+	if tradeDate == "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "交易日期不能为空"
+		return
+	}
+	baseFromTradeGuangzhouContractId, err := this.GetInt("BaseFromTradeGuangzhouContractId", 0)
+	fmt.Println(err)
+	fmt.Println(baseFromTradeGuangzhouContractId)
+
+	var condition string
+	var pars []interface{}
+
+	if baseFromTradeGuangzhouContractId > 0 {
+		condition += `  b.data_time=? `
+		pars = append(pars, tradeDate)
+		condition += ` AND a.base_from_trade_guangzhou_classify_id=? `
+		pars = append(pars, baseFromTradeGuangzhouClassifyId)
+	} else {
+		if baseFromTradeGuangzhouClassifyId == 11 || baseFromTradeGuangzhouClassifyId == 12 { //月度数据处理
+			td, err := time.Parse(utils.FormatDate, tradeDate)
+			if err != nil {
+				br.Msg = "日期格式错误"
+				br.ErrMsg = "日期格式错误,Err:" + err.Error()
+				return
+			}
+			_, monthEndDay := utils.GetMonthStartAndEnd(strconv.Itoa(td.Year()), strconv.Itoa(int(td.Month())))
+			condition += `  a.data_time=? `
+			pars = append(pars, monthEndDay)
+		} else {
+			condition += `  a.data_time=? `
+			pars = append(pars, tradeDate)
+		}
+
+		condition += ` AND b.base_from_trade_guangzhou_classify_id=? `
+		pars = append(pars, baseFromTradeGuangzhouClassifyId)
+	}
+
+	//if baseFromTradeGuangzhouContractId > 0 {
+	//	condition += ` AND c.base_from_trade_guangzhou_contract_id=? `
+	//	pars = append(pars, baseFromTradeGuangzhouContractId)
+	//}
+
+	gzqhObj := new(data_source.BaseFromTradeGuangzhouIndex)
+	list, err := gzqhObj.GetBaseFromTradeGuangzhouIndex(condition, pars, baseFromTradeGuangzhouContractId)
+	if err != nil {
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		br.Msg = "获取数据失败"
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// @Title 获取广州期货交易所-一次性交割卖方仓单明细
+// @Description 获取广州期货交易所-一次性交割卖方仓单明细
+// @Param   BaseFromTradeGuangzhouIndexId   query   int  true       "指标id"
+// @Param   TradeDate   query   string  true       "日期"
+// @Success 200 {object} []data_source.BaseFromTradeGuangzhouIndexView
+// @router /gfex/index/detail [get]
+func (this *DataSourceController) GfexIndexDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	baseFromTradeGuangzhouIndexId, _ := this.GetInt("BaseFromTradeGuangzhouIndexId", 0)
+	if baseFromTradeGuangzhouIndexId < 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	tradeDate := this.GetString("TradeDate")
+	if tradeDate == "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "交易日期不能为空"
+		return
+	}
+
+	var condition string
+	var pars []interface{}
+
+	condition += ` a.base_from_trade_guangzhou_classify_id = ? `
+	pars = append(pars, baseFromTradeGuangzhouIndexId)
+
+	td, err := time.Parse(utils.FormatDate, tradeDate)
+	if err != nil {
+		br.Msg = "日期格式错误"
+		br.ErrMsg = "日期格式错误,Err:" + err.Error()
+		return
+	}
+	_, monthEndDay := utils.GetMonthStartAndEnd(strconv.Itoa(td.Year()), strconv.Itoa(int(td.Month())))
+	condition += ` AND a.end_date = ? `
+	pars = append(pars, monthEndDay)
+
+	gzqhObj := new(data_source.BaseFromTradeGuangzhouIndex)
+	list, err := gzqhObj.GetBaseFromTradeGuangzhouIndexDetail(condition, pars)
+	if err != nil {
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		br.Msg = "获取数据失败"
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = list
+}
+
+// @Title 导出广州期货交易所-一次性交割卖方仓单明细
+// @Description 导出广州期货交易所-一次性交割卖方仓单明细
+// @Param   BaseFromTradeGuangzhouIndexId   query   int  true       "指标id"
+// @Param   TradeDate   query   string  true       "日期"
+// @Success 200  导出成功
+// @router /gfex/index/detail/export [get]
+func (this *DataSourceController) ExportGfexIndexDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	baseFromTradeGuangzhouIndexId, _ := this.GetInt("BaseFromTradeGuangzhouIndexId", 0)
+	if baseFromTradeGuangzhouIndexId < 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	tradeDate := this.GetString("TradeDate")
+	if tradeDate == "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "交易日期不能为空"
+		return
+	}
+
+	var condition string
+	var pars []interface{}
+
+	condition += ` a.base_from_trade_guangzhou_classify_id = ? `
+	pars = append(pars, baseFromTradeGuangzhouIndexId)
+
+	td, err := time.Parse(utils.FormatDate, tradeDate)
+	if err != nil {
+		br.Msg = "日期格式错误"
+		br.ErrMsg = "日期格式错误,Err:" + err.Error()
+		return
+	}
+	_, monthEndDay := utils.GetMonthStartAndEnd(strconv.Itoa(td.Year()), strconv.Itoa(int(td.Month())))
+	condition += ` AND a.end_date = ? `
+	pars = append(pars, monthEndDay)
+
+	gzqhObj := new(data_source.BaseFromTradeGuangzhouIndex)
+	list, err := gzqhObj.GetBaseFromTradeGuangzhouIndexDetail(condition, pars)
+	if err != nil {
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		br.Msg = "获取数据失败"
+		return
+	}
+
+	dir, _ := os.Executable()
+	exPath := filepath.Dir(dir)
+
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+	sheetNew, err := xlsxFile.AddSheet("详情")
+	if err != nil {
+		br.ErrMsg = "导出失败,Err:" + err.Error()
+		br.Msg = "导出失败"
+		return
+	}
+	titleRow := sheetNew.AddRow()
+	titleRow.AddCell().SetValue("指标ID")
+	titleRow.AddCell().SetValue("指标名称")
+	titleRow.AddCell().SetValue("数值")
+	titleRow.AddCell().SetValue("单位")
+	titleRow.AddCell().SetValue("频度")
+	titleRow.AddCell().SetValue("起始日期")
+	titleRow.AddCell().SetValue("最新日期")
+
+	var indexCode string
+	for _, sv := range list {
+		dataRow := sheetNew.AddRow()
+		dataRow.AddCell().SetValue(sv.IndexCode)
+		dataRow.AddCell().SetValue(sv.IndexName)
+		dataRow.AddCell().SetValue(sv.Value)
+		dataRow.AddCell().SetValue(sv.Unit)
+		dataRow.AddCell().SetValue(sv.Frequency)
+		dataRow.AddCell().SetValue(sv.StartDate)
+		dataRow.AddCell().SetValue(sv.EndDate)
+
+		indexCode = sv.IndexCode
+	}
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		//有指标无数据时先导出一遍空表
+		sheet, err := xlsxFile.AddSheet("无数据")
+		if err != nil {
+			br.Msg = "新增Sheet失败"
+			br.ErrMsg = "新增Sheet失败,Err:" + err.Error()
+			return
+		}
+		rowSecName := sheet.AddRow()
+		celSecName := rowSecName.AddCell()
+		celSecName.SetValue("")
+		err = xlsxFile.Save(downLoadnFilePath)
+		if err != nil {
+			br.Msg = "保存文件失败"
+			br.ErrMsg = "保存文件失败"
+			return
+		}
+	}
+	fileName := `一次性交割卖方仓单详情`
+	fileName = indexCode[:6] + fileName + `.xlsx` //文件名称
+	this.Ctx.Output.Download(downLoadnFilePath, fileName)
+	defer func() {
+		os.Remove(downLoadnFilePath)
+	}()
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "success"
+
+}

+ 28 - 16
controllers/ppt_english.go

@@ -543,22 +543,34 @@ func (this *PptEnglishController) PptUpload() {
 
 	//上传到阿里云 和 minio
 	pptxUrl := ``
-	if utils.ObjectStorageClient == "minio" {
-		err = services.UploadFileToMinIo("", fpath, savePptxToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		pptxUrl = utils.MinIoImghost + savePptxToOssPath
-	} else {
-		err = services.UploadFileToAliyun("", fpath, savePptxToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		pptxUrl = utils.Imghost + savePptxToOssPath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = services.UploadFileToMinIo("", fpath, savePptxToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	pptxUrl = utils.MinIoImghost + savePptxToOssPath
+	//} else {
+	//	err = services.UploadFileToAliyun("", fpath, savePptxToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	pptxUrl = utils.Imghost + savePptxToOssPath
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	pptxUrl, err = ossClient.UploadFile("", fpath, savePptxToOssPath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 
 	defer func() {

+ 28 - 16
controllers/ppt_v2.go

@@ -544,22 +544,34 @@ func (this *PptV2Controller) PptUpload() {
 
 	//上传到阿里云 和 minio
 	pptxUrl := ``
-	if utils.ObjectStorageClient == "minio" {
-		err = services.UploadFileToMinIo("", fpath, savePptxToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		pptxUrl = utils.MinIoImghost + savePptxToOssPath
-	} else {
-		err = services.UploadFileToAliyun("", fpath, savePptxToOssPath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		pptxUrl = utils.Imghost + savePptxToOssPath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = services.UploadFileToMinIo("", fpath, savePptxToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	pptxUrl = utils.MinIoImghost + savePptxToOssPath
+	//} else {
+	//	err = services.UploadFileToAliyun("", fpath, savePptxToOssPath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	pptxUrl = utils.Imghost + savePptxToOssPath
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	pptxUrl, err = ossClient.UploadFile("", fpath, savePptxToOssPath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 
 	defer func() {

+ 46 - 24
controllers/report.go

@@ -929,20 +929,32 @@ func (this *ReportController) Upload() {
 
 	resourceUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-	} else {
-		resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 
 	defer func() {
@@ -1243,16 +1255,26 @@ func (this *ReportUploadCommonController) UploadImg() {
 	}
 	resourceUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
-		if err != nil {
-			return
-		}
-	} else {
-		resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
-		if err != nil {
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
+	//	if err != nil {
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
+	//	if err != nil {
+	//		return
+	//	}
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		err = fmt.Errorf("初始化OSS服务失败")
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
+		return
 	}
 
 	defer func() {

+ 183 - 104
controllers/resource.go

@@ -60,20 +60,32 @@ func (this *ResourceController) Upload() {
 	}
 	resourceUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-	} else {
-		resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 
 	defer func() {
@@ -237,28 +249,41 @@ func (this *ResourceController) VideoUpload() {
 	utils.FileLog.Info("start update oss ")
 	utils.FileLog.Info("%s:", time.Now().Format(utils.FormatDateTime))
 
-	savePath := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
-	savePath += fileName
+	//savePath := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+	//savePath += fileName
 
 	//上传到阿里云 和 minio
 	resourceUrl := ``
-	if utils.ObjectStorageClient == "minio" {
-		err = services.UploadVideoToMinIo(fileName, fpath, savePath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.MinIoImghost + savePath
-	} else {
-		err = services.UploadVideoAliyun(fileName, fpath, savePath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.Imghost + savePath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = services.UploadVideoToMinIo(fileName, fpath, savePath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.MinIoImghost + savePath
+	//} else {
+	//	err = services.UploadVideoAliyun(fileName, fpath, savePath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.Imghost + savePath
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
+
 	utils.FileLog.Info("%s:", time.Now().Format(utils.FormatDateTime))
 	utils.FileLog.Info("end update oss ")
 
@@ -414,26 +439,38 @@ func (this *ResourceController) VoiceUpload() {
 	utils.FileLog.Info("start update oss ")
 	utils.FileLog.Info(fmt.Sprintf("%s:", time.Now().Format(utils.FormatDateTime)))
 
-	savePath := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
-	savePath += fileName
+	//savePath := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+	//savePath += fileName
 	//上传到阿里云 和 minio
 	resourceUrl := ``
-	if utils.ObjectStorageClient == "minio" {
-		err = services.UploadVideoToMinIo(fileName, fpath, savePath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.MinIoImghost + savePath
-	} else {
-		err = services.UploadVideoAliyun(fileName, fpath, savePath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.Imghost + savePath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = services.UploadVideoToMinIo(fileName, fpath, savePath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.MinIoImghost + savePath
+	//} else {
+	//	err = services.UploadVideoAliyun(fileName, fpath, savePath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.Imghost + savePath
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 	utils.FileLog.Info(fmt.Sprintf("%s:", time.Now().Format(utils.FormatDateTime)))
 	utils.FileLog.Info("end update oss ")
@@ -582,22 +619,34 @@ func (this *ResourceController) UploadImageBase64() {
 
 	//上传到阿里云 和 minio
 	resourceUrl := ``
-	if utils.ObjectStorageClient == "minio" {
-		err = services.UploadFileToMinIo(fileName, fpath, savePath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.MinIoImghost + savePath
-	} else {
-		err = services.UploadFileToAliyun(fileName, fpath, savePath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-		resourceUrl = utils.Imghost + savePath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = services.UploadFileToMinIo(fileName, fpath, savePath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.MinIoImghost + savePath
+	//} else {
+	//	err = services.UploadFileToAliyun(fileName, fpath, savePath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//	resourceUrl = utils.Imghost + savePath
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, savePath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 	utils.FileLog.Info("%s:", time.Now().Format(utils.FormatDateTime))
 	utils.FileLog.Info("end update oss ")
@@ -723,20 +772,32 @@ func (this *ResourceController) UploadV2() {
 	}
 	resourceUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-	} else {
-		resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = services.UploadImgToMinIo(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, err = services.UploadAliyunV2(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 
 	defer func() {
@@ -775,29 +836,47 @@ func (this *ResourceController) OssSTSToken() {
 		this.ServeJSON()
 	}()
 
-	source, _ := this.GetInt("StorageSource")
-
-	if source == utils.STORAGESOURCE_OSS {
-		resp, err := services.GetOssSTSToken()
-		if err != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取STSToken失败, Err: " + err.Error()
-			return
-		}
-		br.Data = resp
-		br.Msg = "获取成功"
-		br.Ret = 200
-		br.Success = true
-	} else if source == utils.STORAGESOURCE_MINIO {
-		resp, err := services.GetMinIOSTSToken()
-		if err != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取STSToken失败, Err: " + err.Error()
-			return
-		}
-		br.Data = resp
-		br.Msg = "获取成功"
-		br.Ret = 200
-		br.Success = true
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
 	}
+	resp, e := ossClient.GetUploadToken()
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取OSS上传Token失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Msg = "获取成功"
+	br.Ret = 200
+	br.Success = true
+
+	//source, _ := this.GetInt("StorageSource")
+	//
+	//if source == utils.STORAGESOURCE_OSS {
+	//	resp, err := services.GetOssSTSToken()
+	//	if err != nil {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = "获取STSToken失败, Err: " + err.Error()
+	//		return
+	//	}
+	//	br.Data = resp
+	//	br.Msg = "获取成功"
+	//	br.Ret = 200
+	//	br.Success = true
+	//} else if source == utils.STORAGESOURCE_MINIO {
+	//	resp, err := services.GetMinIOSTSToken()
+	//	if err != nil {
+	//		br.Msg = "获取失败"
+	//		br.ErrMsg = "获取STSToken失败, Err: " + err.Error()
+	//		return
+	//	}
+	//	br.Data = resp
+	//	br.Msg = "获取成功"
+	//	br.Ret = 200
+	//	br.Success = true
+	//}
 }

+ 27 - 15
controllers/smart_report/smart_report.go

@@ -1235,24 +1235,36 @@ func (this *SmartReportController) VoiceUpload() {
 	defer func() {
 		_ = os.Remove(filePath)
 	}()
-	ossDir := "static/audio/"
+	//ossDir := "static/audio/"
 
 	resourceUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, e = services.UploadMinIoToDir(ossFileName, filePath, ossDir, "")
-		if e != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败, Err:" + e.Error()
-			return
-		}
-	} else {
-		resourceUrl, e = services.UploadAliyunToDir(ossFileName, filePath, ossDir, "")
-		if e != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败, Err:" + e.Error()
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, e = services.UploadMinIoToDir(ossFileName, filePath, ossDir, "")
+	//	if e != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败, Err:" + e.Error()
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, e = services.UploadAliyunToDir(ossFileName, filePath, ossDir, "")
+	//	if e != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败, Err:" + e.Error()
+	//		return
+	//	}
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, e = ossClient.UploadFile(ossFileName, filePath, "")
+	if e != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + e.Error()
+		return
 	}
 
 	resource := new(models.Resource)

+ 26 - 14
controllers/voice.go

@@ -76,20 +76,32 @@ func (this *VoiceController) Upload() {
 
 	resourceUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadAudioToMinIo(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
-	} else {
-		resourceUrl, err = services.UploadAudioAliyun(fileName, fpath)
-		if err != nil {
-			br.Msg = "文件上传失败"
-			br.ErrMsg = "文件上传失败,Err:" + err.Error()
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = services.UploadAudioToMinIo(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, err = services.UploadAudioAliyun(fileName, fpath)
+	//	if err != nil {
+	//		br.Msg = "文件上传失败"
+	//		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//		return
+	//	}
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, "")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
 	}
 
 	defer func() {

+ 1 - 0
go.mod

@@ -13,6 +13,7 @@ require (
 	github.com/aliyun/alibaba-cloud-sdk-go v1.61.1656
 	github.com/aliyun/aliyun-oss-go-sdk v3.0.1+incompatible
 	github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
+	github.com/aws/aws-sdk-go v1.42.23
 	github.com/beego/bee/v2 v2.0.4
 	github.com/beego/beego/v2 v2.0.7
 	github.com/beevik/etree v1.2.0

+ 1 - 0
go.sum

@@ -73,6 +73,7 @@ github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb
 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
 github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
+github.com/aws/aws-sdk-go v1.42.23 h1:V0V5hqMEyVelgpu1e4gMPVCJ+KhmscdNxP/NWP1iCOA=
 github.com/aws/aws-sdk-go v1.42.23/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs=
 github.com/beego/bee/v2 v2.0.4 h1:nEjPwxJ8D+cr54eWChJGoGRH7bJ7OQwbhx8rU0OQf7E=
 github.com/beego/bee/v2 v2.0.4/go.mod h1:wq0YrEmPcdNfDNpaUgiTkaW9zso7M8n0HCCShEBOzM0=

+ 144 - 0
models/data_manage/base_from_fenwei.go

@@ -0,0 +1,144 @@
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+type BaseFromFenweiIndex struct {
+	FenweiIndexId int `orm:"column(fenwei_index_id);pk"`
+	ClassifyId    int
+	IndexCode     string
+	IndexName     string
+	Frequency     string
+	Unit          string
+	Sort          int
+	CreateTime    time.Time
+	ModifyTime    time.Time
+}
+
+type BaseFromFenweiIndexList struct {
+	FenweiIndexId int `orm:"column(fenwei_index_id);pk"`
+	ClassifyId    int
+	IndexCode     string
+	IndexName     string
+	Frequency     string
+	Unit          string
+	Sort          int
+	CreateTime    string
+	ModifyTime    string
+	DataList      []*BaseFromFenweiData
+	Paging        *paging.PagingItem `description:"分页数据"`
+}
+
+type FenweiSingleDataResp struct {
+	FenweiIndexId int
+	ClassifyId    int
+	IndexCode     string
+	IndexName     string
+	Frequency     string
+	Unit          string
+	CreateTime    string
+	ModifyTime    string
+	Data          []*FenweiSingleData
+}
+
+type FenweiSingleData struct {
+	Value    string `orm:"column(value)" description:"日期"`
+	DataTime string `orm:"column(data_time)" description:"值"`
+}
+
+func GetFenweiIndex(condition string, pars interface{}) (items []*BaseFromFenweiIndexList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_fenwei_index WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY sort ASC, fenwei_index_id asc`
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func GetFenweiIndexDataCount(indexCode string) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count FROM base_from_fenwei_data WHERE index_code=? `
+	err = o.Raw(sql, indexCode).QueryRow(&count)
+	return
+}
+
+type FenweiIndexDataCountGroup struct {
+	IndexCode string
+	Count     int
+}
+
+func GetFenweiIndexDataCountGroup(indexCodes []string) (items []*FenweiIndexDataCountGroup, err error) {
+	if len(indexCodes) <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count, index_code FROM base_from_fenwei_data WHERE index_code IN (` + utils.GetOrmInReplace(len(indexCodes)) + `) GROUP BY index_code`
+	_, err = o.Raw(sql, indexCodes).QueryRows(&items)
+	return
+}
+
+func GetFenweiIndexData(indexCode string, startSize, pageSize int) (items []*BaseFromFenweiData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM base_from_fenwei_data WHERE index_code=? ORDER BY data_time DESC LIMIT ?,? `
+	_, err = o.Raw(sql, indexCode, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetFenweiIndexDataByCodes(indexCode []string) (items []*BaseFromFenweiData, err error) {
+	if len(indexCode) <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT *  FROM base_from_fenwei_data WHERE index_code in (` + utils.GetOrmInReplace(len(indexCode)) + `) ORDER BY data_time DESC  `
+	_, err = o.Raw(sql, indexCode).QueryRows(&items)
+	return
+}
+
+type BaseFromFenweiData struct {
+	FenweiDataId  int `orm:"column(fenwei_data_id);pk"`
+	FenweiIndexId int
+	IndexCode     string
+	DataTime      string
+	Value         string
+	CreateTime    string
+	ModifyTime    string
+	DataTimestamp int64
+}
+
+type BaseFromFenweiIndexSearchItem struct {
+	FenweiIndexId int `orm:"column(fenwei_index_id);pk"`
+	ClassifyId    int
+	IndexCode     string
+	IndexName     string
+}
+
+// GetFenweiItemList 模糊查询汾渭数据库指标列表
+func GetFenweiItemList(condition string) (items []*BaseFromFenweiIndexSearchItem, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := "SELECT * FROM base_from_fenwei_index WHERE 1=1"
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+func GetFenweiIndexDataByCode(indexCode string) (list []*BaseFromFenweiData, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_fenwei_data WHERE index_code=? `
+	_, err = o.Raw(sql, indexCode).QueryRows(&list)
+	return
+}
+
+func GetBaseFromFenweiIndexByIndexCode(indexCode string) (list *BaseFromFenweiIndex, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_fenwei_index WHERE index_code=? `
+	err = o.Raw(sql, indexCode).QueryRow(&list)
+	return
+}

+ 55 - 0
models/data_manage/base_from_fenwei_classify.go

@@ -0,0 +1,55 @@
+package data_manage
+
+import (
+	"eta/eta_api/utils"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// BaseFromFenweiClassify 汾渭原始数据分类表
+type BaseFromFenweiClassify struct {
+	ClassifyId      int       `orm:"column(classify_id);pk"`
+	ClassifyName    string    `description:"分类名称"`
+	ParentId        int       `description:"父级id"`
+	SysUserId       int       `description:"创建人id"`
+	SysUserRealName string    `description:"创建人姓名"`
+	Level           int       `description:"层级"`
+	Sort            int       `description:"排序字段,越小越靠前,默认值:10"`
+	ModifyTime      time.Time `description:"修改时间"`
+	CreateTime      time.Time `description:"创建时间"`
+}
+
+// GetBaseFromFenweiClassify 获取所有分类
+func GetBaseFromFenweiClassify() (items []*BaseFromFenweiClassify, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_fenwei_classify ORDER BY parent_id ASC, sort ASC, classify_id ASC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// BaseFromFenweiClassifyItem 汾渭数据分类信息
+type BaseFromFenweiClassifyItem struct {
+	ClassifyId   int                           `description:"分类ID"`
+	ClassifyName string                        `description:"分类名称"`
+	ParentId     int                           `description:"父级id"`
+	Level        int                           `description:"层级"`
+	Sort         int                           `description:"排序字段"`
+	CreateTime   string                        `description:"创建时间"`
+	ModifyTime   string                        `description:"修改时间"`
+	Child        []*BaseFromFenweiClassifyItem `description:"子分类"`
+}
+
+func (y *BaseFromFenweiClassify) Format2Item(origin *BaseFromFenweiClassify) (item *BaseFromFenweiClassifyItem) {
+	if origin == nil {
+		return
+	}
+	item = new(BaseFromFenweiClassifyItem)
+	item.ClassifyId = origin.ClassifyId
+	item.ClassifyName = origin.ClassifyName
+	item.ParentId = origin.ParentId
+	item.Level = origin.Level
+	item.Sort = origin.Sort
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	return
+}

+ 54 - 2
models/data_manage/chart_info.go

@@ -26,7 +26,7 @@ type ChartInfo struct {
 	EndDate           string `description:"自定义结束日期"`
 	IsSetName         int    `description:"设置名称"`
 	EdbInfoIds        string `description:"指标id"`
-	ChartType         int    `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图,8:商品价格曲线图,9:相关性图"`
+	ChartType         int    `description:"生成样式:1:曲线图,2:季节性图,3:面积图,4:柱状图,5:散点图,6:组合图,7:柱方图,8:商品价格曲线图,9:相关性图,10:截面散点图, 11:雷达图"`
 	Calendar          string `description:"公历/农历"`
 	SeasonStartDate   string `description:"季节性图开始日期"`
 	SeasonEndDate     string `description:"季节性图开始日期"`
@@ -47,6 +47,8 @@ type ChartInfo struct {
 	Instructions      string `description:"图表说明"`
 	MarkersLines      string `description:"标识线"`
 	MarkersAreas      string `description:"标识区"`
+	Unit              string `description:"中文单位名称"`
+	UnitEn            string `description:"英文单位名称"`
 }
 
 type ChartInfoMore struct {
@@ -235,6 +237,8 @@ type EditChartInfoReq struct {
 	Instructions         string                  `description:"图表说明"`
 	MarkersLines         string                  `description:"标识线"`
 	MarkersAreas         string                  `description:"标识区"`
+	Unit                 string                  `description:"中文单位名称"`
+	UnitEn               string                  `description:"英文单位名称"`
 }
 
 type EditChartEnInfoReq struct {
@@ -701,6 +705,8 @@ func EditChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr string, calenda
 	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
@@ -718,7 +724,9 @@ func EditChartInfoAndMapping(req *EditChartInfoReq, edbInfoIdStr string, calenda
  			  sources_from = ?,
  			  instructions = ?,
  			  markers_lines = ?,
- 			  markers_areas = ?
+ 			  markers_areas = ?,
+ 			  unit = ?,
+ 			  unit_en = ?
 			`
 	if calendar != "" {
 		sql += `,calendar = ? `
@@ -1069,6 +1077,8 @@ type AddChartInfoReq struct {
 	Instructions         string                  `description:"图表说明"`
 	MarkersLines         string                  `description:"标识线"`
 	MarkersAreas         string                  `description:"标识区"`
+	Unit                 string                  `description:"中文单位名称"`
+	UnitEn               string                  `description:"英文单位名称"`
 }
 
 type PreviewChartInfoReq struct {
@@ -1900,3 +1910,45 @@ func EditChartInfoExtraConfig(chartId int, extraConfig string) (err error) {
 
 	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:"每个指标的值"`
+}

+ 4 - 2
models/data_manage/edb_data_base.go

@@ -165,6 +165,8 @@ func GetEdbDataTableName(source, subSource int) (tableName string) {
 		tableName = "edb_data_calculate_zdyfx" // 自定义分析->74
 	case utils.DATA_SOURCE_CALCULATE_RJZ: //日均值->75
 		tableName = "edb_data_calculate_rjz"
+	case utils.DATA_SOURCE_GFEX: //广州期货交易所->76
+		tableName = "edb_data_gz"
 	default:
 		edbSource := EdbSourceIdMap[source]
 		if edbSource != nil {
@@ -307,11 +309,11 @@ func GetEdbDataAllByEdbCodes(edbCodes []string, limit int) (items []*EdbInfoSear
 	pars = append(pars, edbCodes)
 	o := orm.NewOrmUsingDB("data")
 
-	sql := ` SELECT * FROM edb_data_ys WHERE edb_code IN (`+ utils.GetOrmInReplace(len(edbCodes)) +`) ORDER BY data_time DESC`
+	sql := ` SELECT * FROM edb_data_ys WHERE edb_code IN (` + utils.GetOrmInReplace(len(edbCodes)) + `) ORDER BY data_time DESC`
 	if limit > 0 {
 		sql += `  LIMIT ?  `
 		pars = append(pars, limit)
 	}
 	_, err = o.Raw(sql, pars).QueryRows(&items)
 	return
-}
+}

+ 39 - 0
models/data_manage/edb_data_gz.go

@@ -0,0 +1,39 @@
+package data_manage
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type GzData struct {
+	InputValue string `orm:"column(DATA_VALUE)" description:"日期"`
+	DataTime   string `orm:"column(DATA_DATE)" description:"值"`
+}
+
+func GetEdbDataGzMaxOrMinDate(edbCode string) (minDate, maxDate string, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT MIN(data_time) AS minDate,MAX(data_time) AS maxDate FROM edb_data_gz WHERE edb_code=? `
+	err = o.Raw(sql, edbCode).QueryRow(&minDate, &maxDate)
+	return
+}
+
+type GzIndexView struct {
+	BaseFromTradeGuangzhouIndexId    int     `description:"指标id"`
+	BaseFromTradeGuangzhouClassifyId int     `description:"分类id"`
+	IndexCode                        string  `description:"指标编码"`
+	IndexName                        string  `description:"指标名称"`
+	Frequency                        string  `description:"频率"`
+	Unit                             string  `description:"单位"`
+	StartDate                        string  `description:"开始日期"`
+	EndDate                          string  `description:"结束日期"`
+	Value                            float64 `description:"数据"`
+}
+
+// GetBaseInfoFromShByIndexCode 获取指标信息
+func GetBaseInfoFromGzByIndexCode(indexCode string) (item *GzIndexView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_trade_guangzhou_index WHERE index_code=? `
+	sql = fmt.Sprintf(sql)
+	err = o.Raw(sql, indexCode).QueryRow(&item)
+	return
+}

+ 134 - 0
models/data_source/guagnzhouqihuo.go

@@ -0,0 +1,134 @@
+package data_source
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type BaseFromTradeGuangzhouClassify struct {
+	BaseFromTradeGuangzhouClassifyId int       `orm:"column(base_from_trade_guangzhou_classify_id);pk"`
+	ClassifyName                     string    `description:"分类名称"`
+	ClassifyCode                     string    `description:"分类编码"`
+	ParentId                         int       `description:"分类父级id"`
+	ModifyTime                       time.Time `description:"修改时间"`
+	CreateTime                       time.Time `description:"创建时间"`
+}
+
+type BaseFromTradeGuangzhouIndex struct {
+	BaseFromTradeGuangzhouIndexId    int       `orm:"column(base_from_trade_guangzhou_index_id);pk"`
+	BaseFromTradeGuangzhouClassifyId int       `description:"分类id"`
+	IndexCode                        string    `description:"指标编码"`
+	IndexName                        string    `description:"指标名称"`
+	Frequency                        string    `description:"频率"`
+	Unit                             string    `description:"单位"`
+	StartDate                        string    `description:"开始日期"`
+	EndDate                          string    `description:"结束日期"`
+	CreateTime                       time.Time `description:"创建日期"`
+	ModifyTime                       time.Time `description:"修改日期"`
+}
+
+type BaseFromTradeGuangzhouData struct {
+	BaseFromTradeGuangzhouDataId  int       `orm:"column(base_from_trade_guangzhou_data_id);pk"`
+	BaseFromTradeGuangzhouIndexId int       `description:"指标id"`
+	IndexCode                     string    `description:"指标编码"`
+	DataTime                      string    `description:"数据日期"`
+	Value                         float64   `description:"数据值"`
+	QtySub                        float64   `description:"增减"`
+	CreateTime                    time.Time `description:"创建日期"`
+	ModifyTime                    time.Time `description:"修改日期"`
+}
+
+type BaseFromTradeGuangzhouClassifyView struct {
+	BaseFromTradeGuangzhouClassifyId int    `orm:"column(base_from_trade_guangzhou_classify_id);pk"`
+	ClassifyName                     string `description:"分类名称"`
+	ClassifyCode                     string `description:"分类编码"`
+	ParentId                         int    `description:"分类父级id"`
+	Children                         []*BaseFromTradeGuangzhouClassifyView
+}
+
+type BaseFromTradeGuangzhouContract struct {
+	BaseFromTradeGuangzhouContractId int    `orm:"column(base_from_trade_guangzhou_contract_id);pk"`
+	BaseFromTradeGuangzhouClassifyId int    `description:"分类id"`
+	ClassifyCode                     string `description:"分类编码"`
+	Contract                         string `description:"合约编码"`
+	TradeDate                        string `description:"合约日期"`
+}
+
+func (obj *BaseFromTradeGuangzhouIndex) GetBaseFromTradeGuangzhouClassifyAll() (list []*BaseFromTradeGuangzhouClassifyView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := `SELECT * FROM base_from_trade_guangzhou_classify`
+	_, err = o.Raw(sql).QueryRows(&list)
+	return list, err
+}
+
+func (obj *BaseFromTradeGuangzhouIndex) GetBaseFromTradeGuangzhouMaxDate() (max_date string, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT MAX(a.end_date) AS max_date FROM base_from_trade_guangzhou_index AS a `
+	err = o.Raw(sql).QueryRow(&max_date)
+	return max_date, err
+}
+
+func (obj *BaseFromTradeGuangzhouIndex) GetBaseFromTradeGuangzhouContract(classifyId int, tradeDate string) (list []*BaseFromTradeGuangzhouContract, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM base_from_trade_guangzhou_contract AS a WHERE base_from_trade_guangzhou_classify_id=? AND trade_date=? `
+	_, err = o.Raw(sql, classifyId, tradeDate).QueryRows(&list)
+	return
+}
+
+type BaseFromTradeGuangzhouIndexView struct {
+	BaseFromTradeGuangzhouIndexId    int     `description:"指标id"`
+	BaseFromTradeGuangzhouClassifyId int     `description:"分类id"`
+	IndexCode                        string  `description:"指标编码"`
+	IndexName                        string  `description:"指标名称"`
+	Frequency                        string  `description:"频率"`
+	Unit                             string  `description:"单位"`
+	StartDate                        string  `description:"开始日期"`
+	EndDate                          string  `description:"结束日期"`
+	Value                            float64 `description:"数据"`
+}
+
+func (obj *BaseFromTradeGuangzhouIndex) GetBaseFromTradeGuangzhouIndex(condition string, pars []interface{}, baseFromTradeGuangzhouContractId int) (list []*BaseFromTradeGuangzhouIndexView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	if baseFromTradeGuangzhouContractId <= 0 {
+		sql := ` SELECT b.base_from_trade_guangzhou_index_id,b.index_code,b.index_name,b.unit,b.frequency,b.start_date,b.end_date,a.value,c.base_from_trade_guangzhou_contract_id 
+ FROM base_from_trade_guangzhou_data AS a
+INNER JOIN base_from_trade_guangzhou_index AS b ON a.base_from_trade_guangzhou_index_id=b.base_from_trade_guangzhou_index_id
+LEFT JOIN base_from_trade_guangzhou_contract AS c ON b.base_from_trade_guangzhou_classify_id=c.base_from_trade_guangzhou_classify_id
+WHERE `
+		if condition != "" {
+			sql += condition
+		}
+		sql += ` ORDER BY a.index_code ASC `
+		_, err = o.Raw(sql, pars).QueryRows(&list)
+		return
+	} else {
+		condition += ` AND a.base_from_trade_guangzhou_contract_id=? `
+		pars = append(pars, baseFromTradeGuangzhouContractId)
+
+		sql := ` SELECT a.*,b.value 
+ FROM base_from_trade_guangzhou_index AS a
+INNER JOIN base_from_trade_guangzhou_data AS b ON a.base_from_trade_guangzhou_index_id=b.base_from_trade_guangzhou_index_id
+WHERE `
+
+		if condition != "" {
+			sql += condition
+		}
+		sql += ` ORDER BY a.index_code ASC `
+		_, err = o.Raw(sql, pars).QueryRows(&list)
+		return
+	}
+}
+
+func (obj *BaseFromTradeGuangzhouIndex) GetBaseFromTradeGuangzhouIndexDetail(condition string, pars []interface{}) (list []*BaseFromTradeGuangzhouIndexView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT a.*
+ FROM base_from_trade_guangzhou_index AS a
+WHERE `
+
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY a.index_code ASC `
+	_, err = o.Raw(sql, pars).QueryRows(&list)
+	return
+}

+ 1 - 1
models/english_report_email.go

@@ -141,7 +141,7 @@ WHERE a.is_deleted = 0 `
 // GetEnglishReportEmailList 获取邮箱列表
 func GetEnglishReportEmailList(condition string, pars []interface{}, order string) (list []*EnglishReportEmail, err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := `SELECT * FROM english_report_email WHERE is_deleted = 0 `
+	sql := `SELECT * FROM english_report_email WHERE is_deleted = 0`
 	sql += condition
 	if order != "" {
 		sql += order

+ 4 - 3
models/roadshow/calendar.go

@@ -33,9 +33,10 @@ func GetResearcherGroup() (list []*ResearcherGroup, err error) {
 
 func GetResearcher() (list []*Researcher, err error) {
 	o := orm.NewOrm()
-	sql := ` SELECT * FROM admin AS a
-			WHERE a.role_type_code IN('researcher','rai_researcher','ficc_researcher','ficc_admin')
-			AND a.enabled=1 AND a.real_name<>'于菲' `
+	//sql := ` SELECT * FROM admin AS a
+	//		WHERE a.role_type_code IN('researcher','rai_researcher','ficc_researcher','ficc_admin')
+	//		AND a.enabled=1 AND a.real_name<>'于菲' `
+	sql := ` SELECT * FROM admin AS a WHERE a.enabled=1 `
 	_, err = o.Raw(sql).QueryRows(&list)
 	return
 }

+ 108 - 0
routers/commentsRouter.go

@@ -2005,6 +2005,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ChartInfoController"],
+        beego.ControllerComments{
+            Method: "PreviewRadarChartInfo",
+            Router: `/chart_info/preview/radar`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ChartInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:ChartInfoController"],
         beego.ControllerComments{
             Method: "PreviewSectionScatterChartInfo",
@@ -3184,6 +3193,51 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "FenweiClassify",
+            Router: `/fenwei/classify`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "ExportFenweiList",
+            Router: `/fenwei/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "FenweiIndexData",
+            Router: `/fenwei/index/data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "FenweiSearchList",
+            Router: `/fenwei/search_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
+        beego.ControllerComments{
+            Method: "FenweiSingleData",
+            Router: `/fenwei/single_data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_manage:EdbInfoController"],
         beego.ControllerComments{
             Method: "GlClassify",
@@ -4201,6 +4255,60 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"],
+        beego.ControllerComments{
+            Method: "GfexClassifyList",
+            Router: `/gfex/classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"],
+        beego.ControllerComments{
+            Method: "GfexContract",
+            Router: `/gfex/contract`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"],
+        beego.ControllerComments{
+            Method: "GfexIndexDetail",
+            Router: `/gfex/index/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"],
+        beego.ControllerComments{
+            Method: "ExportGfexIndexDetail",
+            Router: `/gfex/index/detail/export`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"],
+        beego.ControllerComments{
+            Method: "GfexIndexData",
+            Router: `/gfex/index_data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_source:DataSourceController"],
+        beego.ControllerComments{
+            Method: "GfexMaxDate",
+            Router: `/gfex/max/date`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/data_stat:EdbSourceStatController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/data_stat:EdbSourceStatController"],
         beego.ControllerComments{
             Method: "EdbDeleteLog",

+ 6 - 0
routers/router.go

@@ -18,6 +18,7 @@ import (
 	"eta/eta_api/controllers/data_manage/line_equation"
 	"eta/eta_api/controllers/data_manage/line_feature"
 	"eta/eta_api/controllers/data_manage/supply_analysis"
+	"eta/eta_api/controllers/data_source"
 	"eta/eta_api/controllers/data_stat"
 	"eta/eta_api/controllers/english_report"
 	"eta/eta_api/controllers/eta_trial"
@@ -336,6 +337,11 @@ func init() {
 				&report_approve.ReportApproveFlowController{},
 			),
 		),
+		web.NSNamespace("/data_source",
+			web.NSInclude(
+				&data_source.DataSourceController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 130 - 0
services/aws_s3.go

@@ -0,0 +1,130 @@
+package services
+
+import (
+	"bytes"
+	"eta/eta_api/utils"
+	"fmt"
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/credentials"
+	"github.com/aws/aws-sdk-go/aws/session"
+	"github.com/aws/aws-sdk-go/service/s3"
+	"io/ioutil"
+	"time"
+)
+
+type OssClient interface {
+	UploadFile(string, string, string) (string, error)
+	GetUploadToken() (OssToken, error)
+}
+
+func NewOssClient() OssClient {
+	switch utils.ObjectStorageClient {
+	case utils.STORAGESOURCE_MINIO_NAME:
+		return new(MinioOss)
+	case utils.STORAGESOURCE_S3_NAME:
+		return new(S3Oss)
+	default:
+		// 默认使用阿里云OSS
+		return new(AliOss)
+	}
+}
+
+// OssToken 此处为了兼容前端那边所以有重复的
+type OssToken struct {
+	AccessKeyId string
+	SecretKeyId string
+	RegionId    string
+	Bucketname  string
+	Endpoint    string
+	ImgHost     string
+	UseSSL      string
+	Port        string
+	//AccessKeyId     string
+	AccessKeySecret string
+	SecurityToken   string
+	ExpiredTime     string
+	//RegionId        string
+	//Bucketname      string
+	//Endpoint        string
+	Imghost      string
+	S3ForceStyle bool
+	S3Protocol   string
+}
+
+type S3Oss struct{}
+
+func (m *S3Oss) UploadFile(fileName, localFile, savePath string) (resourceUrl string, err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println(err.Error())
+		}
+	}()
+
+	endpoint := utils.S3Endpoint
+	accessKey := utils.S3AccessKeyId
+	secretKey := utils.S3AccessKeySecret
+	region := utils.S3Region
+	bucketName := utils.S3BucketName
+	uploadDir := utils.S3UploadDir
+	resourceHost := utils.S3Host
+	forceStyle := utils.S3ForceStyle
+	hostStyle := true // 默认true, 使用`endpoint/bucket_name`这种HOST格式
+	if forceStyle == "false" {
+		hostStyle = false
+	}
+
+	// 创建AWS会话
+	sess, e := session.NewSession(&aws.Config{
+		Region:           aws.String(region),
+		Credentials:      credentials.NewStaticCredentials(accessKey, secretKey, ""),
+		Endpoint:         aws.String(endpoint),
+		S3ForcePathStyle: aws.Bool(hostStyle),
+	})
+	if e != nil {
+		err = fmt.Errorf("new session err: %s", e.Error())
+		return
+	}
+
+	// 创建S3服务客户端
+	client := s3.New(sess)
+
+	// 读取文件内容
+	fileContent, e := ioutil.ReadFile(localFile)
+	if e != nil {
+		err = fmt.Errorf("read file err: %s", e.Error())
+		return
+	}
+
+	path := savePath
+	if savePath == "" {
+		path = uploadDir + time.Now().Format("200601/20060102/") + fileName
+	}
+	_, e = client.PutObject(&s3.PutObjectInput{
+		Bucket: aws.String(bucketName),
+		Key:    aws.String(path),
+		Body:   bytes.NewReader(fileContent),
+	})
+	if e != nil {
+		err = fmt.Errorf("put object err: %s", e.Error())
+		return
+	}
+	resourceUrl = resourceHost + path
+	return
+}
+
+func (m *S3Oss) GetUploadToken() (token OssToken, err error) {
+	token.Endpoint = utils.S3Endpoint
+	token.AccessKeyId = utils.S3AccessKeyId
+	token.AccessKeySecret = utils.S3AccessKeySecret
+	token.RegionId = utils.S3Region
+	token.Bucketname = utils.S3BucketName
+	token.ImgHost = utils.S3Host
+	token.Port = utils.S3EndpointPort
+	hostStyle := true // 默认true, 使用`endpoint/bucket_name`这种HOST格式
+	if utils.S3ForceStyle == "false" {
+		hostStyle = false
+	}
+	token.S3ForceStyle = hostStyle
+	token.S3Protocol = utils.S3Protocol
+	return
+}

+ 4 - 0
services/data/base_edb_lib.go

@@ -67,6 +67,8 @@ func AddEdbData(source int, edbCode string) (resp *models.BaseResponse, err erro
 		urlStr = "national_statistics/add"
 	case utils.DATA_SOURCE_FUBAO:
 		urlStr = "fubao/add"
+	case utils.DATA_SOURCE_GFEX:
+		urlStr = "gz/add"
 	default:
 		edbSource := data_manage.EdbSourceIdMap[source]
 		if edbSource != nil {
@@ -246,6 +248,8 @@ func RefreshEdbData(edbInfoId, source, subSource int, edbCode, startDate string)
 		urlStr = "national_statistics/refresh"
 	case utils.DATA_SOURCE_FUBAO:
 		urlStr = "fubao/refresh"
+	case utils.DATA_SOURCE_GFEX:
+		urlStr = "gz/refresh"
 	default:
 		edbSource := data_manage.EdbSourceIdMap[source]
 		if edbSource != nil {

+ 162 - 21
services/data/chart_info.go

@@ -325,7 +325,20 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 		}
 
 		extraConfig = tmpExtraConfig
-
+	case utils.CHART_TYPE_RADAR:
+		var barConfig data_manage.RadarChartInfoReq
+		if extraConfigStr == `` {
+			errMsg = "雷达图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &barConfig)
+		if err != nil {
+			errMsg = "雷达图配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+		extraConfig = barConfig
 	default:
 		xEdbIdValue = make([]int, 0)
 		yDataList = make([]data_manage.YData, 0)
@@ -379,8 +392,10 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 		for _, v := range edbList {
 			v.DataList = nil
 		}
+	case utils.CHART_TYPE_RADAR: //雷达图
+		radarConf := extraConfig.(data_manage.RadarChartInfoReq)
+		xEdbIdValue, dataResp, err = RadarChartData(mappingList, edbDataListMap, radarConf)
 	}
-
 	return
 }
 
@@ -569,7 +584,7 @@ func getEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate
 				}
 				item.DataList = quarterDataList
 			}
-		} else if chartType == 7 { //柱方图
+		} else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
 			//item.DataList = dataList
 		} else {
 			item.DataList = dataList
@@ -1476,8 +1491,20 @@ func CheckChartExtraConfig(chartType int, extraConfigStr string) (edbIdList []in
 				edbIdList = append(edbIdList, v.YEdbInfoId)
 			}
 		}
+	case utils.CHART_TYPE_RADAR:
+		var extraConfig data_manage.RadarChartInfoReq
+		if extraConfigStr == `` {
+			errMsg = "雷达图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &extraConfig)
+		if err != nil {
+			errMsg = "雷达图配置异常"
+			err = errors.New(errMsg)
+			return
+		}
 	}
-
 	return
 }
 
@@ -1860,7 +1887,12 @@ func AddChartInfo(req data_manage.AddChartInfoReq, sysUserId int, sysUserRealNam
 
 	chartType := req.ChartType
 	extraConfig := req.ExtraConfig
-
+	var extraConfigEdbInfoIdArr []int
+	extraConfigEdbInfoIdArr, err, errMsg = CheckChartExtraConfig(chartType, extraConfig)
+	if err != nil {
+		err = errors.New("添加失败:" + err.Error())
+		return
+	}
 	// 季节性图表额外配置信息
 	var seasonExtraConfig string
 	// 关联指标
@@ -1936,14 +1968,7 @@ func AddChartInfo(req data_manage.AddChartInfoReq, sysUserId int, sysUserRealNam
 			err = errors.New(errMsg)
 			return
 		}
-
-		tmpEdbInfoIdArr, tmpErr, tmpErrMsg := CheckChartExtraConfig(chartType, extraConfig)
-		if err != nil {
-			errMsg = tmpErrMsg
-			err = errors.New("添加失败:" + tmpErr.Error())
-			return
-		}
-		edbInfoIdArr = tmpEdbInfoIdArr
+		edbInfoIdArr = extraConfigEdbInfoIdArr
 		lenEdbInfoIdArr := len(edbInfoIdArr)
 		if lenEdbInfoIdArr > 0 {
 			tmpEdbList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdArr)
@@ -2108,6 +2133,8 @@ func AddChartInfo(req data_manage.AddChartInfoReq, sysUserId int, sysUserRealNam
 	chartInfo.Instructions = req.Instructions
 	chartInfo.MarkersLines = req.MarkersLines
 	chartInfo.MarkersAreas = req.MarkersAreas
+	chartInfo.Unit = req.Unit
+	chartInfo.UnitEn = req.UnitEn
 	newId, err := data_manage.AddChartInfo(chartInfo)
 	if err != nil {
 		errMsg = `保存失败`
@@ -2218,6 +2245,13 @@ func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin) (cha
 		return
 	}
 
+	var extraConfigEdbInfoIdArr []int
+	extraConfigEdbInfoIdArr, err, errMsg = CheckChartExtraConfig(req.ChartType, req.ExtraConfig)
+	if err != nil {
+		err = errors.New("添加失败:" + err.Error())
+		return
+	}
+
 	// 季节性图表额外配置信息
 	var seasonExtraConfig string
 	// 图表关联指标id
@@ -2299,14 +2333,7 @@ func EditChartInfo(req data_manage.EditChartInfoReq, sysUser *system.Admin) (cha
 			return
 		}
 
-		// 校验配置的指标列表
-		tmpEdbInfoIdArr, tmpErr, tmpErrMsg := CheckChartExtraConfig(req.ChartType, req.ExtraConfig)
-		if tmpErr != nil {
-			errMsg = tmpErrMsg
-			err = errors.New("添加失败:" + tmpErr.Error())
-			return
-		}
-		edbInfoIdArr = tmpEdbInfoIdArr
+		edbInfoIdArr = extraConfigEdbInfoIdArr
 		lenEdbInfoIdArr := len(edbInfoIdArr)
 		if lenEdbInfoIdArr > 0 {
 			tmpEdbList, tmpErr := data_manage.GetEdbInfoByIdList(edbInfoIdArr)
@@ -2514,3 +2541,117 @@ func GetEdbSourceByEdbInfoIdList(chartEdbInfoMappingList []*data_manage.ChartEdb
 	}
 	return
 }
+
+// RadarChartData 雷达图的数据处理
+func RadarChartData(mappingList []*data_manage.ChartEdbInfoMapping, edbDataListMap map[int][]*data_manage.EdbDataList, extraConfig data_manage.RadarChartInfoReq) (edbIdList []int, chartDataResp data_manage.RadarChartInfoResp, err error) {
+	// 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
+	edbDataMap := make(map[int]map[string]float64)
+	for edbInfoId, edbDataList := range edbDataListMap {
+		edbDateData := make(map[string]float64)
+		for _, edbData := range edbDataList {
+			edbDateData[edbData.DataTime] = edbData.Value
+		}
+		edbDataMap[edbInfoId] = edbDateData
+	}
+	// edbIdList 指标展示顺序;x轴的指标顺序
+	edbIdList = make([]int, 0)
+	for _, v := range mappingList {
+		edbIdList = append(edbIdList, v.EdbInfoId)
+	}
+	chartDateList := extraConfig.DateList
+
+	yDataList := make([]data_manage.RadarYData, 0) //y轴的数据列表
+
+	for _, chartDate := range chartDateList {
+		var maxDate time.Time
+
+		findDataList := make([]float64, 0) // 当前日期的数据值
+		for _, edbInfoId := range edbIdList {
+			findDate := chartDate.Date            //需要的日期值
+			dataList := edbDataListMap[edbInfoId] //指标的所有数据值
+			if len(dataList) <= 0 {
+				// 没有数据的指标id
+				findDataList = append(findDataList, 0)
+				continue
+			}
+			switch chartDate.Type {
+			case 1: //最新值
+				findDate = dataList[len(dataList)-1].DataTime
+			case 2: //近期几天
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				findDateTime = findDateTime.AddDate(0, 0, -chartDate.Value)
+
+				lenData := len(dataList) - 1
+				for i := lenData; i >= 0; i-- {
+					currDateTime, e := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
+					if e != nil {
+						err = e
+						return
+					}
+					if currDateTime.Equal(findDateTime) || currDateTime.Before(findDateTime) {
+						findDate = dataList[i].DataTime
+						break
+					}
+				}
+			case 3: // 固定日期
+				//最早的日期
+				minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				//寻找固定日期的数据
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, chartDate.Date, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
+					tmpDate := tmpDateTime.Format(utils.FormatDate)
+					if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
+						findDate = tmpDate
+						break
+					}
+				}
+			default:
+				err = errors.New(fmt.Sprint("日期类型异常,Type:", chartDate.Type))
+				return
+			}
+			findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
+			if maxDate.IsZero() {
+				maxDate = findDateTime
+			} else {
+				if findDateTime.After(maxDate) {
+					maxDate = findDateTime
+				}
+			}
+			if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
+				tmpValue, _ = decimal.NewFromFloat(tmpValue).Round(4).Float64()
+				findDataList = append(findDataList, tmpValue)
+			} else {
+				findDataList = append(findDataList, 0)
+			}
+		}
+
+		yDate := "0000-00-00"
+		if !maxDate.IsZero() {
+			yDate = maxDate.Format(utils.FormatDate)
+		}
+		yDataList = append(yDataList, data_manage.RadarYData{
+			Date:  yDate,
+			Value: findDataList,
+			Color: chartDate.Color,
+			Name:  chartDate.Name,
+		})
+	}
+
+	chartDataResp = data_manage.RadarChartInfoResp{
+		YDataList:   yDataList,
+		XEdbIdValue: edbIdList,
+	}
+	return
+}

+ 19 - 3
services/data/chart_theme.go

@@ -49,7 +49,20 @@ func GetThemePreviewChartEdbData(chartType int, calendar, startDate, endDate str
 		}
 
 		extraConfig = tmpExtraConfig
-
+	case utils.CHART_TYPE_RADAR:
+		var barConfig data_manage.RadarChartInfoReq
+		if extraConfigStr == `` {
+			errMsg = "雷达图未配置"
+			err = errors.New(errMsg)
+			return
+		}
+		err = json.Unmarshal([]byte(extraConfigStr), &barConfig)
+		if err != nil {
+			errMsg = "雷达图配置异常"
+			err = errors.New(errMsg)
+			return
+		}
+		extraConfig = barConfig
 	default:
 		xEdbIdValue = make([]int, 0)
 		yDataList = make([]data_manage.YData, 0)
@@ -103,8 +116,11 @@ func GetThemePreviewChartEdbData(chartType int, calendar, startDate, endDate str
 		for _, v := range edbList {
 			v.DataList = nil
 		}
-	}
 
+	case utils.CHART_TYPE_RADAR: //雷达图
+		radarConf := extraConfig.(data_manage.RadarChartInfoReq)
+		xEdbIdValue, dataResp, err = RadarChartData(mappingList, edbDataListMap, radarConf)
+	}
 	return
 }
 
@@ -228,7 +244,7 @@ func getThemePreviewEdbDataMapList(chartType int, calendar, startDate, endDate s
 				return
 			}
 			item.DataList = quarterDataList
-		} else if chartType == 7 { //柱方图
+		} else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
 			//item.DataList = dataList
 		} else {
 			item.DataList = dataList

+ 1 - 0
services/data/edb_info.go

@@ -2307,6 +2307,7 @@ func EdbInfoAdd(source, subSource, classifyId int, edbCode, edbName, frequency,
 		utils.DATA_SOURCE_STOCK_PLANT:         "存量装置",
 		utils.DATA_SOURCE_NATIONAL_STATISTICS: "国家统计局",
 		utils.DATA_SOURCE_FUBAO:               "富宝数据",
+		utils.DATA_SOURCE_GFEX:                "广期所",
 	}
 
 	sourceName, ok := sourceNameMap[source]

+ 15 - 4
services/data/excel/excel_op.go

@@ -262,14 +262,25 @@ func UpdateExcelInfoFileUrl(excelInfo *excelModel.ExcelInfo) {
 
 	var resourceUrl string
 	//上传到阿里云
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = services.UploadImgToMinIo(fileName, downloadFilePath)
-	} else {
-		resourceUrl, err = services.UploadAliyunV2(fileName, downloadFilePath)
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = services.UploadImgToMinIo(fileName, downloadFilePath)
+	//} else {
+	//	resourceUrl, err = services.UploadAliyunV2(fileName, downloadFilePath)
+	//}
+	//if err != nil {
+	//	return
+	//}
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		err = fmt.Errorf("初始化OSS服务失败")
+		return
 	}
+	resourceUrl, err = ossClient.UploadFile(fileName, downloadFilePath, "")
 	if err != nil {
+		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
 		return
 	}
+
 	excelInfo.FileUrl = resourceUrl
 	err = excelInfo.Update([]string{"FileUrl"})
 }

+ 219 - 0
services/email.go

@@ -2,11 +2,230 @@ package services
 
 import (
 	"eta/eta_api/models"
+	"eta/eta_api/utils"
 	"fmt"
 	"gopkg.in/gomail.v2"
 	"strconv"
+	"strings"
 )
 
+func SendEmailToCompany() {
+	// 获取收件人列表
+	//emailCond := " AND enabled = 1 "
+	emailCond := ""
+	emailPars := make([]interface{}, 0)
+	emails, e := models.GetEnglishReportEmailList(emailCond, emailPars, "")
+	if e != nil {
+		fmt.Println("获取收件人列表失败, Err: " + e.Error())
+		return
+	}
+	if len(emails) == 0 {
+		fmt.Println("收件人列表为空")
+		return
+	}
+
+	// TODO:这是HTML模板内容
+	template := `<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,viewport-fit=cover">
+    <title>Horizon Insights x Fastmarkets x FGE: 2024 Macro & Commodities Outlook - Registration Open!</title>
+</head>
+
+<body style="padding:0;margin:0;background-color:#fff">
+<div id="app" style="max-width:1280px;margin:0 auto;font-size:14px;min-height:100vh;">
+    <div class="main-box" style="padding:25px 20px;">
+        <div style="line-height:1.7;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;"
+            class=" __aliyun_node_has_color">
+            <div style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:center;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;"
+                class=" __aliyun_node_has_color"><span
+                    style="font-size:18.0px;font-weight:bold;font-style:normal;text-transform:none;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;color:#000000;text-decoration:underline;"
+                    class=" __aliyun_node_has_color">2024 Macro &amp; Commodities Outlook Invite</span></div>
+            <div style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;"
+                class=" __aliyun_node_has_color"><span
+                    style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;color:#000000;"
+                    class=" __aliyun_node_has_color"><br></span></div>
+            <div style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;"
+                class=" __aliyun_node_has_color"><span
+                    style="font-style:normal;font-weight:400;text-transform:none;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;color:#000000;"
+                    class=" __aliyun_node_has_color">Dear Client,</span></div>
+            <div style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;"
+                class=" __aliyun_node_has_color"><span
+                    style="font-style:normal;font-weight:400;text-transform:none;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;color:#000000;"
+                    class=" __aliyun_node_has_color"><br></span></div>
+            <div style="clear:both;">
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"><span
+                        style="font-style:normal;font-weight:400;text-transform:none;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;color:#000000;"
+                        class=" __aliyun_node_has_color">Happy Year-End Holidays!</span></div>
+            </div>
+            <div style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;"
+                class=" __aliyun_node_has_color"><span
+                    style="font-style:normal;font-weight:400;text-transform:none;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;color:#000000;"
+                    class=" __aliyun_node_has_color"><br></span></div>
+            <div style="clear:both;">
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"><span
+                        style="color:#000000;font-style:normal;font-weight:400;text-transform:none;border:.0px;font-family:arial;margin:.0px;padding:.0px;outline:.0px;font-size:13.0px;"
+                        class=" __aliyun_node_has_color">As we usher in the new year, Horizon Insights, in collaboration
+                        with Fastmarkets and FGE, is proud to announce</span><span
+                        style="color:#000000;font-style:normal;font-weight:400;text-transform:none;font-family:arial;font-size:13.0px;"
+                        class=" __aliyun_node_has_color">&nbsp;our 2024 Macro &amp; Commodities Outlook which will be
+                        held&nbsp;</span><span
+                        style="font-weight:bold;color:#000000;font-style:normal;text-transform:none;font-family:arial;font-size:13.0px;text-decoration:none;"
+                        class=" __aliyun_node_has_color">virtually</span><span
+                        style="color:#000000;font-style:normal;font-weight:400;text-transform:none;font-family:arial;font-size:13.0px;text-decoration:none;"
+                        class=" __aliyun_node_has_color">&nbsp;on&nbsp;</span><span
+                        style="font-weight:bold;color:#000000;font-style:normal;text-transform:none;font-family:arial;font-size:13.0px;text-decoration:none;"
+                        class=" __aliyun_node_has_color">10 &amp; 11 Jan 2024</span><span
+                        style="color:#000000;font-style:normal;font-weight:400;text-transform:none;font-family:arial;font-size:13.0px;"
+                        class=" __aliyun_node_has_color">,&nbsp;</span><span
+                        style="color:#000000;font-family:arial;font-size:13.0px;font-style:normal;font-weight:bold;text-transform:none;"
+                        class=" __aliyun_node_has_color">5pm - 8pm SGT</span><span
+                        style="color:#000000;font-style:normal;font-weight:400;text-transform:none;font-family:arial;font-size:13.0px;"
+                        class=" __aliyun_node_has_color">&nbsp;(i.e.&nbsp;</span><span
+                        style="color:#000000;font-family:arial;font-size:13.0px;font-style:normal;font-weight:bold;text-transform:none;"
+                        class=" __aliyun_node_has_color">9am - 12pm BST</span><span
+                        style="color:#000000;font-style:normal;font-weight:400;text-transform:none;font-family:arial;font-size:13.0px;"
+                        class=" __aliyun_node_has_color">). Our experienced analysts from Horizon Insights together with
+                        guest speakers from our valued partners will present our views in the fields of Macro, Ferrous
+                        Metals, Base Metals, Energy, as well as Petrochemicals.</span></div>
+            </div>
+            <div style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;"
+                class=" __aliyun_node_has_color"><span
+                    style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:13.0px;font-family:arial;"><br></span>
+            </div>
+            <div style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;"
+                class=" __aliyun_node_has_color"><span
+                    style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:13.0px;font-family:arial;">Please
+                    see below for our event schedule:</span></div>
+            <div
+                style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;">
+                <br></div>
+            <div
+                style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;">
+                <span
+                    style="color:#000000;font-style:normal;font-weight:400;text-transform:none;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:13.0px;font-family:arial;"
+                    class=" __aliyun_node_has_color">&nbsp;&nbsp;<img style="vertical-align: bottom; margin: 0px;"
+                        height="3301"
+                        src="https://hzstatic.hzinsights.com/static/images/202312/20231228/KeDTAxIZ3UrZR5DZKKIQLdoIaOVB.png"
+                        width="890"></span></div>
+            <div
+                style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;">
+                <span
+                    style="color:#000000;font-style:normal;font-weight:400;text-transform:none;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:13.0px;font-family:arial;"
+                    class=" __aliyun_node_has_color">&nbsp; &nbsp;</span></div>
+            <div
+                style="clear:both;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-variant-ligatures:normal;font-variant-caps:normal;text-align:start;text-indent:.0px;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;">
+                <br></div>
+            <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                class=" __aliyun_node_has_color"><span
+                    style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;"><br></span>
+            </div>
+            <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                class=" __aliyun_node_has_color"><span
+                    style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;">To
+                    register, simply scan the QR code in the posters above to indicate your interest. Alternatively, you
+                    may also&nbsp;</span><span
+                    style="font-weight:bold;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;"><a
+                        href="https://forms.gle/yhPRDcri43P2QyPt8" target="_blank">register here</a></span><span
+                    style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;">.</span>
+            </div>
+            <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                class=" __aliyun_node_has_color"><span
+                    style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;color:#000000;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline;"
+                    class=" __aliyun_node_has_color">Should you encounter any difficulties registering, please contact
+                    Stephanie (stephanie@hzinsights.com).</span></div>
+            <div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"><span
+                        style="font-weight:bold;margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;">The
+                        virtual meeting details will be disseminated to you a few days prior to the event.</span></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"><br></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"><span
+                        style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;">Lastly,
+                        our firm would like to wish all of you a prosperous Happy New Year! We look forward to seeing
+                        everyone on the 10th &amp; 11th.</span></div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"><span
+                        style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;"><br></span>
+                </div>
+                <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;text-align:start;text-indent:.0px;text-transform:none;text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial;clear:both;"
+                    class=" __aliyun_node_has_color"><span
+                        style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-family:arial;font-size:13.0px;">Cheers!</span>
+                </div>
+            </div>
+            <div><br></div>
+            <div>
+                <div style="clear:both;"><span style="font-family:arial;font-size:13.0px;color:#000000;"
+                        class=" __aliyun_node_has_color"><br></span></div>
+                <div style="clear:both;">
+                    <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;clear:both;font-variant-caps:normal;text-align:start;text-indent:.0px;"
+                        class="x___aliyun_node_has_color"><br></div>
+                    <div style="margin:.0px;padding:.0px;border:.0px;outline:.0px;clear:both;font-variant-caps:normal;text-align:start;text-indent:.0px;"
+                        class="x___aliyun_node_has_color"></div>
+                </div>
+            </div>
+            <div><br></div>
+            <div><br></div>
+            <div><br></div>
+            <div style="line-height:20.0px;clear:both;"><br></div>
+        </div>
+    </div>
+</div>
+</body>
+
+</html>`
+
+	// 推送信息
+	sendData := make([]*EnglishReportSendEmailRequest, 0)
+	for i := range emails {
+		r := new(EnglishReportSendEmailRequest)
+		r.EmailId = emails[i].Id
+		r.Email = strings.Replace(emails[i].Email, " ", "", -1)
+		r.Subject = "Horizon Insights x Fastmarkets x FGE: 2024 Macro & Commodities Outlook - Registration Open!" // TODO:这是主题
+		r.FromAlias = "Horizon FICC"                                                                              // TODO:这是推送人(中文)
+
+		r.HtmlBody = template
+		sendData = append(sendData, r)
+	}
+	if len(sendData) == 0 {
+		fmt.Println("无邮件可推送")
+		return
+	}
+
+	// 请求阿里云接口批量推送
+	aliEmail := new(AliyunEmail)
+	resultList, e := aliEmail.BatchSendEmail(sendData)
+	if e != nil {
+		fmt.Println("批量推送失败, Err: " + e.Error())
+		return
+	}
+	for _, r := range resultList {
+		utils.FileLog.Info("email: %s, ok: %v, res: %s", r.Email, r.Ok, r.ResultData)
+		if r.Ok {
+			fmt.Println("发送成功")
+		} else {
+			fmt.Println("发送失败:" + r.ResultData)
+		}
+	}
+}
+
 type SendEmailReq struct {
 	Title   string   `description:"标题"`
 	Content string   `description:"内容"`

+ 1 - 1
services/excel_info.go

@@ -52,7 +52,7 @@ func UpdateExcelEditMark(excelInfoId, nowUserId, status int, nowUserName string)
 		if opUserId > 0 {
 			utils.Rc.Do("SETEX", key, int64(300), string(bt)) //3分钟缓存
 		} else {
-			utils.Rc.SetNX(key, string(bt), time.Second*60*5) //3分钟缓存
+			utils.Rc.SetNX(key, string(bt), time.Second*60*3) //3分钟缓存
 		}
 	} else if status == 0 {
 		//清除编辑缓存

+ 23 - 12
services/file.go

@@ -4,6 +4,7 @@ import (
 	"errors"
 	"eta/eta_api/models"
 	"eta/eta_api/utils"
+	"fmt"
 	"io"
 	"mime/multipart"
 	"os"
@@ -29,18 +30,28 @@ func UploadToOssAndFileName(fileMulti multipart.File, newFileName string) (resou
 	}
 
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		resourceUrl, err = UploadImgToMinIo(newFileName, fpath)
-		if err != nil {
-			err = errors.New("文件上传失败,Err:" + err.Error())
-			return
-		}
-	} else {
-		resourceUrl, err = UploadAliyunV2(newFileName, fpath)
-		if err != nil {
-			err = errors.New("文件上传失败,Err:" + err.Error())
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	resourceUrl, err = UploadImgToMinIo(newFileName, fpath)
+	//	if err != nil {
+	//		err = errors.New("文件上传失败,Err:" + err.Error())
+	//		return
+	//	}
+	//} else {
+	//	resourceUrl, err = UploadAliyunV2(newFileName, fpath)
+	//	if err != nil {
+	//		err = errors.New("文件上传失败,Err:" + err.Error())
+	//		return
+	//	}
+	//}
+	ossClient := NewOssClient()
+	if ossClient == nil {
+		err = fmt.Errorf("初始化OSS服务失败")
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(newFileName, fpath, "")
+	if err != nil {
+		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
+		return
 	}
 
 	defer func() {

+ 399 - 290
services/minio.go

@@ -7,163 +7,402 @@ import (
 	"github.com/minio/minio-go/v7"
 	"github.com/minio/minio-go/v7/pkg/credentials"
 	"log"
-	"os"
 	"time"
 )
 
-func GetMinIOSTSToken() (item *Token, err error) {
-	// MinIO服务的访问信息
-	item = new(Token)
-	//useSSL := false
-	//if utils.MinIoUseSSL == "true" {
-	//	useSSL = true
-	//}
-	// 创建MinIO客户端
-	//minioClient, err := minio.New(utils.MinIoEndpoint, &minio.Options{
-	//	Creds:  credentials.NewStaticV4(utils.MinIoAccessKeyId, utils.MinIoAccessKeySecret, ""),
-	//	Secure: useSSL,
-	//})
-	//if err != nil {
-	//	return nil, err
-	//}
-	// 设置STS凭证请求参数
-	//policy := `{
-	//    "Version": "2012-10-17",
-	//    "Statement": [
-	//        {
-	//            "Sid": "",
-	//            "Effect": "Allow",
-	//            "Principal": {"AWS": "arn:aws:iam::1234567890:root"},
-	//            "Action": "s3:GetObject",
-	//            "Resource": "arn:aws:s3:::<YourBucketName>/*"
-	//        }
-	//    ]
-	//}`
-	//expiry := time.Hour * 24 // STS凭证的过期时间
-	//获取STS凭证
-	//stsCredentials, err := minioClient.PresignedPutObject(context.Background(), "etastatic", "myobject", expiry)
-	//if err != nil {
-	//	return
-	//}
-	item.AccessKeyId = utils.MinIoAccessKeyId
-	item.SecretKeyId = utils.MinIoAccessKeySecret
-	item.Endpoint = utils.MinIoEndpoint
-	item.ImgHost = utils.MinIoImghost
-	item.Bucketname = utils.MinIoBucketname
-	item.UseSSL = utils.MinIoUseSSL
-	item.RegionId = utils.MinIoRegion
-	item.Port = utils.MinIoPort
-	return
-}
+//func GetMinIOSTSToken() (item *Token, err error) {
+//	// MinIO服务的访问信息
+//	item = new(Token)
+//	//useSSL := false
+//	//if utils.MinIoUseSSL == "true" {
+//	//	useSSL = true
+//	//}
+//	// 创建MinIO客户端
+//	//minioClient, err := minio.New(utils.MinIoEndpoint, &minio.Options{
+//	//	Creds:  credentials.NewStaticV4(utils.MinIoAccessKeyId, utils.MinIoAccessKeySecret, ""),
+//	//	Secure: useSSL,
+//	//})
+//	//if err != nil {
+//	//	return nil, err
+//	//}
+//	// 设置STS凭证请求参数
+//	//policy := `{
+//	//    "Version": "2012-10-17",
+//	//    "Statement": [
+//	//        {
+//	//            "Sid": "",
+//	//            "Effect": "Allow",
+//	//            "Principal": {"AWS": "arn:aws:iam::1234567890:root"},
+//	//            "Action": "s3:GetObject",
+//	//            "Resource": "arn:aws:s3:::<YourBucketName>/*"
+//	//        }
+//	//    ]
+//	//}`
+//	//expiry := time.Hour * 24 // STS凭证的过期时间
+//	//获取STS凭证
+//	//stsCredentials, err := minioClient.PresignedPutObject(context.Background(), "etastatic", "myobject", expiry)
+//	//if err != nil {
+//	//	return
+//	//}
+//	item.AccessKeyId = utils.MinIoAccessKeyId
+//	item.SecretKeyId = utils.MinIoAccessKeySecret
+//	item.Endpoint = utils.MinIoEndpoint
+//	item.ImgHost = utils.MinIoImghost
+//	item.Bucketname = utils.MinIoBucketname
+//	item.UseSSL = utils.MinIoUseSSL
+//	item.RegionId = utils.MinIoRegion
+//	item.Port = utils.MinIoPort
+//	return
+//}
 
-type Token struct {
-	AccessKeyId string
-	SecretKeyId string
-	RegionId    string
-	Bucketname  string
-	Endpoint    string
-	ImgHost     string
-	UseSSL      string
-	Port        string
-}
+//type Token struct {
+//	AccessKeyId string
+//	SecretKeyId string
+//	RegionId    string
+//	Bucketname  string
+//	Endpoint    string
+//	ImgHost     string
+//	UseSSL      string
+//	Port        string
+//}
 
-func UploadMinIo() {
-	ctx := context.Background()
-	endpoint := "8.136.199.33:9000/"
-	accessKeyID := "LfQ8uiJiLP7vLxjRrmNW"
-	secretAccessKey := "IszGVHsNicJMQxHC46cYFtbrOiapo0ynwOIJ6c2R"
-	useSSL := false
+//func UploadMinIo() {
+//	ctx := context.Background()
+//	endpoint := "8.136.199.33:9000/"
+//	accessKeyID := "LfQ8uiJiLP7vLxjRrmNW"
+//	secretAccessKey := "IszGVHsNicJMQxHC46cYFtbrOiapo0ynwOIJ6c2R"
+//	useSSL := false
+//
+//	// Initialize minio client object.
+//	minioClient, err := minio.New(endpoint, &minio.Options{
+//		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+//		Secure: useSSL,
+//	})
+//	if err != nil {
+//		log.Fatalln(err)
+//	}
+//
+//	// Make a new bucket called mymusic.
+//	bucketName := "etastatic"
+//	location := "/"
+//
+//	err = minioClient.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{Region: location})
+//	if err != nil {
+//		// Check to see if we already own this bucket (which happens if you run this twice)
+//		exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
+//		if errBucketExists == nil && exists {
+//			log.Printf("We already own %s\n", bucketName)
+//		} else {
+//			log.Fatalln(err)
+//		}
+//	} else {
+//		log.Printf("Successfully created %s\n", bucketName)
+//	}
+//	//buckets, err := minioClient.ListBuckets(ctx)
+//	//for _, bucket := range buckets {
+//	//	fmt.Println(bucket)
+//	//}
+//	// Upload the zip file
+//	objectName := "1111.xlsx"
+//	filePath := "/Users/xi/Desktop/1111.xlsx"
+//	contentType := "application/xlsx"
+//
+//	// Upload the zip file with FPutObject
+//	info, err := minioClient.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{ContentType: contentType})
+//	if err != nil {
+//		log.Fatalln(err)
+//	}
+//
+//	log.Printf("Successfully uploaded %s of size %d\n", objectName, info.Size)
+//}
 
-	// Initialize minio client object.
-	minioClient, err := minio.New(endpoint, &minio.Options{
-		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
-		Secure: useSSL,
-	})
-	if err != nil {
-		log.Fatalln(err)
-	}
+// UploadImgToMinIo 图片上传
+//func UploadImgToMinIo(fileName, filePath string) (string, error) {
+//	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
+//		return "0", errors.New("MinIo信息未配置")
+//	}
+//
+//	ctx := context.Background()
+//	endpoint := utils.MinIoEndpoint
+//	accessKeyID := utils.MinIoAccessKeyId
+//	secretAccessKey := utils.MinIoAccessKeySecret
+//	useSSL := false
+//	if utils.MinIoUseSSL == "true" {
+//		useSSL = true
+//	}
+//	minioClient, err := minio.New(endpoint, &minio.Options{
+//		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+//		Secure: useSSL,
+//	})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "1", err
+//	}
+//	bucketName := utils.MinIoBucketname
+//	// Check to see if we already own this bucket (which happens if you run this twice)
+//	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
+//	if errBucketExists == nil && exists {
+//		log.Printf("We already own %s\n", bucketName)
+//	} else {
+//		log.Fatalln(err)
+//		return "2", err
+//	}
+//	path := utils.MinIoUploadDir + time.Now().Format("200601/20060102/")
+//	path += fileName
+//	// Upload the zip file with FPutObject
+//	//contentType := "application/xlsx"
+//	_, err = minioClient.FPutObject(ctx, bucketName, path, filePath, minio.PutObjectOptions{})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "3", err
+//	}
+//
+//	path = utils.MinIoImghost + path
+//	return path, err
+//}
 
-	// Make a new bucket called mymusic.
-	bucketName := "etastatic"
-	location := "/"
+// UploadAudioToMinIo 音频上传
+//func UploadAudioToMinIo(fileName, filePath string) (string, error) {
+//	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
+//		return "0", errors.New("MinIo信息未配置")
+//	}
+//
+//	ctx := context.Background()
+//	endpoint := utils.MinIoEndpoint
+//	accessKeyID := utils.MinIoAccessKeyId
+//	secretAccessKey := utils.MinIoAccessKeySecret
+//	useSSL := false
+//	if utils.MinIoUseSSL == "true" {
+//		useSSL = true
+//	}
+//	minioClient, err := minio.New(endpoint, &minio.Options{
+//		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+//		Secure: useSSL,
+//	})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "1", err
+//	}
+//	bucketName := utils.MinIoBucketname
+//	// Check to see if we already own this bucket (which happens if you run this twice)
+//	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
+//	if errBucketExists == nil && exists {
+//		log.Printf("We already own %s\n", bucketName)
+//	} else {
+//		log.Fatalln(err)
+//		return "2", err
+//	}
+//
+//	path := utils.MinIoUpload_Audio_Dir + time.Now().Format("200601/20060102/")
+//	path += fileName
+//
+//	// Upload the zip file with FPutObject
+//	//contentType := "application/xlsx"
+//	_, err = minioClient.FPutObject(ctx, bucketName, path, filePath, minio.PutObjectOptions{})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "3", err
+//	}
+//
+//	path = utils.MinIoImghost + path
+//	return path, err
+//}
 
-	err = minioClient.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{Region: location})
-	if err != nil {
-		// Check to see if we already own this bucket (which happens if you run this twice)
-		exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
-		if errBucketExists == nil && exists {
-			log.Printf("We already own %s\n", bucketName)
-		} else {
-			log.Fatalln(err)
-		}
-	} else {
-		log.Printf("Successfully created %s\n", bucketName)
-	}
-	//buckets, err := minioClient.ListBuckets(ctx)
-	//for _, bucket := range buckets {
-	//	fmt.Println(bucket)
-	//}
-	// Upload the zip file
-	objectName := "1111.xlsx"
-	filePath := "/Users/xi/Desktop/1111.xlsx"
-	contentType := "application/xlsx"
+// UploadVideoToMinIo 视频上传
+//func UploadVideoToMinIo(filename, filePath, savePath string) error {
+//	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
+//		return errors.New("MinIo信息未配置")
+//	}
+//	defer func() {
+//		os.Remove(filePath)
+//	}()
+//
+//	ctx := context.Background()
+//	endpoint := utils.MinIoEndpoint
+//	accessKeyID := utils.MinIoAccessKeyId
+//	secretAccessKey := utils.MinIoAccessKeySecret
+//	useSSL := false
+//	if utils.MinIoUseSSL == "true" {
+//		useSSL = true
+//	}
+//	minioClient, err := minio.New(endpoint, &minio.Options{
+//		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+//		Secure: useSSL,
+//	})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return err
+//	}
+//	bucketName := utils.MinIoBucketname
+//	// Check to see if we already own this bucket (which happens if you run this twice)
+//	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
+//	if errBucketExists == nil && exists {
+//		log.Printf("We already own %s\n", bucketName)
+//	} else {
+//		log.Fatalln(err)
+//		return err
+//	}
+//
+//	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+//	//path += filename
+//	_, err = minioClient.FPutObject(ctx, bucketName, savePath, filePath, minio.PutObjectOptions{})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return err
+//	}
+//	//path = utils.Imghost + path
+//	//return path,err
+//	return err
+//}
 
-	// Upload the zip file with FPutObject
-	info, err := minioClient.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{ContentType: contentType})
-	if err != nil {
-		log.Fatalln(err)
-	}
+// UploadFileToMinIo 上传文件
+//func UploadFileToMinIo(filename, filePath, savePath string) error {
+//	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
+//		return errors.New("MinIo信息未配置")
+//	}
+//	defer func() {
+//		os.Remove(filePath)
+//	}()
+//	ctx := context.Background()
+//	endpoint := utils.MinIoEndpoint
+//	accessKeyID := utils.MinIoAccessKeyId
+//	secretAccessKey := utils.MinIoAccessKeySecret
+//	useSSL := false
+//	if utils.MinIoUseSSL == "true" {
+//		useSSL = true
+//	}
+//	minioClient, err := minio.New(endpoint, &minio.Options{
+//		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+//		Secure: useSSL,
+//	})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return err
+//	}
+//	bucketName := utils.MinIoBucketname
+//	// Check to see if we already own this bucket (which happens if you run this twice)
+//	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
+//	if errBucketExists == nil && exists {
+//		log.Printf("We already own %s\n", bucketName)
+//	} else {
+//		log.Fatalln(err)
+//		return err
+//	}
+//	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+//	//path += filename
+//	_, err = minioClient.FPutObject(ctx, bucketName, savePath, filePath, minio.PutObjectOptions{})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return err
+//	}
+//	//path = utils.Imghost + path
+//	//return path,err
+//	return err
+//}
 
-	log.Printf("Successfully uploaded %s of size %d\n", objectName, info.Size)
-}
+// UploadMinIoToDir 上传至hzchart
+//func UploadMinIoToDir(filename, filePath, uploadDir, fileDir string) (string, error) {
+//	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
+//		return "0", errors.New("MinIo信息未配置")
+//	}
+//	ctx := context.Background()
+//	endpoint := utils.MinIoEndpoint
+//	accessKeyID := utils.MinIoAccessKeyId
+//	secretAccessKey := utils.MinIoAccessKeySecret
+//	useSSL := false
+//	if utils.MinIoUseSSL == "true" {
+//		useSSL = true
+//	}
+//	minioClient, err := minio.New(endpoint, &minio.Options{
+//		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+//		Secure: useSSL,
+//	})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "1", err
+//	}
+//	bucketName := utils.MinIoBucketname
+//	// Check to see if we already own this bucket (which happens if you run this twice)
+//	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
+//	if errBucketExists == nil && exists {
+//		log.Printf("We already own %s\n", bucketName)
+//	} else {
+//		log.Fatalln(err)
+//		return "2", err
+//	}
+//	if uploadDir == "" {
+//		uploadDir = utils.MinIoUploadDir
+//	}
+//	if fileDir == "" {
+//		fileDir = time.Now().Format("200601/20060102/")
+//	}
+//	path := uploadDir + fileDir
+//	path += filename
+//	_, err = minioClient.FPutObject(ctx, bucketName, path, filePath, minio.PutObjectOptions{})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "3", err
+//	}
+//	path = utils.MinIoImghost + path
+//	return path, err
+//}
 
-// UploadImgToMinIo 图片上传
-func UploadImgToMinIo(fileName, filePath string) (string, error) {
-	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
-		return "0", errors.New("MinIo信息未配置")
-	}
+//func UploadImgToMinIoTest(fileName, filePath string) (string, error) {
+//	ctx := context.Background()
+//	endpoint := utils.Endpoint
+//	accessKeyID := utils.AccessKeyId
+//	secretAccessKey := utils.AccessKeySecret
+//	useSSL := false
+//	if utils.MinIoUseSSL == "true" {
+//		useSSL = true
+//	}
+//	minioClient, err := minio.New(endpoint, &minio.Options{
+//		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
+//		Secure: useSSL,
+//	})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "1", err
+//	}
+//	bucketName := utils.Bucketname
+//	// Check to see if we already own this bucket (which happens if you run this twice)
+//
+//	buckets, e := minioClient.ListBuckets(ctx)
+//	if e != nil {
+//		fmt.Println("ListBuckets: ", e.Error())
+//		return "", e
+//	}
+//	for k := range buckets {
+//		fmt.Println(k)
+//	}
+//
+//	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
+//	fmt.Println("exists: ", exists)
+//	fmt.Println("errBucketExists: ", errBucketExists)
+//	if errBucketExists == nil && exists {
+//		log.Printf("We already own %s\n", bucketName)
+//	} else {
+//		log.Fatalln(err)
+//		return "2", err
+//	}
+//	path := utils.UploadDir + time.Now().Format("200601/20060102/")
+//	path += fileName
+//	// Upload the zip file with FPutObject
+//	//contentType := "application/xlsx"
+//	_, err = minioClient.FPutObject(ctx, bucketName, path, filePath, minio.PutObjectOptions{})
+//	if err != nil {
+//		log.Fatalln(err)
+//		return "3", err
+//	}
+//
+//	path = utils.Imghost + path
+//	return path, err
+//}
 
-	ctx := context.Background()
-	endpoint := utils.MinIoEndpoint
-	accessKeyID := utils.MinIoAccessKeyId
-	secretAccessKey := utils.MinIoAccessKeySecret
-	useSSL := false
-	if utils.MinIoUseSSL == "true" {
-		useSSL = true
-	}
-	minioClient, err := minio.New(endpoint, &minio.Options{
-		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
-		Secure: useSSL,
-	})
-	if err != nil {
-		log.Fatalln(err)
-		return "1", err
-	}
-	bucketName := utils.MinIoBucketname
-	// Check to see if we already own this bucket (which happens if you run this twice)
-	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
-	if errBucketExists == nil && exists {
-		log.Printf("We already own %s\n", bucketName)
-	} else {
-		log.Fatalln(err)
-		return "2", err
-	}
-	path := utils.MinIoUploadDir + time.Now().Format("200601/20060102/")
-	path += fileName
-	// Upload the zip file with FPutObject
-	//contentType := "application/xlsx"
-	_, err = minioClient.FPutObject(ctx, bucketName, path, filePath, minio.PutObjectOptions{})
-	if err != nil {
-		log.Fatalln(err)
-		return "3", err
-	}
-
-	path = utils.MinIoImghost + path
-	return path, err
-}
+type MinioOss struct{}
 
-// UploadAudioToMinIo 音频上传
-func UploadAudioToMinIo(fileName, filePath string) (string, error) {
+// UploadFile 上传文件
+func (m *MinioOss) UploadFile(fileName, filePath, savePath string) (string, error) {
 	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
 		return "0", errors.New("MinIo信息未配置")
 	}
@@ -185,7 +424,6 @@ func UploadAudioToMinIo(fileName, filePath string) (string, error) {
 		return "1", err
 	}
 	bucketName := utils.MinIoBucketname
-	// Check to see if we already own this bucket (which happens if you run this twice)
 	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
 	if errBucketExists == nil && exists {
 		log.Printf("We already own %s\n", bucketName)
@@ -194,156 +432,27 @@ func UploadAudioToMinIo(fileName, filePath string) (string, error) {
 		return "2", err
 	}
 
-	path := utils.MinIoUpload_Audio_Dir + time.Now().Format("200601/20060102/")
-	path += fileName
-
-	// Upload the zip file with FPutObject
-	//contentType := "application/xlsx"
+	path := savePath
+	if savePath == "" {
+		path = utils.MinIoUploadDir + time.Now().Format("200601/20060102/") + fileName
+	}
 	_, err = minioClient.FPutObject(ctx, bucketName, path, filePath, minio.PutObjectOptions{})
 	if err != nil {
 		log.Fatalln(err)
 		return "3", err
 	}
-
-	path = utils.MinIoImghost + path
-	return path, err
+	resourceUrl := utils.MinIoImghost + path
+	return resourceUrl, err
 }
 
-// UploadVideoToMinIo 视频上传
-func UploadVideoToMinIo(filename, filePath, savePath string) error {
-	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
-		return errors.New("MinIo信息未配置")
-	}
-	defer func() {
-		os.Remove(filePath)
-	}()
-
-	ctx := context.Background()
-	endpoint := utils.MinIoEndpoint
-	accessKeyID := utils.MinIoAccessKeyId
-	secretAccessKey := utils.MinIoAccessKeySecret
-	useSSL := false
-	if utils.MinIoUseSSL == "true" {
-		useSSL = true
-	}
-	minioClient, err := minio.New(endpoint, &minio.Options{
-		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
-		Secure: useSSL,
-	})
-	if err != nil {
-		log.Fatalln(err)
-		return err
-	}
-	bucketName := utils.MinIoBucketname
-	// Check to see if we already own this bucket (which happens if you run this twice)
-	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
-	if errBucketExists == nil && exists {
-		log.Printf("We already own %s\n", bucketName)
-	} else {
-		log.Fatalln(err)
-		return err
-	}
-
-	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
-	//path += filename
-	_, err = minioClient.FPutObject(ctx, bucketName, savePath, filePath, minio.PutObjectOptions{})
-	if err != nil {
-		log.Fatalln(err)
-		return err
-	}
-	//path = utils.Imghost + path
-	//return path,err
-	return err
-}
-
-// UploadFileToMinIo 上传文件
-func UploadFileToMinIo(filename, filePath, savePath string) error {
-	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
-		return errors.New("MinIo信息未配置")
-	}
-	defer func() {
-		os.Remove(filePath)
-	}()
-	ctx := context.Background()
-	endpoint := utils.MinIoEndpoint
-	accessKeyID := utils.MinIoAccessKeyId
-	secretAccessKey := utils.MinIoAccessKeySecret
-	useSSL := false
-	if utils.MinIoUseSSL == "true" {
-		useSSL = true
-	}
-	minioClient, err := minio.New(endpoint, &minio.Options{
-		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
-		Secure: useSSL,
-	})
-	if err != nil {
-		log.Fatalln(err)
-		return err
-	}
-	bucketName := utils.MinIoBucketname
-	// Check to see if we already own this bucket (which happens if you run this twice)
-	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
-	if errBucketExists == nil && exists {
-		log.Printf("We already own %s\n", bucketName)
-	} else {
-		log.Fatalln(err)
-		return err
-	}
-	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
-	//path += filename
-	_, err = minioClient.FPutObject(ctx, bucketName, savePath, filePath, minio.PutObjectOptions{})
-	if err != nil {
-		log.Fatalln(err)
-		return err
-	}
-	//path = utils.Imghost + path
-	//return path,err
-	return err
-}
-
-// UploadMinIoToDir 上传至hzchart
-func UploadMinIoToDir(filename, filePath, uploadDir, fileDir string) (string, error) {
-	if utils.MinIoAccessKeyId == `` || utils.MinIoAccessKeySecret == `` {
-		return "0", errors.New("MinIo信息未配置")
-	}
-	ctx := context.Background()
-	endpoint := utils.MinIoEndpoint
-	accessKeyID := utils.MinIoAccessKeyId
-	secretAccessKey := utils.MinIoAccessKeySecret
-	useSSL := false
-	if utils.MinIoUseSSL == "true" {
-		useSSL = true
-	}
-	minioClient, err := minio.New(endpoint, &minio.Options{
-		Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
-		Secure: useSSL,
-	})
-	if err != nil {
-		log.Fatalln(err)
-		return "1", err
-	}
-	bucketName := utils.MinIoBucketname
-	// Check to see if we already own this bucket (which happens if you run this twice)
-	exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
-	if errBucketExists == nil && exists {
-		log.Printf("We already own %s\n", bucketName)
-	} else {
-		log.Fatalln(err)
-		return "2", err
-	}
-	if uploadDir == "" {
-		uploadDir = utils.MinIoUploadDir
-	}
-	if fileDir == "" {
-		fileDir = time.Now().Format("200601/20060102/")
-	}
-	path := uploadDir + fileDir
-	path += filename
-	_, err = minioClient.FPutObject(ctx, bucketName, path, filePath, minio.PutObjectOptions{})
-	if err != nil {
-		log.Fatalln(err)
-		return "3", err
-	}
-	path = utils.MinIoImghost + path
-	return path, err
+func (m *MinioOss) GetUploadToken() (token OssToken, err error) {
+	token.AccessKeyId = utils.MinIoAccessKeyId
+	token.SecretKeyId = utils.MinIoAccessKeySecret
+	token.Endpoint = utils.MinIoEndpoint
+	token.ImgHost = utils.MinIoImghost
+	token.Bucketname = utils.MinIoBucketname
+	token.UseSSL = utils.MinIoUseSSL
+	token.RegionId = utils.MinIoRegion
+	token.Port = utils.MinIoPort
+	return
 }

+ 149 - 104
services/oss.go

@@ -4,8 +4,8 @@ import (
 	"encoding/json"
 	"errors"
 	"eta/eta_api/services/alarm_msg"
+	"fmt"
 	"github.com/aliyun/aliyun-oss-go-sdk/oss"
-	"os"
 	"time"
 
 	"eta/eta_api/utils"
@@ -13,104 +13,104 @@ import (
 )
 
 // UploadAliyunV2 图片上传到阿里云
-func UploadAliyunV2(filename, filepath string) (string, error) {
-	if utils.AccessKeyId == `` {
-		return "0", errors.New("阿里云信息未配置")
-	}
-	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
-	if err != nil {
-		return "1", err
-	}
-	bucket, err := client.Bucket(utils.Bucketname)
-	if err != nil {
-		return "2", err
-	}
-	path := utils.UploadDir + time.Now().Format("200601/20060102/")
-	path += filename
-	err = bucket.PutObjectFromFile(path, filepath)
-	if err != nil {
-		return "3", err
-	}
-	path = utils.Imghost + path
-	return path, err
-}
+//func UploadAliyunV2(filename, filepath string) (string, error) {
+//	if utils.AccessKeyId == `` {
+//		return "0", errors.New("阿里云信息未配置")
+//	}
+//	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+//	if err != nil {
+//		return "1", err
+//	}
+//	bucket, err := client.Bucket(utils.Bucketname)
+//	if err != nil {
+//		return "2", err
+//	}
+//	path := utils.UploadDir + time.Now().Format("200601/20060102/")
+//	path += filename
+//	err = bucket.PutObjectFromFile(path, filepath)
+//	if err != nil {
+//		return "3", err
+//	}
+//	path = utils.Imghost + path
+//	return path, err
+//}
 
 // UploadAudioAliyun 音频上传到阿里云
-func UploadAudioAliyun(filename, filepath string) (string, error) {
-	if utils.AccessKeyId == `` {
-		return "0", errors.New("阿里云信息未配置")
-	}
-	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
-	if err != nil {
-		return "1", err
-	}
-	bucket, err := client.Bucket(utils.Bucketname)
-	if err != nil {
-		return "2", err
-	}
-	path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
-	path += filename
-	err = bucket.PutObjectFromFile(path, filepath)
-	if err != nil {
-		return "3", err
-	}
-	path = utils.Imghost + path
-	return path, err
-}
+//func UploadAudioAliyun(filename, filepath string) (string, error) {
+//	if utils.AccessKeyId == `` {
+//		return "0", errors.New("阿里云信息未配置")
+//	}
+//	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+//	if err != nil {
+//		return "1", err
+//	}
+//	bucket, err := client.Bucket(utils.Bucketname)
+//	if err != nil {
+//		return "2", err
+//	}
+//	path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+//	path += filename
+//	err = bucket.PutObjectFromFile(path, filepath)
+//	if err != nil {
+//		return "3", err
+//	}
+//	path = utils.Imghost + path
+//	return path, err
+//}
 
 // UploadVideoAliyun 视频上传到阿里云
-func UploadVideoAliyun(filename, filepath, savePath string) error {
-	if utils.AccessKeyId == `` {
-		return errors.New("阿里云信息未配置")
-	}
-	defer func() {
-		os.Remove(filepath)
-	}()
-	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
-	if err != nil {
-		return err
-	}
-	bucket, err := client.Bucket(utils.Bucketname)
-	if err != nil {
-		return err
-	}
-	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
-	//path += filename
-	err = bucket.PutObjectFromFile(savePath, filepath)
-	if err != nil {
-		return err
-	}
-	//path = utils.Imghost + path
-	//return path,err
-	return err
-}
+//func UploadVideoAliyun(filename, filepath, savePath string) error {
+//	if utils.AccessKeyId == `` {
+//		return errors.New("阿里云信息未配置")
+//	}
+//	defer func() {
+//		os.Remove(filepath)
+//	}()
+//	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+//	if err != nil {
+//		return err
+//	}
+//	bucket, err := client.Bucket(utils.Bucketname)
+//	if err != nil {
+//		return err
+//	}
+//	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+//	//path += filename
+//	err = bucket.PutObjectFromFile(savePath, filepath)
+//	if err != nil {
+//		return err
+//	}
+//	//path = utils.Imghost + path
+//	//return path,err
+//	return err
+//}
 
 // UploadFileToAliyun 上传文件到阿里云
-func UploadFileToAliyun(filename, filepath, savePath string) error {
-	if utils.AccessKeyId == `` {
-		return errors.New("阿里云信息未配置")
-	}
-	defer func() {
-		os.Remove(filepath)
-	}()
-	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
-	if err != nil {
-		return err
-	}
-	bucket, err := client.Bucket(utils.Bucketname)
-	if err != nil {
-		return err
-	}
-	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
-	//path += filename
-	err = bucket.PutObjectFromFile(savePath, filepath)
-	if err != nil {
-		return err
-	}
-	//path = utils.Imghost + path
-	//return path,err
-	return err
-}
+//func UploadFileToAliyun(filename, filepath, savePath string) error {
+//	if utils.AccessKeyId == `` {
+//		return errors.New("阿里云信息未配置")
+//	}
+//	defer func() {
+//		os.Remove(filepath)
+//	}()
+//	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+//	if err != nil {
+//		return err
+//	}
+//	bucket, err := client.Bucket(utils.Bucketname)
+//	if err != nil {
+//		return err
+//	}
+//	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+//	//path += filename
+//	err = bucket.PutObjectFromFile(savePath, filepath)
+//	if err != nil {
+//		return err
+//	}
+//	//path = utils.Imghost + path
+//	//return path,err
+//	return err
+//}
 
 type STSToken struct {
 	AccessKeyId     string
@@ -223,7 +223,38 @@ func NewSTSToken() (item *STSToken, err error) {
 }
 
 // UploadAliyunToDir 上传至hzchart
-func UploadAliyunToDir(filename, filepath, uploadDir, fileDir string) (string, error) {
+//func UploadAliyunToDir(filename, filepath, uploadDir, fileDir string) (string, error) {
+//	if utils.AccessKeyId == `` {
+//		return "0", errors.New("阿里云信息未配置")
+//	}
+//	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+//	if err != nil {
+//		return "1", err
+//	}
+//	bucket, err := client.Bucket(utils.Bucketname)
+//	if err != nil {
+//		return "2", err
+//	}
+//	if uploadDir == "" {
+//		uploadDir = utils.UploadDir
+//	}
+//	if fileDir == "" {
+//		fileDir = time.Now().Format("200601/20060102/")
+//	}
+//	path := uploadDir + fileDir
+//	path += filename
+//	err = bucket.PutObjectFromFile(path, filepath)
+//	if err != nil {
+//		return "3", err
+//	}
+//	path = utils.Imghost + path
+//	return path, err
+//}
+
+type AliOss struct{}
+
+// UploadFile 上传文件
+func (m *AliOss) UploadFile(fileName, filePath, savePath string) (string, error) {
 	if utils.AccessKeyId == `` {
 		return "0", errors.New("阿里云信息未配置")
 	}
@@ -235,18 +266,32 @@ func UploadAliyunToDir(filename, filepath, uploadDir, fileDir string) (string, e
 	if err != nil {
 		return "2", err
 	}
-	if uploadDir == "" {
-		uploadDir = utils.UploadDir
-	}
-	if fileDir == "" {
-		fileDir = time.Now().Format("200601/20060102/")
+
+	path := savePath
+	if savePath == "" {
+		path = utils.UploadDir + time.Now().Format("200601/20060102/") + fileName
 	}
-	path := uploadDir + fileDir
-	path += filename
-	err = bucket.PutObjectFromFile(path, filepath)
+	err = bucket.PutObjectFromFile(path, filePath)
 	if err != nil {
 		return "3", err
 	}
-	path = utils.Imghost + path
-	return path, err
+	resourceUrl := utils.Imghost + path
+	return resourceUrl, err
+}
+
+func (m *AliOss) GetUploadToken() (token OssToken, err error) {
+	stsToken, e := GetOssSTSToken()
+	if e != nil {
+		err = fmt.Errorf("GetOssSTSToken err: %s", e.Error())
+		return
+	}
+	token.AccessKeyId = stsToken.AccessKeyId
+	token.AccessKeySecret = stsToken.AccessKeySecret
+	token.SecurityToken = stsToken.SecurityToken
+	token.ExpiredTime = stsToken.ExpiredTime
+	token.RegionId = stsToken.RegionId
+	token.Bucketname = stsToken.Bucketname
+	token.Endpoint = stsToken.Endpoint
+	token.Imghost = stsToken.Imghost
+	return
 }

+ 45 - 26
services/report.go

@@ -638,23 +638,31 @@ func reportBase64ToImg(imageBase64 string) (resourceUrl string, err error) {
 	savePath += fileName
 
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		err = UploadFileToMinIo(fileName, fpath, savePath)
-		if err != nil {
-			err = errors.New("文件上传失败" + err.Error())
-			return
-		}
-		resourceUrl = utils.MinIoImghost + savePath
-	} else {
-		err = UploadFileToAliyun(fileName, fpath, savePath)
-		if err != nil {
-			err = errors.New("文件上传失败" + err.Error())
-			return
-		}
-		resourceUrl = utils.Imghost + savePath
+	//if utils.ObjectStorageClient == "minio" {
+	//	err = UploadFileToMinIo(fileName, fpath, savePath)
+	//	if err != nil {
+	//		err = errors.New("文件上传失败" + err.Error())
+	//		return
+	//	}
+	//	resourceUrl = utils.MinIoImghost + savePath
+	//} else {
+	//	err = UploadFileToAliyun(fileName, fpath, savePath)
+	//	if err != nil {
+	//		err = errors.New("文件上传失败" + err.Error())
+	//		return
+	//	}
+	//	resourceUrl = utils.Imghost + savePath
+	//}
+	ossClient := NewOssClient()
+	if ossClient == nil {
+		err = fmt.Errorf("初始化OSS服务失败")
+		return
+	}
+	resourceUrl, err = ossClient.UploadFile(fileName, fpath, savePath)
+	if err != nil {
+		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
+		return
 	}
-
-
 
 	item := new(models.Resource)
 	item.ResourceUrl = resourceUrl
@@ -876,16 +884,27 @@ func PcCreateAndUploadSunCode(scene, page string) (imgUrl string, err error) {
 	fileDir := "yb/suncode/"
 
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		imgUrl, err = UploadMinIoToDir(fileName, fpath, "", fileDir)
-		if err != nil {
-			return
-		}
-	} else {
-		imgUrl, err = UploadAliyunToDir(fileName, fpath, "", fileDir)
-		if err != nil {
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	imgUrl, err = UploadMinIoToDir(fileName, fpath, "", fileDir)
+	//	if err != nil {
+	//		return
+	//	}
+	//} else {
+	//	imgUrl, err = UploadAliyunToDir(fileName, fpath, "", fileDir)
+	//	if err != nil {
+	//		return
+	//	}
+	//}
+	savePath := fileDir + time.Now().Format("200601/20060102/") + fileName
+	ossClient := NewOssClient()
+	if ossClient == nil {
+		err = fmt.Errorf("初始化OSS服务失败")
+		return
+	}
+	imgUrl, err = ossClient.UploadFile(fileName, fpath, savePath)
+	if err != nil {
+		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
+		return
 	}
 
 	if err != nil {

+ 44 - 25
services/video.go

@@ -100,18 +100,28 @@ func CreateVideo(report *models.ReportDetail) (err error) {
 
 	uploadUrl := ``
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		uploadUrl, err = UploadAudioToMinIo(saveName, savePath)
-		if err != nil {
-			err = errors.New("UploadAudioAliyun Err:" + err.Error())
-			return
-		}
-	} else {
-		uploadUrl, err = UploadAudioAliyun(saveName, savePath)
-		if err != nil {
-			err = errors.New("UploadAudioAliyun Err:" + err.Error())
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	uploadUrl, err = UploadAudioToMinIo(saveName, savePath)
+	//	if err != nil {
+	//		err = errors.New("UploadAudioAliyun Err:" + err.Error())
+	//		return
+	//	}
+	//} else {
+	//	uploadUrl, err = UploadAudioAliyun(saveName, savePath)
+	//	if err != nil {
+	//		err = errors.New("UploadAudioAliyun Err:" + err.Error())
+	//		return
+	//	}
+	//}
+	ossClient := NewOssClient()
+	if ossClient == nil {
+		err = fmt.Errorf("初始化OSS服务失败")
+		return
+	}
+	uploadUrl, err = ossClient.UploadFile(saveName, savePath, "")
+	if err != nil {
+		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
+		return
 	}
 
 	fileBody, err := ioutil.ReadFile(savePath)
@@ -300,20 +310,29 @@ func CreateReportVideo(reportTitle, reportContent, reportTime string) (uploadUrl
 		time.Sleep(5 * time.Second)
 	}
 
-
 	//上传到阿里云 和 minio
-	if utils.ObjectStorageClient == "minio" {
-		uploadUrl, err = UploadAudioToMinIo(saveName, savePath)
-		if err != nil {
-			err = errors.New("UploadAudioAliyun Err:" + err.Error())
-			return
-		}
-	} else {
-		uploadUrl, err = UploadAudioAliyun(saveName, savePath)
-		if err != nil {
-			err = errors.New("UploadAudioAliyun Err:" + err.Error())
-			return
-		}
+	//if utils.ObjectStorageClient == "minio" {
+	//	uploadUrl, err = UploadAudioToMinIo(saveName, savePath)
+	//	if err != nil {
+	//		err = errors.New("UploadAudioAliyun Err:" + err.Error())
+	//		return
+	//	}
+	//} else {
+	//	uploadUrl, err = UploadAudioAliyun(saveName, savePath)
+	//	if err != nil {
+	//		err = errors.New("UploadAudioAliyun Err:" + err.Error())
+	//		return
+	//	}
+	//}
+	ossClient := NewOssClient()
+	if ossClient == nil {
+		err = fmt.Errorf("初始化OSS服务失败")
+		return
+	}
+	uploadUrl, err = ossClient.UploadFile(saveName, savePath, "")
+	if err != nil {
+		err = fmt.Errorf("文件上传失败, Err: %s", err.Error())
+		return
 	}
 
 	fileBody, err := ioutil.ReadFile(savePath)

+ 28 - 0
utils/config.go

@@ -213,6 +213,20 @@ var (
 	EtaSecret string
 )
 
+// S3配置
+var (
+	S3Endpoint        string
+	S3BucketName      string
+	S3UploadDir       string
+	S3AccessKeyId     string
+	S3AccessKeySecret string
+	S3Host            string
+	S3Region          string
+	S3ForceStyle      string
+	S3EndpointPort    string
+	S3Protocol        string
+)
+
 func init() {
 	tmpRunMode, err := web.AppConfig.String("run_mode")
 	if err != nil {
@@ -471,6 +485,20 @@ func init() {
 		MinIoRegion = config["minio_region"]
 	}
 
+	// S3-OSS相关
+	{
+		S3Endpoint = config["s3_endpoint"]
+		S3BucketName = config["s3_bucket_name"]
+		S3Host = config["s3_host"]
+		S3AccessKeyId = config["s3_access_key_id"]
+		S3AccessKeySecret = config["s3_access_key_secret"]
+		S3UploadDir = config["s3_upload_dir"]
+		S3Region = config["s3_region"]
+		S3ForceStyle = config["s3_force_style"]
+		S3EndpointPort = config["s3_endpoint_port"]
+		S3Protocol = config["s3_protocol"]
+	}
+
 	// 生成长图服务地址
 	PythonUrlReport2Img = config["python_url_report2img"]
 

+ 8 - 0
utils/constants.go

@@ -168,6 +168,7 @@ const (
 	DATA_SOURCE_PREDICT_CALCULATE_ZSXY                          // 预测指数修匀->73
 	DATA_SOURCE_CALCULATE_ZDYFX                                 // 自定义分析->74
 	DATA_SOURCE_CALCULATE_RJZ                                   // 日均值计算->75
+	DATA_SOURCE_GFEX                                 = 78       // 广州期货交易所->78
 )
 
 // 数据刷新频率
@@ -302,6 +303,7 @@ const (
 	CHART_TYPE_CURVE           = 1  //曲线图
 	CHART_TYPE_BAR             = 7  //柱形图
 	CHART_TYPE_SECTION_SCATTER = 10 //截面散点图样式
+	CHART_TYPE_RADAR           = 11 //雷达图
 )
 
 // 指标类型
@@ -351,6 +353,12 @@ const (
 	STORAGESOURCE_MINIO = 2 //MinIo
 )
 
+const (
+	STORAGESOURCE_OSS_NAME   = "oss"
+	STORAGESOURCE_MINIO_NAME = "minio"
+	STORAGESOURCE_S3_NAME    = "s3"
+)
+
 // DIR_MOD 目录创建权限
 const DIR_MOD fs.FileMode = 0766 // Unix permission bits