Browse Source

Merge branch 'master' into ETA1.9.5

jwyu 11 months ago
parent
commit
832b7b9b1f
100 changed files with 10550 additions and 483 deletions
  1. 6 2
      src/api/api.js
  2. 40 1
      src/api/modules/chartApi.js
  3. 153 11
      src/api/modules/chartRelevanceApi.js
  4. 65 2
      src/api/modules/dataApi.js
  5. 8 1
      src/api/modules/predictEdbApi.js
  6. 7 2
      src/api/modules/reportEnApi.js
  7. 429 0
      src/api/modules/reportV2.js
  8. 194 1
      src/api/modules/thirdBaseApi.js
  9. BIN
      src/assets/img/data_m/move_ico.png
  10. 1 0
      src/assets/img/icons/baseinfo_ico.svg
  11. BIN
      src/assets/img/icons/edb-stopping.png
  12. BIN
      src/assets/img/icons/formula-add.png
  13. 4 0
      src/assets/img/icons/preview_ico.svg
  14. 4 0
      src/assets/img/icons/publish_ico.svg
  15. 5 0
      src/assets/img/icons/save_ico.svg
  16. 4 0
      src/assets/img/icons/submit_ico.svg
  17. 4 0
      src/assets/img/icons/timing_ico.svg
  18. 14 0
      src/assets/img/icons/wx_round.svg
  19. 10 1
      src/components/antvVueComponents/tooltipCom.vue
  20. 32 8
      src/components/lzTable.vue
  21. 58 2
      src/lang/commonLang.js
  22. 52 0
      src/lang/modules/DataSources/En.js
  23. 51 0
      src/lang/modules/DataSources/Zh.js
  24. 16 0
      src/lang/modules/ETATables/commonLang.js
  25. 20 0
      src/lang/modules/EtaBase/En.js
  26. 20 0
      src/lang/modules/EtaBase/Zh.js
  27. 42 3
      src/lang/modules/EtaBase/commonLang.js
  28. 37 0
      src/lang/modules/EtaChart/En.js
  29. 34 0
      src/lang/modules/EtaChart/Zh.js
  30. 110 0
      src/lang/modules/EtaChart/commonLang.js
  31. 4 4
      src/lang/modules/ReportManagement/CategoryList.js
  32. 117 9
      src/lang/modules/ReportManagement/ReportList.js
  33. 4 4
      src/lang/modules/ReportManagement/SmartReport.js
  34. 4 2
      src/lang/modules/Slides/pptPresent.js
  35. 73 2
      src/lang/modules/StatisticAnalysis/ChartRelevance.js
  36. 59 0
      src/lang/modules/systemManage/DataRefresh.js
  37. 2 2
      src/lang/modules/systemManage/ReportApprove.js
  38. 5 2
      src/mixins/reportApproveConfig.js
  39. 11 0
      src/routes/modules/chartRoutes.js
  40. 16 0
      src/routes/modules/dataRoutes.js
  41. 28 16
      src/routes/modules/oldRoutes.js
  42. 7 0
      src/styles/global.scss
  43. 21 1
      src/utils/buttonConfig.js
  44. 12 0
      src/utils/common.js
  45. 2 3
      src/views/Home.vue
  46. 1 1
      src/views/Login.vue
  47. 4 4
      src/views/approve_manage/approveDetail.vue
  48. 14 8
      src/views/approve_manage/approveEdit.vue
  49. 2 2
      src/views/approve_manage/components/flowNode/approveNode.vue
  50. 1 1
      src/views/approve_manage/mixins/approveMixins.js
  51. 61 19
      src/views/chartRelevance_manage/components/chartCard.vue
  52. 10 2
      src/views/chartRelevance_manage/components/explainText.js
  53. 111 0
      src/views/chartRelevance_manage/components/saveChartSetting.vue
  54. 44 8
      src/views/chartRelevance_manage/components/saveChartTobaseDia.vue
  55. 2 2
      src/views/chartRelevance_manage/components/saveEdbToBaseDia.vue
  56. 5 0
      src/views/chartRelevance_manage/components/selectTarget.vue
  57. 7 6
      src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue
  58. 4 1
      src/views/chartRelevance_manage/css/index.scss
  59. 18 8
      src/views/chartRelevance_manage/mixins/classifyMixin.js
  60. 210 0
      src/views/chartRelevance_manage/relevance/components/batchSelectFormula.vue
  61. 257 0
      src/views/chartRelevance_manage/relevance/components/batchSelectTable.vue
  62. 38 0
      src/views/chartRelevance_manage/relevance/components/formMixin.js
  63. 137 0
      src/views/chartRelevance_manage/relevance/components/modifyClassifyDialog.vue
  64. 616 0
      src/views/chartRelevance_manage/relevance/components/multipleIndForm.vue
  65. 268 0
      src/views/chartRelevance_manage/relevance/components/singleIndForm.vue
  66. 294 23
      src/views/chartRelevance_manage/relevance/list.vue
  67. 1089 0
      src/views/chartRelevance_manage/relevance/relevanceChartEditorV2.vue
  68. 111 0
      src/views/chartRelevance_manage/relevance/utils/config.js
  69. 70 0
      src/views/chartRelevance_manage/relevance/utils/index.js
  70. 28 14
      src/views/classify_manage/chapterSettingV2.vue
  71. 11 2
      src/views/classify_manage/classifyEnlistV2.vue
  72. 142 29
      src/views/classify_manage/classifylistV2.vue
  73. 36 11
      src/views/dataEntry_manage/addChart.vue
  74. 35 11
      src/views/dataEntry_manage/chartSetting.vue
  75. 46 2
      src/views/dataEntry_manage/codecount/index.vue
  76. 17 4
      src/views/dataEntry_manage/components/SaveChartOther.vue
  77. 180 0
      src/views/dataEntry_manage/components/addAverageDialog.vue
  78. 490 115
      src/views/dataEntry_manage/components/addMarkerDialog.vue
  79. 319 0
      src/views/dataEntry_manage/components/addRightEdbDialog.vue
  80. 1 3
      src/views/dataEntry_manage/components/barOptionSection.vue
  81. 3 2
      src/views/dataEntry_manage/components/chartReleationEdbTable.vue
  82. 245 3
      src/views/dataEntry_manage/components/markersSection.vue
  83. 15 2
      src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue
  84. 1 1
      src/views/dataEntry_manage/databaseComponents/batchComputedV2.vue
  85. 24 7
      src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue
  86. 1 1
      src/views/dataEntry_manage/databaseComponents/operationDialog.vue
  87. 55 1
      src/views/dataEntry_manage/databaseList.vue
  88. 48 5
      src/views/dataEntry_manage/editChart.vue
  89. 180 20
      src/views/dataEntry_manage/mixins/addOreditMixin.js
  90. 189 41
      src/views/dataEntry_manage/mixins/chartPublic.js
  91. 387 0
      src/views/dataEntry_manage/thirdBase/Wind.vue
  92. 721 0
      src/views/dataEntry_manage/thirdBase/components/highFrequency/addHighFrequencyData.vue
  93. 473 0
      src/views/dataEntry_manage/thirdBase/components/highFrequency/addToIndexDatabaseBatch.vue
  94. 635 0
      src/views/dataEntry_manage/thirdBase/components/highFrequency/classifySetting.vue
  95. 1022 0
      src/views/dataEntry_manage/thirdBase/highFrequencyData.vue
  96. 2 2
      src/views/dataEntry_manage/thirdBase/selfDataBase.vue
  97. 7 5
      src/views/dataEntry_manage/thirdBase/steelChemicalbase.vue
  98. 70 32
      src/views/datasheet_manage/common/customTable.js
  99. 1 1
      src/views/datasheet_manage/components/BalanceAddChart.vue
  100. 7 5
      src/views/datasheet_manage/components/BalanceSheetChartItem.vue

+ 6 - 2
src/api/api.js

@@ -18,7 +18,9 @@ import {
   zczxInterface,
   coalWordInterface,
   bloombergInterface,
-  ccfDataInterface
+  ccfDataInterface,
+  windInterface,
+  highFrequencyDataInterface
 } from './modules/thirdBaseApi';
 
 //手工指标 手工数据 手工数据权限
@@ -128,7 +130,9 @@ export {
   zczxInterface,
   coalWordInterface,
   bloombergInterface,
-  ccfDataInterface
+  ccfDataInterface,
+  windInterface,
+  highFrequencyDataInterface
 };
 
 //老接口 研报 ppt等

+ 40 - 1
src/api/modules/chartApi.js

@@ -307,6 +307,15 @@ const dataBaseInterface = {
 	/* 刷新校验 */
 	updateCheck: params => {
 		return http.post('/datamanage/edb_info/updates/check',params)
+	},
+		/**
+	 * 设置指标刷新状态
+	 * @param {EdbInfoId} params 
+	 * @param {ModifyStatus} params 需要更改的状态:启用、暂停
+	 * @returns 
+	 */
+	edbRefreshStatusSet: params => {
+		return http.post('/datamanage/edb_info/single_refresh/status/save',params)
 	},
 	/**
 	 * 指标替换
@@ -411,10 +420,20 @@ const dataBaseInterface = {
 		return http.post('/datamanage/edb_info/batch/add',params)
 	},
 	// 批量计算指标时获取当前筛选条件下选择的指标
+	/**
+	 * @param {Object} params
+	 * @param {Number} params.EdbInfoType 0-指标;1-预测指标
+	 * @returns 
+	 */
 	getBatchFilterAddEdbList:params=>{
 		return http.get('/datamanage/edb_info/calculate/multi/choice',params)
 	},
 	//批量计算指标时待选指标的搜索列表
+	/**
+	 * @param {Object} params
+	 * @param {Number} params.EdbInfoType 0-指标;1-预测指标
+	 * @returns 
+	 */
 	getBatchAddEdbSearchList:params=>{
 		return http.get('/datamanage/edb_info/calculate/multi/search',params)
 	},
@@ -669,6 +688,15 @@ const dataBaseInterface = {
 		setChartImage: params => {
 			return http.post('/datamanage/chart_info/image/set',params)
 		},
+		/**
+		 * 设置图表缩略图 formData
+		 * @param {Img} string 
+		 * @param {Chartlnfold} number 
+		 * @returns 
+		 */
+		setChartThumbnail: params => {
+			return http.post('/datamanage/chart_info/image/set_by_svg',params)
+		},
 		/**
 		 * 通过unicode获取图表信息
 		 * @param {UniqueCode} params 
@@ -850,6 +878,9 @@ const dataBaseInterface = {
 	sectionScatterPreviewData: params => {
 		return http.post('/datamanage/chart_info/preview/time_section',params)
 	},
+	seasonPreviewData:params=>{
+		return http.post('/datamanage/chart_info/preview/season',params)
+	},
 
 	 /* 批量计算
 	 * @param {*} params 
@@ -962,7 +993,15 @@ const dataBaseInterface = {
 	saveEdbChartImg:(params)=>{
 		return http.post('/datamanage/edb_info/image/set',params)
 	},
-
+	/**
+	 * 设置图表缩略图 formData
+	 * @param {Number} EdbInfoId 
+	 * @param {String} Img 
+	 * @returns 
+	 */
+	saveEdbChartThumbnail:(params)=>{
+		return http.post('/datamanage/edb_info/image/set_by_svg',params)
+	},
 	/** 
 	 * 获取图表批量刷新结果
 	 * @param {Object} params

+ 153 - 11
src/api/modules/chartRelevanceApi.js

@@ -3,11 +3,22 @@ import http from "@/api/http.js"
 export default{
     /**
    * 获取分类
+   * IsShowMe 是否仅展示我的:true-是
+   * ParentId 父级ID,一级分类不传或者0即可
+   * Source 来源:3-相关性(不传默认也为这个);4-滚动相关性
    * @returns 
    */
   classifyList:  params =>{
     return http.get('/correlation/chart_classify/list',params)
   },
+  /**
+   * 分类树
+   * @param {*} params 
+   * @returns 
+   */
+  classifyTree:params=>{
+    return http.get('/correlation/chart_classify/tree',params)
+  },
 
   /**
    * 新增分类
@@ -46,8 +57,14 @@ export default{
   },
 
   /**
-   * 移动分类
-   * @param {*} params ClassifyId "PrevClassifyId":1, "NextClassifyId":2,
+   * 移动分类or图表
+   * @param {*} params "ClassifyId": 228, //分类ID
+    "ParentClassifyId": 0, //父级分类ID
+    "PrevClassifyId": 0, //上一个兄弟节点分类ID
+    "NextClassifyId": 227, //下一个兄弟节点分类ID
+    "ChartInfoId": 0, //图表ID,如果图表ID>0则移动对象为图表,否则默认为移动分类
+    "PrevChartInfoId": 0, //上一个兄弟节点图表ID
+    "NextChartInfoId": 0 //下一个兄弟节点图表ID
    * @returns 
    */
   classifyMove: params => {
@@ -253,15 +270,140 @@ export default{
     return http.post('/datamanage/multiple_graph/preview_cure',params)
   },
 
-  /**
-	 * 设置图表对应版本信息
-	 * @param {*} params 
-	 * ChartInfoId ChartName
-	 * @returns 
-	 */
-	setChartLangInfo: params => {
-		return http.post('/correlation/chart_info/base/edit',params)
-	},
+    /**
+     * 设置图表对应版本信息
+     * @param {*} params 
+     * ChartInfoId ChartName
+     * @returns 
+     */
+    setChartLangInfo: params => {
+        return http.post('/correlation/chart_info/base/edit',params)
+    },
+
+    /* 相关性功能拓展 */
+
+    /**
+     * 获取计算方式列表
+     * @param {Object} params 
+     * @param {Number} params.EdbInfoType  指标类型:0-普通指标;1-预测指标
+     * @returns 
+     */
+    getCalculateFormula:params => {
+        return http.get('/datamanage/factor_edb_series/calculate_func/list',params)
+    },
+    /**
+     * 添加多因子系列
+     * @param {Object} params 
+     * @param {String} params.SeriesName 系列名称
+     * @param {Number} params.EdbInfoType 指标类型:0-普通指标; 1-预测指标
+     * @param {Object[]} params.Calculates 选择的计算公式
+     * @param {String} params.Calculates[].Formula N值/移动天数/指数修匀alpha值/计算公式等
+     * @param {String} params.Calculates[].Calendar 公历/农历
+     * @param {String} params.Calculates[].Frequency 需要转换的频度
+     * @param {String} params.Calculates[].MoveType 移动方式:1-领先(默认);2-滞后
+     * @param {String} params.Calculates[].MoveFrequency 移动频度
+     * @param {String} params.Calculates[].FromFrequency 来源的频度
+     * @param {Number} params.Calculates[].Source 计算方式来源
+     * @param {Number} params.Calculates[].Sort 计算顺序
+     * @param {Number[]} params.EdbInfoIds 需要计算的指标
+     * @returns 
+     */
+    addFactorSeries:params=>{
+        return http.post('/datamanage/factor_edb_series/add',params)
+    },
+    /**
+     * 编辑多因子系列
+     * @param {Object} params 
+     * @param {String} params.SeriesId //因子系列ID
+     * //其他同添加
+     * @returns 
+     */
+    editFactorSeries:params=>{
+        return http.post('/datamanage/factor_edb_series/edit',params)
+    },
+    /**
+     * 获取多因子系列详情
+     * @param {Object} params
+     * @param {Number} params.SeriesId 因子指标系列ID
+     * @returns 
+     */
+    getFactorSeriesDetail:params=>{
+        return http.get('/datamanage/factor_edb_series/detail',params)
+    },
+    /**
+     * 获取相关性矩阵
+     * @param {Object} params
+     * @param {Number} params.BaseEdbInfoId 标的指标ID
+     * @param {Object} params.Correlation
+     * @param {Number} params.Correlation.CalculateValue 计算窗口
+     * @param {String} params.Correlation.CalculateUnit 计算窗口频度
+     * @param {Number} params.Correlation.LeadValue 分析周期
+     * @param {String} params.Correlation.LeadUnit 分析周期频度
+     * @param {Number[]} params.SeriesIds 因子系列Id
+     * @returns 
+     */
+    getCorrelationMatrix:params=>{
+        return http.post('datamanage/factor_edb_series/correlation/matrix',params)
+    },
+    /**
+     * 新增多因子相关性图表
+     * @param {Object} params 
+     * @param {String} params.ChartName
+     * @param {Number} params.ClassifyId
+     * @param {Number} params.AnalysisMode 分析模式:0-单因子;1-多因子
+     * @param {Number} params.BaseEdbInfoId 标的指标ID
+     * @param {Object} params.FactorCorrelation
+     * @param {Number} params.FactorCorrelation.CalculateValue 领先期数
+     * @param {String} params.FactorCorrelation.CalculateUnit 频度
+     * @param {Number} params.FactorCorrelation.LeadValue 计算窗口
+     * @param {String} params.FactorCorrelation.LeadUnit 计算频度
+     * @param {Object[]} params.FactorCorrelation.SeriesEdb 关联系列指标
+     * @param {Number} params.FactorCorrelation.SeriesEdb[].SeriesId
+     * @param {Number} params.FactorCorrelation.SeriesEdb[].EdbInfoId
+     * @param {Object} params.ExtraConfig
+     * @param {Object[]} params.ExtraConfig.LegendConfig 
+     * @param {String} params.ExtraConfig.LegendConfig.LegendName
+     * @param {Number} params.ExtraConfig.LegendConfig.SeriesId
+     * @param {Number} params.ExtraConfig.LegendConfig.EdbInfoId 
+     * @param {String} params.ExtraConfig.LegendConfig.Color 
+     * @param {Object} params.SourcesFrom
+     * @param {Boolean} params.SourcesFrom.isShow
+     * @param {String} params.SourcesFrom.text
+     * @param {String} params.SourcesFrom.color
+     * @param {Number} params.SourcesFrom.fontSize
+     * @returns 
+     */
+    addMultipleFactor:params=>{
+        return http.post('/correlation/chart_info/multi_factor/add',params)
+    },
+    /**
+     * 更新多因子相关性图表
+     * @param {*} params 
+     * @param {Number} params.ChartInfoId
+     * 其他同新增
+     * @returns 
+     */
+    editMultipleFactor:params=>{
+        return http.post('/correlation/chart_info/multi_factor/edit',params)
+    },
+    /**
+     * 多因子图表详情
+     * @param {Object} params 
+     * @param {String} params.UniqueCode
+     * @returns 
+     */
+    getMultipleChartDetail:params=>{
+        return http.get('/datamanage/chart_info/common/detail/from_unique_code',params)
+    },
+    /**
+     * 多因子表单及矩阵详情
+     * @param {*} params
+     * @param {Number} params.UniqueCode 
+     * @returns 
+     */
+    getMultipleFactorDetail:params=>{
+        return http.get('/correlation/chart_info/multi_factor/detail',params)
+    }
 
 }
 

+ 65 - 2
src/api/modules/dataApi.js

@@ -515,8 +515,71 @@ const dataRefreshInterface = {
     getSimgleEdbRefreshTime(params){
         return http.get("/datamanage/edb_info/refresh/edb_config",params)
     },
-
-
+// -------------------刷新状态设置
+	/**
+	 * 获取引用指标数据
+	 * @param {Object} params 
+	 * @param {Number} params.Source
+	 * @param {String} params.ClassifyId 多选
+	 * @param {String} params.SysUserId 多选
+	 * @param {String} params.Frequency
+	 * @param {String} params.Keyword
+	 * @param {String} params.Status
+	 * @param {String} params.SortParam 枚举值:'RelationTime':引用日期 'RelationNum' 引用次数
+	 * @param {String} params.SortType
+	 * @param {String} params.CurrentIndex
+	 * @param {String} params.PageSize
+	 * @returns 
+	 */
+	getRelationEdbDataList:params=>{
+		return http.get("/datamanage/edb_info/relation/edb_list",params)
+	},
+	/**
+	 * 获取指标的引用详情
+	 * @param {Object} params 
+	 * @param {Number} params.EdbInfoId
+	 * @returns 
+	 */
+	getRelationEdbDetail:params=>{
+		return http.get("/datamanage/edb_info/relation/detail",params)
+	},
+	/**
+	 * 获取默认刷新规则
+	 * @param {Object} params 
+	 * @param {Number} params.ConfKey EdbStopRefreshRule
+	 * @returns 
+	*/
+	getEdbStopRefreshRule:params=>{
+		return http.get("/business_conf/single",params)
+	},
+		/**
+	 * 设置默认刷新规则
+	 * @param {Object} params 
+	 * @param {Number} params.ConfKey EdbStopRefreshRule
+	 * @param {Number} params.ConfVal "{\"IsOpen\":1,\"BaseIndexStopDays\":90,\"EdbStopDays\":300}"
+	 * @returns 
+	*/
+	setEdbStopRefreshRule:params=>{
+		return http.post("/business_conf/single/save",params)
+	},
+	/**
+	 * 批量设置被引用的指标刷新的状态
+	 * @param {Object} params 
+	 * @param {Number} params.Source
+	 * @param {String} params.ClassifyId 多选
+	 * @param {String} params.SysUserId 多选
+	 * @param {String} params.Frequency
+	 * @param {String} params.Keyword
+	 * @param {String} params.Status
+	 * @param {String} params.IsSelectAll 是否全选
+	 * @param {String} params.EdbSelectIdList 如果不是全选,则表示选中的指标,如果全选则表示需要排除的指标
+	 * @param {String} params.ModifyStatus 枚举值:状态,枚举值:启用、暂停
+	 * @returns 
+	*/
+	setRelationEdbsRefreshStatus:params=>{
+		return http.post("/datamanage/edb_info/relation/refresh/save",params)
+	},
+	
 }
 
 export {

+ 8 - 1
src/api/modules/predictEdbApi.js

@@ -166,7 +166,14 @@ export const edbSearch = params => {
 export const setImg = params => {
 	return http.post('/datamanage/predict_edb_info/image/set',params)
 }
-
+/**
+ * 设置缩略图 formData
+ * @param {*} params EdbInfoId  Img
+ * @returns 
+ */
+export const setThumbnail = params => {
+	return http.post('/datamanage/predict_edb_info/image/set_by_svg',params)
+}
 /**
  * 指标刷新
  * @param {*} params EdbInfoId

+ 7 - 2
src/api/modules/reportEnApi.js

@@ -142,12 +142,17 @@ export const saveCustomEamil=params=>{
 }
 
 /**
- * 点击量
+ * 点击量 PV
  */
 export const PVDetailList=params=>{
 	return http.get('/english_report/email/pv_list',params)
 }
-
+/**
+ * UV
+ */
+export const UVDetailList=params=>{
+	return http.get('/english_report/email/uv_list',params)
+}
 /**
  * 批量发送邮件
  */

+ 429 - 0
src/api/modules/reportV2.js

@@ -0,0 +1,429 @@
+//研报改版  一些接口复用以前的 一些新增的 都捞过来放一块
+import http from "@/api/http.js"
+
+
+/* 新增的接口 */
+export const reportV2Interface = {
+
+  /**
+   * 获取有权限的列表 
+   * @param {
+   *  CurrentIndex PageSize KeyWord ClassifyIdFirst ClassifyIdSecond ClassifyIdThird
+   * } params 
+   * @returns 
+   */
+  getAuthReportList: params => {
+    return http.get('/report/list/authorized',params)
+  },
+
+  /**
+   * 报告基础信息
+   * @param {*ReportId} params 
+   * @returns 
+   */
+  getRportBase: params => {
+    return http.get('/report/detail/base',params)
+  },
+
+  /**
+   * 修改章节基础信息
+   * @param {*} params 
+   * @returns 
+   */
+  editChapterBase: params => {
+    return http.post('/report/chapter/base_info/edit',params)
+  },
+
+  /**
+   * 章节拖动排序
+   * @param {*ReportChapterId PrevReportChapterId NextReportChapterId} params 
+   * @returns 
+   */
+  moveChapter: params => {
+    return http.post('/report/chapter/move',params)
+  },
+
+	/**
+	 * 删除章节
+	 * @param {*ReportChapterId} params 
+	 * @returns 
+	 */
+	removeChapter: params => {
+		return http.post('/report/chapter/del',params)
+	},
+
+	/**
+	 * 添加章节
+	 * 
+	 * @param {* Title  ReportId PermissionIdList AdminIdList} params 
+	 * @returns 
+	 */
+	addChapter: params => {
+		return http.post('/report/chapter/add',params)
+	},
+
+	/**
+	 * 上传章节音频
+	 * @param {*ReportChapterId File} params 
+	 * @returns 
+	 */
+	uploadChpterAudio: params => {
+		return http.post('/report/chapter/voice/upload',params)
+	},
+
+	/**
+	 * 校验所有章节是否发布
+	 * @param {*ReportId} params 
+	 * @returns 
+	 */
+	checkChaterPublishState: params => {
+		return http.get('/report/chapter/un_publish/list',params)
+	},
+
+	/**
+	 * 设置版图
+	 * @param {*ReportId HeadImg HeadResourceId EndImg EndResourceId CanvasColor} params 
+	 * @returns 
+	 */
+	setReportLayoutImg: params => {
+		return http.post('/report/layout_img/edit',params)
+	},
+
+	/**
+	 * 获取分类关联的品种列表
+	 * @param {*ClassifyId} params 
+	 * @returns 
+	 */
+	getClassifyPermissionList: params => {
+		return	http.get('/classify/permission/list',params)
+	},
+
+	/**
+	 * 保存章节标题 
+	 * @param {*ReportChapterId Title} params 
+	 * @returns 
+	 */
+	saveChapterTitle: params => {
+		return http.post('/report/chapter/title/edit',params)
+	}
+
+}
+
+
+const reportlist = params => { return http.get('/report/list',params); };  //获取报告列表
+
+const classifylist = params => { return http.get('/classify/list',params); };  //获取分类列表
+
+ const reportpublish = params => { return http.post('/report/publish',params); };  //批量发布报告
+ const reportpublishcancle = params => { return http.post('/report/publish/cancle',params); };  //取消发布报告
+ const voiceupload = params => { return http.post('/voice/upload',params); };  //上传音频
+ const resourceVoiceupload = params => { return http.post('/resource/voice/upload',params); };  //上传音频
+ const reportadd = params => { return http.post('/report/add',params); };  //新增报告
+ const reportedit = params => { return http.post('/report/edit',params); };  //编辑报告
+ const reportdelete = params => { return http.post('/report/delete',params); };  //删除报告
+ const reportdetail = params => { return http.get('/report/detail',params); };  //获取报告详情
+ const classifyIdDetail = params => { return http.get('/report/classifyIdDetail',params); };  //通过二级分类id获取报告详情
+ const sendTemplateMsg = params => { return http.post('/report/sendTemplateMsg',params); };  //推送消息
+ const reportauthor = params => { return http.get('/report/author',params); };  //获取作者
+ const getDraft = params => { return http.get('/report/getDraft',params); };  //获取草稿
+ const autosave = params => { return http.post('/report/saveReportContent',params); };  //保存
+ const reportSetPrepublish=params=>{return http.post('/report/pre_publish',params);};//报告设置定时发布
+
+ const classifyparent = params => { return http.get('/classify/parent',params); };  //获取父级分类
+ const classifyadd = params => { return http.post('/classify/add',params); };  //新增分类
+ const classifydelete = params => { return http.post('/classify/delete',params); };  //删除分类
+ const classifyedit = params => { return http.post('/classify/edit',params); };  //编辑分类
+ const checkDeleteClassify = params => { return http.get('/classify/checkDeleteClassify',params); };  //检测分类
+ const classifyTelList = params=>{return http.get('/classify/tel_list',params)};//电话会分类
+
+
+
+ /* 客群消息推送接口 */
+const messagePushPost= params => {
+	return http.post('/report/ths/sendTemplateMsg',params)
+}
+
+// 晨周报章节类型列表
+const dayWeekReportChapterList=params=>{
+	return http.get('/report/getDayWeekReportChapterTypeList',params)
+}
+
+//新增晨周报
+const addDayWeekReport=params=>{
+	return http.post('/report/addDayWeekReport',params)
+}
+
+//编辑晨周报
+const editDayWeekReport=params=>{
+	return http.post('/report/editDayWeekReport',params)
+}
+
+// 晨周报章节列表
+const dayWeekChapterList=params=>{
+	return http.get('/report/getReportChapterList',params)
+}
+
+//章节标签列表
+const chapterTrendTagList=()=>{
+	return http.get('/report/getChapterTrendTag',{})
+}
+
+//编辑章节标签
+const editChapterTrendTag=params=>{
+	return http.post('/report/editChapterTrendTag',params)
+}
+
+//晨报周报章节详情
+const chapterDetail=params=>{
+	return http.get('/report/getDayWeekChapter',params)
+}
+
+//晨报数据指标列表
+const dayTicketList=params=>{
+	return http.get('/report/getDayReportTickerList',params)
+}
+
+//保存晨报周报章节报告
+const saveChapterReport=params=>{
+	return http.post('/report/editDayWeekChapter',params)
+}
+
+//获取晨报/周报上一篇内容
+const getChapterReportBefore=params=>{
+	return http.get('/report/getLastDayWeekReportChapter',params)
+}
+
+//判断晨报周报当前章节是否为最后一篇发布的
+const getChapterReportIsLast=params=>{
+	return http.get('/report/isLastDayWeekReportChapter',params)
+}
+
+//发布晨报周报章节
+const publishChapterReport=params=>{
+	return http.post('/report/publishDayWeekReportChapter',params)
+}
+
+//发布晨报周报
+const publishDayOrWeekReport=params=>{
+	return http.post('/report/publishDayWeekReport',params)
+}
+
+//晨报周报更新暂停的时间
+const dayWeekPauseTime=params=>{
+	return http.get('/report/getDayWeekReportPauseTime',{})
+}
+
+//晨报周报设置更新规则
+const dayWeekUpdateRule=params=>{
+	return http.post('/report/setDayWeekReportUpdateRule',params)
+}
+
+// 周报校验音频
+const weekReportValidAudio=params=>{
+	return http.get('/report/CheckDayWeekReportChapterVideo',params)
+}
+
+
+const chapterQRCodeImg=params=>{
+	return http.post('/report/getSunCode',params)
+}
+
+/* 推送客户群设置 */
+// 获取待推送报告类型
+/**
+ * @returns 
+ * List - 报告类型列表
+ * 
+ */
+const getBeingPushedReportType=()=>{
+	return http.get('/yb/ths_send/report_type',{})
+}
+// 获取待推送列表
+/**
+ * 
+ * @param {
+ * Title 推送标题
+ * ReportType 内容类型
+ * CreateTimeStart 创建开始日期
+ * CreateTimeEnd 创建结束日期
+ * PushTimeStart 推送开始日期
+ * PushTimeEnd 推送结束日期
+ * PageSize 每页条数
+ * CurrentIndex 当前页数
+ * } params 
+ * @returns 
+ */
+const getBeingPushedReportList=params=>{
+	return http.get('/yb/ths_send/list',params)
+}
+// 设置推送时间
+/** 
+ * @param {
+ * SendId 序号
+ * PushTime 新的推送时间
+ * } params 
+ * @returns 
+ */
+const setPushingTime=params=>{
+	return http.post('/yb/ths_send/modify_push_time',params)
+}
+
+//研报标记状态
+/**
+ * 
+ * @param {
+ * Status 编辑状态
+ * ReportId 报告ID
+ * } params
+ * @returns 
+ */
+const markReport = params =>{
+  return http.post('/report/mark',params)
+}
+
+// 获取章节类型列表
+/**
+ * @param params.ReportType Enum-报告类型:day-晨报;week-周报
+ * @param params.PageSize Integer-每页条数
+ * @param params.CurrentIndex Integer-当前页数
+ * @returns 章节类型列表
+ */
+const getchapterTypeList=params=>{
+ return http.get('/report/chapter_type/list',params)
+}
+
+// 新增章节类型
+/**
+ * @param params.ReportChapterTypeName String-章节名称
+ * @param params.Sort Integer-排序
+ * @param params.ReportType Enum-报告类型:day-晨报;week-周报
+ * @param params.SelectedImage String-选中的icon
+ * @param params.UnselectedImage String-未选中的icon
+ * @param params.WordsImage String-带字的icon
+ * @param params.EditImgUrl String-后台-章节列表封面图
+ * @param params.IsShow Enum-小程序端是否展示:0-隐藏;1-显示
+ */
+const addChapterType=params=>{
+	return http.post('/report/chapter_type/add',params)
+ }
+
+ // 编辑章节类型
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ * @param params.ReportChapterTypeName String-章节名称
+ * @param params.Sort Integer-排序
+ * @param params.ReportType Enum-报告类型:day-晨报;week-周报
+ * @param params.SelectedImage String-选中的icon
+ * @param params.UnselectedImage String-未选中的icon
+ * @param params.WordsImage String-带字的icon
+ * @param params.EditImgUrl String-后台-章节列表封面图
+ * @param params.IsShow Enum-小程序端是否展示:0-隐藏;1-显示
+ */
+const editChapterType=params=>{
+	return http.post('/report/chapter_type/edit',params)
+ }
+ 
+// 删除章节
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ */
+const deleteChapterType=params=>{
+	return http.post('/report/chapter_type/del',params)
+}
+
+// 获取章节类型的权限列表
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ * @returns 权限列表
+ */
+const getchapterTPermissionList=params=>{
+	return http.get('/report/chapter_type/permission_list',params)
+ }
+
+// 设置章节类型的权限
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ * @param params.ChartPermissionIdList Array<Integer>-权限IDs
+ */
+const setchapterTPermission=params=>{
+	return http.post('/report/chapter_type/auth_setting',params)
+}
+
+//章节启用\禁用
+const setChapterEnable=params=>{
+	return http.post('/report/chapter_type/enabled/set',params)
+}
+
+//章节拖动排序
+const setChapterSort=params=>{
+	return http.post('/report/chapter_type/move',params)
+}
+
+// 同时推送客群和模板消息
+const reportMessageSend=params=>{
+	return http.post('/report/sendMsg',params)
+}
+
+// 中英文研报、智能研报转pdf和长图
+const report2PdfImg=params=>{
+	return http.post('/smart_report/get_pdf_url',params)
+}
+
+
+
+export {
+	reportlist,
+	reportpublish,
+	reportpublishcancle,
+	voiceupload,
+	resourceVoiceupload,
+	reportadd,
+	reportedit,
+	reportdelete,
+	reportdetail,
+	classifyIdDetail,
+	sendTemplateMsg,
+	reportauthor,
+	getDraft,
+	autosave,
+	reportSetPrepublish,
+	classifylist,
+	classifyparent,
+	classifyadd,
+	classifydelete,
+	classifyedit,
+	checkDeleteClassify,
+	messagePushPost,
+	dayWeekReportChapterList,
+	addDayWeekReport,
+	dayWeekChapterList,
+	chapterTrendTagList,
+	editChapterTrendTag,
+	editDayWeekReport,
+	chapterDetail,
+	dayTicketList,
+	saveChapterReport,
+	getChapterReportBefore,
+	getChapterReportIsLast,
+	publishChapterReport,
+	publishDayOrWeekReport,
+	dayWeekPauseTime,
+	dayWeekUpdateRule,
+	chapterQRCodeImg,
+  classifyTelList,
+	getBeingPushedReportType,
+	getBeingPushedReportList,
+	setPushingTime,
+  markReport,
+	getchapterTypeList,
+	addChapterType,
+	editChapterType,
+	deleteChapterType,
+	getchapterTPermissionList,
+	setchapterTPermission,
+	reportMessageSend,
+	weekReportValidAudio,
+	setChapterEnable,
+	setChapterSort,
+	report2PdfImg
+}

+ 194 - 1
src/api/modules/thirdBaseApi.js

@@ -1009,6 +1009,197 @@ const ccfDataInterface={
 		return http.get('/datamanage/ccf/search_list',params);
 	}
 }
+/* 数据源-Wind */
+const windInterface={
+	/**
+	 * 分类列表
+	 * params: ParentId
+	 */
+	classifyList:params=>{
+			return http.get('/datamanage/wind/classify',params)
+	},
+	/**
+	 * 数据列表
+	 * params:  EdbInfoId,ClassifyId
+	 */
+	dataList:params=>{
+			return http.get('/datamanage/wind/index',params)
+	}
+}
+
+/* CCF化纤信息 */
+const highFrequencyDataInterface={
+	/**
+	 * 分类树
+	 * @param {} params 
+	 * @returns 
+	 */
+	classifyListTree: params => {
+		return http.get('/datamanage/ths_hf/classify/tree',params);
+	},
+	/**
+	 * 分类列表 懒加载
+	 * @param {} params ParentId
+	 * @returns 
+	*/
+	classifyList: params => {
+		return http.get('/datamanage/ths_hf/classify/list',params);
+	},
+	/**
+	 * 添加分类
+	 * @param {} params ClassifyName ParentId-第一级传0 Level-第一级传0, 其余传上一级的层级
+	 * @returns 
+	*/
+	classifyAdd: params => {
+		return http.post('/datamanage/ths_hf/classify/add',params);
+	},
+	/**
+	 * 编辑分类
+	 * @param {} params ClassifyId ClassifyName
+	 * @returns 
+	*/
+	classifyEdit: params => {
+		return http.post('/datamanage/ths_hf/classify/edit',params);
+	},
+	/**
+	 * 删除分类 ClassifyId
+	 */
+	classifyDelete: params => {
+		return http.post('/datamanage/ths_hf/classify/remove',params);
+	},
+	/**
+	 * 移动分类 
+	 * "ClassifyId": 0, //分类ID
+		"ParentClassifyId": 0, //父级分类ID
+		"PrevClassifyId": 0, //上一个兄弟节点分类ID
+		"NextClassifyId": 0, //下一个兄弟节点分类ID
+		"ItemId": 0, //指标ID, 如果指标ID有值,则移动对象为指标,否则认为移动对象为分类
+		"PrevItemId": 0, //上一个指标ID
+		"NextItemId": 0 //下一个指标ID
+	*/
+	classifyMove: params => {
+		return http.post('/datamanage/ths_hf/classify/move',params);
+	},
+	/**
+	 * 获取高频数据列表 
+	 * PageSize、CurrentIndex、ClassifyId(多选)、IncludeChild(是否关联子分类)、Frequency(多选)、SysAdminId(多选)、
+	 * Keywords、SortField、SortType
+	*/
+	getTableDataApi:params=>{
+		return http.get('/datamanage/ths_hf/index/list',params);
+	},
+	/**
+	 * 检验高频数据指标是否重复 
+	 * StockCode、EdbCode、StartTime、EndTime、Interval(number)、Fill、CPS、BaseDate
+	*/
+	checkHighFreData:params=>{
+		return http.get('/datamanage/ths_hf/index/exist_check',params);
+	},
+	/**
+	 * 搜索高频数据指标 
+	 * StockCode、EdbCode、StartTime、EndTime、Interval(number)、Fill、CPS、BaseDate
+	*/
+	searchHighFreData:params=>{
+		return http.get('/datamanage/ths_hf/index/search',params);
+	},
+	/**
+	 * 批量添加高频数据指标 
+	 * StartTime、EndTime、Interval(number)、Fill、CPS、BaseDate
+	 * IndexList:[{ClassifyId,StockCode,EdbCode,IndexName,Frequency,Unit}]
+	*/
+	addHighFreDatas:params=>{
+		return http.post('/datamanage/ths_hf/index/add',params);
+	},
+	/**
+	 * 高频数据详情
+	 * IndexId(number)、DataDate(数据日期(非必填,默认为有数据的最新日期))
+	*/
+	highFreDataDetail:params=>{
+		return http.get('/datamanage/ths_hf/index/detail',params);
+	},
+	/**
+	 * 高频数据编辑
+	 * IndexId(number)、IndexName、ClassifyId、Unit
+	*/
+	highFreDataEdit:params=>{
+		return http.post('/datamanage/ths_hf/index/edit',params);
+	},
+	/**
+	 * 高频数据刷新
+	 * IndexId(number)
+	*/
+	highFreDataRefresh:params=>{
+		return http.post('/datamanage/ths_hf/index/refresh',params);
+	},
+	/**
+	 * 高频数据删除
+	 * IndexId(number)
+	*/
+	highFreDataDelete:params=>{
+		return http.post('/datamanage/ths_hf/index/remove',params);
+	},
+	/**
+	 * 高频数据列表选择
+	 * ClassifyId IncludeChild Frequency SysAdminId Keywords ListIds SelectAll
+	*/
+	highFreDataChoice:params=>{
+		return http.get('/datamanage/ths_hf/index/list_choice',params);
+	},
+	/**
+	 * 批量操作
+	 * IndexIds(array) OptType(1-移动分类; 2-删除; 3-刷新) MoveClassifyId RefreshType(1-最近6小时; 2-全部刷新(操作为3时必填))
+	*/
+	highFreDataBatchOperation:params=>{
+		return http.post('/datamanage/ths_hf/index/multi_opt',params);
+	},
+	/**
+	 * 获取新增指标(批量新增前)
+	 * {
+		* IndexIds(array) 
+		* ConvertRule:{
+			*	ConvertType //转换类型: 1-指定时间值; 2-区间计算值
+			*	ConvertFixed:{
+					FixedDay, //指定时间值日期: 1-当日; 2-前一日
+					FixedTime
+				},
+				ConvertArea:{
+					StartDay, //起始时间日期: 1-当日; 2-前一日
+					StartTime,
+					EndDay,//截止时间日期: 1-当日; 2-前一日
+					EndTime,
+					CalculateType //计算类型: 1-区间均值; 2-最大值; 3-最小值
+				}
+		* }
+	 * }
+	*/
+	highFreDataSavePre:params=>{
+		return http.post('/datamanage/ths_hf/index/save2edb_pre',params);
+	},
+	/**
+	 * 批量新增指标
+	 * {
+		* NewIndexes(array) 
+		* ConvertRule:{
+			*	ConvertType //转换类型: 1-指定时间值; 2-区间计算值
+			*	ConvertFixed:{
+					FixedDay, //指定时间值日期: 1-当日; 2-前一日
+					FixedTime
+				},
+				ConvertArea:{
+					StartDay, //起始时间日期: 1-当日; 2-前一日
+					StartTime,
+					EndDay,//截止时间日期: 1-当日; 2-前一日
+					EndTime,
+					CalculateType //计算类型: 1-区间均值; 2-最大值; 3-最小值
+				}
+		* }
+	 * }
+	*/
+	highFreDataSave:params=>{
+		return http.post('/datamanage/ths_hf/index/save2edb',params);
+	},
+}
+
 export { 
 	lzDataInterface,
 	glDataInterface,
@@ -1027,5 +1218,7 @@ export {
 	zczxInterface,
 	coalWordInterface,
 	bloombergInterface,
-	ccfDataInterface
+	ccfDataInterface,
+	windInterface,
+	highFrequencyDataInterface
 }

BIN
src/assets/img/data_m/move_ico.png


File diff suppressed because it is too large
+ 1 - 0
src/assets/img/icons/baseinfo_ico.svg


BIN
src/assets/img/icons/edb-stopping.png


BIN
src/assets/img/icons/formula-add.png


+ 4 - 0
src/assets/img/icons/preview_ico.svg

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.93819 5.46945V3.40708C2.93819 3.14802 3.14818 2.93806 3.40728 2.93806H5.46994C5.72904 2.93806 5.93903 2.72809 5.93903 2.46903C5.93903 2.20996 5.72904 2 5.46994 2H2.46909C2.20999 2 2 2.20996 2 2.46903V5.46945C2 5.72852 2.20999 5.93848 2.46909 5.93848C2.7265 5.93848 2.93819 5.72852 2.93819 5.46945ZM10.5334 2.93806H12.5927C12.8518 2.93806 13.0618 3.14802 13.0618 3.40708V5.46945C13.0618 5.72852 13.2718 5.93848 13.5309 5.93848C13.79 5.93848 14 5.72852 14 5.46945V2.46903C14 2.20996 13.79 2 13.5309 2H10.5334C10.2743 2 10.0644 2.20996 10.0644 2.46903C10.0644 2.72809 10.276 2.93806 10.5334 2.93806ZM5.46825 13.0603H3.40728C3.14818 13.0603 2.93819 12.8503 2.93819 12.5912V10.5322C2.93819 10.2732 2.7282 10.0632 2.46909 10.0632C2.20999 10.0632 2 10.2732 2 10.5322V13.5293C2 13.7883 2.20999 13.9983 2.46909 13.9983H5.46825C5.72735 13.9983 5.93734 13.7883 5.93734 13.5293C5.93734 13.2702 5.72735 13.0603 5.46825 13.0603ZM13.0618 10.5322V12.5929C13.0618 12.852 12.8518 13.0619 12.5927 13.0619H10.5334C10.2743 13.0619 10.0644 13.2719 10.0644 13.531C10.0644 13.79 10.2743 14 10.5334 14H13.5309C13.79 14 14 13.79 14 13.531V10.5339C14 10.2749 13.79 10.0649 13.5309 10.0649C13.2718 10.0632 13.0618 10.2732 13.0618 10.5322Z" fill="#0052D9"/>
+<path d="M8 5.59888C9.5061 5.59888 10.8019 6.58141 11.4093 8H12C11.3605 6.2408 9.81237 5 8 5C6.18931 5 4.64114 6.2408 4 8H4.59066C5.19815 6.58328 6.49558 5.59888 8 5.59888ZM8 10.4011C6.4939 10.4011 5.19815 9.41859 4.59066 8H4C4.64114 9.7592 6.18931 11 8 11C9.81069 11 11.3605 9.75733 12 8H11.4093C10.8035 9.41859 9.5061 10.4011 8 10.4011ZM6.56121 8C6.56121 8.88334 7.20572 9.60012 8 9.60012C8.79428 9.60012 9.43879 8.88334 9.43879 8C9.43879 7.11666 8.79428 6.39988 8 6.39988C7.20572 6.39988 6.56121 7.11666 6.56121 8ZM8.90029 8C8.90029 8.55209 8.49811 9.00125 8 9.00125C7.50358 9.00125 7.10139 8.55396 7.10139 8C7.10139 7.44791 7.50358 6.99875 8 6.99875C8.49811 7.00062 8.90029 7.44791 8.90029 8Z" fill="#0052D9"/>
+</svg>

+ 4 - 0
src/assets/img/icons/publish_ico.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.74769 17.4324C4.19134 17.4317 3.658 17.2233 3.2646 16.8528C2.8712 16.4823 2.64985 15.98 2.64908 15.4561C2.64908 14.3664 3.59054 13.4798 4.74769 13.4798H10.1965C10.2716 13.0217 10.4212 12.5773 10.6401 12.1622H7.85772L9.28769 8.59764C9.3011 8.58447 9.31451 8.55921 9.3285 8.53451C9.36916 8.46974 9.39556 8.39792 9.40613 8.32334C9.41669 8.24876 9.4112 8.17294 9.38999 8.1004C9.36877 8.02785 9.33226 7.96008 9.28264 7.90111C9.23301 7.84213 9.17129 7.79318 9.10115 7.75715C8.63788 7.50327 8.25371 7.13905 7.98725 6.70107C7.72079 6.26309 7.58142 5.76679 7.58315 5.26202C7.58315 3.68204 8.94142 2.40346 10.6063 2.40346C12.2835 2.40346 13.6411 3.69357 13.6411 5.27464C13.6405 5.77884 13.5002 6.27415 13.2342 6.71171C12.9682 7.14927 12.5857 7.51396 12.1243 7.76978C12.0975 7.78185 12.0707 7.79448 12.0573 7.81918C11.8183 7.99486 11.7512 8.30778 11.9115 8.55921C11.9244 8.58447 11.9506 8.60862 11.964 8.63388L12.5983 10.2122C12.9629 10.0179 13.3529 9.86893 13.7583 9.76917L13.2162 8.43405C13.6411 8.12561 13.9983 7.74225 14.2678 7.30534C14.6541 6.68603 14.8562 5.98024 14.8531 5.26202C14.8564 4.73596 14.7487 4.21452 14.5361 3.72802C14.3236 3.24153 14.0104 2.79968 13.6149 2.42816C12.8157 1.66343 11.7512 1.25005 10.6063 1.25005C10.0467 1.24751 9.49211 1.35043 8.97532 1.55276C8.45853 1.75508 7.98994 2.05273 7.59714 2.42816C6.80253 3.18152 6.3573 4.20072 6.35896 5.26257C6.35896 5.97734 6.55891 6.69212 6.94424 7.30588C7.22405 7.74507 7.58315 8.13375 8.00987 8.44722L6.50819 12.1622H4.74769C4.28837 12.1622 3.83354 12.2474 3.40918 12.4129C2.98482 12.5785 2.59924 12.8211 2.27445 13.127C1.94966 13.4328 1.69202 13.7959 1.51625 14.1956C1.34047 14.5952 1.25 15.0235 1.25 15.4561C1.25 15.8887 1.34047 16.317 1.51625 16.7166C1.69202 17.1163 1.94966 17.4794 2.27445 17.7852C2.59924 18.0911 2.98482 18.3337 3.40918 18.4993C3.83354 18.6648 4.28837 18.75 4.74769 18.75H15C13.7211 18.7511 12.4932 18.2778 11.5822 17.4324H4.74769Z" fill="#0052D9"/>
+<path d="M14.3747 10C12.0124 10 10 11.6502 10 13.7503C10 15.7751 11.9252 17.5 14.3747 17.5C16.8248 17.5 18.75 15.8504 18.75 13.7503C18.75 11.6502 16.7376 10 14.3747 10ZM16.3871 13.3004H14.9002V16.225H13.9376V13.3004H12.4501L14.3747 11.2003L16.3871 13.3004Z" fill="#0052D9"/>
+</svg>

+ 5 - 0
src/assets/img/icons/save_ico.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.7723 1.1297C15.0455 1.3226 15.0776 1.6633 14.8429 1.88887L10.1474 6.41202C10.0917 6.4657 10.0237 6.50979 9.94727 6.54177C9.87088 6.57375 9.78761 6.593 9.70221 6.59842C9.61681 6.60383 9.53095 6.59531 9.44954 6.57334C9.36813 6.55137 9.29276 6.51637 9.22773 6.47036C9.1627 6.42434 9.10929 6.3682 9.07054 6.30514C9.0318 6.24209 9.00848 6.17335 9.00192 6.10285C8.99535 6.03236 9.00568 5.96148 9.0323 5.89428C9.05891 5.82708 9.10131 5.76486 9.15705 5.71118L13.8535 1.18804C13.9092 1.13434 13.9772 1.09024 14.0536 1.05825C14.13 1.02625 14.2133 1.007 14.2987 1.00158C14.3841 0.996165 14.47 1.00469 14.5514 1.02667C14.6328 1.04866 14.7082 1.08366 14.7732 1.1297H14.7723Z" fill="#0052D9"/>
+<path d="M3.01946 1.00082C2.48401 1.00082 1.97047 1.21872 1.59177 1.60661C1.21307 1.9945 1.00021 2.52063 1 3.0693V12.9299C0.999896 13.2017 1.05205 13.4709 1.15349 13.722C1.25493 13.9732 1.40367 14.2014 1.59121 14.3936C1.77874 14.5859 2.0014 14.7384 2.24646 14.8424C2.49153 14.9464 2.7542 15 3.01946 15H11.9789C12.2443 15.0002 12.5071 14.9468 12.7522 14.843C12.9974 14.7391 13.2203 14.5867 13.4079 14.3945C13.5956 14.2023 13.7445 13.9741 13.8461 13.723C13.9477 13.4718 14 13.2026 14 12.9307V5.63025C14 5.4805 13.9419 5.33689 13.8386 5.23101C13.7353 5.12512 13.5951 5.06563 13.449 5.06563C13.3028 5.06563 13.1627 5.12512 13.0594 5.23101C12.956 5.33689 12.898 5.4805 12.898 5.63025V12.9307C12.898 13.4501 12.4866 13.8708 11.9797 13.8708H3.02026C2.77687 13.8708 2.54343 13.7718 2.37126 13.5955C2.19908 13.4192 2.10224 13.1801 2.10203 12.9307V3.07012C2.10203 2.54994 2.51261 2.12923 3.01946 2.12923H11.1355C11.2817 2.12923 11.4218 2.06974 11.5251 1.96386C11.6285 1.85797 11.6865 1.71436 11.6865 1.56461C11.6865 1.41487 11.6285 1.27126 11.5251 1.16537C11.4218 1.05949 11.2817 1 11.1355 1H3.01946V1.00082Z" fill="#0052D9"/>
+<path d="M3.52554 5C3.38626 5 3.25268 5.05824 3.1542 5.16191C3.05571 5.26558 3.00038 5.40619 3.00038 5.5528C3.00038 5.69941 3.05571 5.84002 3.1542 5.94369C3.25268 6.04736 3.38626 6.1056 3.52554 6.1056H6.25562C6.3949 6.1056 6.52848 6.04736 6.62697 5.94369C6.72545 5.84002 6.78078 5.69941 6.78078 5.5528C6.78078 5.40619 6.72545 5.26558 6.62697 5.16191C6.52848 5.05824 6.3949 5 6.25562 5H3.52554ZM3 8.4996C3 8.19466 3.23509 7.9472 3.52554 7.9472H6.88506C7.02434 7.9472 7.15791 8.00544 7.2564 8.10911C7.35489 8.21278 7.41022 8.35339 7.41022 8.5C7.41022 8.64661 7.35489 8.78722 7.2564 8.89089C7.15791 8.99456 7.02434 9.0528 6.88506 9.0528H3.52554C3.4565 9.0529 3.38811 9.03867 3.32431 9.0109C3.2605 8.98314 3.20253 8.9424 3.15371 8.89101C3.10488 8.83962 3.06618 8.77859 3.0398 8.71142C3.01343 8.64426 2.9999 8.57228 3 8.4996ZM3.52554 10.8944C3.38626 10.8944 3.25268 10.9526 3.1542 11.0563C3.05571 11.16 3.00038 11.3006 3.00038 11.4472C3.00038 11.5938 3.05571 11.7344 3.1542 11.8381C3.25268 11.9418 3.38626 12 3.52554 12H9.47484C9.61412 12 9.7477 11.9418 9.84618 11.8381C9.94467 11.7344 10 11.5938 10 11.4472C10 11.3006 9.94467 11.16 9.84618 11.0563C9.7477 10.9526 9.61412 10.8944 9.47484 10.8944H3.52554Z" fill="#0052D9"/>
+</svg>

+ 4 - 0
src/assets/img/icons/submit_ico.svg

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9 3V5H10V2.5C10 2.22386 9.77614 2 9.5 2H1.5C1.22386 2 1 2.22386 1 2.5V13.5C1 13.7761 1.22386 14 1.5 14H9.5C9.77614 14 10 13.7761 10 13.5V11H9V13H2V3H9Z" fill="#0052D9"/>
+<path d="M11.2316 5.25423L13.4774 7.50001L5.99994 7.49999L5.99994 8.49999L13.4774 8.50001L11.2316 10.7458L11.9387 11.4529L15.038 8.35356C15.2333 8.1583 15.2333 7.84172 15.038 7.64646L11.9387 4.54712L11.2316 5.25423Z" fill="#0052D9"/>
+</svg>

+ 4 - 0
src/assets/img/icons/timing_ico.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.375 5V10.4862L12.5003 13.75L13.3842 12.8661L10.625 9.96839V5H9.375Z" fill="#0052D9"/>
+<path d="M18.75 10C18.75 14.8325 14.8325 18.75 10 18.75C5.16751 18.75 1.25 14.8325 1.25 10C1.25 5.16751 5.16751 1.25 10 1.25C14.8325 1.25 18.75 5.16751 18.75 10ZM17.5 10C17.5 5.85786 14.1421 2.5 10 2.5C5.85786 2.5 2.5 5.85786 2.5 10C2.5 14.1421 5.85786 17.5 10 17.5C14.1421 17.5 17.5 14.1421 17.5 10Z" fill="#0052D9"/>
+</svg>

+ 14 - 0
src/assets/img/icons/wx_round.svg

@@ -0,0 +1,14 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_6030_16278)">
+<path d="M6.23633 7.52735C6.23633 7.70094 6.30529 7.86743 6.42804 7.99018C6.55079 8.11293 6.71728 8.18189 6.89087 8.18189C7.06447 8.18189 7.23096 8.11293 7.35371 7.99018C7.47646 7.86743 7.54542 7.70094 7.54542 7.52735C7.54542 7.35375 7.47646 7.18727 7.35371 7.06451C7.23096 6.94176 7.06447 6.8728 6.89087 6.8728C6.71728 6.8728 6.55079 6.94176 6.42804 7.06451C6.30529 7.18727 6.23633 7.35375 6.23633 7.52735Z" fill="#50B674"/>
+<path d="M9.16357 7.50904C9.16357 7.68263 9.23253 7.84912 9.35529 7.97187C9.47804 8.09462 9.64452 8.16358 9.81812 8.16358C9.99172 8.16358 10.1582 8.09462 10.281 7.97187C10.4037 7.84912 10.4727 7.68263 10.4727 7.50904C10.4727 7.33544 10.4037 7.16896 10.281 7.0462C10.1582 6.92345 9.99172 6.85449 9.81812 6.85449C9.64452 6.85449 9.47804 6.92345 9.35529 7.0462C9.23253 7.16896 9.16357 7.33544 9.16357 7.50904Z" fill="#50B674"/>
+<path d="M10.7998 10.4365C10.7998 10.557 10.8477 10.6726 10.9329 10.7579C11.0182 10.8431 11.1338 10.891 11.2543 10.891C11.3749 10.891 11.4905 10.8431 11.5758 10.7579C11.661 10.6726 11.7089 10.557 11.7089 10.4365C11.7089 10.3159 11.661 10.2003 11.5758 10.1151C11.4905 10.0298 11.3749 9.98193 11.2543 9.98193C11.1338 9.98193 11.0182 10.0298 10.9329 10.1151C10.8477 10.2003 10.7998 10.3159 10.7998 10.4365Z" fill="#50B674"/>
+<path d="M13.1089 10.4726C13.1089 10.5932 13.1568 10.7088 13.242 10.794C13.3273 10.8793 13.4429 10.9272 13.5634 10.9272C13.684 10.9272 13.7996 10.8793 13.8848 10.794C13.9701 10.7088 14.018 10.5932 14.018 10.4726C14.018 10.3521 13.9701 10.2364 13.8848 10.1512C13.7996 10.066 13.684 10.0181 13.5634 10.0181C13.4429 10.0181 13.3273 10.066 13.242 10.1512C13.1568 10.2364 13.1089 10.3521 13.1089 10.4726Z" fill="#50B674"/>
+<path d="M10 0C4.47273 0 0 4.47273 0 10C0 15.5273 4.47273 20 10 20C15.5273 20 20 15.5273 20 10C20 4.47273 15.5273 0 10 0ZM8.29091 12.3091C7.76364 12.3091 7.34545 12.2 6.81818 12.0909L5.34545 12.8182L5.76364 11.5636C4.70909 10.8364 4.09091 9.89091 4.09091 8.72727C4.09091 6.72727 5.98182 5.16364 8.29091 5.16364C10.3455 5.16364 12.1636 6.41818 12.5273 8.10909C12.4 8.09091 12.2545 8.09091 12.1273 8.09091C10.1273 8.09091 8.56364 9.58182 8.56364 11.4182C8.56364 11.7273 8.61818 12.0182 8.69091 12.2909C8.54545 12.2909 8.41818 12.3091 8.29091 12.3091ZM14.4364 13.7818L14.7455 14.8364L13.6 14.2C13.1818 14.3091 12.7636 14.4182 12.3455 14.4182C10.3455 14.4182 8.78182 13.0545 8.78182 11.3818C8.78182 9.70909 10.3455 8.34545 12.3455 8.34545C14.2364 8.34545 15.9091 9.70909 15.9091 11.3818C15.9091 12.3091 15.2909 13.1455 14.4364 13.7818Z" fill="#50B674"/>
+</g>
+<defs>
+<clipPath id="clip0_6030_16278">
+<rect width="20" height="20" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 10 - 1
src/components/antvVueComponents/tooltipCom.vue

@@ -7,6 +7,7 @@
     </el-tooltip>
     <i :class="data.fold?'el-icon-circle-plus':'el-icon-remove'" v-if="!data.isLeaf"
     class="fold-icon" @click="flodApi" v-show="show"></i>
+    <img src="~@/assets/img/icons/edb-stopping.png" class="stop-mark" v-if="data.isStop==1" />
   </div>
 </template>
 
@@ -50,7 +51,7 @@ export default {
       this.graph= this.getGraph()
       this.node.data = this.node.data?{...this.data,...this.node.data}:this.data
       this.data = this.node.data
-      
+
       let {style} = this.data
       this.initStyle(style)
 
@@ -150,5 +151,13 @@ export default {
     left: 50%;
     transform: translateX(-50%);
   }
+  .stop-mark{
+    height: 48px;
+    width: 48px;
+    position: absolute;
+    right: -1px;
+    top: 0;
+    pointer-events: none;
+  }
 }
 </style>

+ 32 - 8
src/components/lzTable.vue

@@ -8,15 +8,21 @@
 				class="header"
 			>
 				<th>{{ labelArr.get(item) }}</th>
-				<td v-for="(data, sub_index) in tableOption" :key="sub_index">
+				<td v-for="(data, sub_index) in tableOption" :key="sub_index"  
+					:style="{color:item=='IsStop' && data.IsStop?'#F56C6C':'#333333'}">
 					<template v-if="source!=='baiinfo'">
-						{{
-							(['FrequencyName','Frequency'].includes(item)) 
-							? (source === 'lz')
-								? frequencyType.get(data[item])
-								: frequencyMap.get(data[item])
-							: data[item] 
-						}}
+						<template v-if="item=='IsStop'">
+							{{ refreshStatusMap.get(data[item]) }}
+						</template>
+						<template v-else>
+							{{
+								(['FrequencyName','Frequency'].includes(item)) 
+								? (source === 'lz')
+									? frequencyType.get(data[item])
+									: frequencyMap.get(data[item])
+								: data[item] 
+							}}
+						</template>
 					</template>
 					<!-- 百川盈孚数据源 频度和单位需要可编辑 -->
 					<template v-else>
@@ -79,6 +85,8 @@ export default {
 
 			if(this.source==='gl'){
 				arr=['IndexName','IndexCode','FrequencyName','UnitName','UpdateTime']
+			}else if(this.source === 'glhg'){
+				arr=['IndexName','IndexCode','FrequencyName','UnitName','UpdateTime','IsStop']
 			}else if(sourceTypeOne.includes(this.source)){
 				arr=['IndexName','IndexCode','Frequency','Unit','ModifyTime']
 			}
@@ -96,12 +104,21 @@ export default {
 			let sourceTypeOne = ['smm','coal','baiinfo','yyzx','icpi','coalWord','ccf']
 
 			if(this.source==='gl'){
+				temMap=new Map([
+					['IndexName', this.$t('Edb.Detail.e_name')],
+					['IndexCode', this.$t('Edb.Detail.e_id')],
+					['FrequencyName', this.$t('Edb.Detail.e_fre')],
+					['UnitName', this.$t('Edb.Detail.e_unit')],
+					['UpdateTime', this.$t('Edb.Detail.e_update_time')]
+				])
+			}else if(this.source === 'glhg'){
 				temMap=new Map([
 					['IndexName', this.$t('Edb.Detail.e_name')],
 					['IndexCode', this.$t('Edb.Detail.e_id')],
 					['FrequencyName', this.$t('Edb.Detail.e_fre')],
 					['UnitName', this.$t('Edb.Detail.e_unit')],
 					['UpdateTime', this.$t('Edb.Detail.e_update_time')],
+					['IsStop',this.$t('Edb.Detail.e_status')]
 				])
 			}else if(sourceTypeOne.includes(this.source)){
 				temMap=new Map([
@@ -147,6 +164,13 @@ export default {
 				['半年度',this.$t('Edb.FreAll.half_year')],
 				['年度',this.$t('Edb.FreAll.year')]
 			])
+		},
+		//刷新状态
+		refreshStatusMap(){
+			return new Map([
+				[0,this.$t('SystemManage.DataRefresh.enabled')],
+				[1,this.$t('SystemManage.DataRefresh.disabled')]
+			])
 		}
 	},
 	data() {

+ 58 - 2
src/lang/commonLang.js

@@ -13,6 +13,10 @@ export default {
       en: "Confirm",
       zh: "确定",
     },
+    calculate_btn:{
+        en:'Calculate',
+        zh:'计算'
+    },
     confirm_save_btn: {
       en: "Save",
       zh: "保存 ",
@@ -64,7 +68,11 @@ export default {
     complete_btn: {
       en: 'Complete',
       zh: '完成'
-    }
+    },
+    operation_prompt: {
+      en: 'Operation Prompt',
+      zh: '操作提示'
+    },
   },
   Table: {
     add_btn: {
@@ -87,6 +95,14 @@ export default {
       en: "Copy",
       zh: "复制",
     },
+    detail_btn:{
+      en: "Detail",
+      zh: "详情",
+    },
+    refresh_btn:{
+      en: "Refresh",
+      zh: "刷新",
+    },
     column_operations: {
       en: "Operations",
       zh: "操作",
@@ -192,6 +208,10 @@ export default {
       en: "Entry Successful",
       zh: "录入成功",
     },
+    submit_msg: {
+      en: "Submit Successful",
+      zh: "提交成功",
+    },
     delete_info_msg: {
       en: "Are you sure you want to permanently delete this file?",
       zh: "删除后不可恢复,是否确认删除?",
@@ -224,6 +244,10 @@ export default {
       en: "Delete failed",
       zh: "删除失败",
     },
+    add_fail_msg: {
+      en: "Failed to add new",
+      zh: "新增失败",
+    },
     known: {
       en: "Known",
       zh: "知道了",
@@ -312,6 +336,18 @@ export default {
       en: 'No data available for this date.',
       zh: '该日期暂无数据'
     },
+    request_frequency:{
+      zh:'请求频繁,请数据加载完成后再试!',
+      en:'Request frequency, please try again after the data is loaded!'
+    },
+    please_complete:{
+      en: 'Please fill it out completely',
+      zh: '请填写完整'
+    },
+    name_none: {
+      zh: '名称不能为空',
+      en: 'Name can not be empty'
+    },
   },
   Common: {
     category: {
@@ -370,6 +406,10 @@ export default {
       en: 'No Charts',
       zh: '暂无图表'
     },
+    no_cont_msg: {
+      en: 'No Content',
+      zh: '暂无内容'
+    },
     exp_excel: {
       en: ' Export Excel',
       zh: '导出excel',
@@ -409,7 +449,23 @@ export default {
     sim_hei:{
       en:'SimHei',
       zh:'黑体'
-    }
+    },
+    latest:{
+      en:'latest',
+      zh:'最新'
+    },
+    fixed:{
+      en:'fixed',
+      zh:'固定'
+    },  
+    yes_text: {
+      en: 'Yes',
+      zh: '是'
+    },
+    no_text: {
+      en: 'No',
+      zh: '否'
+    },
   },
   Edb,
   Chart,

+ 52 - 0
src/lang/modules/DataSources/En.js

@@ -217,6 +217,58 @@ export default {
     add_edb_hint:'Max 30 indicators for bulk add!',
     add_edb_check_hint1:'Incomplete Indicator Info',
     add_edb_check_hint2:'Indicator name exists, please re-enter'
+  },
+
+  /* 高频数据 */
+  HighFrequencyData:{
+    add_high_frequency_data:'Add High-Freqcy Data',
+    select_classify_prompt:'Please select category',
+    associative_sub_classify:'Linked to Subcategory',
+    classify_setting:'Classification Settings',
+    add_to_eta_indicators:'Add to ETA Indicators',
+    batch_operation:'Batch Operation',
+    data_source_classify:'Data Source Classification',
+    data_date: 'Date of data',
+    belong_to_classify:'Category',
+    period:'Period',
+    adjustment:'Adjustment',
+    base_point:"Base Point",
+    no_interval_handle:'Non-Trading Interval',
+    move_to_new_classify:'Move to new classification',
+    last_six_hours:'The last 6 hours',
+    refresh_all:'Full refresh (Choose carefully, or it may exceed the quota)',
+
+    data_transformation: "Data Transformation",
+    edb_save:'Indicator Saving',
+    get_point_time:'Value at a Specified Time',
+    today:'Current Day',
+    yesterday:'Previous day',
+    get_range_time:'Interval Calculation',
+    range_average_value:'Interval Average',
+    range_max_value:'Maximum Value',
+    range_min_value:'Minimum Value',
+
+    stock_code_numer_prompt:'The total number of stock codes does not exceed 10.',
+    index_code_numer_prompt:'The total number of indicator codes does not exceed 20.',
+    start_time_right_end_time:'The start time cannot be greater than the deadline.',
+    batch_operation_limit:'The upper limit of batch operation is 500 indicators.',
+    index_has_exist_prompt:'The following indicator names are duplicated with the existing indicators in the indicator library. Please modify the indicator name and confirm.',
+    indicator_been_referenced_prompt:'The indicator has been referenced.',
+
+    no_rehabilitation:'No',
+    forward_rehabilitation_1:'Pre-restoration rights (calculation of dividend plan)',
+    backward_rehabilitation_1:'Post-restoration rights (calculation of dividend plan)',
+    forward_rehabilitation_3:'Pre-restoration rights (calculation of exchange price)',
+    backward_rehabilitation_3:'Post-restoration rights (calculation of exchange price)',
+    forward_rehabilitation_2:'Pre-restoration rights for full circulation (calculation of dividend plan)',
+    backward_rehabilitation_2:'Post-restoration rights for full circulation (calculation of dividend plan)',
+    forward_rehabilitation_4:'Pre-restoration rights for full circulation (calculation of exchange pricen)',
+    backward_rehabilitation_4:'Post-restoration rights for full circulation (calculation of exchange price)',
+
+    original:'Original',
+    previous:'Previous',
+    blank:'Blank',
+
   }
   
 }

+ 51 - 0
src/lang/modules/DataSources/Zh.js

@@ -219,5 +219,56 @@ export default {
     add_edb_hint:'批量添加指标数量不得超过30个!',
     add_edb_check_hint1:'指标信息未填写完整',
     add_edb_check_hint2:'指标名称已存在,请重新填写'
+  },
+
+  /* 高频数据 */
+  HighFrequencyData:{
+    add_high_frequency_data:'添加高频数据',
+    select_classify_prompt:'请选择分类',
+    associative_sub_classify:'关联子分类',
+    classify_setting:'分类设置',
+    add_to_eta_indicators:'批量添加到指标库',
+    batch_operation:'批量操作',
+    data_source_classify:'数据源分类',
+    data_date: '数据日期',
+    belong_to_classify:'所属分类',
+    period:'时间周期',
+    adjustment:"复权方式",
+    base_point:"复权基点",
+    no_interval_handle:'非交易间隔处理',
+    move_to_new_classify:'移动至新分类',
+    last_six_hours:'最近6个小时',
+    refresh_all:'全部刷新(慎选,或超出额度)',
+
+    data_transformation: "数据转换",
+    edb_save:'指标保存',
+    get_point_time:'取指定时间的值',
+    today:'当日',
+    yesterday:'前一日',
+    get_range_time:'区间计算值',
+    range_average_value:'区间均值',
+    range_max_value:'最大值',
+    range_min_value:'最小值',
+
+    stock_code_numer_prompt:'证券代码总数不超过10个',
+    index_code_numer_prompt:'指标代码总数不超过20个',
+    start_time_right_end_time:'起始时间不能大于截止时间',
+    batch_operation_limit:'批量操作的上限为500个指标',
+    index_has_exist_prompt:'以下指标名称与指标库已有指标重复,请修改指标名称后确定',
+    indicator_been_referenced_prompt:'指标已被引用',
+
+    no_rehabilitation:'不复权',
+    forward_rehabilitation_1:'前复权(分红方案计算)',
+    backward_rehabilitation_1:'后复权(分红方案计算)',
+    forward_rehabilitation_3:'前复权(交易所价格计算)',
+    backward_rehabilitation_3:'后复权(交易所价格计算)',
+    forward_rehabilitation_2:'全流通前复权(分红方案计算)',
+    backward_rehabilitation_2:'全流通后复权(分红方案计算)',
+    forward_rehabilitation_4:'全流通前复权(交易所价格计算)',
+    backward_rehabilitation_4:'全流通后复权(交易所价格计算)',
+
+    original:'不处理',
+    previous:'沿用之前数据',
+    blank:'空值',
   }
 }

+ 16 - 0
src/lang/modules/ETATables/commonLang.js

@@ -52,6 +52,18 @@ export default {
       en: "Renewing",
       zh: "更新中...",
     },
+    merge_cell:{
+      en: "Merge Cells",
+      zh: "合并单元格",
+    },
+    unmerge_cell:{
+      en: "Unmerge Cells",
+      zh: "取消合并单元格",
+    },
+    unmerge:{
+      en: "Unmerge",
+      zh: "取消合并",
+    }
   },
   Msg: {
     is_del_table_msg: {
@@ -86,6 +98,10 @@ export default {
       en:'After deletion, this chart will no longer be referenced. Are you sure to delete it?',
       zh:'删除后该图表将不能再引用,确认删除吗?',
     },
+    merge_cell_fail_msg:{
+      en:'Select cells to merge, ensuring that at most one value or relationship exists within the selected cells.',
+      zh:'选择合并的单元格中最多存在一个值或关联关系',
+    },
   },
   Date: {
     monday: {

+ 20 - 0
src/lang/modules/EtaBase/En.js

@@ -29,13 +29,16 @@ export default {
     date_serie: 'Date Series',
     stock_input_pholder: 'Please enter the stock code, only one stock code can be queried at a time',
     edb_input_pholder: 'Please enter the indicator codes, separated by commas for multiple indicator codes',
+    stocks_input_pholder: 'Please enter the stock codes, separated by commas for multiple stock codes',
     edb_wind_tip: 'When entering "CG" in the Wind Financial Terminal, a code generator will pop up, which can be used to obtain codes for other indicators',
     edb_ifind_tip: 'Use Excel iFind plug-in / date series function, according to the selected indicator to obtain the indicator code, futures and stock common code can be ticked below',
     future_common_edb: 'Future Common indicators',
     stock_common_edb: 'Stock Common indicators',
+    option_selectable:'Parameter (Optional)',
     pre_price: 'Previous Closing Price',
     op_price: 'Opening Price',
     high_price: 'Highest Price',
+    average_price: 'Average Price',
     low_price: 'Lowest Price',
     close_price: 'Closing Price',
     settle_price: 'Settlement Price',
@@ -165,6 +168,7 @@ export default {
     table_col_creator:'Creator',
     label_all_check:'Select All List',
     full_metric_name:'Full Metric Name',
+    origin_full_metric_name:'Full name of the original indicator',
     add_to_selections:'Add to Selections',
     serial_num:'Serial Number',
     search_value_days_options:'Search Nearest Value Within 35 Days Before and After',
@@ -209,6 +213,22 @@ export default {
     field_instru: '*Field Description',
     res_show_col1: 'Date',
     res_show_col2: 'Value',
+    opt_tip_btn:'Operation instruction',
+    opt_tip_btn_text:`<div>1. Enter the code in the code input box to invoke the index library indicators for analysis and calculation. After running, output the analysis results:</div>
+    <div>2. Click on the index information, select the data source and search for the index ID/index name, then display the table structure where the index is located, and you can copy and fetch the index code with one click:</div>
+    <div>3. Add a line of code at the end of the calculation for formatted output, where "raw" is the data after final calculation (fill in with actual variable names):</div>
+    <div>result = format_data(raw, "data_time", "value")</div>
+    <div>4. Here is a runnable code example (the code to fetch index data needs to be replaced according to the system query):</div>
+    <br />
+    <div># Fetching Index Data Code:</div>
+    <div>sql1 = f'""'SELECT data_time,\`value\` FROM edb_data_ths WHERE edb_code = 'S004414853' ;'""'</div>
+    <div>raw = pandas_fetch_all(sql1, db)</div>
+    <div># Index Calculation Method Code:</div>
+    <div>raw['value'] = raw['value'] + 1</div>
+    <div># Date Format Conversion Code:</div>
+    <div>raw['data_time'] = raw['data_time'].apply(lambda x: x.strftime("%Y-%m-%d"))</div>
+    <div># Print Calculation Result Code:</div>
+    <div>result = format_data(raw, "data_time", "value")</div>`
   },
 
   /* 数据调整页面 */

+ 20 - 0
src/lang/modules/EtaBase/Zh.js

@@ -29,14 +29,17 @@ export default {
     date_serie: '日期序列',
     stock_input_pholder: '请输入证券代码,每次只查询一个证券代码',
     edb_input_pholder: '请输入指标代码,多个指标代码用英文逗号分隔',
+    stocks_input_pholder: '请输入证券代码,多个证券代码用英文逗号分隔',
     edb_wind_tip: 'wind金融终端输入”CG“会弹出代码生成器,可在代码生成器上获取其他指标的代码',
     edb_ifind_tip: '可用Excel同花顺插件/日期序列功能,根据所选指标获取指标代码,期货和股票常用代码可在下方勾选',
     future_common_edb: '期货常用指标',
     stock_common_edb: '股票常用指标',
+    option_selectable:'参数(可选)',
     pre_price: '前收盘价',
     op_price: '开盘价',
     high_price: '最高价',
     low_price: '最低价',
+    average_price: '均价',
     close_price: '收盘价',
     settle_price: '结算价',
     trade_volume: '成交量',
@@ -165,6 +168,7 @@ export default {
     table_col_creator:'创建人',
     label_all_check:'列表全选',
     full_metric_name:'指标全称',
+    origin_full_metric_name:'原指标全称',
     add_to_selections:'加入已选指标',
     serial_num:'序号',
     search_value_days_options:'查找前后35天最近值',
@@ -210,6 +214,22 @@ export default {
     field_instru: '*字段说明',
     res_show_col1: '日期',
     res_show_col2: '值',
+    opt_tip_btn:'操作说明',
+    opt_tip_btn_text:`<div>1、在代码输入框中输入代码,可调用指标库指标进行分析计算,运行后输出分析结果;</div>
+    <div>2、点击指标信息,选择数据来源并检索指标ID/指标名称后,展示指标所在表结构,可一键复制调取指标代码;</div>
+    <div>3、代码运算的最后需要加一行代码用于格式化输出,其中raw是最后计算后的数据(变量名以实际名填写):</div>
+    <div>result = format_data(raw, "data_time", "value")</div>
+    <div>4、以下是可运行的代码示例(其中调取指标数据代码需根据系统查询替换):</div>
+    <br />
+    <div>#调取指标数据代码:</div>
+    <div>sql1 = f'""'SELECT data_time,\`value\` FROM edb_data_ths WHERE edb_code = 'S004414853' ;'""'</div>
+    <div>raw = pandas_fetch_all(sql1, db)</div>
+    <div>#指标计算方式代码:</div>
+    <div>raw['value'] = raw['value'] + 1</div>
+    <div>#日期格式转化代码:</div>
+    <div>raw['data_time'] = raw['data_time'].apply(lambda x: x.strftime("%Y-%m-%d"))</div>
+    <div>#打印运算结果代码:</div>
+    <div>result = format_data(raw, "data_time", "value")</div>`
   },
 
   /* 数据调整页面 */

+ 42 - 3
src/lang/modules/EtaBase/commonLang.js

@@ -48,6 +48,10 @@ export default {
     zh:'查看数据',
     en:'View indicators'
   },
+  detail_lookdata2_btn: {
+    zh:'查看详情',
+    en:'View indicators'
+  },
   detail_formula_btn: {
     zh:'查看公式',
     en:'Formula'
@@ -192,10 +196,18 @@ export default {
       zh:'指标目录',
       en:'Data Catalogue'
     },
+    e_catalogue: {
+      zh:'目录',
+      en:'Catalogue'
+    },
     e_start_time: {
       zh:'起始时间',
       en:'Start Time'
     },
+    e_deadline_time: {
+      zh:'截止时间',
+      en:'Deadline'
+    },
     e_end_time: {
       zh: '结束时间',
       en: 'End Time'
@@ -206,7 +218,7 @@ export default {
     },
     e_status: {
       zh:'刷新状态',
-      en:'Update Status'
+      en:'Refresh Status'
     },
     e_latest_date: {
       zh:'最新日期',
@@ -216,6 +228,10 @@ export default {
       zh:'起始日期',
       en:'Start Date'
     },
+    e_creator: {
+      zh:'创建人',
+      en:'Creator'
+    },
     e_latest_value: {
       zh:'最新值',
       en:'Latest Value'
@@ -224,9 +240,21 @@ export default {
       zh:'最近更新',
       en:'Recent Update'
     },
+    e_start_time_whole:{
+      zh:'指标开始时间',
+      en:'Indicator Start Time'
+    },
+    e_latest_time_whole:{
+      zh:'指标最新时间',
+      en:'Indicator Latest Time'
+    },
     e_stock_code: {
       zh:'证券代码',
-      en:' Security Code'
+      en:'Security Code'
+    },
+    e_indicator_code: {
+      zh:'指标代码',
+      en:'Indicator Code'
     },
     e_opera: {
       zh:'操作',
@@ -268,6 +296,10 @@ export default {
       zh:'所属目录',
       en:'catalogue'
     },
+    calculation_mode:{
+      zh:'计算方式',
+      en:'Calculation Method'
+    },
   },
 
   /* 单位 */
@@ -724,6 +756,10 @@ export default {
       zh: '请选择日期',
       en: 'Please select date'
     },
+    input_time: {
+      zh: '请选择时间',
+      en: 'Please select time'
+    },
     select_edb_name:{
       zh: '请选择指标名称',
       en: 'Please select an indicator name'
@@ -751,8 +787,11 @@ export default {
     input_value: {
       zh: '请输入值',
       en: 'Please input a value'
+    },
+    select_creator: {
+      zh: '请选择创建人',
+      en: 'Please select creator'
     }
-    
   },
   
   /* 公示说明 */

+ 37 - 0
src/lang/modules/EtaChart/En.js

@@ -28,6 +28,13 @@ export default {
       1、If the start date is earlier than the end date, the default is not to cross the year, and you can check the check box to cross the year.</br>
       2、If the start date is later than or equal to the end date, it will cross the year and the check is not allowed.
     `,
+    dynamic_time_tip:`
+    <p>Purpose: To set a dynamically updating end time based on the system date or the latest date of the indicator.</p>
+    <p> For example, the end of the last month, this "end of the month" will dynamically update as the latest date is updated. </p>
+    <p>Method: 1. Select the base date. The default is the system date (the current natural date), or you can choose the latest date of the indicator (which updates with the indicator).</p>
+    <p> On the premise of choosing the latest date of the indicator, you can perform period shifting, assuming a shift of 1 period, then select the date of the previous period of the indicator.</p> 
+    <p>2. Based on the base date, you can perform date transformations. The transformation methods include date displacement and specified frequency, which can be freely combined.</p>
+    <p> The default is to specify a frequency (the first day of the current month) plus a date transformation (-1 day), which means to provide the end date of the last month. </p>`,
     label_cross_year:'Cross the year',
     label_legend_set:'Legend Name Settings',
     no_set_msg: 'No configuration available',
@@ -51,6 +58,10 @@ export default {
     edit_plotline_btn: 'Edit Marker Line',
     edit_plotarea_btn: 'Edit Marker Area',
     add_intro_btn: 'Add Chart Description',
+    add_right_edb_btn:'Add Right Axis',
+    limits_btn:'Limits Area',
+    avg_line_btn:'Average Line',
+    std_btn:'StdEV Area',
     label_select_serie:'Select axis',
     label_select_seris_placeholder:'Please select the date axis',
     label_line_scale:'Marker line position',
@@ -67,6 +78,32 @@ export default {
     section_pos_top: 'Top',
     section_pos_center: 'Center',
     section_pos_bot: 'Bottom',
+    right_edb_type_on_year:'Left Axis Year-on-Year',
+    right_edb_type_lib:'Indicator Library',
+    right_edb_type_pred:'Predictive Indicators',
+    right_edb_gen_style:'Generate Style',
+    right_edb_gen_column:'Column',
+    right_edb_gen_mark:'Mark Point',
+    right_edb_mark_shape:'Mark Point Shape',
+    right_edb_color_set:'Color and transparency',
+    right_edb_mark_size:'Mark Point Size',
+    right_edb_legend:'Legend Name',
+    right_edb_format:'Number Format',
+    right_edb_format_per:'Percent',
+    right_edb_format_dec:'Decimal',
+    right_edb_mark_connect_text:'Mark Point Line',
+    right_edb_mark_connected:'Connected',
+    right_edb_mark_not_connected:'Not Connected',
+    right_edb_mark_connect_line_color:'Line Color',
+    right_edb_mark_connect_line_style:'Line Style',
+    right_edb_mark_connect_line_width:'Line Width',
+    limit_range:'Range of Limits',
+    average_range:'Range of Average',
+    std_range:'Range of STDEV',
+    year_placeholder:'Please enter year',
+    linewidth_placeholder:'Please enter line width',
+    multiple_placeholder:'Please enter the multiple',
+    year_on_right:'Year On Year(Right Axis)',
 
     //截面散点图区域
     label_serie_set:'Series {index} Configuration',

+ 34 - 0
src/lang/modules/EtaChart/Zh.js

@@ -28,6 +28,10 @@ export default {
       1、若开始日期小于结束日期,则默认不跨年,允许勾选跨年</br>
       2、若开始日期大于等于结束日期,则跨年,不允许取消勾选
     `,
+    dynamic_time_tip:`<p>配置目的:根据系统日期或者指标最新日期,设置一个动态更新的结束时间。比如上个月的月末,这个“月末”会随着最新日期的更新而动态更新。</p>
+    <p>配置方法:1、选择基准日期。默认选则系统日期(当前的自然日期),也可选指标最新日期(跟随指标的更新而更新)。在选择指标最新日期的前提下,可进行期数前移,假设前移1期,则选择指标上一期的日期。</p>
+    <p>2、根据基准日期,可进行日期变换。变换方式有日期位移和指定频率两种,可自由组合。默认给出指定频率(当月第一天)加日期变换(-1天),意味着给出上个月的月末日期。</p>
+    <p>配置示例:把起始日期设置在指标最新日期所在年份上一年的年末。基准日期选则指标最新日期,日期变换添加指定频率为当年第一天,再添加日期位移为-1。</p>`,
     label_cross_year:'跨年',
     label_legend_set:'图例名称设置',
     no_set_msg: '暂无配置',
@@ -51,6 +55,10 @@ export default {
     edit_plotline_btn: '编辑标识线',
     edit_plotarea_btn: '编辑标识区',
     add_intro_btn: '添加图表说明',
+    add_right_edb_btn:'添加右轴指标',
+    limits_btn:'同期上下限',
+    avg_line_btn:'同期均线',
+    std_btn:'同期标准差',
     label_select_serie:'选择坐标轴',
     label_select_seris_placeholder:'请选择日期坐标轴',
     label_line_scale:'标识线所在刻度',
@@ -67,6 +75,32 @@ export default {
     section_pos_top: '顶部',
     section_pos_center: '居中',
     section_pos_bot: '底部',
+    right_edb_type_on_year:'左轴指标同比',
+    right_edb_type_lib:'指标库',
+    right_edb_type_pred:'预测指标',
+    right_edb_gen_style:'生成样式',
+    right_edb_gen_column:'柱形',
+    right_edb_gen_mark:'标记点',
+    right_edb_mark_shape:'标记点形状',
+    right_edb_color_set:'颜色及透明度',
+    right_edb_mark_size:'标记点大小',
+    right_edb_legend:'图例名称',
+    right_edb_format:'数字格式',
+    right_edb_format_per:'百分数',
+    right_edb_format_dec:'小数',
+    right_edb_mark_connect_text:'标记点连线',
+    right_edb_mark_connected:'有',
+    right_edb_mark_not_connected:'无',
+    right_edb_mark_connect_line_color:'连线颜色',
+    right_edb_mark_connect_line_style:'连线线型',
+    right_edb_mark_connect_line_width:'连线粗细',
+    limit_range:'上下限取数范围',
+    average_range:'均线取数范围',
+    std_range:'取数范围',
+    year_placeholder:'请输入年份',
+    linewidth_placeholder:'请输入线宽',
+    multiple_placeholder:'请输入倍数',
+    year_on_right:'同比(右轴)',
 
     //截面散点图区域
     label_serie_set:'系列{index}配置',

+ 110 - 0
src/lang/modules/EtaChart/commonLang.js

@@ -56,6 +56,10 @@ export default {
     zh: '农历',
     en: 'Lunar Calendar'
   },
+  calendar_lunar_text: {
+    zh: '春节对齐',
+    en: 'Lunar Calendar'
+  },
   chart_share_btn:{
     zh:'分享',
     en:'Share'
@@ -456,7 +460,113 @@ export default {
     text_size: {
       zh:'字号',
       en:'Size'
+    },
+    chart_first_edb:{
+        zh:'图上第一个指标',
+        en:'The first indicator on the graph'
+    },
+    chart_other_edb:{
+        zh:'其他指标',
+        en:'Other indicator',
+    },
+    time_interval:{
+        zh:'时间区间',
+        en:'Time Interval'
+    },
+    follow_chart:{
+        zh:'跟随图表',
+        en:'follow the chart'
+    },
+    custom:{
+        zh:'自定义',
+        en:'custom'
+    },
+    plot_style:{
+        zh:'样式',
+        en:'style'
+    },
+    plot_calculation:{
+        zh:'计算方式',
+        en:'Calculation'
+    },
+    cal_range_val:{
+        zh:'区间',
+        en:'Range'
+    },
+    cal_range_mean:{
+        zh:'均值',
+        en:'Mean'
+    },
+    cal_range_plus:{
+        zh:'加',
+        en:'Plus'
+    },
+    cal_range_times:{
+        zh:'倍',
+        en:'times'
+    },
+    cal_range_times2:{
+        zh:'倍数',
+        en:'times'
+    },
+    cal_range_std:{
+        zh:'标准差',
+        en:'STDEV'
+    },
+    cal_range_count:{
+        zh:'个数',
+        en:'Count'
+    },
+    cal_range_value:{
+        zh:'数值',
+        en:'Value'
+    },
+    cal_range_quantile:{
+        zh:'分位',
+        en:'Quantile'
+    },
+    time_base:{
+        zh:'基准日期',
+        en:'Base Date'
+    },
+    sys_time:{
+        zh:'系统日期',
+        en:'System Date'
+    },
+    edb_new_time:{
+        zh:'指标最新日期',
+        en:'Indicator Latest Date'
+    },
+    edb_periods:{
+        zh:'期数',
+        en:'periods'
+    },
+    edb_periods_lead:{
+        zh:'前移',
+        en:' forward lead'
+    },
+    edb_period:{
+        zh:'期',
+        en:'periods'
+    },
+    edb_time_fix:{
+        zh:'固定',
+        en:'Fix'
+    },
+    edb_time_now:{
+        zh:'至今',
+        en:'So Far'
+    },
+    edb_time_dyn:{
+        zh:'动态',
+        en:'Dynamic'
+    },
+    pass_year:{
+        zh:'过去',
+        en:'pass'
     }
+
+
   },
 
   /* form校验 */

+ 4 - 4
src/lang/modules/ReportManagement/CategoryList.js

@@ -104,8 +104,8 @@ export const CategoryListEn = {
     section_settings: "Section Settings",
     add_section: "Add Section",
     edit_section: "Edit Section",
-    section_name: "Section Name",
-    section_name_hint: "Enter Section Name",
+    section_name: "Section Type",
+    section_name_hint: "Enter Section Type",
     parent_category: "Parent Category",
     parent_none: "none",
     related_variety: "Related Variety",
@@ -225,8 +225,8 @@ export const CategoryListZh = {
     section_settings: "章节设置",
     add_section: "添加章节",
     edit_section: "编辑章节",
-    section_name: "章节名称",
-    section_name_hint: "请输入章节名称",
+    section_name: "章节类型",
+    section_name_hint: "请输入章节类型",
     parent_category: "上级分类",
     parent_none:'无',
     related_variety: "关联品种",

+ 117 - 9
src/lang/modules/ReportManagement/ReportList.js

@@ -14,6 +14,8 @@ export const ReportListEn = {
   designated_personnel: "Designated personnel",
   designated_sender_information: "Designated sender information:",
   please_select_personnel: "Please select personnel",
+  pv_detail:'PV Details',
+  uv_detail:'UV Details',
   click_through_details: "Click through details",
   customer_name: "Customer Name",
   email_address: "e-mail address",
@@ -22,8 +24,8 @@ export const ReportListEn = {
   information_title: "Basic information",
   new_report_radio: "New report",
   inherit_report_radio: "Inherit report",
-  please_select_category: "Please select a category",
-  input_title_please: "Please input title",
+  please_select_category: "Please select a Report category",
+  input_title_please: "Please input Report title",
   please_input_abstract: "Please input abstract",
   please_select_author: "Please select the author",
   please_select_frequency: "Please select the frequency",
@@ -34,10 +36,12 @@ export const ReportListEn = {
   no_reports_msg: "There are currently no reports for this category",
   chart_insertion_progress: "Batch chart insertion in progress",
   last_save_time: "Last save time",
+  click_clear_btn: "Clear Content",
   click_refresh_btn: "Rfrsh",
   preview_btn: "Preview",
   save_draft_btn: "Draft",
   scheduled_publish_btn: "Schedule",
+  submit_chapter_btn:'Submit Section',
   publish_btn: "Publish",
   submission_btn: "Submission",
   new_method_btn: "New method",
@@ -55,7 +59,7 @@ export const ReportListEn = {
   intercommodity_analysis_radio: "Cross-Comm",
   just_mine_radio: "Just Mine",
   insert_sandbox_tabs: "Insert Sandbox",
-  no_reports_msg: "Sandbox Name/Commodity",
+  no_sandbox_msg: "Sandbox Name/Commodity",
   insert_table_tabs: "Insert Table",
   table_name_tabs: "Table Name",
   bulk_insertion_tabs: "My gallery batch insert",
@@ -85,7 +89,7 @@ export const ReportListEn = {
   img_uplaod_title: "Image Upload",
   click_img_upload: "Click to Upload Image",
   select_img_card: "Select Image",
-  img_name_ipt: "Please input image name",
+  img_name_ipt: "Please input layout name",
   select_img_type: "Please select an image type",
   page_header_op: "Page Header",
   page_trailer_op: "Page Trailer",
@@ -103,6 +107,7 @@ export const ReportListEn = {
   recorded_audio: "The recording has been uploaded.",
   not_recorded_audio: "The recording has not been uploaded.",
   weChat_share: "WeChat share",
+  copy_share_link:'Copy Link',
   set_tags_title: "Set tags",
   select_ipt_pld: "Enter or select",
   input_email_subject: "Please input email subject",
@@ -118,6 +123,55 @@ export const ReportListEn = {
   upload_img_error_msg: "Some images have not finished uploading, please wait.",
   all_update_publish_msg: "This report's varieties have all been updated. Clicking 'Publish' will also release the weekly report. Are you sure you want to publish both simultaneously?",
   is_publish_report_msg: "You have not uploaded an audio recording file yet. Are you sure you want to publish the report?",
+
+
+
+  tab_public:'Public Research Report',
+  tab_share:'Shared Research Report',
+  tab_mine:'My Research Report',
+  /* 添加报告弹窗 */
+  label_add_way:'Addition Method',
+  label_report_tit:'Report Title',
+  choose_inherit_report: 'Select Inherited Report',
+  label_report_classify:'Report Category',
+  label_relation_variety: 'Associated Varieties',
+  label_report_abstract:'Report Abstract',
+  label_report_author:'Report Author',
+  label_frequency:'Frequency',
+  label_createtime:'CreateTime',
+  label_coop:'Collaboration Method',
+  choose_cooper:'Select Collaborators',
+  coop_own: 'Individual',
+  coop_more: 'Collaborative (Multiple People)',
+  label_report_layout:'Report Layout',
+  layout_default:'Standard Layout',
+  layout_smart:'Intelligent Layout',
+  label_public:'Public Release',
+
+  tit_report_chap:'Research Report Section',
+  btn_add_chap: 'Add Section',
+  /* 添加章节弹窗 */
+  label_chap_name:'Section Name',
+  label_chap_editor:'Editor',
+  tit_choose_inher:'Select Report',
+  ph_report_tit: 'Please input the report title',
+  check_report_len: 'Only one report can be selected',
+  ph_select_user: 'Please select user',
+  del_chapter_msg: 'Are you sure you want to delete this section?',
+  report_empty_msg:'Please input the report content',
+  img_set_btn: 'Layout Settings',
+  no_chapter_msg:'No section information available',
+  chapter_nosubmit_msg:'{name},the content of the section has not been submitted',
+
+  choose_head_img:'Select Header',
+  choose_end_img:'Select Footer',
+  canvas_set:'Canvas Settings',
+  choose_layout_img:'Select Layout',
+  variety_tip:`If a section is associated with a variety, then the reading permissions for the section are controlled by the permissions of the associated variety;<br>
+  If a section is not associated with any variety, then the reading permissions for the section are controlled by the permissions of the category-associated varieties;`,
+  chapter_has_submit:'Submitted',
+  chapter_no_submit:'Not Submitted',
+  choose_msg: 'Choose'
 };
 
 /* 中文 */
@@ -132,16 +186,18 @@ export const ReportListZh = {
   designated_personnel: "指定人员",
   designated_sender_information: "指定发送人员信息:",
   please_select_personnel: "请选择人员",
+  pv_detail:'PV详情',
+  uv_detail:'UV详情',
   click_through_details: "点击量详情",
-  click_through_details: "客户名称",
+  customer_name:"客户名称",
   email_address: "邮箱地址",
   Last_click_time: "最近点击时间",
   hits_btn: "点击量",
   information_title: "基础信息",
   new_report_radio: "新增报告",
   inherit_report_radio: "继承报告",
-  please_select_category: "请选择分类",
-  input_title_please: "请输入标题",
+  please_select_category: "请选择报告分类",
+  input_title_please: "请输入报告标题",
   please_input_abstract: "请输入摘要",
   please_select_author: "请选择作者",
   please_select_frequency: "请选择频度",
@@ -152,10 +208,12 @@ export const ReportListZh = {
   no_reports_msg: "此分类暂无报告",
   chart_insertion_progress: "图表批量插入中...",
   last_save_time: "最近保存时间",
+  click_clear_btn: "一键清空内容",
   click_refresh_btn: "一键刷新",
   preview_btn: "预览",
   save_draft_btn: "存草稿",
   scheduled_publish_btn: "定时发布",
+  submit_chapter_btn:'提交章节',
   publish_btn: "发布",
   submission_btn: "提交",
   new_method_btn: "新增方式",
@@ -174,7 +232,7 @@ export const ReportListZh = {
   intercommodity_analysis_radio: "跨品种分析",
   just_mine_radio: "只看我的",
   insert_sandbox_tabs: "沙盘插入",
-  no_reports_msg: "沙盘名称/品种",
+  no_sandbox_msg: "沙盘名称/品种",
   insert_table_tabs: "表格插入",
   table_name_tabs: "表格名称",
   bulk_insertion_tabs: "我的图库批量插入",
@@ -204,7 +262,7 @@ export const ReportListZh = {
   img_uplaod_title: "图片上传",
   click_img_upload: "点击上传图片",
   select_img_card: "选择图片",
-  img_name_ipt: "请输入图名称",
+  img_name_ipt: "请输入图名称",
   select_img_type: "请选择图片类型",
   page_header_op: "版头",
   page_trailer_op: "版尾",
@@ -222,6 +280,7 @@ export const ReportListZh = {
   recorded_audio: "已传录音",
   not_recorded_audio: "未传录音",
   weChat_share: "微信分享",
+  copy_share_link:'复制链接',
   set_tags_title: "设置标签",
   select_ipt_pld: "输入或者选择",
   input_email_subject: "请输入邮件主题",
@@ -236,4 +295,53 @@ export const ReportListZh = {
   upload_img_error_msg: "有图片未上传完成,请稍等",
   all_update_publish_msg: "本期报告品种已全部更新,点击发布将同时发布周报,确认同时发布吗?",
   is_publish_report_msg: "您还未上传录音文件,确定发布报告吗?",
+
+
+
+  tab_public:'公共研报',
+  tab_share:'共享研报',
+  tab_mine:'我的研报',
+  /* 添加报告弹窗 */
+  label_add_way:'新增方式',
+  label_report_tit:'报告标题',
+  choose_inherit_report: '选择继承报告',
+  label_report_classify:'报告分类',
+  label_relation_variety: '关联品种',
+  label_report_abstract:'报告摘要',
+  label_report_author:'报告作者',
+  label_frequency:'频度',
+  label_createtime:'创建时间',
+  label_coop:'协作方式',
+  choose_cooper:'选择协作人',
+  coop_own: '个人',
+  coop_more: '多人协作',
+  label_report_layout:'报告布局',
+  layout_default:'常规布局',
+  layout_smart:'智能布局',
+  label_public:'公开发布',
+
+  tit_report_chap:'研报章节',
+  btn_add_chap: '添加章节',
+  /* 添加章节弹窗 */
+  label_chap_name:'章节名称',
+  label_chap_editor:'编辑人',
+  tit_choose_inher:'选择报告',
+  ph_report_tit: '请输入报告标题',
+  check_report_len: '只能选择一篇报告',
+  ph_select_user: '请选择用户',
+  del_chapter_msg: '是否确认删除该章节?',
+  report_empty_msg:'请输入报告内容',
+  img_set_btn: '版图设置',
+  no_chapter_msg:'暂无章节信息',
+  chapter_nosubmit_msg:'{name}内容未提交',
+
+  choose_head_img:'选择版头',
+  choose_end_img:'选择版尾',
+  canvas_set:'画布设置',
+  choose_layout_img:'选择版图',
+  variety_tip:`若章节关联品种,则章节阅读权限受章节关联品种的权限控制;<br>
+  若章节不关联品种,则章节阅读权限受分类关联品种的权限控制;`,
+  chapter_has_submit:'已提交',
+  chapter_no_submit:'未提交',
+  choose_msg: '选择'
 };

+ 4 - 4
src/lang/modules/ReportManagement/SmartReport.js

@@ -35,7 +35,7 @@ export const SmartReportEn = {
   smart_notification_pushed: "Notification Pushed",
   smart_filtering_criteria_btn: "Filter options",
   smart_title_creator_btn: "Title/Creator",
-  smart_report_type: "Report type",
+  smart_report_type: "Category",
   smart_creator_btn: "Creator",
   table_col02:'Operator',
   smart_release_approval_time: "Release/Approval Time",
@@ -52,7 +52,7 @@ export const SmartReportEn = {
   smart_release_prompt_btn: "Release prompt",
   smart_template_msg: "The report has been set to be released regularly. Do you want to publish the report immediately and push the template message?",
   smart_push_template_btn: "Do you want to publish the report immediately and push template messages?",
-  smart_status_table: "status",
+  smart_status_table: "Report status",
   smart_abstract_table: "Abstract",
   smart_select_file: "Select file",
   smart_sync_policy_report: "Sync Policy Report",
@@ -163,7 +163,7 @@ export const SmartReportZh = {
   smart_notification_pushed: "已推送消息",
   smart_filtering_criteria_btn: "筛选条件",
   smart_title_creator_btn: "标题 / 创建人",
-  smart_report_type: "报告类型",
+  smart_report_type: "分类",
   smart_creator_btn: "创建人",
   table_col02:'更新人',
   smart_release_approval_time: "发布/审批时间",
@@ -180,7 +180,7 @@ export const SmartReportZh = {
   smart_release_prompt_btn: "发布提示",
   smart_template_msg: "该报告已设置定时发布,是否立即发布报告并推送模板消息?",
   smart_push_template_btn: "是否立即发布报告,并推送模板消息?",
-  smart_status_table: "状态",
+  smart_status_table: "报告状态",
   smart_abstract_table: "摘要",
   smart_select_file: "选择文件",
   smart_sync_policy_report: "同步策略报告",

+ 4 - 2
src/lang/modules/Slides/pptPresent.js

@@ -103,7 +103,8 @@ export const presentEn = {
   apply_to_the_entire:'Apply to the entire PPT',
   title_style_fontfamily:"Font Family",
   title_style_fontsize:'Font Size',
-  title_style_color:'Font Color'
+  title_style_color:'Font Color',
+  title_paste_hint:'The clipboard is empty, please paste the text',
 };
 
 /* 中文 */
@@ -207,7 +208,8 @@ export const presentZh = {
   apply_to_the_entire:'应用至整个PPT',
   title_style_fontfamily:"字体设置",
   title_style_fontsize:'字号设置',
-  title_style_color:'字体颜色'
+  title_style_color:'字体颜色',
+  title_paste_hint:'粘贴板获取为空,请粘贴文本',
 };
 
 /**

+ 73 - 2
src/lang/modules/StatisticAnalysis/ChartRelevance.js

@@ -34,7 +34,31 @@ export const ChartRelevanceEn = {
     update_edb:'update',
     update_success:'Update success',
     chart_save_as:'Save Chart As',
-    check_value_hint:'Correlation calculation window must be ≥2* analysis period'
+    check_value_hint:'Correlation calculation window must be ≥2* analysis period',
+
+    analytical_model:'Mode',
+    single_indicator:'Single Indicator',
+    multiple_indicators:'Multiple Indicators',
+    target_indicator:'Target Indicator',
+    factor_indicators:'Factor Indicators',
+    add_factor_indicators:'Add factor indicators',
+
+    multiple_table_head_01:'Correlation matrix with the Target Indicator',
+    multiple_table_head_02:'Original Indicator name',
+    multiple_table_head_03:'Number of leading periods({unit})', //$t('xxx',{unit:''})
+    multiple_table_btn_add:'Add Curve',
+    multiple_table_btn_del:'Del Curve',
+    chart_curve_add_hint:'Only 10 curves are supported',
+    infoform_rules_hint_01:'IndexA not selected',
+    infoform_rules_hint_02:'IndexB not selected',
+    infoform_rules_hint_03:'Target Index not selected',
+    infoform_rules_hint_04:'Calculation Window not filled in',
+    infoform_rules_hint_05:'Analysis Period not filled in',
+    formula_add_btn:'Add Formula',
+    series_name:'Index Series Name',
+    series_name_placeholder:'Input Index Series Name',
+    formulaform_add_hint:'Only 5 formulas are supported',
+    batch_select_hint:'Please Select Index',
 };
   
 /* 中文 */
@@ -70,7 +94,54 @@ export const ChartRelevanceZh = {
     update_success:'更新成功',
     chart_save_as:'图表另存为',
 
-    check_value_hint:'相关性计算窗口必须≥2*分析周期'
+    check_value_hint:'相关性计算窗口必须≥2*分析周期',
+
+    analytical_model:'分析模式',
+    single_indicator:'单因子',
+    multiple_indicators:'多因子',
+    target_indicator:'标的指标',
+    factor_indicators:'因子指标系列',
+    add_factor_indicators:'添加因子指标系列',
+    /**
+     * Chart.ChartType
+     * 曲线图:spline_name
+     * 相关性:correlation_name
+     * 滚动相关性:rolling_correlation_name
+     * Chart
+     * 请选择时间段:choose_time
+     * 
+     * 操作 Edb.Detail.e_opera
+     * 数据来源 Edb.Detail.source
+     * 暂无信息 Common.no_info_msg
+     * 加入已选指标 EtaBasePage.add_to_selections
+     * N不能为空 Edb.Valids.n_msg
+     * alpha值不能为空 Edb.Valids.alpha_msg
+     */
+    multiple_table_head_01:'与标的指标的相关性矩阵',
+    multiple_table_head_02:'原始指标名称',
+    multiple_table_head_03:'领先期数({unit})', //$t('xxx',{unit:''})
+    multiple_table_btn_add:'添加曲线',
+    multiple_table_btn_del:'删除曲线',
+    chart_curve_add_hint:'最多只支持添加10条曲线',
+    infoform_rules_hint_01:'指标A未选择',
+    infoform_rules_hint_02:'指标B未选择',
+    infoform_rules_hint_03:'标的指标未选择',
+    infoform_rules_hint_04:'计算窗口未填写',
+    infoform_rules_hint_05:'分析周期未填写',
+    formula_add_btn:'添加计算公式',
+    series_name:'指标系列名称',
+    series_name_placeholder:'请输入指标系列名称',
+    formulaform_add_hint:'最多仅能添加5个计算公式',
+    batch_select_hint:'请选择需要添加的指标',
+
+
+
+
+
+
+
+
+
 };
   
 /**

+ 59 - 0
src/lang/modules/systemManage/DataRefresh.js

@@ -25,9 +25,11 @@ export const DataRefreshZh = {
 
   terminal_code_select: "终端编码",
   eta_class_select: "ETA指标库分类",
+  edb_classify: "指标库分类",
   enable_op: "启用刷新",
   pause_op: "暂停刷新",
   all_list: "列表全选",
+  selected:"已选",
   set_time: "设置刷新时间",
   please_select: "请选择",
   set_status: "设置刷新状态",
@@ -43,6 +45,17 @@ export const DataRefreshZh = {
   table_creator: "创建人",
   table_status: "刷新状态",
 
+  table_Id:"指标ID",
+  table_recent_reference_time:"最近引用时间",
+  table_reference_count:"引用次数",
+  table_refresh_status:"刷新状态",
+  enabled:"启用",
+  disabled:"停用",
+
+  reference_time:"引用时间",
+  reference_source:"引用来源",
+  reference_chart_table:"引用图表/表格",
+
   refresh_rate: "刷新频率",
   trading_day: "每交易日",
   daily_date: "每自然日",
@@ -56,6 +69,23 @@ export const DataRefreshZh = {
   last_day: "最后一天",
   select_refresh_rate: "请选择刷新频率",
   select_refresh_time: "请选择刷新时间",
+
+  time_setting_tab:"刷新时间设置",
+  status_setting_tab:"刷新状态设置",
+  enable:"启用",
+  disable:"停用",
+
+  default_refresh_rule:"默认刷新规则",
+  set_default_refresh_rule:"设置默认刷新规则",
+  disableRulePrompt:"关闭配置后,指标将不会自动处理为停用",
+  enable_configuration:"启用配置",
+  baseIndexStopDays_hint_front:"数据源间隔",
+  baseIndexStopDays_hint_behind:"天未加入指标库则停用",
+  edbStopDays_hint_front:"指标库间隔",
+  edbStopDays_hint_behind:"天未引用则停用",
+  IntervalDaysError:"请输入正确的格式",
+  disable_indicator_prompt:"停用后该数据将停止刷新,是否继续操作?",
+  status_rule_prompt:"只针对wind和钢联化工指标生效"
 };
 
 /* 英文 */
@@ -77,9 +107,11 @@ export const DataRefreshEn = {
 
   terminal_code_select: "Terminal Code",
   eta_class_select: "ETA Indicator Library Classification",
+  edb_classify: "Indicator Library Classification",
   enable_op: "Enable Refresh",
   pause_op: "Pause Refresh",
   all_list: "Select All in List",
+  selected: "Selected",
   set_time: "Set Refresh Time",
   please_select: "Please Select",
   set_status: "Set Refresh Status",
@@ -95,6 +127,16 @@ export const DataRefreshEn = {
   table_creator: "Creator",
   table_status: "Refresh Status",
 
+  table_Id:"Indicator ID",
+  table_recent_reference_time:"Recent Reference Time",
+  table_reference_count:"Reference Count",
+  table_refresh_status:"Refresh Status",
+  enabled:"Enabled",
+  disabled:"Disabled",
+  
+  reference_time:"Reference Time",
+  reference_source:"Reference Source",
+  reference_chart_table:"Refer to the chart/table",
 
   refresh_rate: "Refresh Rate",
   trading_day: "Every Trading Day",
@@ -109,4 +151,21 @@ export const DataRefreshEn = {
   last_day: "Last Day",
   select_refresh_rate: "Please select a refresh rate",
   select_refresh_time: "Please select a refresh time",
+
+  time_setting_tab:"Refresh Time Setting",
+  status_setting_tab:"Refresh Status Setting",
+  enable:"Enable",
+  disable:"Disable",
+
+  default_refresh_rule:"Default Refresh Rules",
+  set_default_refresh_rule:"Set Default Refresh Rules",
+  enable_configuration:"Enable configuration",
+  baseIndexStopDays_hint_front:"If a data source has not been added to the metric repository for",
+  baseIndexStopDays_hint_behind:"days, it will be deactivated.",
+  edbStopDays_hint_front:"If the metric repository has not been referenced for",
+  edbStopDays_hint_behind:"days, it will be deactivated.",
+  disableRulePrompt:"After closing the configuration, metrics will not be automatically processed as disabled",
+  IntervalDaysError:"Please enter the correct format",
+  disable_indicator_prompt:"After disabling, the data will stop refreshing. Do you want to continue?",
+  status_rule_prompt:"Only effective for Wind and Ganglian Chemical indicators."
 };

+ 2 - 2
src/lang/modules/systemManage/ReportApprove.js

@@ -30,7 +30,7 @@ export const ReportApproveEn = {
     approval_type03:'Or Sign (Approval or rejection by any one approver is sufficient)',
     des01:'Multiple approvers review and approve in sequence; The node passes only when all approvers agree; Approve in order of selection',
     des02:'The node passes only when all approvers agree; There is no sequence in approval.',
-    des03:'If any approver agrees, the node wil pass; There is no sequence in approval.',
+    des03:'Approval by one reviewer is sufficient.',
     warning_msg01:'Please select at least one person',
     search_btn:'Search',
     has_selected:'has been selected',
@@ -65,7 +65,7 @@ export const ReportApproveZh = {
     approval_type03:'或签(一名审批人同意或拒绝即可)',
     des01:'多个审批人依次进行审批;只有当所有审批人同意,该节点才能通过;按选择顺序审批',
     des02:'所有审批人同意,该节点才能通过;审批无先后顺序',
-    des03:'任意一名审批人同意,该节点即通过;审批无先后顺序',
+    des03:'一名审批人同意即可',
     warning_msg01:'请至少选择一人',
     search_btn:'搜索',
     has_selected:'项',

+ 5 - 2
src/mixins/reportApproveConfig.js

@@ -43,14 +43,17 @@ export default{
             const {IsReportApprove='',ReportApproveType=''} = res.Data
             this.IsReportApprove = IsReportApprove==='true'?true:false,
             this.ReportApproveType = ReportApproveType
+
+            console.log(this.isApprove)
         },
         //检查是否有审批流
         checkClassifyNameArr(type=1,classify=[]){
             this.checkLoading=true
             let params = {
                 ReportType:type,
-                ClassifyFirstId:classify[classify.length-2]||0,
-                ClassifySecondId:classify[classify.length-1]||0,
+                ClassifyFirstId:classify[0]||0,
+                ClassifySecondId:classify[1]||0,
+                ClassifyThirId:classify[2]||0,
             }
             approveInterence.checkClassifyApprove(params).then(res=>{
                 this.checkLoading=false

+ 11 - 0
src/routes/modules/chartRoutes.js

@@ -381,6 +381,17 @@ export default [
 					pathName_en:"Correlation analysis"
 				}
 			},
+			{
+				path: 'relevancechartEditorV2',
+				name: '编辑图表',
+				component:()=>import('@/views/chartRelevance_manage/relevance/relevanceChartEditorV2.vue'),
+				meta: {
+					name_en:"edit Correlation analysis",
+					pathFrom: "chartrelevance",
+					pathName: "相关性图表",
+					pathName_en:"Correlation analysis"
+				}
+			},
 			{
 				path: 'statisticFeatureList',
 				name: '统计特征',

+ 16 - 0
src/routes/modules/dataRoutes.js

@@ -340,6 +340,22 @@ export default [
           name_en:'CCF Fiber Info'
         },
       },
+      {
+        path: "windbase",
+        component: () => import("@/views/dataEntry_manage/thirdBase/Wind.vue"),
+        name: "Wind",
+        meta:{
+          name_en:'Wind'
+        },
+      },
+      {
+        path: "highFrequencyData",
+        component: () => import("@/views/dataEntry_manage/thirdBase/highFrequencyData.vue"),
+        name: "高频数据",
+        meta:{
+          name_en:'High Frequency Data'
+        }
+      },
     ],
   },
 ];

+ 28 - 16
src/routes/modules/oldRoutes.js

@@ -62,7 +62,26 @@ export default [
   {
     path: "/smartReportDetail",
     name: "智能报告",
-    component: () => import("@/views/smartReport/reportDetail.vue"),
+    component: () => import("@/views/report_manage/reportV2/smartReport/reportDetail.vue"),
+  },
+
+
+  {
+    path: '/reportEditV2',
+    name:'编辑研报',
+    component: () => import("@/views/report_manage/reportV2/normalReport/editReport.vue")
+  },
+  {
+    path: '/smpartReportEditV2',
+    name:'编辑研报',
+    component: () => import("@/views/report_manage/reportV2/smartReport/editReport.vue")
+  },
+
+  {
+    path: "/reportdtlV2",
+    component: () => import("@/views/report_manage/reportV2/normalReport/reportdtl.vue"),
+    name: "预览报告",
+    hidden: true,
   },
 
   // 主页
@@ -200,21 +219,6 @@ export default [
           pathName_en:"Add/Edit Day or Week Report"
         },
       },
-      // {
-      //   path: "reportupdate",
-      //   component: () => import("@/views/report_manage/dayWeekUpdate.vue"),
-      //   name: "更新管理",
-      //   hidden: true,
-      //   meta: {
-      //     keepAlive: false,
-      //   },
-      // },
-      // {
-      //   path: "reportlabel",
-      //   component: () => import("@/views/report_manage/tagLib.vue"),
-      //   name: "标签库",
-      //   hidden: true,
-      // },
       {
         path: "reportEnList",
         component: () =>
@@ -306,6 +310,14 @@ export default [
             name_en:"Smart Report"
         }
       },
+      {
+        path: 'reportNew',
+        name:'研报中心',
+        component: () => import("@/views/report_manage/reportV2/list.vue"),
+        meta:{
+          name_en:"Report Center"
+        }
+      }
     ],
   },
 

+ 7 - 0
src/styles/global.scss

@@ -153,4 +153,11 @@ button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusri
     .chart-instruction {
         width:30%;
     }
+}
+// 联级选择器 浮窗高度拉高
+.el-cascader-menu__wrap{
+    height: calc(100% + 7px);
+    // height: auto;    
+    max-height: 408px;
+    // overflow-x: auto;
 }

+ 21 - 1
src/utils/buttonConfig.js

@@ -33,8 +33,15 @@ export const reportManageBtn={
     reportManage_reportList:'reportManage:reportList',//研报列表的选项
     reportManage_reportList_uv:'reportManage:reportList:uv',//研报列表-PV/UV
     reportManage_reportList_sendTime:'reportManage:reportList:sendTime',//研报列表-报告推送时间
-    reportManage_dayWeekReportAdd:'reportManage:dayWeekReportAdd',//添加晨报周报
+    // reportManage_dayWeekReportAdd:'reportManage:dayWeekReportAdd',//添加晨报周报
     reportManage_reportAdd:'reportManage:reportAdd',//添加研报
+
+    reportManage_clearCont:'reportMange:clearCont',//一键清空内容
+
+    reportMange_chapter_add: 'reportMange:chapter:add',//章节添加
+    reportMange_chapter_sort: 'reportMange:chapter:sort',//章节排序
+    reportMange_chapter_share: 'reportMange:chapter:share',//章节分享
+    reportMange_chapter_editTag: 'reportMange:chapter:editTag',//章节添加标签
 }
 /*
  *--------智能研报列表----------- 
@@ -271,12 +278,23 @@ export const dataSourcePermission = {
     Bloomberg_add2edb:'Bloomberg:add2edb',//添加指标库
     /* 自有数据 */
     selfData_addEdb:'selfData:addEdb',//添加到指标库
+    selfData_detail:'selfData:detail',//查看详情
     /*--------卓创资讯---- */
     zczx_showData:'zczx:showData',
     zczx_exportData:'zczx:exportData',
     /*--------CCF化纤信息--- */
     ccfData_view:'ccfData:view',//查看
     ccfData_exportExcel:'ccfData:exportExcel',//导出
+    /*--------高频数据--- */
+    highFrequency_adds:'highFrequency:adds',//添加高频数据
+    highFrequency_addTo_database:'highFrequency:addTo:database',//批量添加至指标库
+    highFrequency_operations:'highFrequency:operations',//批量操作
+    highFrequency_operation_detail:'highFrequency:operation:detail',//操作-详情
+    highFrequency_operation_refresh:'highFrequency:operation:refresh',//操作-刷新
+    highFrequency_operation_delete:'highFrequency:operation:delete',//操作-删除
+    highFrequency_classify_move:'highFrequency:classify:move',//分类设置-移动
+    highFrequency_classify_delete:'highFrequency:classify:delete',//分类设置-删除
+    highFrequency_classify_editAdd:'highFrequency:classify:editAdd',//分类设置-编辑/添加
 }
 
 /*
@@ -312,6 +330,7 @@ export const edbDataPermission = {
     edbData_checkRelatedChart:'edbData:checkRelatedChart',//查看关联图表
     edbData_checkRelatedEdb:'edbData:checkRelatedEdb',//查看关联指标
     edbData_checkCalcChart:'edbData:checkCalcChart',//查看计算指标
+    edbData_enableOrDisable:'edbData:enableOrDisable',//启用/停用
 }
 /*
  * ---------------------------------------------------------------------------ETA预测指标------------------------------------------------
@@ -547,6 +566,7 @@ export const statisticPermission = {
     corrAnalysis_onlyMine:'corrAnalysis:onlyMine',//只看我的
     corrAnalysis_classifyOpt_edit:'corrAnalysis:classifyOpt:edit',//添加/编辑分类
     corrAnalysis_classifyOpt_delete:'corrAnalysis:classifyOpt:delete',//删除分类
+    corrAnalysis_classifyOpt_move:'corrAnalysis:classifyOpt:move',//移动分类
         /*---图表操作栏--- */
     corrAnalysis_del:'corrAnalysis:del',
     corrAnalysis_enNameSetting:'corrAnalysis:enNameSetting',

+ 12 - 0
src/utils/common.js

@@ -355,4 +355,16 @@ export const waitRequestReturn=(flag,callBack,timeout)=>{
   }else{
     callBack()
   }
+}
+
+/* 获取url的query */
+export function GetQueryString(url) {
+  let urlStr=url.split('?')[1]
+  let obj={}
+  let paramsArr=urlStr.split('&')
+  for (let index = 0; index < paramsArr.length; index++) {
+      let arr=paramsArr[index].split('=')
+      obj[arr[0]]=arr[1]
+  }
+  return obj
 }

+ 2 - 3
src/views/Home.vue

@@ -43,7 +43,7 @@
                   :style="!isCollapse ? 'text-align:left' : ''"
                   v-if="item.IsLevel === 1&&!item.hidden"
                 >
-                  <span class="el-level-path" v-if="item.path==='etaForum'" @click.prevent="handleGoETAForum">
+                  <div class="el-level-path" v-if="item.path==='etaForum'" @click.prevent="handleGoETAForum">
                     <img
                       :src="getMenuIcon(item)"
                       alt=""
@@ -62,7 +62,7 @@
                       "
                       >{{ $i18nt.locale==='zh'?item.name:item.name_en }}</span
                     >
-                  </span>
+                  </div>
                   <a
                     v-else
                     :href="`/${item.level_path}`"
@@ -92,7 +92,6 @@
                     >
                   </a>
                 </el-menu-item>
-
                 <el-submenu v-else-if="item.IsLevel!==1&&!item.hidden" :index="index" :key="index">
                   <template slot="title">
                     <img

+ 1 - 1
src/views/Login.vue

@@ -608,7 +608,7 @@ export default {
                 case "rai_researcher":
                 case "ficc_researcher":
                 case "researcher":
-                    path = "/reportlist";
+                    path = "/reportNew";
                     break;
                 // case "compliance": //合规
                 //     path = "/contractapprovallist";

+ 4 - 4
src/views/approve_manage/approveDetail.vue

@@ -58,8 +58,8 @@
 </template>
 
 <script>
-import ReportDetail from '@/views/smartReport/reportDetail.vue';
-import Reportdtl from '@/views/report_manage/reportdtl.vue'
+import ReportDetail from '@/views/report_manage/reportV2/smartReport/reportDetail.vue';
+import Reportdtl from '@/views/report_manage/reportV2/normalReport/reportdtl.vue'
 import TimeLine from './components/timeLine.vue';
 import RejectDialog from './components/rejectDialog.vue';
 import {approveInterence} from '@/api/modules/approve.js';
@@ -116,8 +116,8 @@ export default {
                     title:Report.ReportTitle||'',
                     classify:Report.ReportClassify||'',
                     approver:Approve.ApplyUserName||'',
-                    componentName:Report.ReportType===3?'ReportDetail':'Reportdtl',
-                    type:Report.ReportType
+                    componentName:Report.ReportLayout===2?'ReportDetail':'Reportdtl',
+                    type:Report.ReportLayout===2?3:Report.ReportType
                 }
                 this.formType = type||'detail'
                 this.approveInfo.state=Approve.State

+ 14 - 8
src/views/approve_manage/approveEdit.vue

@@ -5,7 +5,7 @@
             <el-form :inline="true" :model="approveForm" ref="approve-form" :rules="formRules"
                 label-width="180px" label-position="left">
                 <el-form-item :label="$t('SystemManage.ReportApprove.table_col01')" prop="name">
-                    <el-input v-model="approveForm.name" :disabled="this.$route.query.flowId" :placeholder="$t('ApprovalEdit.name_placeholder')"></el-input>
+                    <el-input v-model="approveForm.name" :placeholder="$t('ApprovalEdit.name_placeholder')"></el-input>
                 </el-form-item>
                 <el-form-item :label="$t('SystemManage.ReportApprove.table_col02')" prop="classify">
                     <el-cascader v-model="approveForm.classify"
@@ -116,8 +116,9 @@ export default {
             const params = {
                 FlowName:name,
                 ReportType:classify[0],
-                ClassifyFirstId:classify[classify.length-2]||0,
-                ClassifySecondId:classify[classify.length-1]||0,
+                ClassifyFirstId:classify[1]||0,
+                ClassifySecondId:classify[2]||0,
+                ClassifyThirdId:classify[3]||0,
                 Nodes
             }
             let res
@@ -141,13 +142,18 @@ export default {
                     ReportApproveFlowId:Number(id)
                 }).then(res=>{
                     if(res.Ret!==200) return 
-                    const {FlowName,ReportType,ClassifySecondId,Nodes} = res.Data||{}
+                    const {FlowName,ReportType,ClassifyFirstId,ClassifySecondId,Nodes,ClassifyThirdId} = res.Data||{}
                     this.approveForm.name = FlowName||''
                     //递归获取所有父级id
-                    const classify = this.classifyTree.find(i=>i.ClassifyId===ReportType)||{}
-                    const tempArr = findParentNode(classify.Children||[],ClassifySecondId)
-                    tempArr.push(ReportType)
-                    this.approveForm.classify = tempArr.reverse()
+                    // const classify = this.classifyTree.find(i=>i.ClassifyId===ReportType)||{}
+                    // const tempArr = findParentNode(classify.Children||[],ClassifySecondId)
+                    // tempArr.push(ReportType)
+                    // this.approveForm.classify = tempArr.reverse()
+                    this.approveForm.classify = ClassifyThirdId 
+                        ? [ReportType,ClassifyFirstId,ClassifySecondId,ClassifyThirdId]
+                        : ClassifySecondId
+                        ? [ReportType,ClassifyFirstId,ClassifySecondId]
+                        : [ReportType,ClassifyFirstId]
                     this.approveForm.flowNodes = Nodes||[]
                 })
             }

+ 2 - 2
src/views/approve_manage/components/flowNode/approveNode.vue

@@ -57,14 +57,14 @@
                     <div class="block" style="margin-top:30px;">
                         <p>{{$t('SystemManage.ReportApprove.mutl_person')}}</p>
                         <el-radio-group v-model="approveType">
-                            <el-radio :label="1">
+                            <!-- <el-radio :label="1">
                                 {{$t('SystemManage.ReportApprove.approval_type01')}}
                                 <el-tooltip effect="dark" placement="top" :content="$t('SystemManage.ReportApprove.des01')" >
                                     <span class="hint-text">
                                         <i class="el-icon-info"></i>
                                     </span>
                                 </el-tooltip>
-                            </el-radio>
+                            </el-radio> -->
                             <el-radio :label="2">
                                 {{$t('SystemManage.ReportApprove.approval_type02')}}
                                 <el-tooltip effect="dark" placement="top" :content="$t('SystemManage.ReportApprove.des02')" >

+ 1 - 1
src/views/approve_manage/mixins/approveMixins.js

@@ -1,7 +1,7 @@
 import {approveInterence} from '@/api/modules/approve.js'
 const filterNodes = (arr,hasDisabled)=>{
     arr.length &&arr.forEach((item) => {
-        hasDisabled&&(item.disabled = item.HasFlow)
+        hasDisabled&&(item.disabled = (item.Children&&item.Children.length)?false:item.HasFlow)
         item.Children.length && filterNodes(item.Children,hasDisabled);
         if (!item.Children.length) {
             delete item.Children;

+ 61 - 19
src/views/chartRelevance_manage/components/chartCard.vue

@@ -18,6 +18,7 @@
               <el-dropdown-item :command="{entryType,scence:'saveOther'}">{{$t('StatisticAnalysis.ChartRelevance.save_other')}}</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
+          <!-- 保存指标 -->
           <el-button type="primary" v-show="!isEdbAdd" @click="saveEdb(entryType)">{{$t('StatisticAnalysis.ChartRelevance.save_edb')}}</el-button>
         </template>
 
@@ -28,13 +29,17 @@
           @click="updateChartHandle(entryType)" 
           @command="chartCommandHandle"
         >
+          <!-- 更新图表/指标 -->
           {{$t('StatisticAnalysis.ChartRelevance.update_edb')}}
           <el-dropdown-menu slot="dropdown" v-show="isHaveSaveOtherHandle">
+            <!-- 另存为图表/指标 -->
             <el-dropdown-item :command="{entryType,scence:'saveOther'}">{{$t('Table.save_as')}}</el-dropdown-item>
           </el-dropdown-menu>
         </el-dropdown>
+        <!-- 保存图表 -->
         <el-button type="primary" @click="saveChart(entryType)" v-show="!isChartAdd">{{$t('Dialog.confirm_save_btn')}}</el-button>
-
+        <!-- 图例设置 -->
+        <el-button type="primary" plain @click="handleChartSettiing" v-show="isChartSetting">图例设置</el-button>
       </div>
     </div>
     <div class="chartWrapper">
@@ -46,7 +51,7 @@
         :options="options"
         :index="String(entryType)"
         :ref="`chartRef${entryType}`"
-        height="350"
+        :height="height||350"
       />
     </div>
   </div>
@@ -62,32 +67,42 @@ export default {
   mixins: [chartSetMixin],
   computed: {
     isHaveButton() {
-      let routes = ['/relevancechartEditor','/statisticFeatureChartEditor']
+      let routes = ['/relevancechartEditor','/statisticFeatureChartEditor','/relevancechartEditorV2']
       return routes.includes(this.$route.path)
     },
     cardTitle() {
       let title='';
       if(this.$route.path==='/relevancechartEditor') {
         title = [3,4].includes(this.entryType) ? `滚动相关性${this.entryType-2}` : this.entryType===1 ? this.chartInfo.ChartName : ''
-      }else if(this.$route.path==='/statisticFeatureChartEditor') {
+      }else if(this.$route.path==='/relevancechartEditorV2'){
+        if(this.settings.Model===1){
+            title = [3,4].includes(this.entryType) ? `滚动相关性${this.entryType-2}` : this.entryType===1 ? this.chartInfo.ChartName : this.relevanceChartData.ChartName
+        }else{
+            title = this.relevanceChartData.ChartName
+        }
+      }
+      else if(this.$route.path==='/statisticFeatureChartEditor') {
         title = this.chartInfo.ChartName
       }
       return title
     },
     isHaveEdbHandle() { //有指标操作的区域
       //相关性 3,4区域可保存指标 统计图 2,3区域
-      return (([3,4].includes(this.entryType)&&this.$route.path==='/relevancechartEditor')
+      return (([3,4].includes(this.entryType)&&['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path))
         || ([2,3].includes(this.entryType)&&this.$route.path==='/statisticFeatureChartEditor'))
     },
     isHaveSaveOtherHandle() {//有图表另存的区域
         //相关性 1,2区域有另存 统计图 4个区域都有另存
-      return (([1,2].includes(this.entryType) && this.$route.path==='/relevancechartEditor')
+      return (([1,2].includes(this.entryType) && ['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path))
        || (this.$route.path==='/statisticFeatureChartEditor'))
     }
   },
   watch: {
-    data(nval) {
-      this.setRenderChartData(nval)
+    data:{
+        handler(nval) {
+            this.setRenderChartData(nval)
+        },
+        deep:true
     }
   },
   props: {
@@ -108,6 +123,13 @@ export default {
     },
     settings: {
       type: Object
+    },
+    isChartSetting:{ //是否显示图表设置
+        type:Boolean,
+        default:false
+    },
+    height:{
+        type:String
     }
 
   },
@@ -132,6 +154,7 @@ export default {
         case 3: //3相关性 
           this.chartInfo = data.ChartInfo;
           this.relevanceChartData={
+            ChartName:data.ChartInfo.ChartName,
             ChartInfo:data.ChartInfo,
             EdbInfoList:data.EdbInfoList,
             XEdbIdValue:data.XEdbIdValue || data.XDateTimeValue,
@@ -139,12 +162,16 @@ export default {
             YDataList:[
               {
                 Value:data.YDataList[0].Value,
-                Color:'#00f',
-                Name:data.ChartInfo.ChartName,
+                Color:data.YDataList[0].Color||'#00f',
+                Name:data.YDataList[0].Name||data.ChartInfo.ChartName,
                 NameEn:''
               }
             ]
           }
+          if(this.settings.Model===2){
+            this.relevanceChartData.YDataList = data.YDataList
+            //this.relevanceChartData.ChartName = data.ChartInfo.EdbName+'相关性分析(xxx)'
+          }
           this.tableData=data.EdbInfoList||[]
           this.initRelevanceChartData()
           break
@@ -172,6 +199,10 @@ export default {
           break
       }
     },
+    handleChartSettiing(){
+        this.$emit('chartSettingChange',this.relevanceChartData)
+    },
+    
 
     /* 拟合方程曲线 */
     initFittingEquation(data) {
@@ -222,11 +253,13 @@ export default {
     },
 
     async setImageHandle(form,id) {
-      let { Data } = await dataBaseInterface.uploadImgSvg(form);
-      await dataBaseInterface.setChartImage({
-        ChartInfoId: id,
-        ImageUrl: Data.ResourceUrl,
-      });
+      // let { Data } = await dataBaseInterface.uploadImgSvg(form);
+      // await dataBaseInterface.setChartImage({
+      //   ChartInfoId: id,
+      //   ImageUrl: Data.ResourceUrl,
+      // });
+      form.append('ChartInfoId',id)
+      await dataBaseInterface.setChartThumbnail(form)
     },
 
     /* 更新图表 */
@@ -239,8 +272,17 @@ export default {
         4: 10
       }
       let Source;
-      if(this.$route.path==='/relevancechartEditor') {
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
         Source = entryType;
+        //多因子参数不一样,这里直接返回
+        if(this.$parent.chartInfo.Model===2){
+            this.$emit('handleEdit',{
+                ChartName:this.chartInfo.ChartName,
+                ClassifyId:this.chartInfo.ClassifyId,
+                type:'edit'
+            })
+            return
+        }
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         Source = sourceMap[entryType]
       }
@@ -251,7 +293,7 @@ export default {
         ...this.settings
       }
       let res = null;
-      if(this.$route.path==='/relevancechartEditor') {
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
         res = await chartRelevanceApi.saveChart(params)
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         res = await statisticFeatureInterface.saveChart(params);
@@ -273,7 +315,7 @@ export default {
         4: 10
       }
       let Source;
-      if(this.$route.path==='/relevancechartEditor') {
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
         Source = entryType;
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         Source = sourceMap[entryType]
@@ -286,7 +328,7 @@ export default {
 			}
       
       let res = null;
-      if(this.$route.path==='/relevancechartEditor') {
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
         res = await chartRelevanceApi.saveEdb(params)
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         res = await statisticFeatureInterface.saveEdb(params);

+ 10 - 2
src/views/chartRelevance_manage/components/explainText.js

@@ -1,6 +1,7 @@
 //相关性分析
 export const chartrelevanceTextArr = [
     `<p style='font-weight:bold;'>相关性计算处理逻辑:</p>
+    <p style='font-weight:bold;'>单因子:</p>
     <p>1、取数:取计算窗口的时间长度,从当前时间往前推移对应的时间长度,取该日期区间,指标A序列值和指标B序列值;</p>
     <p>2、变频:根据指标A和指标B的频度对取出的数据序列做如下处理</p>
     <p>①指标A高频,对指标B升频(线性方程插值法补全数据);</p>
@@ -14,10 +15,14 @@ export const chartrelevanceTextArr = [
     <p>2、分析周期:指标B领先A的期数,如配置参数10个月,表示B领先A -10月、B领先A -9月,...,B领先A 9月、B领先A 10月,每期分别计算相关性值;</p>`,
     `<p style='font-weight:bold;'>滚动相关性配置:</p>
     <p>1、计算窗口:参与计算的时间段长度,从两个指标都有值的日期开始滚动的取计算窗口长度的值进行计算,如配置计算窗口1个月,则2023.7.28的值取2023.6.28~2023.7.28时间段,2023.7.27的值取2023.6.27~2023.7.27时间段;</p>
-    <p>2、B领先A:B指标领先A指标的参数,为0时不领先;</p>`
+    <p>2、B领先A:B指标领先A指标的参数,为0时不领先;</p>
+    <p style='height:20px;'></p>
+    <p style='font-weight:bold;'>多因子:</p>
+    <p>可一次选择多个指标,与标的指标进行相关性计算。每一个因子指标与标的指标的计算逻辑,同单因子模式。</p>`
 ]
 export const chartrelevanceTextArrEn=[
     `<p style='font-weight:bold;'>Instruction for Correlation Calculation Processing Logic:</p>
+    <p style='font-weight:bold;'>Single Indicator:</p>
     <p>1、 Data Retrieval: Determine the time length of the calculation window, and move backwards from the current time by this duration to obtain a range of dates. Retrieve values for indicator A series and indicator B series within this date range.</p>
     <p>2、Frequency Adjustment:</p>
     <p>a. If indicator A is higher frequency, upsample indicator B (use linear equation interpolation to fill in data).</p>
@@ -31,7 +36,10 @@ export const chartrelevanceTextArrEn=[
     <p>2. Analysis Period: The number of periods that indicator B leads ahead of A; for instance, if configured with a parameter of 10 months, it indicates that B leads A by -10 months to +10 months, with correlation values calculated separately for each period.</p>`,
     `<p style='font-weight:bold;'>Rolling Correlation Configuration:</p>
     <p>1. Calculation Window: The length of time involved in calculations starts from when both indicators have available values and rolls forward taking values within the duration of the calculation window for computation. For example, if configured with a 1-month calculation window, then the value for July 28th, 2023 will be taken from June 28th to July 28th, 2023; while the value for July 27th will be taken from June 27th to July 27th.</p>
-    <p>2. B Leads A: The parameter by which indicator B leads ahead of indicator A; when set to 0, there is no lead.</p>`
+    <p>2. B Leads A: The parameter by which indicator B leads ahead of indicator A; when set to 0, there is no lead.</p>
+    <p style='height:20px;'></p>
+    <p style='font-weight:bold;'>Multiple Indicators:</p>
+    <p>Multiple indicators can be selected at a time to calculate the correlation with the target indicator. The calculation logic of each factor index and the target index is the same as the Single Indicato.</p>`
 ]
 
 //拟合方程曲线

+ 111 - 0
src/views/chartRelevance_manage/components/saveChartSetting.vue

@@ -0,0 +1,111 @@
+<template>
+    <el-dialog 
+        :visible.sync="isSettingChartShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body='false'
+        @close="$emit('close')"
+        center width="500px"
+        title="图例设置"
+        custom-class="chart-setting-dialog"
+    >
+        <div class="dialog-content">
+            <el-form 
+                :modal="settingData" 
+                :rules="formRules"
+                label-width="100px"
+                ref="settingForm">
+                <el-form-item label="图表名称">
+                    <el-input v-model="settingData.chartName"></el-input>
+                </el-form-item>
+                <el-form-item label="图例名称" style="margin-bottom: 0;">
+                </el-form-item>
+                <el-form-item label-width="0px">
+                    <div class="option-box">
+                        <div class="option-item" v-for="(data,index) in settingData.YDataList" :key="index">
+                            <el-color-picker
+                                v-model="data.Color"
+                                size="mini"
+                                show-alpha
+                                :predefine="predefineColors"/>
+                            <el-input v-model="data.Name"></el-input>
+                        </div>
+                    </div>
+                </el-form-item>
+                <el-form-item label="数据来源">
+                    <el-input v-model="settingData.SourcesFrom.text"></el-input>
+                    <el-switch v-model="settingData.SourcesFrom.isShow"></el-switch>
+                </el-form-item>
+            </el-form>
+        </div>
+        <div class="dialog-footer">
+            <el-button type="primary" plain @click="$emit('close')">{{$t('Dialog.cancel_btn')}}</el-button>
+            <el-button type="primary" @click="handleSaveChartSetting">{{$t('Dialog.confirm_btn')}}</el-button>
+        </div>
+
+    </el-dialog>
+</template>
+
+<script>
+import { defaultOpts } from '@/utils/defaultOptions';
+export default {
+    props:{
+        isSettingChartShow:{
+            type:Boolean
+        },
+        settingData:{
+            type:Object,
+        }
+    },
+    data() {
+        return {
+            predefineColors: defaultOpts.colors.slice(0, 2),
+            formRules:{},
+        };
+    },
+    methods: {
+        handleSaveChartSetting(){
+            this.$emit('saveChartSetting')
+        },
+
+    },
+};
+</script>
+
+<style lang="scss">
+.chart-setting-dialog{
+    .el-input{
+        width:230px;
+    }
+    .el-color-picker--mini .el-color-picker__trigger {
+        width: 60px;
+        height: 25px;
+        padding: 0;
+        margin:0 12px 0 28px;
+    }
+    .el-color-picker--mini .el-color-picker__mask {
+        width: 60px;
+        height: 25px;
+    }
+    .el-form{
+        display: flex;
+        flex-direction: column;
+        margin:0 auto;
+        .option-box{
+            .option-item{
+                display: flex;
+                align-items: center;
+                margin-bottom:10px;
+                &:last-child{
+                    margin-bottom: 0;
+                }
+            }
+
+        }
+    }
+    
+    .dialog-footer{
+        text-align:center;
+        margin:30px 0 20px 0;
+    }
+}
+</style>

+ 44 - 8
src/views/chartRelevance_manage/components/saveChartTobaseDia.vue

@@ -34,7 +34,8 @@
                 label: 'ChartClassifyName',
                 value: 'ChartClassifyId',
                 children: 'Children',
-                emitPath: false
+                emitPath: false,
+                checkStrictly:isRelevanceChart
               }"
               style="width: 80%"
               :placeholder="$t('Edb.InputHolderAll.input_classify')"
@@ -92,6 +93,9 @@ export default {
 					{ required: true, message: /* '图表分类不能为空' */this.$t('Chart.Vailds.classify_msg'), trigger: 'blur' },
 				],
 			}
+		},
+		isRelevanceChart(){
+			return ['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)&&this.chartData.Source!==1
 		}
 	},
 	data () {
@@ -111,19 +115,31 @@ export default {
       let res = null;
       if(this.chartData.Source===1) {
         res = await dataBaseInterface.chartClassify();
-      }else if(this.$route.path==='/relevancechartEditor'&&this.chartData.Source!==1) {
-        res = await chartRelevanceApi.classifyList();
+      }else if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)&&this.chartData.Source!==1) {
+        res = await chartRelevanceApi.classifyTree();
       }else if(this.$route.path==='/statisticFeatureChartEditor'&&this.chartData.Source!==1) {
         res = await statisticFeatureInterface.classifyList();
       }
 
       if(res.Ret !== 200) return
-      this.filterNodes(res.Data.AllNodes,this.chartData.Source===1?3:1)
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)&&this.chartData.Source!==1){
+        this.filterNodesAll(res.Data.AllNodes)
+      }else{
+        this.filterNodes(res.Data.AllNodes,this.chartData.Source===1?3:1)
+      }
+      
 
 			this.classifyOptions = res.Data.AllNodes || [];
     
 		},
-
+		filterNodesAll(arr){
+			arr.length && arr.forEach(item => {
+				item.Children && item.Children.length && this.filterNodesAll(item.Children)
+				if(!item.Children.length) {
+					delete item.Children
+				}
+			})
+		},
 		// 递归改变第三级目录结构
 		filterNodes(arr,n) {
 			arr.length && arr.forEach(item => {
@@ -147,8 +163,14 @@ export default {
         4: 10
       }
       let Source;
-      if(this.$route.path==='/relevancechartEditor') {
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
         Source = this.source;
+        //多因子的参数和接口都不一样,这里直接返回
+        if(this.$parent.chartInfo.Model===2){
+            this.$emit('handleSave',{ChartName: name,ClassifyId: classify,type:this.saveScence})
+            return
+        }
+        
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         Source = sourceMap[this.source]
       }
@@ -162,8 +184,22 @@ export default {
       }
 
       let res = null;
-      if(this.$route.path==='/relevancechartEditor') {
-        res = await chartRelevanceApi.saveChart(params)
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
+        //单因子-相关性额外参数
+        let otherParams = this.source===2?{
+            CorrelationExtraConfig:{
+                LegendConfig:this.$parent.chartBatchData.CorrelationData.YDataList.map(i=>{
+                    return {
+                        LegendName:i.Name,
+                        SeriesId:i.SeriesId,
+                        EdbInfoId:i.Id,
+                        Color:i.Color
+                    }
+                })
+            },
+            SourcesFrom:this.$parent.chartBatchData.SourcesFrom
+        }:{}
+        res = await chartRelevanceApi.saveChart({...params,...otherParams})
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         res = await statisticFeatureInterface.saveChart(params);
       } 

+ 2 - 2
src/views/chartRelevance_manage/components/saveEdbToBaseDia.vue

@@ -173,7 +173,7 @@ export default {
         4: 10
       }
       let Source;
-      if(this.$route.path==='/relevancechartEditor') {
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
         Source = this.source;
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         Source = sourceMap[this.source]
@@ -190,7 +190,7 @@ export default {
 			}
 
 			let res = null;
-      if(this.$route.path==='/relevancechartEditor') {
+      if(['/relevancechartEditor','/relevancechartEditorV2'].includes(this.$route.path)) {
         res = await chartRelevanceApi.saveEdb(params);
       }else if(this.$route.path==='/statisticFeatureChartEditor') {
         res = await statisticFeatureInterface.saveEdb(params);

+ 5 - 0
src/views/chartRelevance_manage/components/selectTarget.vue

@@ -4,6 +4,7 @@
       style="width: 100%"
       v-model="targetType"
       :placeholder="$t('StatisticAnalysis.StatisticFeatureChart.selecr_indicator_pld')"
+      :disabled="isDisabled"
       @change="targetTypeChange"
       v-if="selectStyleType===1&&filter"
     >
@@ -82,6 +83,7 @@
       :filterable="!search_txt"
       remote
       clearable
+      :disabled="isDisabled"
       :placeholder="$t('Edb.InputHolderAll.select_edb_name')"
       :style="`width: ${width}; ${filter?'margin-top: 20px':''}`"
       :remote-method="searchHandle"
@@ -136,6 +138,9 @@ export default {
       },
       width: {
         default:'100%'
+      },
+      isDisabled:{
+        default:false
       }
     },
     watch:{

+ 7 - 6
src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue

@@ -429,12 +429,13 @@ export default {
       this.setImageHandle(form,data);
     },
     async setImageHandle(form,{ UniqueCode,ChartInfoId }) {
-      let { Data } = await dataBaseInterface.uploadImgSvg(form);
-      await dataBaseInterface.setChartImage({
-        ChartInfoId: ChartInfoId,
-        ImageUrl: Data.ResourceUrl,
-      });
-
+      // let { Data } = await dataBaseInterface.uploadImgSvg(form);
+      // await dataBaseInterface.setChartImage({
+      //   ChartInfoId: ChartInfoId,
+      //   ImageUrl: Data.ResourceUrl,
+      // });
+      form.append('ChartInfoId',ChartInfoId)
+      await dataBaseInterface.setChartThumbnail(form)
 			this.$message.success(/* '保存成功' */this.$t('StatisticAnalysis.FittingEquationChart.detail_dialog_save_success'));
 			this.$router.replace({
 				path: '/crossVarietyChartList',

+ 4 - 1
src/views/chartRelevance_manage/css/index.scss

@@ -146,13 +146,16 @@ $normal-font: 14px;
               text-align: center;
               margin-bottom: 10px;
             }
-            .chart-author {
+            .chart-author,.chart-source {
               font-size: 14px;
               color: #333;
               position: absolute;
               bottom: 0;
               right: 50px;
             }
+            .chart-source{
+                left:50px;
+            }
             .chartWrapper {
               position: relative;
               .range-cont {

+ 18 - 8
src/views/chartRelevance_manage/mixins/classifyMixin.js

@@ -37,6 +37,14 @@ export default {
         let search_obj = this.searchOptions.find(
           (_) => _.ChartInfoId === newval
         );
+        if(this.$route.path==='/chartrelevance'){
+            if(!search_obj) return 
+            // 重置筛选状态
+            this.select_id = newval;
+            this.select_node = search_obj.UniqueCode;
+            this.select_classify = 0;
+            return 
+        }
         let deep_arr = _.cloneDeep(this.treeData);
         // 查找图表的分类父级id
 
@@ -121,8 +129,8 @@ export default {
 				width > 500
 					? 'auto'
 					: width <= 260
-					? 90
-					: 0.7 * width;
+					? 80
+					: 0.4 * width;
 			this.$set(node, 'Nodewidth', label_wid + 'px');
 		},200),
 
@@ -429,12 +437,14 @@ export default {
     },
 
     async setImageHandle(form) {
-      let { Data } = await dataBaseInterface.uploadImgSvg(form);
-
-      await dataBaseInterface.setChartImage({
-        ChartInfoId: this.select_id,
-        ImageUrl: Data.ResourceUrl,
-      });
+      // let { Data } = await dataBaseInterface.uploadImgSvg(form);
+
+      // await dataBaseInterface.setChartImage({
+      //   ChartInfoId: this.select_id,
+      //   ImageUrl: Data.ResourceUrl,
+      // });
+      form.append('ChartInfoId',this.select_id)
+      await dataBaseInterface.setChartThumbnail(form)
     },
 
     copyChartConfirm(type) {

+ 210 - 0
src/views/chartRelevance_manage/relevance/components/batchSelectFormula.vue

@@ -0,0 +1,210 @@
+<template>
+    <div class="batch-select-formula-wrap">
+        <el-form :model="formulaForm" :rules="formulaRules" label-width="80px" ref="formulaForm">
+            <div class="formula-list">
+                <div class="list-item" v-for="(item,index) in formulaForm.CalculateStep" :key="index">
+                    <span>
+                        <img @click="deleteFormula(index)" style="width:15px;height:15px;cursor: pointer;" src="~@/assets/img/ai_m/delete.png" alt="">
+                    </span>
+                    <el-select v-model="item.formulaType">
+                        <el-option 
+                            v-for="option in formulaOpt"
+                            :key="option.Source"
+                            :value="option.Source"
+                            :label="option.CalculateName"
+                        />
+                    </el-select>
+                    <div class="form-item-box">
+                        <!-- N期 N等于-->
+                        <el-form-item
+                            v-if="[5,6,7].includes(item.formulaType)"
+                            :label="$t('EtaBasePage.label_n_val')"
+                            :prop="`CalculateStep[${index}].nNum`"
+                            :rules="{required:true,message:$t('Edb.Valids.n_msg'),trigger:'blur'}"
+                        >
+                            <el-input v-model="item.nNum" :placeholder="$t('Edb.InputHolderAll.input_n_value')" type="number"></el-input>
+                        </el-form-item>
+                        <!-- 超季节性 N等于 日历-->
+                        <el-form-item 
+                            v-if="item.formulaType===11"
+                            :label="$t('EtaBasePage.label_n_val')"
+                            :prop="`CalculateStep[${index}].nNum`"
+                            :rules="{required:true,message:$t('Edb.Valids.n_msg'),trigger:'blur'}"
+                        >
+                            <el-input v-model="item.nNum" :placeholder="$t('Edb.InputHolderAll.input_n_value')" type="number"></el-input>
+                        </el-form-item>
+                        <el-form-item 
+                            v-if="item.formulaType===11"
+                            :label="$t('EtaBasePage.label_calendar')"
+                        >
+                            <el-select v-model="item.Calendar">
+                                <el-option :label="$t('Chart.calendar_gre')" value="公历"></el-option>
+                                <el-option :label="$t('Chart.calendar_lunar')" value="农历"></el-option>
+                            </el-select>
+                        </el-form-item>
+                        <!-- 指数修匀 alpha值 -->
+                        <el-form-item
+                            v-if="item.formulaType===15"
+                            :label="$t('EtaBasePage.alpha_value_lable')" 
+                            :prop="`CalculateStep[${index}].alphaValue`"
+                            :rules="[
+                                {required:true,message:$t('Edb.Valids.alpha_msg'),trigger:'blur'},
+                                {validator:validator,trigger:['change','blur']}]">
+                            <el-input v-model.trim="item.alphaValue" style="width:140px" :placeholder="$t('Edb.InputHolderAll.input_alpha_val')" type="number"></el-input>
+                        </el-form-item>
+                    </div>
+                    
+                </div>
+            </div>
+            <div class="tool-box-wrap">
+                <!-- 添加计算公式 -->
+                <div class="add-btn" @click="addFormula">
+                        <img style="width:15px;height:15px;vertical-align: middle;" src="~@/assets/img/icons/formula-add.png" alt="">
+                    {{ $t('StatisticAnalysis.ChartRelevance.formula_add_btn') }}
+                </div>
+                <div class="input-box">
+                    <el-form-item
+                        required
+                        :label="$t('StatisticAnalysis.ChartRelevance.series_name')"
+                        label-width="120px"
+                    >
+                        <el-input v-model.trim="formulaForm.SeriesName" style="width:230px" 
+                        :placeholder="$t('StatisticAnalysis.ChartRelevance.series_name_placeholder')"></el-input>
+                    </el-form-item>
+                </div>
+            </div>
+        </el-form>
+        
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        formulaOpt:{
+            type:Array,
+            default:[]
+        },
+        factorData:{
+            type:Object,
+            default:{}
+        }
+    },
+    computed:{
+        //计算方式列表-改为后端获取
+        /* formulaOption(){
+            return [
+                {
+                    value:5,
+                    label:this.$t('Edb.CalculatesAll.on_year'),//同比值
+                },
+                {
+                    value:7,
+                    label:this.$t('Edb.CalculatesAll.differ'),//同差值
+                },
+                {
+                    value:8,
+                    label:this.$t('Edb.CalculatesAll.rule_move_average'),//N期移动均值
+                },
+                {
+                    value:12,
+                    label:this.$t('Edb.CalculatesAll.period_over_period'),//N期环比值
+                },
+                {
+                    value:13,
+                    label:this.$t('Edb.CalculatesAll.period_difference'),//N期环差值
+                },
+                {
+                    value:35,
+                    label:this.$t('Edb.CalculatesAll.super_seasonal'),//超季节性
+                },
+                {
+                    value:72,
+                    label:this.$t('Edb.CalculatesAll.ex_smooth'),//指数修匀
+                },
+            ]
+        } */
+    },
+    watch:{
+        factorData:{
+            handler(newValue){
+                this.formulaForm = _.cloneDeep(newValue)
+            },
+            immediate:true
+        },
+    },
+    data() {
+        return {
+            formulaForm:{
+                CalculateStep:[],
+                SeriesName:''
+            },
+            formulaRules:{},
+        };
+    },
+    methods: {
+        //打开弹窗时,在外层组件调用
+        initFormulaList(){
+            //this.formulaForm.CalculateStep = _.cloneDeep(this.dataFormulaList)
+            this.getFormulaOption()
+        },
+        validator(rule,value,callback){
+            if(Number(value)<=0||Number(value)>=1){
+                callback(new Error(this.$t('Edb.Valids.alpha_value_vaild')))
+            }else{
+                callback()
+            }
+        },
+        addFormula(){
+            this.formulaForm.CalculateStep.push({
+                formulaType:5,
+                Calendar:'公历',
+                nNum:1,
+                alphaValue:0.5
+            })
+        },
+        deleteFormula(index){
+            if(this.formulaForm.CalculateStep.length>=5){
+                return this.$message.warning(/* "最多仅能添加5个计算公式" */ this.$t('StatisticAnalysis.ChartRelevance.formulaform_add_hint'))
+            }
+            this.formulaForm.CalculateStep.splice(index,1)
+        },
+        async checkForm(){
+            return await this.$refs.formulaForm.validate()
+        },
+    },
+};
+</script>
+
+<style lang="scss">
+.batch-select-formula-wrap{
+    .el-input,.el-select{
+        width:140px;
+    }
+    .formula-list{
+        margin-top: 20px;
+        .list-item{
+            margin-bottom: 15px;
+            display: flex;
+            align-items: center;
+            gap:0 15px;
+            .form-item-box{
+                display: flex;
+                .el-form-item{
+                    margin-bottom: 0;
+                }
+            }
+        }
+    }
+    .tool-box-wrap{
+        margin-top: 20px;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        .add-btn{
+            color:#0052D9;
+            cursor: pointer;
+        }
+    }
+}
+</style>

+ 257 - 0
src/views/chartRelevance_manage/relevance/components/batchSelectTable.vue

@@ -0,0 +1,257 @@
+<template>
+    <!-- 封装表格跨页多选逻辑 -->
+    <div class="batch-select-table">
+        <div class="table-box" style="width:50%;">
+            <el-table
+                border height="500px"
+                v-loading="tableLoading"
+                ref="tableRef" 
+                :data="tableData"
+                @select="selectHandle" 
+                @select-all="selectAllHandle"
+            >
+                <el-table-column type="selection" min-width="50" align="center"/>
+                <el-table-column 
+                    align="center"
+                    v-for="column in tableColumns" 
+                    :key="column.key"
+                    :label="column.label"
+                    :prop="column.key"
+                    :width="column.width"
+                    :show-overflow-tooltip="column.showOverflowTooltip">
+                    <template slot-scope="{row}">
+                        <span v-if="column.key==='Frequency'">{{ getFrequencyTrans(row.Frequency) }}</span>
+                        <span v-else-if="['UniEn','Unit'].includes(column.key)">{{ getUnitTrans(row.Unit) }}</span>
+                        <span v-else>{{ row[column.key] }}</span>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <m-page 
+                style="margin-top:10px"
+                class="table-page" 
+                v-show="tableParams.total"
+                :total="tableParams.total" 
+                :pageSize="tableParams.pageSize"
+                :page_no="tableParams.pageNo"
+                :pagercount="tableParams.pagerCount"
+                @handleCurrentChange="pageNumberChange"
+            />
+        </div>
+        <!-- 加入已选指标 -->
+        <el-button type="primary" @click="handleAddSelectData">{{ $t('EtaBasePage.add_to_selections') }}</el-button>
+        <div class="select-box" style="width: 35%;">
+            <el-table
+                border height="500px"
+                ref="selectRef" 
+                :data="selectData"
+            >
+            <el-table-column
+                align="center"
+                :label="tableColumns[0].label"
+                :prop="tableColumns[0].key"
+             />
+             <el-table-column width="50px" align="center" v-if="selectData.length">
+                <template slot="header" slot-scope="scope">
+                    <img @click="handleDelSelect(_,'all')" style="width:15px;height:15px;cursor: pointer;" src="~@/assets/img/ai_m/delete.png" alt="">
+                </template>
+                <template slot-scope="{row,$index}">
+                    <img @click="handleDelSelect($index,'')" style="width:15px;height:15px;cursor: pointer;" src="~@/assets/img/ai_m/delete.png" alt="">
+                </template>
+            </el-table-column>
+        </el-table>
+        </div>
+    </div>
+</template>
+
+<script>
+import mPage from '@/components/mPage.vue'
+export default {
+    components:{mPage},
+    props:{
+        tableData:{
+            type:Array,
+            default:[]
+        },
+        tableLoading:{
+            type:Boolean,
+            default:false
+        },
+        tableColumns:{
+            type:Array,
+            default:[]
+        },
+        tableParams:{
+            type:Object,
+            default:()=>{
+                return {
+                    total:0,
+                    pageSize:20,
+                    pageNo:1,
+                    pagerCount:5,
+                    uniqueKey:'Id'
+                }
+            }
+        },
+        isSelectAll:{
+            type:Boolean,
+            default:false,
+        },
+        factorData:{
+            type:Object,
+            default:{}
+        }
+    },
+    watch:{
+        /* isSelectAll(newValue){
+            this.listCheckAllChange(newValue)
+        }, */
+        factorData:{
+            handler(newValue){
+                this.selectData = _.cloneDeep(newValue.EdbMappings||[])
+            },
+            immediate:true,
+            deep:true
+        }
+        
+    },
+    data() {
+        return {
+            selectList:[],//左侧表格已选择/已剔除的数据
+            selectData:[],//右侧表格的数据
+            selectionReactCancel:false,
+        };
+    },
+    methods: {
+        //点击数据行的checkbox触发 selection:已选择的所有数据行;row:当前点击的数据行
+        selectHandle(selection,row){
+            const {uniqueKey} = this.tableParams
+            //通过判断selection中有无row确定是勾选了checkbox还是取消勾选
+            //当为勾选时,判断selectList是否表示已选择的数据(isSelectAll===false),若不是则不加入
+            //当为取消勾选时,判断selectList是否表示已剔除的数据(isSelectAll===true),若不是则不加入
+            let check = selection.some(i=>i[uniqueKey] == row[uniqueKey])?(!this.isSelectAll):(this.isSelectAll)
+            if(check){
+                this.selectList.push(row[uniqueKey])
+            }else{
+                this.selectList = this.selectList.filter(i=>i!=row[uniqueKey])
+            }
+            this.selectionChange()
+        },
+        //点击表头全选 or 调用toggleAllSelection 触发
+        selectAllHandle(selection){
+            //当前table的所有数据
+            const tableIds = this.tableData.map(it => it[this.tableParams.uniqueKey])
+            //通过判断selection中有无数据确定是全选or取消全选
+            //当为全选时,判断selectList是否表示已选择的数据(isSelectAll===false),若不是则从selectList中剔除
+            //当为取消全选时,判断selectList是否表示已剔除的数据(isSelectAll===true),若不是则从selectList中剔除
+            let check = selection&&selection.length?(!this.isSelectAll):this.isSelectAll
+            if(check){
+                this.selectList =  [...this.selectList,...tableIds]
+            }else{
+                this.selectList = this.selectList.filter(it => !tableIds.includes(it))
+            }
+            this.selectionChange()
+        },
+        //当勾选项改变时 处理数据
+        selectionChange(){
+            //去重 selectList
+            let duplicateArr = Array.from(new Set(this.selectList))
+            let isCheckAll = false,isIndeterminate = false
+            //判断已选择的数据,更改列表全选checkbox的状态
+            /**
+             * 全选:
+             * 1.selectList.length === total && isSelectAll === false (已选择的数据为全部数据)
+             * 2.selectList.length === 0 && isSelectAll === true (已剔除的指标为空)
+             * 以上两种满足其一即可
+             */
+            const selectAll = duplicateArr.length===this.tableParams.total && (!this.isSelectAll)
+                || duplicateArr.length===0 && this.isSelectAll
+            /**
+             * 全不选:
+             * 1.selectList.length === total && isSelectAll === true (剔除了全部数据)
+             * 2.selectList.length === 0 && isSelectAll === false (没选择任何数据)
+             * 以上两种满足其一即可
+             */
+            const selectNone = duplicateArr.length===this.tableParams.total && this.isSelectAll
+                || duplicateArr.length===0 && (!this.isSelectAll)
+            //其余情况均为半选
+
+            if(selectAll){
+                isCheckAll = true
+                isIndeterminate = false
+            }else if(selectNone){
+                isCheckAll = false
+                isIndeterminate = false
+            }else{
+                isCheckAll = false
+                isIndeterminate = true
+            }
+
+            this.$emit('changeCheckAll',{isCheckAll,isIndeterminate})
+        },
+        //切换页面时调整勾选项 (在外层组件调用)
+        adjustSelection(){
+            const {uniqueKey} = this.tableParams
+            this.$refs.tableRef.clearSelection()
+            this.tableData.forEach(data=>{
+                if(this.selectList.includes(data[uniqueKey])){
+                    //isSelectAll===false,selectList为已选择的数据,则对应数据行打勾
+                    //isSelectAll === true,selectList为已剔除的数据,则对应的数据行取消打勾
+                    this.$nextTick(()=>{
+                        this.$refs.tableRef.toggleRowSelection(data,!this.isSelectAll)
+                    })
+                }else{
+                    this.$nextTick(()=>{
+                        this.$refs.tableRef.toggleRowSelection(data,this.isSelectAll)
+                    })
+                }
+            })
+        },
+        listCheckAllChange(newValue){
+            this.selectList = []
+            this.$refs.tableRef && this.tableData.length && this.$refs.tableRef.clearSelection()
+            if(newValue){
+                //会触发select-all
+                this.$refs.tableRef && this.tableData.length && this.$refs.tableRef.toggleAllSelection()
+                /* //不会触发select-all
+                this.$refs.tableRef && this.tableData.length && this.$refs.tableRef.toggleRowSelection(this.tableData[0],true) */
+            }
+        },
+        pageNumberChange(page){
+            this.$emit('pageChange',page)
+        },
+        handleAddSelectData(){
+            //外层组件处理校验和添加逻辑
+            this.$emit('addSelectData',{selectList:this.selectList,selectData:this.selectData})
+
+        },
+        //外层组件调用
+        addSelectData(data){
+            this.selectData = _.cloneDeep(data)
+            
+        },
+        handleDelSelect(index,type){
+            if(type==='all'){
+                return (this.selectData = [])
+            }
+            this.selectData.splice(index,1)
+        },
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.batch-select-table{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    gap:0 20px;
+    .table-box,.select-box{
+        flex:1;
+    }
+    &::after{
+        content:'';
+        flex:0 0 auto;
+        visibility: hidden;
+    }
+}
+</style>

+ 38 - 0
src/views/chartRelevance_manage/relevance/components/formMixin.js

@@ -0,0 +1,38 @@
+//单因子,多因子的表单 共同逻辑
+import {yearSelector} from '@/utils/defaultOptions';
+import selectTarget from '../../components/selectTarget.vue'
+export default{
+    components:{selectTarget},
+    props:{
+        chartInfoData:{
+            type:Object,
+            default:{}
+        },
+        infoForm:{
+            type:Object,
+            default:()=>{return {Curve:{},Correlation:{},RollingCorrelation:[]}}
+        }
+    },
+    computed:{
+        yearSelector(){
+            return [
+                ...yearSelector,
+                { name: this.$i18n.locale == 'zh'?'自定义':'custom',value: 5 }
+            ]
+        },
+        dayOpt(){
+            return [
+                {label:this.$t('Edb.FreAll.year_min'),val:'年'},
+                {label:this.$t('Edb.FreAll.quarter_min'),val:'季'},
+                {label:this.$t('Edb.FreAll.month_min'),val:'月'},
+                {label:this.$t('Edb.FreAll.week_min'),val:'周'},
+                {label:this.$t('Edb.FreAll.day_min'),val:'天'},
+            ]
+        }
+    },
+    methods: {
+        handleSelectTarget(type='A',target=''){
+            this.$emit(`selectTarget`,{type,target})
+        },
+    },
+}

+ 137 - 0
src/views/chartRelevance_manage/relevance/components/modifyClassifyDialog.vue

@@ -0,0 +1,137 @@
+<template>
+    <div class="Dialog-box">
+        <el-dialog
+        :visible.sync="isOpenDialog"
+        :close-on-click-modal="false"
+        :modal-append-to-body='false'
+        @close="cancelHandle"
+        custom-class="dialog"
+        center
+        width="560px"
+        v-dialogDrag>
+            <div slot="title" style="display:flex;alignItems:center;">
+                <img :src="type=='add'?$icons.add:$icons.edit" style="color:#fff;width:16px;height:16px;marginRight:5px;">
+                <span style="fontSize:16px;">{{type==='add' ? $t('Table.add_btn') : $t('Table.edit_btn')}}</span>
+            </div>
+            <div class="dialog-main">
+                <el-form
+                ref="diaForm"
+                label-position="left"
+                hide-required-asterisk
+                label-width="120px"
+                :model="formData"
+                :rules="formRules">
+                    <el-form-item :label="$t('OnlineExcelPage.parent_directory_lable')" v-if="formData.level>0">
+                        <el-tooltip class="item" effect="dark" :content="getParentName" placement="top">
+                            <span class="parentStr">{{getParentName}}</span>
+                        </el-tooltip>
+                    </el-form-item>
+                    <el-form-item :label="$t('EtaBasePage.menu_name')" prop="levelVal">
+                        <el-input
+                        v-model="formData.levelVal"
+                        style="width: 80%"
+                        :placeholder="$t('Dialog.require_vaild')"></el-input>
+                    </el-form-item>
+                </el-form>
+            </div>
+            <div class="dia-bot">
+                <el-button type="primary" style="margin-right:20px" @click="saveHandle"><!-- 保存 -->{{$t('Dialog.confirm_save_btn')}}</el-button>
+                <el-button type="primary" plain @click="cancelHandle"><!-- 取消 -->{{$t('Dialog.cancel_btn')}}</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import chartRelevanceApi from "@/api/modules/chartRelevanceApi.js";
+export default {
+    props: {
+        isOpenDialog: {
+            type: Boolean,
+        },
+        type:{
+            type:String,
+            default:'add'
+        },
+        formData: {
+            type: Object,//{parentArr父级数据}
+        }
+    },
+    computed:{
+        getParentName(){
+            const arr=this.formData.parentArr||['无']
+            let strArr=arr.reverse().map(item=>{
+                return item.classifyName
+            })
+            
+            return strArr.join('/')
+        }
+    },
+    data () {
+        return {
+            formRules: {
+                levelVal:[
+                    { required: true, message: this.$t('EtaBasePage.input_menu_msg'), trigger: 'blur' },
+                ],
+            },
+            options:  [],
+
+        };
+    },
+    methods: {
+        async saveHandle() {
+            await this.$refs.diaForm.validate();
+            let addParams = {
+                ChartClassifyName:this.formData.levelVal,
+                Level:this.formData.level,
+                ParentId:this.formData.parent_id,
+            }
+            let editParams = {
+                ChartClassifyName:this.formData.levelVal,
+                ChartClassifyId:this.formData.nodeId
+            }
+            const res = this.type==='add'?await chartRelevanceApi.classifyAdd(addParams):await chartRelevanceApi.classifyEdit(editParams)
+            if(res.Ret!==200) return 
+            this.$message.success(`${this.type==='add'?'新增':'编辑'}成功`)
+            this.callbackHandle()
+
+
+        },
+        /* 成功回调 */
+        callbackHandle(type) {
+            this.$refs.diaForm.resetFields();
+            this.$emit('sucessCallback',type)
+        },
+        /* 取消 */
+        cancelHandle() {
+            this.$refs.diaForm.resetFields();
+            this.$emit('closeDia')
+        },
+    },
+    created() {},
+    mounted() {},
+}
+</script>
+<style lang='scss'>
+.Dialog-box {
+    .parentStr{
+        display: block;
+        width: 304px;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+    }
+    .dialog-main {
+        padding-left: 50px;
+    }
+    .el-cascader .el-input {
+        width: 100%;
+    }
+    .dia-bot {
+        margin: 52px 0 30px;
+        display: flex;
+        justify-content: center;
+
+    }
+    }
+</style>

+ 616 - 0
src/views/chartRelevance_manage/relevance/components/multipleIndForm.vue

@@ -0,0 +1,616 @@
+<template>
+    <div class="multiple-model-form model-form">
+        <!-- 标的指标 -->
+        <el-form-item 
+            :label="$t('StatisticAnalysis.ChartRelevance.target_indicator')" 
+            prop="IndTarget" class="select-target">
+            <!-- 添加后的图表不允许修改标的指标 -->
+            <selectTarget 
+                :isDisabled="isMultipleChartAdd"
+                :defaultId="chartInfoData.EdbInfoList?chartInfoData.EdbInfoList[0].EdbInfoId:''"
+                :defaultOpt="chartInfoData.EdbInfoList?[chartInfoData.EdbInfoList[0]]:[]" 
+                :defaultType="chartInfoData.EdbInfoList?chartInfoData.EdbInfoList[0].EdbInfoCategoryType:''"
+                @select="(target)=>handleSelectTarget('IndTarget',target)"
+            />
+        </el-form-item>
+        <!-- 因子指标系列 -->
+        <div class="factor-form-item">
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.factor_indicators')" required>
+            </el-form-item>
+            <div class="factor-list">
+                    <div class="list-item" 
+                        v-for="(item,index) in factorList" :key="index">
+                        <span>
+                            <!-- <i class="el-icon-arrow-right"></i> -->
+                            {{ item.SeriesName }}
+                        </span>
+                        <span  @click.stop="openAddDialog(item)" style="margin-left: auto;">
+                            <img src="~@/assets/img/icons/edit_blue_new.png" alt="" style="width: 16px; height: 16px; margin-right: 5px">
+                        </span>
+                        <span @click="deleteFactorIndicators(index)">
+                            <img src="~@/assets/img/set_m/del_icon.png" alt="" style="width: 14px; height: 14px;">
+                        </span>
+                    </div>
+            </div>
+            <div class="add-factor-btn" @click="openAddDialog(null)">
+                <img src="~@/assets/img/add-quadrate-blue.png" />
+                {{ $t('StatisticAnalysis.ChartRelevance.add_factor_indicators') }}
+            </div>
+        </div>
+        <div class="form-box">
+            <!-- 相关性 -->
+            <div class="label-title">{{ $t('Chart.ChartType.correlation_name') }}</div>
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.calculation_window')"
+                prop="Correlation.CalculateValue" class="flex-form-item">
+                <el-input
+                    style="flex:2"
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Correlation.CalculateValue"
+                    @change="val => { infoForm.Correlation.CalculateValue = Number(val); }"
+                />
+                <el-select
+                        style="flex:2"
+                        v-model="infoForm.Correlation.CalculateUnit">
+                    <el-option
+                        v-for="item in dayOpt"
+                        :key="item.val"
+                        :label="item.label"
+                        :value="item.val"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.analysis_cycle')" 
+                prop="Correlation.LeadValue" class="flex-form-item">
+                <el-input
+                    style="flex:2"
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Correlation.LeadValue"
+                    @change="val => { infoForm.Correlation.LeadValue = Number(val); }"
+                />
+                <el-select
+                    style="flex:2"
+                    v-model="infoForm.Correlation.LeadUnit">
+                    <el-option
+                        v-for="item in dayOpt"
+                        :key="item.val"
+                        :label="item.label"
+                        :value="item.val"
+                    />
+                </el-select>
+            </el-form-item>
+        </div>
+        <!-- 添加/编辑因子系列弹窗 -->
+        <el-dialog
+            :visible.sync="isAddFactorDialogShow"
+            :close-on-click-modal="false"
+            :modal-append-to-body='false'
+            @close="isAddFactorDialogShow=false"
+            center width="75%" top="30px"
+            :title="$t('StatisticAnalysis.ChartRelevance.add_factor_indicators')"
+            custom-class="add-factor-dialog"
+        >
+            <div class="dialog-content">
+                <!-- 选择指标 or 预测指标 -->
+                <div class="table-radio-wrap">
+                    <el-radio-group v-model="factorData.EdbInfoType" @input="changeEdbType">
+                        <el-radio :label="0">ETA指标</el-radio>
+                        <el-radio :label="1">预测指标</el-radio>
+                    </el-radio-group>
+                    
+                </div>
+                <!-- 表格筛选项 -->
+                <div class="table-select-box">
+                    <el-cascader
+                        v-model="tableSelectParams.classify"
+                        :options="classifyOpt"
+                        :props="{
+                            label: 'ClassifyName',
+                            value: 'ClassifyId',
+                            children: 'Children',
+                            multiple: true,
+                            emitPath:false
+                        }"
+                        clearable collapse-tags
+                        :placeholder="$t('EtaBasePage.label_classify')"
+                        @change="handleFilter"
+                    />
+                    <el-select
+                        v-model="tableSelectParams.frequency"
+                        :placeholder="$t('EtaBasePage.select_frequency')"
+                        clearable multiple collapse-tags
+                        @change="handleFilter">
+                        <el-option
+                            v-for="item in frequencyArr"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                        >
+                        </el-option>
+                    </el-select>
+                    <el-cascader
+                        v-model="tableSelectParams.creator"
+                        :placeholder="$t('EtaBasePage.table_col_creator')"
+                        :options="sysUserOpt"
+                        :props="{
+                            value: 'AdminId',
+                            label: 'RealName',
+                            children: 'ChildrenList',
+                            multiple: true,
+                            emitPath:false
+                        }"
+                        collapse-tags
+                        :show-all-levels="false"
+                        clearable filterable
+                        @change="handleFilter"
+                    />
+                    <el-input 
+                        :placeholder="$t('Edb.InputHolderAll.input_name_orid')" 
+                        v-model="tableSelectParams.keyword"
+                        style="width: 240px"
+                        @keydown.enter.native="handleFilter"
+                    >
+                        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+                    </el-input>
+                    <el-checkbox 
+                        :label="$t('EtaBasePage.label_all_check')"
+                        :indeterminate="isIndeterminate" 
+                        v-model="isCheckAll" 
+                        @change="listCheckAllChange"/>
+                </div>
+                <!-- 表格 -->
+                <batchSelectTable
+                    ref="batchSelectTable"
+                    :tableColumns="tableColumns"
+                    :tableData="tableData"
+                    :tableParams="tableParams"
+                    :tableLoading="tableLoading"
+                    :isSelectAll="isSelectAll"
+                    :factorData="factorData"
+                    @pageChange="tablePageChange"
+                    @changeCheckAll="changeCheckAll"
+                    @addSelectData="addSelectData"
+                ></batchSelectTable>
+                <!-- 计算公式 -->
+                <batchSelectFormula
+                    ref="batchSelectFormula"
+                    :factorData="factorData"
+                    :formulaOpt="formulaOpt"
+                ></batchSelectFormula>
+            </div>
+            <div class="dialog-footer">
+                <el-button type="primary" plain @click="isAddFactorDialogShow=false">{{$t('Dialog.cancel_btn')}}</el-button>
+                <el-button type="primary" @click="handleAddFactor" :loading="addFactorLoading">{{$t('Dialog.confirm_btn')}}</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import batchSelectTable from './batchSelectTable'
+import batchSelectFormula from './batchSelectFormula'
+import formMixin from './formMixin'
+import { frequencySelectList } from '@/utils/defaultOptions'
+import {checkListChange,checkStepsChange} from '../utils/index'
+
+import { dataBaseInterface,departInterence } from '@/api/api.js'
+import * as preDictEdbInterface from "@/api/modules/predictEdbApi.js"
+import chartRelevanceApi from '@/api/modules/chartRelevanceApi'
+export default {
+    mixins:[formMixin],
+	components: { batchSelectTable, batchSelectFormula },
+    props:{
+        SeriesList:{
+            type:Object,
+            default:[]
+        },
+        isMultipleChartAdd:{
+            type:Boolean,
+            default:false
+        }
+    },
+    computed:{
+        tableColumns(){
+            return [
+                {
+                    key:this.$i18nt.locale==='en'?'EdbNameEn':'EdbName',
+                    label:this.$t('EtaBasePage.full_metric_name'),//指标全称
+                    width:'240px',
+                    showOverflowTooltip:true,
+                },
+                {
+                    key:'EndDate',
+                    label:this.$t('Edb.Detail.e_latest_date'),//最新日期
+                    width:'120px',
+                },
+                {
+                    key:'EndValue',
+                    label:this.$t('Edb.Detail.e_latest_value'),//最新值
+                    width:'80px',
+                    showOverflowTooltip:true,
+                },
+                {
+                    key:'SysUserRealName',
+                    label:this.$t('EtaBasePage.table_col_creator'),//创建人
+                    width:'80px',
+                    showOverflowTooltip:true,
+                },
+                {
+                    key:'Frequency',
+                    label:this.$t('Edb.Detail.e_fre'),//频率
+                    width:'50px',
+                    showOverflowTooltip:true,
+                },
+                {
+                    key:this.$i18nt.locale==='en'?'UnitEn':'Unit',
+                    label:this.$t('Edb.Detail.e_unit'),//单位
+                    width:'50px',
+                    showOverflowTooltip:true,
+                },
+            ]
+        },
+        frequencyArr(){
+            return frequencySelectList()
+        },
+    },
+    data(){
+        return {
+            factorList:[], //多因子系列列表
+            isAddFactorDialogShow:false,
+            addFactorLoading:false,
+            factorData:{
+                SeriesName:'',//因子系列名称
+                CalculateStep:[],//因子系列计算公式
+                EdbMappings:[],//因子系列选择的指标
+                EdbInfoType:0,//选择的指标类型:0指标1预测指标
+            },
+            tableData:[],
+            tableSelectParams:{
+                classify:'',
+                frequency:'',
+                creator:'',
+                keyword:'',
+            },
+            classifyOpt:[],
+            sysUserOpt:[],
+            formulaOpt:[],
+            tableParams:{
+                total:0,
+                pageSize:20,
+                pageNo:1,
+                pagerCount:5,
+                uniqueKey:'EdbInfoId',//数据行的唯一key
+            },
+            tableLoading:false,
+            isIndeterminate:false,//与isCheckAll一起表示列表全选的状态
+            isCheckAll:false,//与isIndeterminate一起表示列表全选的状态
+            isSelectAll:false,//是否勾选了列表全选:为true时,selectList是剔除的指标,为false时selectList是已选择的指标
+        }
+    },
+    methods:{
+        openAddDialog(data){
+            if(data){
+                this.factorData = _.cloneDeep(data)
+            }else{
+                this.factorData = {
+                    SeriesName:'',
+                    CalculateStep:[],
+                    EdbMappings:[],
+                    EdbInfoType:0,
+                }
+            }
+            
+            this.getClassifyOpt()
+            this.getSysUserOpt()
+            this.getFormulaOption()
+            //清空筛选项
+            this.initSelectOpt()
+            this.tableData = []
+            this.isAddFactorDialogShow = true
+        },
+        changeEdbType(){
+            if(this.isAddFactorDialogShow){
+                //若切换指标类型,清空选项
+                this.factorData.SeriesName = ''
+                this.factorData.EdbMappings = []
+                this.factorData.CalculateStep =[]
+                this.getFormulaOption()
+                this.getClassifyOpt()
+            }
+        },
+        initSelectOpt(){
+            this.tableSelectParams = {
+                classify:'',
+                frequency:'',
+                creator:'',
+                keyword:'',
+            }
+            this.tableParams = {
+                total:0,
+                pageSize:20,
+                pageNo:1,
+                pagerCount:5,
+                uniqueKey:'EdbInfoId',//数据行的唯一key
+            }
+            this.isIndeterminate = false
+            this.isCheckAll = false
+            this.listCheckAllChange(false)
+        },
+        async getClassifyOpt(){
+            const res= this.factorData.EdbInfoType===0
+                        ?await dataBaseInterface.menuListV3()
+                        :await preDictEdbInterface.classifyListV2()
+            if (res.Ret !== 200) return
+
+            const filterNodes = (arr)=>{
+                arr.length &&
+                    arr.forEach((item) => {
+                        item.Children.length && filterNodes(item.Children);
+                        if (!item.Children.length) {
+                            delete item.Children;
+                        }
+                    });
+            }
+            filterNodes(res.Data.AllNodes||[]);
+
+            this.classifyOpt = res.Data.AllNodes || [];
+        },
+        async getSysUserOpt(){
+            const res = await departInterence.getQuestionAdminList();
+            if (res.Ret === 200) {
+                this.sysUserOpt = res.Data.List||[];
+            }
+        },
+        async getFormulaOption(){
+            const res = await chartRelevanceApi.getCalculateFormula({
+                EdbInfoType:this.factorData.EdbInfoType
+            })
+            if(res.Ret===200){
+                this.formulaOpt = res.Data||[]
+            }
+        },
+        handleFilter(){
+            this.tableParams.pageNo = 1
+            this.tableData = []
+            this.getTableData()
+        },
+        listCheckAllChange(value){
+            this.isSelectAll = value
+            this.$nextTick(()=>{
+                this.$refs.batchSelectTable&&this.$refs.batchSelectTable.listCheckAllChange(value)
+            })
+        },
+        changeCheckAll({isCheckAll,isIndeterminate}){
+            this.isCheckAll = isCheckAll
+            this.isIndeterminate = isIndeterminate
+        },
+        tablePageChange(page){
+            this.tableParams.pageNo = page
+            this.getTableData('pageChange')
+        },
+        async addSelectData({selectList=[],selectData=[]}){
+            //校验:没选择任何指标
+            if(!this.isCheckAll&&!this.isIndeterminate){
+                return this.$message.warning(this.$t('StatisticAnalysis.ChartRelevance.batch_select_hint'))
+            }
+            //通过接口获取选中的所有指标
+            const {classify,frequency,creator,keyword} = this.tableSelectParams
+            const ClassifyIds = classify?classify.join(','):''
+            const Frequency = frequency?frequency.join(','):''
+            const SysUserIds = creator?creator.join(','):''
+            const res=await dataBaseInterface.getBatchFilterAddEdbList({
+                SysUserIds,ClassifyIds,
+                Keyword:keyword,
+                Frequency,
+                SelectAll:this.isSelectAll,
+                EdbInfoIds:selectList.join(','),
+                EdbInfoType:Number(this.factorData.EdbInfoType||0)
+            })
+            if(res.Ret!==200) return 
+            //去重
+            //const data = this.mergeAndDistinct(selectData,res.Data.SearchItem||[])
+            const data = selectData.concat(res.Data.SearchItem||[]).filter((item,index,self)=>{
+                return index ===self.findIndex(t=>t.EdbInfoId === item.EdbInfoId)
+            })||[]
+            //加入到selectData中
+            this.$refs.batchSelectTable.addSelectData(data)
+            //自动填写指标系列名称
+            if(!this.$refs.batchSelectFormula.formulaForm.SeriesName){
+                this.$refs.batchSelectFormula.formulaForm.SeriesName = selectData[0]?selectData.EdbName:data[0]?data[0].EdbName:''
+            }
+        },
+        async getTableData(type){
+            this.tableLoading=true
+            const {classify,frequency,creator,keyword} = this.tableSelectParams
+            const ClassifyIds = classify?classify.join(','):''
+            const Frequency = frequency?frequency.join(','):''
+            const SysUserIds = creator?creator.join(','):''
+            //没有任何筛选项时不展示数据
+            if(!ClassifyIds&&!Frequency&&!SysUserIds&&!keyword){
+                this.tableLoading = false
+                this.tableData = []
+                this.tableParams.total = 0
+                this.isIndeterminate = false
+                this.isCheckAll = false
+                return 
+            }
+            const res=await dataBaseInterface.getBatchAddEdbSearchList({
+                CurrentIndex:this.tableParams.pageNo,
+                PageSize: this.tableParams.pageSize,
+                SysUserIds,ClassifyIds,Frequency,
+                Keyword:keyword,
+                NotFrequency:'',
+                EdbInfoType:Number(this.factorData.EdbInfoType||0)
+            })
+            this.tableLoading=false
+            if(res.Ret!==200) return 
+
+            this.tableData=res.Data.SearchItem||[]
+            this.tableParams.total=res.Data.Paging.Totals||0
+
+            if(type==='pageChange'){
+                this.$nextTick(()=>{
+                    this.$refs.batchSelectTable.adjustSelection()
+                })
+            }else{
+                this.listCheckAllChange(true)
+            }
+        },
+        async handleAddFactor(){
+            //校验 是否选择了指标
+            //校验 计算公式填写
+            await this.$refs.batchSelectFormula.checkForm()
+            //是否超过100个指标
+            if(!this.checkLimitFactor()){
+                return this.$message.warning('所有因子指标已超过100个,请检查')
+            }
+            this.addFactorIndicators()
+        },
+        checkLimitFactor(){
+            let total = 0
+            //已添加过的因子系列
+            this.factorList.forEach(i=>total += i.EdbMappings.length)
+            //当前要添加的因子系列
+            const selectData = this.$refs.batchSelectTable.selectData
+            if(!this.factorData.SeriesId){
+                total+=selectData.length
+            }else{
+                const currentFactor = this.factorList.find(i=>i.SeriesId===this.factorData.SeriesId)
+                const EdbNum = (currentFactor&&currentFactor.EdbMappings.length)||0
+                total -=EdbNum
+                total+=selectData.length
+            }
+            return total<=100
+        },
+        //格式化因子系列计算方式的格式
+        formattingStep(steps=[],isTrans=true){
+            return isTrans
+                ?steps.map((step,index)=>{ //接口需要的格式
+                    const {formulaType,nNum,alphaValue,Calendar} = step
+                    return {
+                        Sort:index+1,
+                        Source:formulaType,
+                        Formula:(formulaType===15?alphaValue:nNum)+'', //N值取nNum,alpha值取alphaValue
+                        Calendar:formulaType===11?Calendar:'',//超季节性取值,其他为空
+                    }
+                })
+                :steps.map(step=>{ //回显需要的格式
+                    const {Source,Calendar,Formula} = step
+                    return {
+                        formulaType:Source,
+                        nNum:Source===15?1:Formula,
+                        alphaValue:Source===15?Formula:0.5,
+                        Calendar
+                    }
+                })
+        },
+        //格式化因子系列所选指标的格式
+        formattingData(data=[],isTrans=true){
+            return isTrans
+                ?data.map(item=>item.EdbInfoId)
+                :data
+        },
+        async addFactorIndicators(){
+            this.addFactorLoading = true
+            //因子指标系列push
+            const selectData = this.$refs.batchSelectTable.selectData
+            const {SeriesName,CalculateStep} = this.$refs.batchSelectFormula.formulaForm
+            const checkList = checkListChange(
+                this.formattingData(selectData),
+                this.formattingData(this.factorData.EdbMappings),
+            )
+            const checkSteps = checkStepsChange(
+                this.formattingStep(CalculateStep),
+                this.formattingStep(this.factorData.CalculateStep),
+            )
+            let factor = {
+                SeriesName,
+                EdbInfoType:this.factorData.EdbInfoType,
+                Calculates:this.formattingStep(CalculateStep),
+                EdbInfoIds:this.formattingData(selectData),
+                Recalculate:checkList||checkSteps,//是否需要重新计算
+            }
+            //添加 Recalculate必为true
+            //编辑 取factor.Recalculate
+            console.log('check list',checkList)
+            console.log('check steps',checkSteps)
+            const res = this.factorData.SeriesId
+                ?await chartRelevanceApi.editFactorSeries({...factor,SeriesId:this.factorData.SeriesId})
+                :await chartRelevanceApi.addFactorSeries({...factor,Recalculate:true})
+            //计算中...
+            this.addFactorLoading = false
+            if(res.Ret!==200) return 
+            //标记计算失败的指标
+            const calculatFailList = res.Data.Fail
+            const baseEdbMappings = selectData
+            //更新factorList
+            if(!this.factorData.SeriesId){
+                this.factorList.push({
+                    SeriesId:res.Data.SeriesId,//接口返的
+                    SeriesName,
+                    EdbInfoType:this.factorData.EdbInfoType,
+                    CalculateStep:CalculateStep,
+                    EdbMappings:selectData,
+                })
+            }else{
+                const index = this.factorList.findIndex(i=>i.SeriesId===this.factorData.SeriesId)
+                this.factorList.splice(index,1,{
+                    SeriesId:this.factorData.SeriesId,
+                    SeriesName,
+                    EdbInfoType:this.factorData.EdbInfoType,
+                    CalculateStep:CalculateStep,
+                    EdbMappings:selectData,
+                })
+            }
+            //如果需要重新计算 抛出事件外层组件处理
+            if(!this.factorData.SeriesId||factor.Recalculate){
+                this.$emit('checkRecalculate')
+            }
+            this.isAddFactorDialogShow = false
+        },
+        deleteFactorIndicators(index){
+            this.factorList.splice(index,1)
+            this.$emit('checkRecalculate')
+        }
+    },
+    mounted(){
+        this.factorList = this.SeriesList.map(i=>{
+            return {
+                SeriesId:i.SeriesId,
+                SeriesName:i.SeriesName,
+                CalculateStep:this.formattingStep(i.CalculateStep||[],false),
+                EdbMappings:i.EdbMappings||[],
+                EdbInfoType:i.EdbInfoType,
+            }
+        })
+    },
+};
+</script>
+
+<style lang="scss">
+.add-factor-dialog{
+    .dialog-content{
+        height: 70%;
+        overflow-y: auto;
+        .table-select-box{
+            margin-bottom: 15px;
+            display: flex;
+            align-items: center;
+            gap:0 15px;
+            .el-cascader,.el-select{
+                .el-input{
+                    width:100%;
+                }
+            }
+        }
+    }
+    .dialog-footer{
+        text-align:center;
+        margin:30px 0 20px 0;
+    }
+}
+</style>

+ 268 - 0
src/views/chartRelevance_manage/relevance/components/singleIndForm.vue

@@ -0,0 +1,268 @@
+<template>
+    <div class="single-model-form model-form">
+        <!-- 指标A -->
+        <el-form-item 
+            :label="$t('StatisticAnalysis.ChartRelevance.edbTagA')" 
+            prop="EdbInfoIdA" class="select-target">
+            <selectTarget  
+                :defaultId="chartInfoData.EdbInfoList?chartInfoData.EdbInfoList[0].EdbInfoId:''"
+                :defaultOpt="chartInfoData.EdbInfoList?[chartInfoData.EdbInfoList[0]]:[]"
+                :defaultType="chartInfoData.EdbInfoList?chartInfoData.EdbInfoList[0].EdbInfoCategoryType:''"
+                @select="(target)=>handleSelectTarget('EdbInfoIdA',target)"
+            />
+        </el-form-item>
+        <!-- 指标B -->
+        <el-form-item 
+            :label="$t('StatisticAnalysis.ChartRelevance.edbTagB')" 
+            prop="EdbInfoIdB" class="select-target">
+            <selectTarget 
+                :defaultId="chartInfoData.EdbInfoList?chartInfoData.EdbInfoList[1].EdbInfoId:''"
+                :defaultOpt="chartInfoData.EdbInfoList?[chartInfoData.EdbInfoList[1]]:[]" 
+                :defaultType="chartInfoData.EdbInfoList?chartInfoData.EdbInfoList[1].EdbInfoCategoryType:''"
+                @select="(target)=>handleSelectTarget('EdbInfoIdB',target)"
+            />
+        </el-form-item>
+        <!-- 曲线图 -->
+        <div class="form-box">
+            <div class="label-title">{{ $t('Chart.ChartType.spline_name') }}</div>
+            <!-- 时间 -->
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.time')" 
+                class="flex-form-item">
+                <!-- 时间类型 -->
+                <el-select
+                    style="width:100%"
+                    v-model="infoForm.Curve.DateType"
+                    @change="getPreviewSplineChart"
+                >
+                    <el-option
+                        v-for="item in yearSelector"
+                        :key="item.value"
+                        :label="item.name"
+                        :value="item.value"
+                    />
+                </el-select>
+                <!-- 时间段 -->
+                <date-picker
+                    v-model="infoForm.Curve.Date"
+                    v-show="infoForm.Curve.DateType===5"
+                    style="margin-left:10px;"
+                    type="month"
+                    range
+                    value-type="format"
+                    :placeholder="$t('Chart.choose_time')"
+                    @change="dateChange"
+                />
+            </el-form-item>
+            <!-- 左轴 -->
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.left_axis')" 
+                class="flex-form-item">
+                <el-input
+                    style=""
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Curve.LeftMin"
+                    @change="val => { infoForm.Curve.LeftMin=Number(val);changeSplineOption() }"
+                />
+                <span>{{ $t('StatisticAnalysis.ChartRelevance.to') }}</span>
+                <el-input
+                    style=""
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Curve.LeftMax"
+                    @change="val => { infoForm.Curve.LeftMax=Number(val);changeSplineOption() }"
+                />
+            </el-form-item>
+            <!-- 右轴 -->
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.right_axis')" 
+                class="flex-form-item">
+                <el-input
+                    style=""
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Curve.RightMin"
+                    @change="val => { infoForm.Curve.RightMin=Number(val);changeSplineOption() }"
+                />
+                <span>{{ $t('StatisticAnalysis.ChartRelevance.to') }}</span>
+                <el-input
+                    style=""
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Curve.RightMax"
+                    @change="val => { infoForm.Curve.RightMax=Number(val);changeSplineOption() }"
+                />
+            </el-form-item>
+            <!-- 指标B -->
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.edbTagB')" >
+                <el-checkbox v-model="infoForm.Curve.IsOrder"  @change="getPreviewSplineChart" style="width:100%">
+                    {{ $t('StatisticAnalysis.ChartRelevance.reverse_sequence') }}
+                </el-checkbox>
+                <div class="edb-type-box">
+                    <el-radio
+                        v-model="infoForm.Curve.EdbInfoType"
+                        :label="true"
+                        style="margin-right:10px;"
+                        @change="getPreviewSplineChart">
+                        {{ $t('StatisticAnalysis.ChartRelevance.standard_index') }}
+                    </el-radio>
+                    <el-radio
+                        v-model="infoForm.Curve.EdbInfoType"
+                        :label="false"
+                        style="margin-right:10px;"
+                        @change="getPreviewSplineChart">
+                        {{ $t('StatisticAnalysis.ChartRelevance.leading_indicator') }}
+                    </el-radio>
+                </div>
+                <div class="edb-type-lead-box" style="text-align: right;" v-if="!infoForm.Curve.EdbInfoType">
+                    <span>{{ $t('StatisticAnalysis.ChartRelevance.lead_tag') }}</span>
+                    <el-input
+                        style="width: 60px"
+                        size="mini"
+                        type="number"
+                        v-model="infoForm.Curve.LeadValue"
+                        @change="(val) => { infoForm.Curve.LeadValue = Number(val);getPreviewSplineChart()}"
+                    ></el-input>
+                    <el-select
+                        v-model="infoForm.Curve.LeadUnit"
+                        placeholder=""
+                        size="mini"
+                        style="width: 60px"
+                        @change="getPreviewSplineChart">
+                        <el-option
+                            v-for="item in dayOpt"
+                            :key="item.val"
+                            :label="item.label"
+                            :value="item.val"
+                        />
+                    </el-select>
+                </div>
+            </el-form-item>
+        </div>
+        <!-- 相关性 -->
+        <div class="form-box">
+            <div class="label-title">{{ $t('Chart.ChartType.correlation_name') }}</div>
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.calculation_window')" 
+                prop="Correlation.CalculateValue" class="flex-form-item">
+                <el-input
+                    style="flex:2"
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Correlation.CalculateValue"
+                    @change="val => { infoForm.Correlation.CalculateValue = Number(val); }"
+                />
+                <el-select
+                        style="flex:2"
+                        v-model="infoForm.Correlation.CalculateUnit"
+                >
+                    <el-option
+                        v-for="item in dayOpt"
+                        :key="item.val"
+                        :label="item.label"
+                        :value="item.val"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.analysis_cycle')" 
+                prop="Correlation.LeadValue" class="flex-form-item">
+                <el-input
+                    style="flex:2"
+                    :step="1"
+                    type="number"
+                    v-model="infoForm.Correlation.LeadValue"
+                    @change="val => { infoForm.Correlation.LeadValue = Number(val); }"
+                />
+                <el-select
+                    style="flex:2"
+                    v-model="infoForm.Correlation.LeadUnit">
+                    <el-option
+                        v-for="item in dayOpt"
+                        :key="item.val"
+                        :label="item.label"
+                        :value="item.val"
+                    />
+                </el-select>
+            </el-form-item>
+        </div>
+        <!-- 滚动相关性 -->
+        <div class="form-box" v-for="(item,index) in infoForm.RollingCorrelation" :key="index">
+            <div class="label-title">{{  $t('Chart.ChartType.rolling_correlation_name') }} {{ index+1 }}</div>
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.calculation_window')" 
+                class="flex-form-item">
+                <el-input
+                    style="flex:2"
+                    :step="1"
+                    type="number"
+                    v-model="item.CalculateValue"
+                    @change="val => { item.CalculateValue = Number(val); }"
+                />
+                <el-select
+                    style="flex:2"
+                    v-model="item.CalculateUnit">
+                    <el-option
+                        v-for="item in dayOpt"
+                        :key="item.val"
+                        :label="item.label"
+                        :value="item.val"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item 
+                :label="$t('StatisticAnalysis.ChartRelevance.B_leads_A')" 
+                class="flex-form-item">
+                <el-input
+                    style="flex:2"
+                    :step="1"
+                    type="number"
+                    v-model="item.LeadValue"
+                    @change="val => { item.LeadValue = Number(val); }"
+                />
+                <el-select
+                    style="flex:2"
+                    v-model="item.LeadUnit">
+                    <el-option
+                        v-for="item in dayOpt"
+                        :key="item.val"
+                        :label="item.label"
+                        :value="item.val"
+                    />
+                </el-select>
+            </el-form-item>
+        </div>
+    </div>
+</template>
+
+<script>
+import formMixin from './formMixin';
+export default {
+    mixins:[formMixin],
+    methods:{
+        dateChange(val){
+            this.infoForm.Curve.DateType = 5
+            if(val[0]) {
+                this.infoForm.Curve.StartDate = val[0];
+                this.infoForm.Curve.EndDate = val[1];
+            }else {
+                this.infoForm.Curve.StartDate = '';
+                this.infoForm.Curve.EndDate = '';
+            }
+            this.getPreviewSplineChart()
+        },
+        getPreviewSplineChart(){
+            this.$emit('previewChart')
+        },
+        changeSplineOption(){
+            this.$emit('changeSpline')
+        },
+    }
+};
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 294 - 23
src/views/chartRelevance_manage/relevance/list.vue

@@ -68,8 +68,9 @@
             :default-expanded-keys="defaultShowNodes"
             draggable
             :expand-on-click-node="false"
-            check-strictly
             empty-text="暂无分类"
+            lazy
+            :load="getLazyTreeData"
             @node-expand="handleNodeExpand"
             @node-collapse="handleNodeCollapse"
             @current-change="nodeChange"
@@ -95,6 +96,7 @@
                 :style="`width:${
                   (select_node === data.UniqueCode && node.Nodewidth) || ''
                 }`"
+                :id="`node${data.UniqueCode}`"
               >
                 <span>{{ currentLang==='en' ? (data.ChartClassifyNameEn||data.ChartClassifyName) : data.ChartClassifyName  }}</span>
               </span>
@@ -106,6 +108,15 @@
                   src="~@/assets/img/data_m/move_ico.png"
                   alt=""
                   style="width: 14px; height: 14px; margin-right: 8px"
+                  v-if="permissionBtn.isShowBtn('statisticPermission','corrAnalysis_classifyOpt_move')"
+                />
+                <!-- 添加子项 -->
+                <img
+                    src="~@/assets/img/set_m/add.png"
+                    alt=""
+                    style="width: 14px; height: 14px; margin-right: 8px"
+                    @click.stop="addNode(node,data)"
+                    v-if="data.Button.AddButton&&node.level<6"
                 />
                 <img
                   src="~@/assets/img/set_m/edit.png"
@@ -167,6 +178,9 @@
                     ref="chartRef"
                   />
                 </div>
+                <span class="chart-source" v-if="chartInfo.SourcesFrom.isShow&&chartInfo.SourcesFrom.text">
+                    数据来源:{{ chartInfo.SourcesFrom.text }}
+                </span>
                 <span class="chart-author"
                   >{{$t('MsgPrompt.author')}}:{{ chartInfo.SysUserRealName }}</span
                 >
@@ -262,7 +276,7 @@
           :total="chart_total" 
           :list="chartList" 
           @loadMoreHandle="loadMoreHandle"
-          @detailShowHandle="detailShowHandle"
+          @detailShowHandle="handleShowChartDetail"
           @addMychartHandle="addMychartHandle"
           ref="chartListWrap"
         />
@@ -270,11 +284,18 @@
     </div>
 
     <!-- 分类弹窗 -->
-    <classify-dia
+    <!-- <classify-dia
       :isOpenDialog.sync="classifyDia"
       :title="dialog_title"
       :form="classifyForm"
       @successCallback="getTreeData"
+    /> -->
+    <modifyClassifyDialog
+      :isOpenDialog.sync="classifyDia"
+      :type="classifyDiaType"
+      :formData="classifyForm"
+      @sucessCallback="sucessCallback"
+      @closeDia="classifyDia = false"
     />
 
     <!-- 加入我的图库弹窗 -->
@@ -319,12 +340,14 @@ import leftMixin from "../mixins/classifyMixin";
 import Chart from "@/views/dataEntry_manage/components/chart";
 import changeLang from "@/views/dataEntry_manage/components/changeLang.vue";
 import classifyDia from "@/views/datasheet_manage/components/sheetClassifyDia.vue";
+import modifyClassifyDialog from './components/modifyClassifyDialog.vue'
 import addMyClassifyDia from "@/views/dataEntry_manage/components/addMyClassifyDia";
 import SaveChartOther from "@/views/dataEntry_manage/components/SaveChartOther";
 import setEnNameDia from "@/views/dataEntry_manage/components/setEnNameDia.vue";
 import { chartSetMixin } from "@/views/dataEntry_manage/mixins/chartPublic";
 import { copyOtherOptions } from '@/utils/defaultOptions';
 import setLangInfoDia from '@/views/dataEntry_manage/components/setLangInfo.vue'
+import { baseSourcesFrom } from './utils/config'
 export default {
   components: {
     changeLang,
@@ -333,7 +356,8 @@ export default {
     addMyClassifyDia,
     SaveChartOther,
     setEnNameDia,
-    setLangInfoDia
+    setLangInfoDia,
+    modifyClassifyDialog
   },
   mixins: [leftMixin, chartSetMixin],
   computed: {
@@ -359,11 +383,12 @@ export default {
       defaultProp: {
         label: "ChartClassifyName",
         children: "Children",
+        isLeaf:'isLeaf'
       }, //树结构配置项
       dynamicNode: null,
 
       /* 分类弹窗 */
-      dialog_title: "",
+      classifyDiaType: "add",//add or edit
       classifyDia: false, //
       classifyForm: {},
 
@@ -392,10 +417,196 @@ export default {
     };
   },
   methods: {
+    /* 判断节点是否能被拖拽 */
+    canDragHandle({data}) {
+        return data.Button.MoveButton&&this.permissionBtn.isShowBtn('statisticPermission','corrAnalysis_classifyOpt_move');
+    },
+    /* 判断节点是否能被拖入 */
+    canDropHandle(draggingNode, dropNode, type) {
+        let canDrop=false
+        
+        // 如果拖动的是图表
+        if(draggingNode.data.ChartInfoId){
+            if(!(dropNode.level===1&&type!=='inner')){
+                canDrop=true
+            }
+        }else{//拖动的是目录
+            //目录层级不能改变
+            if((dropNode.level+1==draggingNode.level&&type==='inner'&&!dropNode.data.ChartInfoId)||(dropNode.level===draggingNode.level&&type!=='inner')){
+                canDrop=true
+            }
+        }
+        return canDrop
+    },
+    /* 拖拽完成 */
+    dropOverHandle(b,a,i,e) {
+        // 被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置
+        const isChart=b.data.ChartInfoId?true:false
+        let list=a.parent.childNodes;
+        let targetIndex=0
+        let ClassifyId=0,//分类ID,若当前节点为图表,则为0
+        ParentClassifyId=0,//移动后,所在位置的父级分类ID
+        PrevClassifyId=0,//前一个节点的分类ID,若前一个节点为图表,则为0
+        NextClassifyId=0,//后一个节点的分类ID,同上
+        ChartInfoId=0,//图表ID,若当前节点为分类,则为0
+        PrevChartInfoId=0,//前一个节点的图表ID,若前一个节点为分类,则为0
+        NextChartInfoId=0;//后一个节点的图表ID
+
+        ClassifyId=isChart?0:b.data.ChartClassifyId
+        ChartInfoId=isChart?b.data.ChartInfoId:0
+        
+
+        if(i!=='inner'){
+            ParentClassifyId=a.parent.data.ChartClassifyId||0
+            list.forEach((item,index)=>{
+                if(isChart){
+                    if(item.data.ChartInfoId===b.data.ChartInfoId){
+                        targetIndex=index
+                    }
+                }else{
+                    if(item.data.ChartClassifyId===b.data.ChartClassifyId){
+                        targetIndex=index
+                    }
+                }
+            })
+
+            console.log(targetIndex);
+            
+            
+            if(targetIndex===0){
+                const data=list[targetIndex+1].data
+                NextClassifyId=data.ChartInfoId?0:data.ChartClassifyId
+                NextChartInfoId=data.ChartInfoId?data.ChartInfoId:0
+            }else if(targetIndex===list.length-1){
+                const data=list[targetIndex-1].data
+                PrevClassifyId=data.ChartInfoId?0:data.ChartClassifyId
+                PrevChartInfoId=data.ChartInfoId?data.ChartInfoId:0
+            }else{
+                const pData=list[targetIndex-1].data
+                PrevClassifyId=pData.ChartInfoId?0:pData.ChartClassifyId
+                PrevChartInfoId=pData.ChartInfoId?pData.ChartInfoId:0
+
+                const nData=list[targetIndex+1].data
+                NextClassifyId=nData.ChartInfoId?0:nData.ChartClassifyId
+                NextChartInfoId=nData.ChartInfoId?nData.ChartInfoId:0
+            }
+        }else{
+            ParentClassifyId=a.data.ChartClassifyId||0
+        }
+
+        const params={
+            ClassifyId,
+            ParentClassifyId,
+            PrevClassifyId,
+            NextClassifyId,
+            ChartInfoId,
+            PrevChartInfoId,
+            NextChartInfoId
+        }
+        console.log(params);
+        chartRelevanceApi.classifyMove(params).then(res=>{
+            if(res.Ret===200){
+                // this.$message.success('移动成功!')
+                this.$message.success(this.$t('MsgPrompt.move_sort_success'))
+            }
+            this.getTreeData()
+            if(this.select_id){
+                this.getDetailHandle();
+            }
+            
+        })
+    },
+
+    /* 拖拽覆盖添加背景色 */
+    dropMouseOver(node1,node2,e) {
+        // console.log(e.layerY);
+        
+        // 被拖拽节点对应的 Node、所进入节点对应的 Node、event
+        if(!node2.data.EdbInfoId&&(node1.level>node2.level||(node1.data.EdbInfoId>0&&!node2.data.EdbInfoId)) && (e.target.childNodes[0].className.includes('el-tree-node__content') 
+        || e.target.className.includes('el-tree-node__content'))) {
+            // console.log(e.target.childNodes[0])
+            e.target.childNodes[0].className.includes('el-tree-node__content') 
+            ? e.target.childNodes[0].style.backgroundColor = '#409eff' 
+            : e.target.style.backgroundColor = '#409eff';
+        }
+        
+    },
+    /* 拖拽离开/拖拽完成重置背景色 */
+    dropMouseLeave(node1,node2,e) {
+        let arrs = $('.el-tree-node__content');
+        for( let a of arrs ) {
+            a.style.backgroundColor = 'transparent';
+        }
+    },
+    sucessCallback(type){
+        this.classifyDia = false;
+        this.getTreeData();
+        if(type === 'add') {
+            //新增分类完成之后,展开父节点显示刚新增的分类,若已展开节点则不做处理
+            let code = sessionStorage.getItem('expandCode');
+            let flag = 	this.defaultShowNodes.some((item) => {
+                return item === code
+            });
+            !flag &&code&& this.defaultShowNodes.push(code);
+            sessionStorage.removeItem('expandCode');
+        }
+    },
+    // 递归节点
+    getNodeParentData(data,arr){
+        if(data.level===0) return
+        arr.push({classifyName:this.currentLang==='en'?data.data.ChartClassifyNameEn:data.data.ChartClassifyName,classifyId:data.data.ChartClassifyId})
+        this.getNodeParentData(data.parent,arr)
+        return arr
+    },
+    addNode(node,data){
+        this.classifyDiaType = 'add';
+        let arr=[]
+        arr=this.getNodeParentData(node,arr)
+        /* 添加目录 */
+        this.classifyForm = {
+            parentArr:arr,
+            parent_id: data.ChartClassifyId,
+            level: node.level,
+            levelVal:'',
+            nodeId:'',
+        }
+        //存储当前要新增子级的目录code
+        sessionStorage.setItem('expandCode', data.UniqueCode);
+        this.classifyDia = true;
+    },
+    //绑定el-tree的load属性
+    async getLazyTreeData (node,resolve){
+        if(node.level===0){
+            resolve(this.treeData)
+        }else{
+            let arr=[]
+            const res=await chartRelevanceApi.classifyList({
+                ParentId:node.data.ChartClassifyId,
+                IsShowMe:this.isOnlyMe,
+                Source: this.classify_tab ? 4 : 3})
+            if (res.Ret === 200) {
+                const temarr = res.Data.AllNodes || [];
+                arr=temarr.map(item=>{
+                    return {
+                        ...item,
+                        isLeaf:item.ChartInfoId?true:false
+                    }
+                })
+            }
+            resolve(arr)
+        }
+    },
+    //展开选中图表父级,选中选择图表
+    handleShowChartDetail({ UniqueCode, ChartInfoId }){
+        this.select_classify = 0;
+        this.select_id = ChartInfoId;
+        this.select_node = UniqueCode;
+    },
     /* 添加图表 */
     goAddChart() {
       if (!this.treeData.length) return this.$message.warning("请先添加分类");
-      this.$router.push({ path: "/relevancechartEditor" });
+      //this.$router.push({ path: "/relevancechartEditor" });
+      this.$router.push({ path: "/relevancechartEditorV2" });
     },
 
     /* 获取分类 */
@@ -410,10 +621,20 @@ export default {
           if (Ret !== 200) return;
 
           this.showData = true;
-          this.treeData = Data.AllNodes || [];
+          //this.treeData = Data.AllNodes || [];
+          this.treeData = Data.AllNodes?Data.AllNodes.map(d=>{
+            return {
+                ...d,
+                Children:[]
+            }
+          }):[]
           this.$nextTick(() => {
             /* 新增完成后 处理树展开和选中 */
-            params && this.selectCurrentNode(params);
+            //params && this.selectCurrentNode(params);
+            if(params){
+                this.select_node = params.code;
+                this.select_id = params.id;
+            }
           });
         });
     },
@@ -471,29 +692,33 @@ export default {
       this.search_txt = "";
       this.select_node = UniqueCode;
       this.select_classify = !ChartInfoId ? ChartClassifyId : 0;
-      // if(this.select_id !== ChartInfoId) {
       this.select_id = ChartInfoId || 0;
-      // }
       this.resetNodeStyle(node);
       this.dynamicNode = node;
     },
 
     /* 添加一级目录 */
     addLevelOneHandle() {
-      this.dialog_title = this.$t('StatisticAnalysis.ChartRelevance.add_chart_classify')||"添加图表分类";
-      this.classifyForm = {
-        classify_name: "",
-      };
-      this.classifyDia = true;
+        this.classifyDiaType = 'add';
+        this.classifyForm = {
+            parent_id: 0,
+            level: 0,
+            levelVal:'',
+        };
+        this.classifyDia = true;
     },
 
     /* 编辑节点 */
     editNode(node, { ChartClassifyName,ChartClassifyNameEn, ChartClassifyId }) {
-      this.dialog_title = this.$t('StatisticAnalysis.ChartRelevance.edit_chart_classify')||"编辑图表分类";
+      this.classifyDiaType = 'edit'
+      let arr=[]
+      arr=this.getNodeParentData(node.parent,arr)
       /* 编辑目录 */
       this.classifyForm = {
-        classify_name: this.currentLang==='en'?ChartClassifyNameEn:ChartClassifyName,
-        classify_id: ChartClassifyId,
+        parentArr:arr,
+        level:node.level,
+        levelVal: this.currentLang==='en'?ChartClassifyNameEn:ChartClassifyName,
+        nodeId: ChartClassifyId,
       };
       this.classifyDia = true;
     },
@@ -520,7 +745,13 @@ export default {
           }).then(() => {
             this.delApi(ChartClassifyId, ChartInfoId);
           })
-        : null;
+        : DeleteStatus===2
+        ? this.$confirm(this.$t('Edb.MsgPrompt.del_confirm_menu_or_children'),this.$t('Confirm.prompt'),{
+            type:"warning",
+        }).then(()=>{
+            this.delApi(ChartClassifyId, ChartInfoId);
+        })
+        :null;
     },
 
     /* 删除方法 */
@@ -618,10 +849,21 @@ export default {
         })
         .then((res) => {
           if (res.Ret !== 200) return;
-
           this.chartInfo = res.Data.ChartInfo;
           this.tableData = res.Data.EdbInfoList;
+          this.defaultShowNodes = res.Data.ClassifyLevels||[];
+          this.$nextTick(()=>{
+            setTimeout(() => {
+                this.$refs.treeRef.setCurrentKey(this.select_node);
+            }, 1200);
+          })
           if(this.chartInfo.Source === 3) {
+            const SourcesFrom = this.chartInfo.SourcesFrom
+            try{
+                this.chartInfo.SourcesFrom = SourcesFrom?JSON.parse(SourcesFrom):baseSourcesFrom
+            }catch(e){
+                this.chartInfo.SourcesFrom = baseSourcesFrom
+            }
             this.relevanceChartData = {
               ChartInfo: res.Data.ChartInfo,
               EdbInfoList: res.Data.EdbInfoList,
@@ -630,12 +872,16 @@ export default {
               YDataList: [
                 {
                   Value: res.Data.YDataList[0].Value,
-                  Color: "#00f",
+                  Color: res.Data.YDataList[0].Color,
                   Name: res.Data.ChartInfo.ChartName,
                   NameEn: res.Data.ChartInfo.ChartNameEn
                 },
               ],
             };
+            //多因子
+            if(res.Data.CorrelationChartInfo.AnalysisMode===1){
+                this.relevanceChartData.YDataList = res.Data.YDataList
+            }
             this.initRelevanceChartData() 
           }else if(this.chartInfo.Source === 4) { //滚动相关性逻辑又换成曲线了
             this.relevanceChartData = {
@@ -643,7 +889,25 @@ export default {
             }
             this.setDefaultChart([res.Data.DataResp]);
           }
-          
+          this.$nextTick(()=>{
+                const _node = this.$refs.treeRef.getNode(this.select_node)
+                this.dynamicNode = _node;
+                this.dynamicNode&&this.resetNodeStyle(this.dynamicNode)
+                setTimeout(() => {
+                    let node = document.getElementById(`node${this.select_node}`)||{}
+                    let parent = document.getElementsByClassName('tree-cont')[0];
+                    //parent可视区间:[scrollTop,scrollTop+offsetHeight]
+                    //node位置:node.offsetTop
+                    const overTop = node.offsetTop+node.clientHeight+30<parent.scrollTop
+                    const overBottom = node.offsetTop+node.clientHeight+30>parent.scrollTop+parent.offsetHeight
+                    if(overTop){
+                        parent.scrollTop = node.offsetTop-60
+                    }
+                    if(overBottom){
+                        parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
+                    }
+                },1500)
+            })
         });
     },
 
@@ -685,11 +949,18 @@ export default {
 
     /* 编辑图表 */
     editChartHandle() {
-      this.$router.push({
+      /* this.$router.push({
         path: "/relevancechartEditor",
         query: {
           code: this.chartInfo.UniqueCode,
         },
+      }); */
+      this.$router.push({
+        path: "/relevancechartEditorV2",
+        query: {
+          code: this.chartInfo.UniqueCode,
+          type:this.relevanceChartData.CorrelationChartInfo.AnalysisMode
+        },
       });
     },
 

+ 1089 - 0
src/views/chartRelevance_manage/relevance/relevanceChartEditorV2.vue

@@ -0,0 +1,1089 @@
+<template>
+    <div class="relevance-chart-editor-wrap" v-loading="previewMatrixLoading" element-loading-text="正在计算相关性矩阵...">
+        <div class="info-wrap content-wrap">
+            <div class="info-top">
+                <el-button type="primary" @click="previewChart">{{$t('Dialog.calculate_btn')}}</el-button>
+                <el-button type="primary" plain @click="$router.back()">{{$t('Dialog.cancel_btn')}}</el-button>
+                <!-- 操作说明 -->
+                <span @click="showExplain = true">
+                    <img style="width:15px;height:15px;" src="~@/assets/img/icons/formula-add.png" alt="">
+                    {{$t('StatisticAnalysis.ChartRelevance.opt_tip_btn')}}
+                </span>
+            </div>
+            <div class="info-form-wrap">
+                <el-form :model="infoForm" :rules="infoRules" label-width="80px" ref="infoFormRef">
+                    <!-- 分析模式 -->
+                    <el-form-item 
+                        :label="$t('StatisticAnalysis.ChartRelevance.analytical_model')" 
+                        prop="Model" required>
+                        <el-select v-model="infoForm.Model" style="width: 100%;" 
+                        :disabled="$route.query.code||isMultipleChartAdd||buttonAuth.isRelevanceChartAdd"
+                        @change="changeModel">
+                            <el-option :label="$t('StatisticAnalysis.ChartRelevance.single_indicator')" :value="1"></el-option>
+                            <el-option :label="$t('StatisticAnalysis.ChartRelevance.multiple_indicators')" :value="2"></el-option>
+                        </el-select>
+                    </el-form-item>
+                    <!-- 单因子模式需要填的 -->
+                    <singleIndForm
+                        v-if="infoForm.Model===1"
+                        :info-form="infoForm"
+                        :chart-info-data="chartInfoData"
+                        @selectTarget="handleSelectTarget"
+                        @previewChart="getPreviewSplineChart"
+                        @changeSpline="changeSplineOption"
+                    ></singleIndForm>
+                    <!-- 多因子模式需要填的 -->
+                    <multipleIndForm
+                        v-if="infoForm.Model===2"
+                        ref="multipleIndForm"
+                        :info-form="infoForm"
+                        :isMultipleChartAdd="isMultipleChartAdd"
+                        :chart-info-data="chartInfoData"
+                        :SeriesList="SeriesList"
+                        @selectTarget="handleSelectTarget"
+                        @checkRecalculate="checkRecalculate"
+                    ></multipleIndForm>
+                </el-form>
+            </div>
+        </div>
+        <div class="model-wrap">
+            <!-- 单因子模式 -->
+            <div class="single-model-wrap" v-if="infoForm.Model===1">
+                <div
+                    class="chart-min-cont"
+                    v-if="chartBatchData"
+                >
+                    <!-- 曲线图 -->
+                    <div class="card-wrapper content-wrap">
+                        <chartCard 
+                            :entryType="1"
+                            ref="chartCard1"
+                            :data="chartBatchData.CurveData"
+                            :settings="infoForm"
+                            :isChartAdd="buttonAuth.isCurveChartAdd"
+                            @saveChart="(params)=>{handleSave(params);isSaveChartToBase = true;}"
+                            @saveEdb="(params)=>{handleSave(params);isSaveEdbToBase = true;}"
+                        />
+                    </div>
+                    <!-- 相关性图表 -->
+                    <div class="card-wrapper content-wrap" v-if="chartBatchData.CorrelationData">
+                        <chartCard 
+                            :entryType="2"
+                            ref="chartCard2"
+                            :data="chartBatchData.CorrelationData"
+                            :settings="infoForm"
+                            :isChartAdd="buttonAuth.isRelevanceChartAdd"
+                            :isChartSetting="true"
+                            @chartSettingChange="handleChangeChartSetting"
+                            @saveChart="(params)=>{handleSave(params);isSaveChartToBase = true;}"
+                            @saveEdb="(params)=>{handleSave(params);isSaveEdbToBase = true;}"
+                        />
+                        <!-- 图表数据来源 -->
+                        <div class="source" v-if="chartBatchData.SourcesFrom.text&&chartBatchData.SourcesFrom.isShow">
+                            {{ $t('Edb.Detail.source') }}:{{ chartBatchData.SourcesFrom.text }}
+                        </div>
+                    </div>
+                    <!-- 滚动相关性1 -->
+                    <template v-if="chartBatchData.RollingCorrelationData">
+                        <div class="card-wrapper content-wrap" v-if="chartBatchData.RollingCorrelationData[0]">
+                            <chartCard 
+                                :entryType="3"
+                                ref="chartCard3"
+                                :data="chartBatchData.RollingCorrelationData[0]"
+                                :settings="infoForm"
+                                :isChartAdd="buttonAuth.isRollChartAdd"
+                                :isEdbAdd="buttonAuth.isRollEdbAdd"
+                                @saveChart="(params)=>{handleSave(params);isSaveChartToBase = true;}"
+                                @saveEdb="(params)=>{handleSave(params);isSaveEdbToBase = true;}"
+                            />
+                        </div>
+                        <!-- 滚动相关性2 -->
+                        <div class="card-wrapper content-wrap" v-if="chartBatchData.RollingCorrelationData[1]">
+                            <chartCard 
+                                :entryType="4"
+                                ref="chartCard4"
+                                :data="chartBatchData.RollingCorrelationData[1]"
+                                :settings="infoForm"
+                                :isChartAdd="buttonAuth.isRollChartTwoAdd"
+                                :isEdbAdd="buttonAuth.isRollEdbTwoAdd"
+                                @saveChart="(params)=>{handleSave(params);isSaveChartToBase = true;}"
+                                @saveEdb="(params)=>{handleSave(params);isSaveEdbToBase = true;}"
+                            />
+                        </div>
+                    </template>
+                </div>
+
+                <div class="nodata" v-else>
+                    <tableNoData text="暂无信息"/>
+                </div>
+            </div>
+            <!-- 多因子模式 -->
+            <div class="multiple-model-wrap" v-if="infoForm.Model===2">
+                <!-- 相关性矩阵表格 -->
+                <div class="relevant-matrix-table-box" v-if="factorTableData.length">
+                    <el-table style="width: 100%;" height="100%" :data="factorTableData" :row-class-name="getTableRowClassname" @sort-change="sortChange">
+                        <el-table-column 
+                            fixed
+                            :label="$t('StatisticAnalysis.ChartRelevance.multiple_table_head_01')"
+                            width="220px"
+                            align="center"
+                            class-name="zip-cell"
+                            >
+                            <el-table-column
+                                width="80px" align="center"
+                                class-name="zip-cell"
+                                :label="$t('Edb.Detail.e_opera')">
+                               <template slot-scope="{row}">
+                                    <template v-if="row.isSuccess">
+                                        <span style="color:#0052D9;cursor: pointer;" @click="addCurve(row)" v-if="!row.isAdd">{{$t('StatisticAnalysis.ChartRelevance.multiple_table_btn_add')}}</span>
+                                        <span style="color:#D54941;cursor: pointer;" @click="deleteCurve(row)" v-else>{{$t('StatisticAnalysis.ChartRelevance.multiple_table_btn_del')}}</span>
+                                    </template>
+                               </template>
+                            </el-table-column>
+                            <el-table-column
+                                width="140px" align="center"
+                                class-name="zip-cell"
+                                show-overflow-tooltip
+                                prop="EdbName"
+                                :label="$t('StatisticAnalysis.ChartRelevance.multiple_table_head_02')">
+                            </el-table-column>
+                        </el-table-column>
+                        <!-- 领先天数 -->
+                        <el-table-column
+                            v-if="SortedArray.length"
+                            class-name="zip-cell"
+                            :label="LeadLabelName">
+                            <el-table-column v-for="(num,index) in SortedArray" :key="num"
+                                min-width="45px"
+                                sortable="custom"
+                                prop="LeadValue"
+                                align="center"
+                                class-name="zip-cell"
+                                :label="num">
+                                <template slot-scope="{row}">
+                                    {{ row.dataList[index] }}
+                                </template>
+                            </el-table-column>
+                        </el-table-column>
+                    </el-table>
+                </div>
+                <!-- 相关性图表 -->
+                <div class="relevant-chart-box content-wrap" v-if="showMultipleChart">
+                    <chartCard
+                        ref="chartCard2"
+                        :data="multipleChartData"
+                        :settings="infoForm"
+                        :entryType="2"
+                        :isChartSetting="true"
+                        :isChartAdd="isMultipleChartAdd"
+                        height="300"
+                        @handleEdit="saveMultipleChart"
+                        @saveChart="(params)=>{handleSave(params);isSaveChartToBase = true;}"
+                        @saveEdb="(params)=>{handleSave(params);isSaveEdbToBase = true;}"
+                        @chartSettingChange="handleChangeChartSetting"
+                    />
+                    <!-- 数据来源 -->
+                    <div class="source" v-if="multipleChartData.SourcesFrom.text&&multipleChartData.SourcesFrom.isShow">
+                        {{ $t('Edb.Detail.source') }}:{{ multipleChartData.SourcesFrom.text }}
+                    </div>
+                </div>
+
+                <div class="nodata" v-if="!factorTableData.length">
+                    <tableNoData :text="$t('Common.no_info_msg')"/>
+                </div>
+            </div>
+        </div>
+        <!-- 图表保存/另存为 -->
+        <saveChartToBase
+            :isShow.sync="isSaveChartToBase"
+            :source="saveSource"
+            :saveScence="saveScence"
+            :chartData="chartData"
+            @saveBack="saveChartBack"
+            @handleSave="saveMultipleChart"
+        />
+
+        <!-- 指标保存/另存为 -->
+        <saveEdbToBase
+            :isShow.sync="isSaveEdbToBase"
+            :source="saveSource"
+            :saveScence="saveScence"
+            :chartData="chartData"
+            @saveBack="saveEdbBack"
+        />
+        <!-- 图例设置 -->
+        <saveChartSetting
+            :isSettingChartShow="isSettingChartShow"
+            :settingData="settingData"
+            @saveChartSetting="changeChartSettingBack"
+            @close="isSettingChartShow = false"
+        />
+        <!-- 操作说明 -->
+        <ExplainDialog 
+            :show-explain="showExplain"
+            @close="showExplain = false"
+        />
+    </div>
+</template>
+
+<script>
+/* api */
+import { dataBaseInterface } from '@/api/api.js'
+import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js'
+import chartRelevanceApi from '@/api/modules/chartRelevanceApi'
+import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
+
+/*components */
+import selectTarget from '../components/selectTarget.vue'
+import singleIndForm from './components/singleIndForm.vue'
+import multipleIndForm from './components/multipleIndForm.vue'
+import chartCard from '../components/chartCard.vue'
+import saveChartToBase from '../components/saveChartTobaseDia.vue'
+import saveEdbToBase from '../components/saveEdbToBaseDia.vue'
+import saveChartSetting from './../components/saveChartSetting.vue'
+import ExplainDialog from '../components/explainDialog.vue'
+/* utils */
+import {generateSortedArray,generateXEdbValue,generateYDataValue} from './utils/index'
+import { baseForm, baseChartInfo,baseSourcesFrom } from './utils/config'
+export default {
+    components:{
+        selectTarget, singleIndForm, multipleIndForm,
+        chartCard,saveChartToBase,saveEdbToBase,saveChartSetting,
+        ExplainDialog
+    },
+    data() {
+        return {
+            typeModel:0,
+            infoForm:_.cloneDeep(baseForm),
+            chartInfoData: {},//单因子指标信息,新增时为空,编辑时有值,用于回显selectTarget,多因子取第一项
+            chartBatchData:null,//单因子图表信息
+            buttonAuth: { //单因子图表按钮控制
+                isCurveChartAdd: false,
+                isRelevanceChartAdd: false,
+                isRollChartAdd: false,
+                isRollEdbAdd: false,
+                isRollChartTwoAdd: false,
+                isRollEdbTwoAdd: false,
+            },
+            isMultipleChartAdd:false,//多因子图表按钮控制
+            SeriesList:[],//多因子系列列表,编辑时有值
+            SortedArray:[],//多因子-领先期数数组 ±N
+            factorTableData:[],//多因子-相关性矩阵表格
+            factorTableDataSortCopy:[],//复制一份,用于还原排序
+            multipleChartData:_.cloneDeep(baseChartInfo),//多因子图表信息
+            IndTarget:{},//存储标的指标信息
+            showMultipleChart:false,//是否显示多因子相关性图表
+
+            isSaveChartToBase:false,
+            isSaveEdbToBase:false,
+            saveScence:'',
+            saveSource:0,
+            chartData:'',
+
+            settingData:{SourcesFrom:{}},//图例信息
+            isSettingChartShow:false,
+
+            showExplain:false,//显示操作说明
+            SourcesFromVisable:false,//数据来源的默认值,仅在新增时生效
+            previewMatrixLoading:false,//计算相关性矩阵loading
+        };
+    },
+    computed:{
+        //领先期数label
+        LeadLabelName(){
+            const UnitEnMap = {
+                    '年': 'Year',
+                    '季': 'Season',
+                    '月': 'Month',
+                    '周': 'Week',
+                    '天': 'Day',
+                }
+            return this.$t('StatisticAnalysis.ChartRelevance.multiple_table_head_03',{unit:UnitEnMap[this.infoForm.Correlation.LeadUnit]})
+        },
+        infoRules(){
+            return {
+                EdbInfoIdA:[{
+                    required:true,
+                    message:/* '指标A未选择' */this.$t('StatisticAnalysis.ChartRelevance.infoform_rules_hint_01'),
+                    trigger:'blur'
+                }],
+                EdbInfoIdB:[{
+                    required:true,
+                    message:/* '指标B未选择' */this.$t('StatisticAnalysis.ChartRelevance.infoform_rules_hint_02'),
+                    trigger:'blur'
+                }],
+                IndTarget:[{
+                    required:true,
+                    message:/* '标的指标未选择' */this.$t('StatisticAnalysis.ChartRelevance.infoform_rules_hint_03'),
+                    trigger:'blur'
+                }],
+                'Correlation.CalculateValue':[{
+                    required:true,
+                    message:/* '计算窗口未填写' */this.$t('StatisticAnalysis.ChartRelevance.infoform_rules_hint_04'),
+                    trigger:'blur'}],
+                'Correlation.LeadValue':[{
+                    required:true,
+                    message:/* '分析周期未填写' */this.$t('StatisticAnalysis.ChartRelevance.infoform_rules_hint_05'),
+                    trigger:'blur'
+                }]
+            }
+        },
+        chartInfo(){ //单因子系列保存/更新/另存为会用到
+            return this.infoForm
+        }
+    },
+    mounted(){
+        this.getRelevanceChartDetail()
+        this.getChartBaseSetting()
+    },
+    methods: {
+        //获取图表全局设置
+        async getChartBaseSetting(){
+            //目前是用基本配置的接口,后续有多个配置再改
+            const res = await etaBaseConfigInterence.getBaseConfig()
+            if(res.Ret!==200) return 
+            const {ChartSourceDisplay} = res.Data||{}
+            this.SourcesFromVisable = ChartSourceDisplay==='true'?true:false
+            //多因子的配置一开始就初始化,在这里设置默认值
+            if(!this.$route.query.code){
+                this.multipleChartData.SourcesFrom.isShow = this.SourcesFromVisable
+            }
+        },
+        sortChange({column,prop,order}){
+            const {label} = column
+            this.factorTableData.sort((a,b)=>{
+                if(order==='ascending'){
+                    return a.dataList[label] - b.dataList[label]
+                }else{
+                    return b.dataList[label] - a.dataList[label]
+                }
+            })
+            //取消order 排序还原为factorTableDataSortCopy的顺序
+            if(!order){
+                const table = this.factorTableDataSortCopy.map(copyItem=>{
+                    return this.factorTableData.find(i=>i.EdbInfoId===copyItem.EdbInfoId&&i.SeriesId===copyItem.SeriesId)
+                })
+                this.factorTableData = table
+            }
+            
+
+        },
+        //禁用表格行的样式
+        getTableRowClassname({row}){
+            if(!row.isSuccess){
+                return 'disable-row'
+            }
+            return ''
+        },
+        changeModel(){
+            this.typeModel = this.infoForm.Model
+            this.resetForm()
+        },
+        //重置表单
+        resetForm(){
+            this.infoForm = _.cloneDeep(baseForm)
+            this.chartBatchData = null
+            this.factorTableData = []
+            this.factorTableDataSortCopy=[]
+            this.showMultipleChart = false
+            this.infoForm.Model = this.typeModel
+            this.typeModel = 0
+        },
+        //选择指标后获取指标详情
+        async getEdbDetail({EdbInfoId,EdbInfoType}) {
+            const { Data } = EdbInfoType 
+            ? await preDictEdbInterface.edbDetail({EdbInfoId})
+            : await dataBaseInterface.calculateDetail({EdbInfoId})
+            return { 
+                max: EdbInfoType ? Data.MaxValue : Data.EdbInfoDetail.MaxValue,
+                min: EdbInfoType ? Data.MinValue : Data.EdbInfoDetail.MinValue,
+                data:EdbInfoType ? Data : Data.EdbInfoDetail,
+            }
+        },
+        //选择指标
+        async handleSelectTarget({type,target}){
+            if(!target) return
+            this.infoForm[type] = target.EdbInfoId||''
+            const {max,min,data} = await this.getEdbDetail(target)
+            if(type==='IndTarget'){
+                this.IndTarget = data
+                //点计算时,才真正赋值ChartInfo
+                //this.multipleChartData.ChartInfo = data
+            }
+            //若为单因子,选择AB指标后预览曲线图
+            if(!['EdbInfoIdA','EdbInfoIdB'].includes(type)) return 
+            if(type==='EdbInfoIdA'){
+                this.infoForm.Curve.LeftMin = min;
+                this.infoForm.Curve.LeftMax = max;
+            }else if(type==='EdbInfoIdB'){
+                this.infoForm.Curve.RightMin = min;
+                this.infoForm.Curve.RightMax = max;
+            }
+            this.getPreviewSplineChart()
+        },
+        //单因子-选择指标后生成曲线图
+        async getPreviewSplineChart(){
+            if(!this.infoForm.EdbInfoIdA || !this.infoForm.EdbInfoIdB) return
+            if(this.infoForm.Curve.DateType===5&&!this.infoForm.Curve.Date[0]) return 
+            let params = {
+                ...this.infoForm 
+            }
+            const res = await chartRelevanceApi.previewSplineChart(params);
+            if(res.Ret !== 200) return
+            this.chartBatchData = this.chartBatchData?{
+                ...this.chartBatchData,
+                CurveData: res.Data.CurveData
+            }:{CurveData: res.Data.CurveData};
+        },
+        //单因子-曲线配置变化时重绘
+        changeSplineOption() {
+            const { LeftMin,LeftMax,RightMin,RightMax,IsOrder } = this.infoForm.Curve;
+            this.$refs.chartCard1.options.yAxis[0].max = Number(LeftMax);
+            this.$refs.chartCard1.options.yAxis[0].min = Number(LeftMin);
+
+            this.$refs.chartCard1.options.yAxis[1].max = Number(RightMax);
+            this.$refs.chartCard1.options.yAxis[1].min = Number(RightMin);
+            this.chartBatchData.CurveData.EdbInfoList[1].IsOrder = IsOrder;
+        },
+        //预览相关性图表/相关性矩阵
+        async previewChart(){
+            //表单校验
+            await this.$refs.infoFormRef.validate()
+            //相关性值校验
+            if(!this.checkValue()) return 
+            
+            if(this.infoForm.Model===1){
+                //单因子:渲染相关性图表,需要保存MultipleGraphConfigId
+                const res = await chartRelevanceApi.chartOptionsSet({...this.infoForm});
+                if(res.Ret !== 200) return
+                const { MultipleGraphConfigId } = res.Data;
+                this.infoForm.MultipleGraphConfigId = MultipleGraphConfigId;
+                this.previewSingleChart({})
+            }else{
+                //已添加指标后重新计算
+                if(this.isMultipleChartAdd){
+                    const {ChartInfoId,UniqueCode,ClassifyId} = this.multipleChartData.ChartInfo
+                    this.multipleChartData.ChartInfo = this.IndTarget
+                    this.multipleChartData.ChartInfo.ChartInfoId = ChartInfoId
+                    this.multipleChartData.ChartInfo.UniqueCode = UniqueCode
+                    this.multipleChartData.ChartInfo.ClassifyId = ClassifyId
+                }else{
+                    this.multipleChartData.ChartInfo = this.IndTarget
+                }
+                //多因子:根据分析周期生成相关性矩阵,在未添加曲线前不生成图表
+                this.previewMultipleTable()
+            }
+        },
+        //校验规则
+        checkValue() {
+            //只用于校验规则条件大小
+            let checkBool = true;
+            const valueMap = {
+                '年': 365,
+                '季': 90,
+                '月': 30,
+                '周': 7,
+                '天': 1
+            }
+            const { Correlation } = this.infoForm;
+            if(Correlation.CalculateValue*valueMap[Correlation.CalculateUnit] < Correlation.LeadValue*valueMap[Correlation.LeadUnit]*2) {
+                this.infoForm.Correlation.CalculateValue = 0;
+                this.$message.warning(/* '相关性计算窗口必须≥2*分析周期' */this.$t('StatisticAnalysis.ChartRelevance.check_value_hint'))
+                checkBool = false
+            }
+            return checkBool
+        },
+        //预览单因子图表 初始化 chartBatchData
+        async previewSingleChart(initConfig=null){
+            const res = await chartRelevanceApi.previewChartBatch({...this.infoForm});
+            if(res.Ret !== 200) return
+            this.chartBatchData = res.Data;
+            //第一次初始化时,需初始化图例和数据来源信息
+            if(initConfig){
+                const {CorrelationExtraConfig,SourcesFrom} = initConfig
+                try{
+                    this.chartBatchData.SourcesFrom = SourcesFrom?JSON.parse(SourcesFrom):_.cloneDeep(baseSourcesFrom)
+                }catch(e){
+                    this.chartBatchData.SourcesFrom = _.cloneDeep(baseSourcesFrom)
+                }
+                //新增时 来源与基本配置设置的一致
+                if(!this.$route.query.code){
+                    this.chartBatchData.SourcesFrom.isShow = this.SourcesFromVisable
+                }
+                //拼接来源
+                const {EdbInfoList} = res.Data.CorrelationData
+                const tempStr = EdbInfoList[0].SourceName+','+EdbInfoList[1].SourceName
+                this.chartBatchData.SourcesFrom.text += `${this.chartBatchData.SourcesFrom.text.length?',':''}${tempStr}`
+                //拼接后去重
+                let concatSourceArr = `${this.chartBatchData.SourcesFrom.text}`.split(',');
+                let sourceStr = Array.from(new Set(concatSourceArr)).join(',');
+                this.chartBatchData.SourcesFrom.text = sourceStr
+                try{
+                    const {LegendConfig} = CorrelationExtraConfig?JSON.parse(CorrelationExtraConfig):{LegendConfig:[]}
+                    this.chartBatchData.CorrelationData.YDataList[0].Color = LegendConfig[0].Color
+                    this.chartBatchData.CorrelationData.YDataList[0].Name = LegendConfig[0].Legendlame
+                }catch(e){
+
+                }
+            }
+        },
+        //预览多因子矩阵 初始化 factorTableData
+        previewMultipleTable(){
+            //全局loading
+            this.previewMatrixLoading = true
+            const {IndTarget,Correlation} = this.infoForm
+            const SeriesIds = this.$refs.multipleIndForm.factorList.map(i=>i.SeriesId)
+            //清空表格和图表
+            this.factorTableData = []
+            this.factorTableDataSortCopy=[]
+            this.multipleChartData.YDataList=[]
+            this.showMultipleChart = false
+            chartRelevanceApi.getCorrelationMatrix({
+                BaseEdbInfoId:IndTarget,
+                Correlation,
+                SeriesIds,
+            }).then(res=>{
+                //loading结束
+                this.previewMatrixLoading = false
+                if(res.Ret!==200) return
+
+                const {Fail=[],Success=[]} = res.Data
+                if(!Success||Success&&!Success.length){
+                    this.$message.warning('所有指标计算失败,请重新选择指标')
+                    return 
+                }
+                //标记失败的
+                const FailList = Fail?Fail.map(i=>{
+                    return {
+                        ...i,
+                        isSuccess:false,
+                        dataList:[]
+                    }
+                }):[]
+                const SuccessList = Success.map(i=>{
+                    return {
+                        ...i,
+                        isSuccess:true,
+                        isAdd:false,
+                        dataList:i.Values.map(v=>v.YData)
+                    }
+                })
+                this.factorTableData = [...SuccessList,...FailList]
+                this.factorTableDataSortCopy = _.cloneDeep(this.factorTableData)
+                //获取分析周期,生成±分析周期的数组
+                const {LeadValue,LeadUnit,CalculateUnit,CalculateValue} = this.infoForm.Correlation
+                this.SortedArray = generateSortedArray(LeadValue)
+                //设置图表默认值
+                this.multipleChartData.ChartInfo.Source = 3
+                this.multipleChartData.ChartInfo.ChartName = this.multipleChartData.ChartInfo.EdbName+`相关性分析(${CalculateValue}${CalculateUnit})`
+                this.multipleChartData.CorrelationChartInfo = {
+                    LeadValue:LeadValue,
+                    LeadUnit:LeadUnit
+                }
+                this.multipleChartData.XEdbIdValue = generateXEdbValue(LeadValue)
+            })
+        },
+        checkRecalculate(){
+            //若当前已预览过图表/矩阵,则重新请求矩阵接口,初始化矩阵和图表数据
+            if(this.showMultipleChart||this.factorTableData.length){
+                this.previewMultipleTable()
+            }
+        },
+        //相关性矩阵-添加曲线
+        addCurve(row){
+            const length = this.multipleChartData.YDataList.length
+            if(length>=10) return this.$message.warning('最多只支持添加10条曲线')
+            this.showMultipleChart = true
+            
+            const colors = ['#00f','#f00','#999','#000','#7cb5ec', '#90ed7d', '#f7a35c', '#8085e9', '#f15c80', '#e4d354', '#2b908f', '#f45b5b', '#91e8e1']
+            this.multipleChartData.YDataList.push({
+                Id:row.EdbInfoId,
+                SeriesId:row.SeriesId,
+                Value:generateYDataValue(row.dataList,this.infoForm.Correlation.LeadValue),
+                Color:colors[length%colors.length],
+                Name:row.EdbName,
+                NameEn:row.EdbNameEn
+            })
+            row.isAdd = true
+            //数据来源拼接
+            this.multipleChartData.SourcesFrom.text += `${this.multipleChartData.SourcesFrom.text.length?',':''}${row.SourceName}`
+            //拼接后去重
+            let concatSourceArr = `${this.multipleChartData.SourcesFrom.text}`.split(',');
+            let sourceStr = Array.from(new Set(concatSourceArr)).join(',');
+            this.multipleChartData.SourcesFrom.text = sourceStr
+        },
+        //相关性矩阵-删除曲线
+        deleteCurve(row){
+            const index = this.multipleChartData.YDataList.findIndex(i=>i.Id===row.EdbInfoId&&i.SeriesId===row.SeriesId)
+            index!==-1&&this.multipleChartData.YDataList.splice(index,1)
+            row.isAdd = false
+            if(!this.multipleChartData.YDataList.length){
+                this.showMultipleChart = false
+            }
+        },
+        //打开图例设置弹窗
+        handleChangeChartSetting(data){
+            //单多因子的data结构是相同的
+            /**
+             * 图表名称:data.ChartName/en
+             * 图例:data.YDataList.Color data.YDataList.Name
+             * 数据来源:新字段 SourcesFrom.text
+             * 数据来源开关:新字段 SourcesFrom.isShow
+             */
+            const SourcesFrom = this.infoForm.Model===1?_.cloneDeep(this.chartBatchData.SourcesFrom):_.cloneDeep(this.multipleChartData.SourcesFrom)
+            this.settingData = {
+                SourcesFrom,
+                chartName:data.ChartName,
+                YDataList:_.cloneDeep(data.YDataList)
+            }
+            this.isSettingChartShow = true
+        },
+        //图例设置回调
+        changeChartSettingBack(){
+            const {chartName,YDataList,SourcesFrom} = this.settingData
+            if(this.infoForm.Model===1){
+                this.chartBatchData.CorrelationData.ChartInfo.ChartName = chartName
+                this.chartBatchData.CorrelationData.YDataList = YDataList
+                this.chartBatchData.SourcesFrom = SourcesFrom
+            }else{
+                //多因子
+                this.multipleChartData.ChartInfo.ChartName = chartName
+                this.multipleChartData.YDataList = YDataList
+                this.multipleChartData.SourcesFrom = SourcesFrom
+            }
+            this.isSettingChartShow = false
+        },
+        //打开保存/另存为图表/指标弹窗
+        handleSave({type,chartData,scence}){
+            this.saveSource = type
+            this.chartData = chartData;
+            this.saveScence = scence;
+           /*  this.isSaveEdbToBase = true;
+            this.isSaveChartToBase = true; */
+        },
+        //单因子-保存/另存为指标回调
+        saveEdbBack({source}){
+            if(source===3) this.buttonAuth.isRollEdbAdd = true;
+            else if(source===4)  this.buttonAuth.isRollEdbTwoAdd = true;
+        },
+        //单因子-保存/另存为图表回调
+        saveChartBack({source,id}){
+            this.$message.success(this.$t('MsgPrompt.saved_msg'));
+            this.setButtonAuth(source);
+            //设置封面图
+            this.$refs[`chartCard`+source].setChartImage(source,id)
+        },
+        //单因子-保存图表后按钮控制 
+        setButtonAuth(source) {
+            const sourceMap = {
+                1: 'isCurveChartAdd',
+                2: 'isRelevanceChartAdd',
+                3: 'isRollChartAdd',
+                4: 'isRollChartTwoAdd'
+            }
+            this.buttonAuth[sourceMap[source]] = true;
+        },
+        //编辑-获取相关性图表详情
+        getRelevanceChartDetail(){
+            //判断是单因子or多因子
+            if(this.$route.query.type!=1){
+                this.getSingleDetail()
+            }else{
+                this.getMultiplyDetail()
+            }
+            
+        },
+        //获取单因子图表详情
+        async getSingleDetail(){
+            if(!this.$route.query.code) return
+            const res = await chartRelevanceApi.getOptionByCode({ UniqueCode: this.$route.query.code});
+            if(res.Ret !== 200) return 
+            this.chartInfoData = {
+                EdbInfoList: res.Data.EdbInfoList
+            }
+            //初始化infoForm
+            const { MultipleGraphConfigId,EdbInfoIdA,EdbInfoIdB,Curve,Correlation,RollingCorrelation } = res.Data.MultipleGraphConfig;
+            this.infoForm = {
+                Model:1,
+                MultipleGraphConfigId,
+                EdbInfoIdA,
+                EdbInfoIdB,
+                Curve: {
+                ...JSON.parse(Curve),
+                Date: [JSON.parse(Curve).StartDate,JSON.parse(Curve).EndDate],
+                },
+                Correlation: JSON.parse(Correlation),
+                RollingCorrelation: JSON.parse(RollingCorrelation)
+            }
+            //初始化权限
+            this.buttonAuth =  {
+                isCurveChartAdd: res.Data.ChartMappingList.some(_ => _.MultipleLocationSource===1),
+                isRelevanceChartAdd: res.Data.ChartMappingList.some(_ => _.MultipleLocationSource===2),
+                isRollChartAdd: res.Data.ChartMappingList.some(_ => _.MultipleLocationSource===3),
+                isRollEdbAdd: res.Data.EdbMappingList.some(_ => _.MultipleLocationSource===3),
+                isRollChartTwoAdd: res.Data.ChartMappingList.some(_ => _.MultipleLocationSource===4),
+                isRollEdbTwoAdd: res.Data.EdbMappingList.some(_ => _.MultipleLocationSource===4)
+            }
+            //初始化chartBatch
+            const RelevanceInfo = res.Data.ChartMappingList.find(_=>_.MultipleLocationSource===2)||{}
+            const {CorrelationExtraConfig,SourcesFrom} = RelevanceInfo
+            this.previewSingleChart({CorrelationExtraConfig,SourcesFrom})
+        },
+        //获取多因子图表详情
+        getMultiplyDetail(){
+            if(!this.$route.query.code) return
+            //获取图表详情
+            chartRelevanceApi.getMultipleChartDetail({
+                UniqueCode:this.$route.query.code
+            }).then(res=>{
+                if(res.Ret!==200) return
+                const {ChartName,ChartClassifyId,ChartInfoId,UniqueCode,ExtraConfig,SourcesFrom} = res.Data.ChartInfo
+                this.multipleChartData.ChartInfo = {
+                    ClassifyId:ChartClassifyId,ChartName,ChartInfoId,UniqueCode,Source:3
+                }
+                const {EdbInfoList,XEdbIdValue,YDataList,CorrelationChartInfo} = res.Data
+                const {LeadValue,LeadUnit} = CorrelationChartInfo
+                this.multipleChartData.CorrelationChartInfo = {
+                    LeadValue,LeadUnit
+                }
+                this.multipleChartData.XEdbIdValue = XEdbIdValue
+                this.multipleChartData.EdbInfoList = EdbInfoList
+                this.multipleChartData.YDataList = YDataList.map(i=>{
+                    return {
+                        ...i,
+                        Id:i.SeriesEdb.EdbInfoId,
+                        SeriesId:i.SeriesEdb.SeriesId
+                    }
+                })
+                try{
+                    this.multipleChartData.SourcesFrom = SourcesFrom?JSON.parse(SourcesFrom):_.cloneDeep(baseSourcesFrom)
+                }catch(e){
+                    this.multipleChartData.SourcesFrom = _.cloneDeep(baseSourcesFrom)
+                }
+                this.showMultipleChart = true
+                this.isMultipleChartAdd = true
+
+            })
+            //获取表单及矩阵详情
+            chartRelevanceApi.getMultipleFactorDetail({
+                UniqueCode:this.$route.query.code
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                const {BaseEdbInfo,CorrelationConfig,EdbSeries,CorrelationMatrix} = res.Data
+                const {LeadValue,LeadUnit,CalculateValue,CalculateUnit} = CorrelationConfig
+                this.infoForm.Model = 2
+                //基础信息表单
+                this.infoForm = {
+                    Model:2,
+                    IndTarget:BaseEdbInfo.EdbInfoId,
+                    Correlation:{
+                        LeadValue,LeadUnit,CalculateValue,CalculateUnit
+                    }
+                }
+                //标的因子信息
+                this.IndTarget = _.cloneDeep(BaseEdbInfo)
+                this.chartInfoData = {
+                    EdbInfoList:[BaseEdbInfo]
+                }
+                //因子列表
+                this.SeriesList = EdbSeries
+                //相关性矩阵
+                this.factorTableData = CorrelationMatrix.map(i=>{
+                    return {
+                        ...i,
+                        isSuccess:true,
+                        isAdd:i.Used,
+                        dataList:i.Values.map(v=>v.YData)
+                    }
+                })
+                this.factorTableDataSortCopy = _.cloneDeep(this.factorTableData)
+                this.SortedArray = generateSortedArray(LeadValue)
+            })
+        },
+        //多因子-保存/更新/另存为图表
+        async saveMultipleChart({ChartName,ClassifyId,type}){
+            const {IndTarget,Correlation} = this.infoForm
+            const {SourcesFrom,YDataList} = this.multipleChartData
+            const SeriesEdb = YDataList.map(i=>{
+                return {
+                    SeriesId:i.SeriesId,
+                    EdbInfoId:i.Id
+                }
+            })
+            //BaseEdbInfoId优先取当前图表内的EdbInfoId,若没有值取表单内的
+            const BaseEdbInfoId = this.multipleChartData.ChartInfo.EdbInfoId||IndTarget
+            const SeriesIds = this.$refs.multipleIndForm.factorList.map(i=>i.SeriesId)
+            const LegendConfig = YDataList.map(i=>{
+                return {
+                    LegendName:i.Name,
+                    SeriesId:i.SeriesId,
+                    EdbInfoId:i.Id,
+                    Color:i.Color
+                }
+            })
+            let params = {
+                ChartName,ClassifyId,
+                AnalysisMode:1,
+                BaseEdbInfoId:BaseEdbInfoId/* IndTarget */,
+                FactorCorrelation:{
+                    ...Correlation,
+                    SeriesEdb,
+                    SeriesIds
+                },
+                ExtraConfig:{
+                    LegendConfig,
+                },
+                SourcesFrom,
+            }
+            const {ChartInfoId} = this.multipleChartData.ChartInfo
+            const isEdit = ChartInfoId&&type!=='saveOther'
+            //另存为/新增->add 更新->edit
+            const res = isEdit
+                ?await chartRelevanceApi.editMultipleFactor({...params,ChartInfoId})
+                :await chartRelevanceApi.addMultipleFactor({...params,SaveAs:type==='saveOther'})
+            //计算中...
+            if(res.Ret!==200) return 
+            if(!isEdit){
+                this.isMultipleChartAdd = true
+                this.multipleChartData.ChartInfo.ChartInfoId = res.Data.ChartInfoId
+                this.multipleChartData.ChartInfo.UniqueCode = res.Data.UniqueCode
+                this.multipleChartData.ChartInfo.ClassifyId = res.Data.ClassifyId
+            }
+            //更新图表名称
+            this.multipleChartData.ChartInfo.ChartName = ChartName
+            this.$message.success(`${isEdit?'更新':'保存'}成功`)
+            //设置缩略图
+            this.$refs[`chartCard`+2].setChartImage(2,res.Data.ChartInfoId)
+            this.isSaveChartToBase = false
+        },
+    },
+};
+</script>
+
+<style lang="scss">
+.relevance-chart-editor-wrap{
+    display: flex;
+    *{
+        box-sizing: border-box;
+    }
+    .content-wrap{
+        background: #fff;
+        border: 1px solid #ececec;
+        border-radius: 4px;
+        .source{
+            padding-left: 20px;
+            padding-bottom:20px;
+            margin-top: -20px;
+        }
+    }
+    .info-wrap{
+        width:380px;
+        min-width: 380px;
+        margin-right: 20px;
+        display: flex;
+        flex-direction: column;
+        height: calc(100vh - 120px);
+        .info-top{
+            padding: 15px 20px;
+            border-bottom: 1px solid #ececec;
+            box-shadow: 0px 3px 6px rgba(167, 167, 167, 0.09);
+            display: flex;
+            align-items: center;
+            >span{
+                color:#0052D9;
+                cursor: pointer;
+                flex: 1;
+                text-align: right;
+                img{
+                    vertical-align: middle;
+                }
+            }
+        }
+        .info-form-wrap{
+            flex: 1;
+            overflow-y: auto;
+            padding:20px;
+            .el-form-item{
+                margin-bottom: 10px;
+            }
+            .form-box{
+                margin-top: 10px;
+                padding-top: 10px;
+                border-top:1px dashed #DCDFE6;
+            }
+            .model-form{
+                .select-target{
+                    display: flex;
+                    margin-top: 10px;
+                    .el-form-item__label{
+                        flex-shrink: 0;
+                    }
+                    .el-form-item__content{
+                        margin-left: 0 !important;
+                        .el-select{
+                            margin-top: 10px !important;
+                        }
+                    }
+                    .el-date-editor.el-input, .el-date-editor.el-input__inner{
+                        width: auto;
+                    }
+                }
+                .flex-form-item{
+                    .el-form-item__content{
+                        display: flex;
+                        gap:0 5px;
+                    }
+                }
+            }
+            .multiple-model-form{
+                .factor-form-item{
+                    .el-form-item {
+                        margin-bottom: 0;
+                    }
+                    .el-form-item__label{
+                        width:auto !important;
+                    }
+                    .factor-list{
+                        .list-item{
+                            padding:10px 20px;
+                            background-color: #EBEFF6;
+                            border:1px solid #C8CDD9;
+                            cursor: pointer;
+                            display: flex;
+                            justify-content: space-between;
+                            align-items: center;
+                            border-bottom: none;
+                            &:last-child{
+                                border-bottom: 1px solid #C8CDD9;
+                            }
+                        }
+                    }
+                    .add-factor-btn{
+                        margin-top: 20px;
+                        display: flex;
+                        gap:10px;
+                        align-items: center;
+                        cursor: pointer;
+                        color:#0052D9;
+                        img{
+                            width: 15px;
+                            height: 15px;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    .model-wrap{
+        flex:1;
+        height: calc(100vh - 120px);
+        overflow-x: hidden;
+        .single-model-wrap{
+            width: 100%;
+            overflow: hidden;
+        }
+        .chart-min-cont {
+            height: calc(100vh - 120px);
+            overflow-y: auto;
+            display: flex;
+            flex-wrap: wrap;
+            gap:15px;
+            .card-wrapper {
+                width: 48%;
+                min-height: 350px;
+                min-width:410px;
+                .card-item {
+                    padding: 20px;
+                    .top {
+                        display: flex;
+                        justify-content: space-between;
+                        align-items: center;
+                        margin-bottom: 15px;
+                    }
+                    .title {
+                        font-size: 15px;
+                        text-align: left;
+                        margin: 10px 0;
+                    }
+                }
+            }
+        }
+        .nodata {
+            height: calc(100vh - 120px);
+            background-color: #fff;
+            text-align: center;
+            font-size: 16px;
+            color: #666;
+            padding: 100px 0;
+        }
+        .multiple-model-wrap{
+            display: flex;
+            flex-direction: column;
+            justify-content: space-between;
+            height: calc(100vh - 120px);
+            .relevant-matrix-table-box,.relevant-chart-box{
+                height: 49%;
+                overflow: auto;
+            }
+            
+            .relevant-matrix-table-box{
+                display: flex;
+                .el-table{
+                    flex:1;
+                    thead{
+                        color:#333;
+                    }
+                    th.zip-cell{
+                        padding:0;
+                        font-size: 12px;
+                        background: #F5F7FA !important;
+                        .cell{
+                            padding:0;
+                            .caret-wrapper{
+                                height:24px;
+                                width:20px;
+                                .sort-caret.ascending{
+                                    top:0;
+                                }
+                                .sort-caret.descending{
+                                    bottom:0;
+                                }
+                            }
+                        }
+                    }
+                    td.zip-cell{
+                        padding:0;
+                        font-size: 12px;
+                        background-color: #fff !important;
+                        .cell{
+                            padding:0;
+                            line-height: 23px;//调整单元格高度
+                        }
+                    }
+                }
+            }
+            .relevant-chart-box{
+                .card-item {
+                    padding: 20px;
+                    .top {
+                        display: flex;
+                        justify-content: space-between;
+                        align-items: center;
+                        .title {
+                            font-size: 15px;
+                            text-align: left;
+                            margin: 10px 0;
+                        }
+                    }
+                    
+                }
+            }
+        }
+    }
+    .disable-row{
+        pointer-events: none;
+        opacity: 0.5;
+        cursor: default; 
+    }
+}
+</style>

+ 111 - 0
src/views/chartRelevance_manage/relevance/utils/config.js

@@ -0,0 +1,111 @@
+//相关性表单
+export const baseForm = {
+    Model:1,//模式 1单因子 2 多因子
+    EdbInfoIdA:'',//指标A
+    EdbInfoIdB:'',//指标B
+    IndTarget:'',//标的指标
+    Curve:{//曲线图
+        DateType:3,
+        Date:'',
+        StartDate:'',
+        EndDate:'',
+        LeftMin:'',
+        LeftMax:'',
+        RightMin:'',
+        RightMax:'',
+        EdbInfoType:true,//显示为标准指标(true)或领先指标(false)
+        LeadValue:0,
+        LeadUnit:'天',
+    },
+    Correlation:{//相关性
+        CalculateValue:0,//计算窗口
+        CalculateUnit:'天',//计算窗口单位(时间)
+        LeadValue:0,//分析周期
+        LeadUnit:'天',//分析周期单位(时间)
+    },
+    RollingCorrelation:[//滚动相关性
+        {
+            CalculateValue:0,
+            CalculateUnit:'天',
+            LeadValue:0,
+            LeadUnit:'天'
+        },
+        {
+            CalculateValue:0,
+            CalculateUnit:'天',
+            LeadValue:0,
+            LeadUnit:'天'
+        }
+    ],
+}
+//多因子图表信息
+export const baseChartInfo = {
+    ChartInfo:{
+        Source:3,
+        ChartName:'',//与单因子保持一致,用于保存/另存为回显
+        ChartInfoId:'',//新增前为空
+        UniqueCode:'',//新增前为空
+        ClassifyId:'',//新增前为空
+        /**
+         * EdbInfoId 当前页面点击计算后有值 标的指标的ID
+         * EdbName 当前页面点击计算后有值 标的指标的名称
+         */
+    },
+    EdbInfoList:[],//第一项为标的指标,其他项为添加的指标
+    XEdbIdValue:[],//SourtedArray
+    CorrelationChartInfo:{
+        LeadValue:0,//分析周期
+        LeadUnit:'天',//分析周期单位(时间)
+    },
+    YDataList:[
+        /* {
+            Value:[],//factorTableData.dataList
+            Color:'#00f',
+            Name:'',//factorTableData.name
+            NameEn:''
+        } */
+    ],
+    SourcesFrom:{
+        isShow:true,//是否显示
+        text:'',//内容
+        color:'#333',
+        fontSize:12,
+    },//
+}
+//多因子-相关性矩阵表格
+const factorTableData = [
+    {
+        EdbInfoId:'指标ID',
+        SeriesId:'指标所属系列ID',//与EdbInfoId一起表示指标的唯一性
+        EdbName:'指标名称',
+        dataList:[],//领先期数数据,下标需和期数对应
+        isAdd:false,//是否已添加曲线
+    }
+]
+//多因子-因子系列
+const factorList = [
+    {
+        "SeriesId": 4, //系列Id
+        "SeriesName": "系列名称A001", //系列名称
+        "EdbInfoType": 0, //0指标,1预测指标
+        "CalculateStep":[ //计算公式
+            {
+                "Formula": "", //N值/移动天数/指数修匀alpha值/计算公式等
+                "Calendar": "", //公历/农历
+                "Source": 3, //计算方式来源
+                "Sort": 1 
+            },
+        ],
+        "EdbMappings":[
+            
+        ],//所选的指标
+    },
+]
+
+//数据来源
+export const baseSourcesFrom = {
+    isShow:true,//是否显示
+    text:'',//内容
+    color:'#333',
+    fontSize:12,
+}

+ 70 - 0
src/views/chartRelevance_manage/relevance/utils/index.js

@@ -0,0 +1,70 @@
+//相关性矩阵表头
+export const generateSortedArray = (N)=>{
+    let positiveArr = [];
+    for (let i = 0; i <= N; i++) {
+        positiveArr.push(i);
+    }
+    
+    let negativeArr = [];
+    for (let i = -1; i >= -N; i--) {
+        negativeArr.push(i);
+    }
+    
+    return positiveArr.concat(negativeArr);
+}
+//mock用 相关性图表x轴
+export const generateXEdbValue = (N)=>{
+    let positiveArr = [];
+    for (let i = 0; i <= N; i++) {
+        positiveArr.push(i);
+    }
+    
+    let negativeArr = [];
+    for (let i = -N; i <= -1; i++) {
+        negativeArr.push(i);
+    }
+    return [...negativeArr,...positiveArr]
+}
+//转换YDataList data是领先期数从0开始的数组
+export const generateYDataValue = (data,n)=>{
+    //取[n+1,length]项 为-1~-n 翻转为-n~-1
+    let arr = data.slice(n+1).reverse()
+    //data从下标n+1处放置
+    let dataArr = data.slice(0,n+1)
+    return [...arr,...dataArr]
+}
+//判断两个指标ID数组是否有变化:指标ID一致视为无变化
+export const checkListChange = (listA,listB)=>{
+    // 将两个数组转换为 Set 对象
+    const setA = new Set(listA);
+    const setB = new Set(listB);
+
+    if (setA.size !== setB.size) {
+        return true;
+    }
+    // 检查 setA 中的每一项是否都在 setB 中
+    for (const item of setA) {
+        if (!setB.has(item)) {
+            return true;
+        }
+    }
+    // 如果所有检查都通过,说明两个数组包含相同的项
+    return false;
+}
+//判断两个计算方式是否有变化:顺序,Source以及Formula的值一致视为无变化
+export const checkStepsChange = (stepsA,stepsB)=>{
+    if(stepsA.length!==stepsB.length) return true
+
+     // 逐个比较数组中的每一项是否都相同且顺序一致
+     for (let i = 0; i < stepsA.length; i++) {
+        if (  stepsA[i].Sort!==stepsB[i].Sort
+            ||stepsA[i].Source!==stepsB[i].Source
+            ||stepsA[i].Formula!==stepsB[i].Formula) {
+            return true
+        }
+        if(stepsA[i].Source===11&&stepsA[i].Calendar!==stepsB[i].Calendar){
+            return true
+        }
+    }
+    return false
+}

+ 28 - 14
src/views/classify_manage/chapterSettingV2.vue

@@ -15,7 +15,7 @@
                     children: 'Child'
                 }"
 				check-strictly
-				:empty-text="$t('Common.no_classify_msg')"
+				:empty-text="$t('ReportManage.ReportList.no_chapter_msg')"
                 draggable
                 :allow-drop="canDropHandle"
                 @node-drop="dropOverHandle"
@@ -65,11 +65,11 @@
                 </el-form-item>
                 <!-- 上级分类 -->
                 <el-form-item :label="$t('ReportManage.CategoryList.parent_category')">
-                    <el-input  disabled :value="researchType=='day'?'晨报':'周报'" style="width: 317px;" 
+                    <el-input  disabled :value="parentClassifyName" style="width: 317px;" 
                     :placeholder="$t('ReportManage.CategoryList.related_variety_inputhint')"></el-input>
                 </el-form-item>
                 <!-- 关联品种 -->
-                <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')">
+                <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')" v-if="reportVarietyList.length">
                     <template slot="label">
                         <el-tooltip class="item" effect="dark" :content="$t('ReportManage.CategoryList.related_variety_hint')">
                             <div>
@@ -104,15 +104,12 @@ import { getchapterTypeList,addChapterType,editChapterType,} from 'api/api.js';
 import {setChapterEnable,setChapterSort} from '@/api/modules/oldApi.js'
 import {reportVarietyInterence} from '@/api/modules/reportVariety'
 import {classifyPermissionInterface} from '@/api/modules/classifyApi.js'
+import { reportV2Interface } from '@/api/modules/reportV2.js'
 export default {
     name:"chapterSetting",
     components:{mDialog},
     beforeRouteEnter(to, from, next) {
-        if(to.query.reportType=='day'){
-            to.matched[1].name='晨报章节设置'
-        }else{
-            to.matched[1].name='周报章节设置'
-        }
+        to.matched[1].name='章节设置'
         next()
     },
     data() {
@@ -123,23 +120,23 @@ export default {
             addDialogShow:false,
             addForm:{
                 ReportChapterTypeName:"",
-                ResearchType:"",
+                // ResearchType:"",.
                 ChartPermissionIdList:''
             },
             researchType:'',// day-晨报;week-周报
+            parentClassifyName: '',
 
             reportVarietyList:[],//中文品种列表
         }
     },
     mounted(){
-        // 类型 周报-晨报
-        this.addForm.ResearchType=this.researchType=this.$route.query.reportType=='week'?'week':'day'
+        this.parentClassifyName = this.$route.query.classifyName || ''
         this.getList()
         this.getReportVarietyList()
     },
     methods: {
         getList(type){
-            getchapterTypeList({ReportType:this.researchType}).then(res=>{
+            getchapterTypeList({ClassifyId:Number(this.$route.query.id)}).then(res=>{
                 if(res.Ret == 200){
                     this.list=res.Data.List || []
                 }
@@ -151,6 +148,7 @@ export default {
             this.addDialogShow=true
             this.addForm.ReportChapterTypeName=''
             this.addForm.ChartPermissionIdList=''
+            this.addForm.ReportChapterTypeId=0
             console.log(this.addForm);
         },
 
@@ -171,7 +169,11 @@ export default {
         this.$refs.addForm.validate((valid)=>{
           if(valid){
             // 添加小程序是否显示参数 0显示,1隐藏
-            let params={...this.addForm,ChartPermissionIdList:this.addForm.ChartPermissionIdList||[]}
+            let params={
+                ...this.addForm,
+                ClassifyId: Number(this.$route.query.id),
+                ChartPermissionIdList:this.addForm.ChartPermissionIdList||[]
+            }
             // 请求方法
             let requestMethod;
             // console.log(params);
@@ -197,12 +199,24 @@ export default {
         })
       },
 
+
+        filterNodes(arr) {
+            arr.length && arr.forEach(item => {
+                item.Child && item.Child.length && this.filterNodes(item.Child)
+                if((item.Child && !item.Child.length)) {
+                    delete item.Child
+                }
+            })
+        },
         
 
         // 获取品种数据
         getReportVarietyList(){
-            reportVarietyInterence.filterVarietyOpts().then(res=>{
+            reportV2Interface.getClassifyPermissionList({
+                ClassifyId: Number(this.$route.query.id),
+            }).then(res=>{
                 this.reportVarietyList=res.Data||[]
+                this.filterNodes(this.reportVarietyList)
             })
         },
 

+ 11 - 2
src/views/classify_manage/classifyEnlistV2.vue

@@ -3,11 +3,19 @@
         <div class="top-wrap">
             <div class="type-box">
                 <!-- 中文分类 -->
-                <div class="item" @click="$emit('typeChange','1')">
+                <div class="item" @click="$emit('typeChange','1')"
+                    v-permission="permissionBtn.classifyBtn.classifyList_cnClassify"
+                >
                     {{ $t('ReportManage.CategoryList.chinese_tabs') }}
                 </div>
                 <!-- 英文分类 -->
-                <div class="item active" style="margin-left: 20px;">{{ $t('ReportManage.CategoryList.english_tabs') }}</div>
+                <div class="item active" style="margin-left: 20px;"
+                    v-permission="[
+                        permissionBtn.classifyBtn.classifyList_cnClassify,
+                        permissionBtn.enClassifyBtn.classifyList_enClassify,
+                        'and'
+                    ]"
+                >{{ $t('ReportManage.CategoryList.english_tabs') }}</div>
             </div>
             <div style="display:flex;padding:10px;gap:10px">
                 <!-- 添加分类 -->
@@ -305,6 +313,7 @@ export default {
 .classify-page{
     .content-box{
         .el-tree-node__content{
+            height: fit-content;
             padding-top: 10px;
             padding-bottom: 10px;
             border-bottom: 1px solid #C8CDD9;

+ 142 - 29
src/views/classify_manage/classifylistV2.vue

@@ -4,7 +4,11 @@
             <div class="type-box">
                 <!-- 中文分类 -->
                 <div class="item active" 
-                    v-permission="permissionBtn.classifyBtn.classifyList_cnClassify">
+                    v-permission="[
+                        permissionBtn.classifyBtn.classifyList_cnClassify,
+                        permissionBtn.enClassifyBtn.classifyList_enClassify,
+                        'and'
+                        ]">
                     {{ $t('ReportManage.CategoryList.chinese_tabs') }}
                 </div>
                 <!-- 英文分类 -->
@@ -14,6 +18,7 @@
                 </div>
             </div>
             <div style="display:flex;padding:10px;gap:10px">
+                <!-- <el-button type="primary" @click="transferReport">分类报告转移</el-button> -->
                 <!-- 添加分类 -->
                 <el-button 
                     type="primary"
@@ -58,7 +63,7 @@
                     <div class="opt-box">
                         <!-- 章节设置 -->
                         <span class="editsty" 
-                            v-if="['晨报','周报'].includes(data.ClassifyName)" 
+                            v-if="!data.Child || (data.Child&&!data.Child.length)" 
                             @click="chapterSetting(data)" 
                             v-permission="permissionBtn.classifyBtn.classifyList_cnClassify_chapterSetting">
                             {{ $t('ReportManage.CategoryList.section_settings') }}
@@ -95,14 +100,27 @@
                     </el-form-item>
                     <!-- 上级分类 -->
                     <el-form-item prop="parent_id" :label="$t('ReportManage.CategoryList.parent_category')">
-                        <el-select v-model="classifyForm.parent_id" 
-                            :placeholder="$t('ReportManage.CategoryList.related_variety_inputhint')" style="width:400px;">
-                            <el-option :label="$t('ReportManage.CategoryList.parent_none')" :value="0"></el-option>
-                            <el-option v-for="(item,index) in classifyparentArr" :key="index" :label="item.ClassifyName" :value="item.Id"></el-option>
-                        </el-select>
+
+                        <el-cascader
+                            v-model="classifyForm.parent_id" 
+                            :options="classifyparentArr"
+                            :disabled="classifyForm.classify_id"
+                            style="width:400px;"
+                            ref="classifyRef"
+                            :props="{ 
+                                checkStrictly: true,
+                                value: 'Id',
+                                label: 'ClassifyName',
+                                children:'Child',
+                                emitPath:false
+                            }"
+                            clearable
+                            @change="changeClassify"
+                        >
+                        </el-cascader>
                     </el-form-item>
                     <!-- 关联品种 -->
-                    <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')" v-if="classifyForm.parent_id&&permissionBtn.classifyBtn.classifyList_cnClassify_connect_variety">
+                    <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')" v-if="canSetPermission">
                         <template slot="label">
                             <el-tooltip class="item" effect="dark" :content="$t('ReportManage.CategoryList.related_variety_hint')">
                                 <div>
@@ -121,6 +139,7 @@
                         ></el-cascader>
                     </el-form-item>
                 </el-form>
+                <div v-html="tips" style="color:#999;"></div>
             </div>
             <div slot="footer" style="margin-top: 20px;">
                 <el-button
@@ -134,6 +153,59 @@
                 >{{ $t('Dialog.confirm_save_btn') }}</el-button>
             </div>
         </m-dialog>
+
+        <!-- 转移报告弹窗 -->
+        <m-dialog
+            title="分类报告转移"
+            :show.sync="isTransferReport"
+            width="650px"
+        >
+
+            <div>
+                <el-form
+                    :model="transferForm"
+                    hide-required-asterisk
+                    label-width="auto"
+                >
+                    <el-form-item prop="classify_name" label="原分类">
+                        <el-cascader
+                          v-model="transferForm.oldClassify"
+                          @change="filterChange"
+                          :options="classifyparentArr"
+                          clearable
+                          placeholder="请选择分类"
+                          style="width:100%;"
+                      ></el-cascader>
+                    </el-form-item>
+                    <!-- 上级分类 -->
+                    <el-form-item prop="parent_id" label="转移至分类">
+
+                        <el-cascader
+                          v-model="transferForm.newClassify"
+                          @change="filterChange"
+                          :options="classifyparentArr"
+                          clearable
+                          placeholder="请选择分类"
+                          style="width:100%;"
+                      ></el-cascader>
+                    </el-form-item>
+                    
+                </el-form>
+            </div>
+
+            <div slot="footer" style="margin-top: 20px;">
+                <el-button
+                @click="isTransferReport=false"
+                style="width: 132px; height: 40px"
+                >{{ $t('Dialog.cancel_btn') }}</el-button>
+                <el-button
+                @click="handleSaveTransferReport"
+                type="primary"
+                style="width: 132px; height: 40px"
+                >{{ $t('Dialog.confirm_save_btn') }}</el-button>
+            </div>
+
+        </m-dialog>
     </div>
 </template>
 
@@ -142,8 +214,21 @@ import mDialog from '@/components/mDialog.vue';
 import { classifylist,classifyparent,classifyadd,classifyedit } from 'api/api.js';
 import {reportVarietyInterence} from '@/api/modules/reportVariety'
 import {classifyPermissionInterface} from '@/api/modules/classifyApi.js'
+import { reportV2Interface } from '@/api/modules/reportV2.js'
 export default {
     components:{mDialog},
+    computed: {
+        canSetPermission() {
+            /* 编辑最小级分类可设置品种 新增分类可设置跑品种 */
+            if(!this.permissionBtn.classifyBtn.classifyList_cnClassify_connect_variety) return false
+            
+            if(this.classifyForm.classify_id) {
+                return this.classifyForm.isLastLevel?true:false
+            }else {
+                return true
+            }
+        }
+    },
     data() {
         return {
             typeVal:1,
@@ -163,6 +248,13 @@ export default {
             classifyparentArr:[],
 
             reportVarietyList:[],//中文品种列表
+
+            /* 转移报告弹窗 */
+            isTransferReport: false,
+            transferForm: {},
+
+            tips: `注:若上级分类已关联报告,则新建的第一个子分类默认继承上级分类(父分类)关联的品种、报告、审批流,且关联品种支持编辑。  `
+
         }
     },
     mounted(){
@@ -170,32 +262,59 @@ export default {
         this.getReportVarietyList()
     },
     methods: {
+        /* 报告转移 */
+        transferReport() {
+            this.isTransferReport = true;
+            this.transferForm = {
+                oldClassify: '',
+                newClassify: ''
+            }
+        },
+        
+        handleSaveTransferReport() {
+            
+        },
+
+
         async getList(type){
             const res=await classifylist({
                 KeyWord:this.searchVal,
             })
             if(res.Ret===200){
                 this.list=res.Data.List||[]
+                
+                this.classifyparentArr=_.cloneDeep(this.list)
+                this.filterNodes(this.classifyparentArr)
             }
         },
 
-        // 晨报周报 去设置章节
+        /* 添加分类默认关联父级品种 */
+        async changeClassify(id) {
+            if(!this.classifyForm.classify_id) {
+                let item = this.$refs.classifyRef.getCheckedNodes(true)
+                console.log(item)
+                if(item&&item.length) {
+                    this.classifyForm.variety = item[0].data.ChartPermissionIdList
+                }
+            }
+        },
+
+        // 去设置章节
 		chapterSetting(row){
-			let reportType;
-			if(row.ClassifyName=='周报'){
-				reportType='week'
-			}else{
-				reportType='day'
-			}
-			this.$router.push({path:'chapterSetting',query:{reportType}})
+			this.$router.push({path:'chapterSetting',query:{ id:row.Id,classifyName: row.ClassifyName }})
 		},
 
+        filterNodes(arr) {
+            arr.length && arr.forEach(item => {
+                item.Child && item.Child.length && this.filterNodes(item.Child)
+                if(!item.Child || (item.Child&&!item.Child.length)  || item.Level===2) {
+                    delete item.Child
+                }
+            })
+        },
+
         async addClassify(){
-            this.classifyparentArr=[];
-            const res=await classifyparent()
-            if(res.Ret===200){
-                this.classifyparentArr=res.Data||[]
-            }
+
             this.classifyForm={
                 show:true,
                 classify_id:0,
@@ -205,14 +324,6 @@ export default {
             }
         },
         async handleEdit(item){
-            this.classifyparentArr=[];
-            const res=await classifyparent()
-            if(res.Ret===200){
-                // 编辑的是子分类或者没有子分类的才能选择上级分类
-                if(!item.Child){
-                    this.classifyparentArr=res.Data||[]
-                }
-            }
             
             this.classifyForm={
                 show:true,
@@ -220,6 +331,7 @@ export default {
                 classify_name:item.ClassifyName,
                 parent_id: item.ParentId,
                 variety:item.ChartPermissionIdList||'',//关联的品种
+                isLastLevel: !item.Child
             }
         },
         async setClassifyHandle(){
@@ -331,6 +443,7 @@ export default {
 .classify-page{
     .content-box{
         .el-tree-node__content{
+            height: fit-content;
             padding-top: 10px;
             padding-bottom: 10px;
             border-bottom: 1px solid #C8CDD9;

+ 36 - 11
src/views/dataEntry_manage/addChart.vue

@@ -205,7 +205,8 @@
             <el-collapse-item v-for="(item,index) in tableData" :key="item.EdbInfoId" :disabled="[2,5].includes(chartInfo.ChartType)">
               <template slot="title">
                 <span class="text_oneLine">{{currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName}}</span>
-								<i class="el-icon-delete del-icon" @click.stop="delTarget(item)"></i>
+								<!-- 当为季节性图的第二个轴时,隐藏删除按钮 -->
+								<i class="el-icon-delete del-icon" @click.stop="delTarget(item)" v-if="!(chartInfo.ChartType===2&&index===1)"></i>
               </template>
               <ul class="setting-cont" v-if="sameOptionType.includes(chartInfo.ChartType)">
 
@@ -357,7 +358,11 @@
 						v-if="tableData.length"
 						ref="markerSectionRef"
 						:chartInfo="chartInfo"
+						:tableData="tableData"
 						@update="setChartMarkerInfo"
+						@updateSeason="updateSeasonChart"
+						@previewSeason="previewSeasonChart"
+						@previewSeasonRight="previewSeasonRight"
 					/>
         </div>
 
@@ -602,7 +607,7 @@
 								@change="getPreviewSplineInfo"
 							>
 								<el-radio-button label="公历">{{$t('Chart.calendar_gre')}}</el-radio-button>
-								<el-radio-button label="农历">{{$t('Chart.calendar_lunar')}}</el-radio-button>
+								<el-radio-button label="农历">{{$t('Chart.calendar_lunar_text')}}</el-radio-button>
 							</el-radio-group>
 
 							<!-- 图表说明 -->
@@ -779,8 +784,8 @@ export default {
 			this.$refs.diaForm.validate((valid) => {
 				if(valid) {
 					// 季节图只允许添加一个指标
-					if(this.chartInfo.ChartType === 2 && this.tableData.length > 1) 
-						return this.$message.warning(/* '您选择的图表样式为季节性图表,只支持单指标画图' */this.$t('Chart.OptMsg.season_one_msg'));
+					if(this.chartInfo.ChartType === 2 && this.tableData.length > 1){}
+						//return this.$message.warning(/* '您选择的图表样式为季节性图表,只支持单指标画图' */this.$t('Chart.OptMsg.season_one_msg'));
 
 					else if([7,11].includes(this.chartInfo.ChartType)  && !this.$refs.BarOptRef.dateList.length)  
 						return this.$message.warning(/*'请添加日期'*/this.$t('ToolBox.CommodityPriceChart.tips_msg06'));
@@ -892,6 +897,25 @@ export default {
 							MinMaxSave:Number(hasLimitChange)
 						}
 					}
+					//如果是季节性图,在这里加上同期/右轴的参数
+					if(this.chartInfo.ChartType===2){
+						//const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = this.chartInfo.SeasonAverageConfig||{}
+						const {SeasonRightConfig={}} = this.chartInfo
+						const tempData = _.cloneDeep(this.chartInfo.SeasonAverageConfig||{})
+						const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = tempData||{}
+						delete MaxMinLimits.List
+						delete SamePeriodAverage.List
+						delete SamePeriodStandardDeviation.List
+						const tempConfig = _.cloneDeep(SeasonRightConfig)
+						delete tempConfig.EdbInfoList
+						params.SeasonExtraConfig = {
+							...this.SeasonExtraConfig,
+							MaxMinLimits:MaxMinLimits.IsAdd?MaxMinLimits:{},
+							SamePeriodAverage:SamePeriodAverage.IsAdd?SamePeriodAverage:{},
+							SamePeriodStandardDeviation:SamePeriodStandardDeviation.IsAdd?SamePeriodStandardDeviation:{},
+							RightAxis:SeasonRightConfig.IsAdd?tempConfig:{}//右轴的具体配置
+						}
+					}
 					dataBaseInterface.chartAdd(params).then(res => {
 						if(res.Ret !== 200) return;
 							this.setChartImage(res.Data);
@@ -913,13 +937,14 @@ export default {
       this.setImageHandle(form,data);
     },
     async setImageHandle(form,{ UniqueCode,ChartInfoId }) {
-      let { Data } = await dataBaseInterface.uploadImgSvg(form);
-      // let { Data } = await dataBaseInterface.uploadImg(form);
-      await dataBaseInterface.setChartImage({
-        ChartInfoId: ChartInfoId,
-        ImageUrl: Data.ResourceUrl,
-      });
-
+      // let { Data } = await dataBaseInterface.uploadImgSvg(form);
+      // // let { Data } = await dataBaseInterface.uploadImg(form);
+      // await dataBaseInterface.setChartImage({
+      //   ChartInfoId: ChartInfoId,
+      //   ImageUrl: Data.ResourceUrl,
+      // });
+      form.append('ChartInfoId',ChartInfoId)
+      await dataBaseInterface.setChartThumbnail(form)
 			// this.$message.success('添加成功');
 			this.$message.success(this.$t('MsgPrompt.add_msg2'));
 			this.$router.replace({

+ 35 - 11
src/views/dataEntry_manage/chartSetting.vue

@@ -542,7 +542,7 @@
                         @change="getPreviewChartInfo"
                       >
                         <el-radio-button label="公历">{{$t('Chart.calendar_gre')}}</el-radio-button>
-                        <el-radio-button label="农历">{{$t('Chart.calendar_lunar')}}</el-radio-button>
+                        <el-radio-button label="农历">{{$t('Chart.calendar_lunar_text')}}</el-radio-button>
                       </el-radio-group>
 
                       <!-- 图表说明 -->
@@ -1698,6 +1698,12 @@ export default {
       }
       if (res.Ret !== 200) return;
       this.chartInfo = res.Data.ChartInfo;
+      //如果是季节性图,存储额外参数(同期/右轴)
+      if(this.chartInfo.ChartType===2){
+        const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={},RightAxis={}} = res.Data.DataResp||{}
+        this.chartInfo.SeasonAverageConfig = {MaxMinLimits,SamePeriodAverage,SamePeriodStandardDeviation}
+        this.chartInfo.SeasonRightConfig = RightAxis
+      }
       this.tableData = res.Data.EdbInfoList;
 
       // //将指标添加进标签列表中
@@ -1834,13 +1840,29 @@ export default {
           ConvertType:Number(_.ConvertType),
           ConvertValue:Number(_.ConvertValue),
           ConvertUnit:Number(_.IsConvert)?_.ConvertUnit:'',
-          ConvertEnUnit:Number(_.IsConvert)?_.ConvertEnUnit:''
-        }))
+          ConvertEnUnit:Number(_.IsConvert)?_.ConvertEnUnit:'',
+          IsAxis:_.IsAxis
+        })),
+        MarkersLines:this.chartInfo.MarkersLines||''
+      }
+      //季节性图 更改SeasonExtraConfig
+      //如果是季节性图,带上额外参数(同期/右轴)
+      if(this.chartInfo.ChartType===2){
+        const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = this.chartInfo.SeasonAverageConfig||{}
+        const {SeasonRightConfig={}} = this.chartInfo
+        params.SeasonExtraConfig = {
+            ...this.SeasonExtraConfig,
+            MaxMinLimits:MaxMinLimits.IsAdd?MaxMinLimits:{},
+            SamePeriodAverage:SamePeriodAverage.IsAdd?SamePeriodAverage:{},
+            SamePeriodStandardDeviation:SamePeriodStandardDeviation.IsAdd?SamePeriodStandardDeviation:{},
+            RightAxis:SeasonRightConfig.IsAdd?SeasonRightConfig:{}
+        }
       }
-
       const res = await dataBaseInterface.getSplinePreviewData(params)
 
       if(res.Ret !== 200) return
+      //标识线回显
+      this.chartInfo.MarkersLines = res.Data.ChartInfo.MarkersLines||''
 
       const { EdbInfoList } = res.Data;
 
@@ -2381,13 +2403,15 @@ export default {
         this.setImageHandle(form);
     },
     async setImageHandle(form) {
-      let { Data } = await dataBaseInterface.uploadImgSvg(form);
-
-      // let { Data } = await dataBaseInterface.uploadImg(form);
-      await dataBaseInterface.setChartImage({
-        ChartInfoId: this.selected_chartid,
-        ImageUrl: Data.ResourceUrl,
-      });
+      // let { Data } = await dataBaseInterface.uploadImgSvg(form);
+
+      // // let { Data } = await dataBaseInterface.uploadImg(form);
+      // await dataBaseInterface.setChartImage({
+      //   ChartInfoId: this.selected_chartid,
+      //   ImageUrl: Data.ResourceUrl,
+      // });
+      form.append('ChartInfoId',this.selected_chartid)
+      await dataBaseInterface.setChartThumbnail(form)
     },
 
     /* 分享图表 */

+ 46 - 2
src/views/dataEntry_manage/codecount/index.vue

@@ -1,7 +1,14 @@
 <template>
 	<el-card class="codecount-container">
 		<div slot="header" class="header">
-			<span><!-- 代码运算 -->{{$t('EtaBasePage.algorithm_btn')}}</span>
+			<div class="header-left">
+				<span><!-- 代码运算 -->{{$t('EtaBasePage.algorithm_btn')}}</span>
+				<span class="opt-btn" @click="operationTipShow=true">
+					<img src="~@/assets/img/data_m/icon01.png" alt="">
+					<!-- 操作说明 -->
+					<span>{{$t('CodeCountPage.opt_tip_btn')}}</span> 
+				</span>
+			</div>
 			<div>
 				<el-button type="primary" @click="runCodeHandle"><!-- 运行 -->{{$t('CodeCountPage.run_btn')}}</el-button>
 				<el-button type="primary" plain @click="saveHandle" v-if="!isView"><!-- 保存 -->{{$t('Dialog.confirm_save_btn')}}</el-button>
@@ -171,6 +178,20 @@
 				</el-tabs>
 			</el-col>
 		</div>
+		<!-- 操作说明 -->
+		<el-dialog
+			:title="$t('CodeCountPage.opt_tip_btn')"
+			:visible.sync="operationTipShow"
+			:close-on-click-modal="false"
+			center
+			v-dialogDrag
+			:append-to-body="true"
+			width="900px"
+		> 
+			<div class="dialog-container">
+				<div style="line-height:20px;color:#000000;font-size: 14px;word-break: normal;" v-html="$t('CodeCountPage.opt_tip_btn_text')"></div>
+			</div>
+		</el-dialog>
 	</el-card>
 </template>
 
@@ -218,7 +239,9 @@ export default {
 				sheetArr:[],
 				sheet_name: '',
 				sql_code: ''
-			}
+			},
+
+			operationTipShow:false
 		};
 	},
 	watch: {
@@ -467,6 +490,24 @@ export default {
 		justify-content: space-between;
 		align-items: center;
 		font-size: 16px;
+		.header-left{
+			display:flex;
+			align-items: center;
+			.opt-btn{
+				display:inline-flex;
+				align-items: center;
+				margin-left: 10px;
+				cursor: pointer;
+				img{
+					width: 32px;
+					height: 34px;
+				}
+				span{
+					color:rgb(64, 158, 255);
+				}
+			}
+		}
+
 	}
 	.bottom {
 		height: calc(100vh - 240px);
@@ -509,6 +550,9 @@ export default {
 		}
 	}
 }
+.dialog-container{
+	padding:0 60px 60px ;
+}
 </style>
 <style lang="scss">
 .codecount-container {

+ 17 - 4
src/views/dataEntry_manage/components/SaveChartOther.vue

@@ -33,7 +33,8 @@
             label: currentLang==='en'?'ChartClassifyNameEn':'ChartClassifyName',
             value: 'ChartClassifyId',
             children: 'Children',
-            emitPath: false
+            emitPath: false,
+            checkStrictly:isRelevanceChart
           }"
           style="width: 80%"
           :placeholder="$t('Chart.InputHolderAll.input_classify')"
@@ -75,6 +76,11 @@ export default {
       }
     }
   },
+  computed:{
+    isRelevanceChart(){
+        return ['/chartrelevance'].includes(this.$route.path)||this.source===3||this.source===4
+    }
+  },
   data() {
     return {
       form: {
@@ -109,7 +115,7 @@ export default {
       if([2,5,'good_price'].includes(this.source)){//商品价格
         res=await futuresInterface.classifyList()
       }else if([3,4,'relevance_chart'].includes(this.source)){//相关性图表
-        res=await chartRelevanceApi.classifyList()
+        res=await chartRelevanceApi.classifyTree()
       }else if([6,'fitting_equation'].includes(this.source)){//拟合方程
         res=await fittingEquationInterface.classifyList()
       }else if([7,8,9,'statistic_feature'].includes(this.source)) { //标准差 百分位 频率图
@@ -125,7 +131,7 @@ export default {
       if([2,5,'good_price'].includes(this.source)){//商品价格
         this.filterNodes(res.Data.AllNodes,1)
       }else if([3,4,'relevance_chart'].includes(this.source)){//相关性图表
-        this.filterNodes(res.Data.AllNodes,1)
+        this.filterNodesAll(res.Data.AllNodes)
       }else if([6,'fitting_equation'].includes(this.source)){//拟合方程
         this.filterNodes(res.Data.AllNodes,1)
       }else if([7,8,9,'statistic_feature'].includes(this.source)) { //标准差 百分位 频率图
@@ -139,7 +145,14 @@ export default {
 			this.classifyOptions = res.Data.AllNodes || [];
     
 		},
-
+		filterNodesAll(arr){
+			arr.length && arr.forEach(item => {
+				item.Children && item.Children.length && this.filterNodesAll(item.Children)
+				if(!item.Children.length) {
+					delete item.Children
+				}
+			})
+		},
 		// 递归改变第三级目录结构
 		filterNodes(arr,n) {
 			arr.length && arr.forEach(item => {

+ 180 - 0
src/views/dataEntry_manage/components/addAverageDialog.vue

@@ -0,0 +1,180 @@
+<template>
+    <!-- 添加同期上下限/均线/标准差 -->
+    <el-dialog
+        :visible.sync="isShow"
+        :close-on-click-modal="false"
+        :append-to-body="true"
+        @close="$emit('close')"
+        custom-class="average-edit-dialog"
+        center
+        width="650px"
+        v-dialogDrag
+        top="8vh"
+        :title="dialogTitle"
+    >
+        <div class="container">
+            <el-form :model="averageForm" :rules="formRules" hide-required-asterisk
+                ref="averageFormRef"
+                label-position="right"
+                label-width="120px">
+                <!-- 倍数 -->
+                <el-form-item :label="$t('Chart.Detail.cal_range_times2')" prop="Multiple" v-if="averageType===3">
+                    <el-input-number 
+                        v-model="averageForm.Multiple" 
+                        controls-position="right" 
+                        :min="0" step-strictly
+                        :step="0.1"
+                        style="width: 90px"
+                        />
+                </el-form-item>
+                <el-form-item prop="Year"
+                    :label="rangeLabelMap[averageType]" >
+                    <span><!-- 过去 -->{{ $t('Chart.Detail.pass_year') }}</span>
+                    <el-input-number 
+                        v-model="averageForm.Year" 
+                        controls-position="right" 
+                        :min="2" step-strictly
+                        style="width: 90px" 
+                        />
+                    <span><!-- 年 -->{{ $t('Edb.FreAll.year_min') }}</span>
+                </el-form-item>
+                <!-- 颜色 -->
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_color_set')" prop="Color">
+                    <el-color-picker
+                      style="width: 90px"
+                      v-model="averageForm.Color"
+                      show-alpha
+                      :predefine="predefineColors"
+                    ></el-color-picker>
+                </el-form-item>
+                <!-- 线型 -->
+                <el-form-item :label="$t('EtaChartAddPage.label_line_sty')" prop="LineType" v-if="averageType===2">
+                    <el-select v-model="averageForm.LineType">
+                        <el-option v-for="lineItem in lineStylesOpts"
+                            :key="lineItem.value"
+                            :label="lineItem.label"
+                            :value="lineItem.value"
+                        >
+                            <svg width="60" height="10" viewBox="0 0 60 10" fill="none" xmlns="http://www.w3.org/2000/svg" v-html="lineItem.svg">
+                            </svg>
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+                <!-- 粗细 -->
+                <el-form-item :label="$t('Chart.Detail.size')" prop="LineWidth" v-if="averageType===2">
+                    <el-input-number 
+                        v-model="averageForm.LineWidth" 
+                        controls-position="right" 
+                        :min="1" step-strictly
+                        style="width: 90px"/>
+                </el-form-item>
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_legend')" prop="Legend">
+                    <el-input v-model="averageForm.Legend"  style="width: 300px;"/>
+                </el-form-item>
+            </el-form>
+        </div>
+        <div slot="footer" class="dialog-footer" style="text-align: center;">
+            <el-button @click="$emit('close')">{{$t('Dialog.cancel_btn')}}</el-button>
+            <el-button type="primary" @click="confirmPerson">{{$t('Dialog.confirm_save_btn')}}</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import { defaultOpts } from '@/utils/defaultOptions';
+import {lineStylesOpts} from '@/views/system_manage/chartTheme/common/config'
+export default {
+    props:{
+        isShow:{
+            type:Boolean,
+            default:false
+        },
+        averageType:{
+            type:Number,
+            default:1, //1同期上下限 2同期均线 3同期标准差
+        },
+        formData:{
+            type:Object,
+            default:{}
+        }
+    },
+    computed:{
+        dialogTitle(){
+            const titleMap = {
+                1:/* '添加同期上下限' */`${this.$t('Table.add_btn')}${this.$i18n.locale!=='zh'?' ':''}${this.$t('EtaChartAddPage.limits_btn')}`,
+                2:/* '添加同期均线' */`${this.$t('Table.add_btn')}${this.$i18n.locale!=='zh'?' ':''}${this.$t('EtaChartAddPage.avg_line_btn')}`,
+                3:/* '添加同期标准差' */`${this.$t('Table.add_btn')}${this.$i18n.locale!=='zh'?' ':''}${this.$t('EtaChartAddPage.std_btn')}`
+            }
+            return titleMap[this.averageType]
+        },
+        rangeLabelMap(){
+            return {
+                1:/* '上下限取数范围' */ this.$t('EtaChartAddPage.limit_range'),
+                2:/* '均线取数范围' */ this.$t('EtaChartAddPage.average_range'),
+                3:/* '取数范围' */ this.$t('EtaChartAddPage.std_range')
+            }
+        },
+        formRules(){ //方便英文翻译
+            return {
+                Legend:[{required:true,message:/* '请输入图例名称' */this.$t('EtaChartAddPage.legend_placeholder')}],
+                Year:[{required:true,message:/* '请输入年份' */this.$t('EtaChartAddPage.year_placeholder')}],
+                LineWidth:[{required:true,message:/* '请选择线宽' */this.$t('EtaChartAddPage.linewidth_placeholder')}],
+                Multiple:[{required:true,message:/* '请选择倍数' */this.$t('EtaChartAddPage.multiple_placeholder')}],
+            }
+        }
+    },
+    watch:{
+        isShow(newval){
+            if(newval){
+                Object.assign(this.averageForm,this.formData)
+                /* if(!this.averageForm.Legend){
+                    this.getLegend()
+                } */
+                this.$refs.averageFormRef&&this.$refs.averageFormRef.clearValidate()
+            }
+        }
+    },
+    data() {
+        return {
+            averageForm:{
+                Legend:'',//图例名称
+                Year:5,//上下限取数范围/均线取数范围/取数范围
+                Color:'#075EEE',//颜色及透明度
+                LineType:'Solid',//线型
+                LineWidth:1,//线宽
+                Multiple:1,//倍数
+            },
+            predefineColors: defaultOpts.colors.slice(0, 2),
+            lineStylesOpts:lineStylesOpts,
+        };
+    },
+    methods: {
+        getLegend(){
+            const nameMap = {
+                1:'年区间',
+                2:'年均值',
+                3:'年标准差'
+            }
+            this.averageForm.Legend = this.averageForm.Year+nameMap[this.averageType]
+        },
+        async confirmPerson(){
+            //校验
+            await this.$refs.averageFormRef.validate()
+            this.$emit('modify',{data:this.averageForm,type:this.averageType})
+        }
+    },
+};
+</script>
+
+<style lang="scss">
+.average-edit-dialog{
+    .container{
+        padding:0 60px;
+        .el-input{
+            width:100%;
+        }
+        .el-color-picker__trigger { width: 100%;padding: 0;border-radius: 4px; }
+        .number-input .el-input__inner { padding: 0 2px 0 10px; }
+    }
+}
+</style>

+ 490 - 115
src/views/dataEntry_manage/components/addMarkerDialog.vue

@@ -6,7 +6,7 @@
 		@close="cancelHandle"
 		custom-class="marker-edit-dialog"
 		center
-		width="650px"
+		width="950px"
 		v-dialogDrag
     top="8vh"
     :title="form.title"
@@ -24,7 +24,7 @@
               v-model="markerForm.axis"
               :placeholder="$t('EtaChartAddPage.label_select_seris_placeholder')"
               style="width:200px;"
-              @change="markerForm.axisName=axisLabelMap[markerForm.axis]"
+              @change="markerForm.axisName=axisLabelMap[markerForm.axis];markerForm.markLineType=1;"
             >
               <el-option :label="$t('Chart.Detail.l_axis')" :value="1" v-if="canSelectLeftYaxis"/>
               <el-option :label="$t('Chart.Detail.h_axis')" :value="3" v-if="canSelectXaxis"/>
@@ -35,45 +35,55 @@
           <el-form-item :label="form.markerType==='line'?$t('EtaChartAddPage.label_line_scale'):$t('EtaChartAddPage.label_area_scale')" prop="value">
             <!-- 标识线 -->
             <template v-if="form.markerType==='line'">
-              <!-- 时间轴1,2,4,6的y轴数字 x轴日期  -->
-              <template v-if="[1,2,4,6].includes(chartInfo.ChartType)">
-                <el-date-picker
-                  v-if="markerForm.axis===3"
-                  v-model="markerForm.value"
-                  :popper-class="{'month-day-picker':chartInfo.ChartType===2}"
-                  type="date"
-                  style="width: 200px;"
-                  :placeholder="$t('EtaChartAddPage.label_date_choose')"
-                  :clearable="false"
-                  :format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
-                  :value-format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
-                ></el-date-picker>
+              <div class="mark-value-wrap form-item-content">
+                <!-- 固定值:原标识线输入框 -->
+                <div class="default-value">
+                    <el-radio v-model="markerForm.markLineType" :label="1" style="margin-right: 20px;">{{$t('PredictEditPage.rule_fix')}}</el-radio>
+                    <!-- 时间轴1,2,4,6的y轴数字 x轴日期  -->
+                    <template v-if="[1,2,4,6].includes(chartInfo.ChartType)">
+                        <el-date-picker
+                            v-if="markerForm.axis===3"
+                            v-model="markerForm.value"
+                            :popper-class="{'month-day-picker':chartInfo.ChartType===2}"
+                            type="date"
+                            style="width: 100px;"
+                            :placeholder="$t('EtaChartAddPage.label_date_choose')"
+                            :clearable="false"
+                            :format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                            :value-format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                        ></el-date-picker>
 
-                <el-input
-                  v-else
-                  v-model="markerForm.value"
-                  class="number-input"
-                  style="width: 200px;"
-                  type="number"
-                  :placeholder="$t('Edb.InputHolderAll.input_number')"
-                />
-
-              </template>
+                        <el-input
+                            v-else
+                            v-model="markerForm.value"
+                            class="number-input"
+                            style="width: 100px;"
+                            type="number"
+                            :placeholder="$t('Edb.InputHolderAll.input_number')"
+                            :disabled="markerForm.markLineType===2"
+                        />
+                    </template>
 
-              <!-- 柱形图,散点,截面散点只可选数字 -->
-              <template v-else-if="[5,7,10].includes(chartInfo.ChartType)">
-                <el-input
-                  v-model="markerForm.value"
-                  style="width: 200px;"
-                  type="number"
-                  class="number-input"
-                  :placeholder="$t('Edb.InputHolderAll.input_number')"
-                  clearable
-                />
-              </template>
+                    <!-- 柱形图,散点,截面散点只可选数字 -->
+                    <template v-else-if="[5,7,10].includes(chartInfo.ChartType)">
+                        <el-input
+                            v-model="markerForm.value"
+                            style="width: 100px;"
+                            type="number"
+                            class="number-input"
+                            :placeholder="$t('Edb.InputHolderAll.input_number')"
+                            :disabled="markerForm.markLineType===2"
+                            clearable
+                        />
+                    </template>
+                </div>
+                <!-- 指标计算 -->
+                <div class="custom-value" v-if="markerForm.axis!==3">
+                    <el-radio v-model="markerForm.markLineType" :label="2" style="margin-left: 20px;">{{ $t('Edb.CalculatesAll.indicator_calculation') }}</el-radio>
+                </div>
+              </div>
             </template>
 
-
             <!-- 标识区 -->
             <template v-else>
               <!-- 时间轴1,2,4,6的y轴数字 x轴日期  -->
@@ -108,6 +118,7 @@
                     class="number-input"
                     style="width: 90px;"
                     type="number"
+                    @change="e => {markerForm.fromValue=Number(e);}"
                     :placeholder="$t('Edb.InputHolderAll.input_number')"
                   />
                   <!-- 至 -->{{$t('Common.to')}}
@@ -116,6 +127,7 @@
                     class="number-input"
                     style="width: 90px;"
                     type="number"
+                    @change="e => {markerForm.toValue=Number(e);}"
                     :placeholder="$t('Edb.InputHolderAll.input_number')"
                   />
 
@@ -129,6 +141,7 @@
                   class="number-input"
                   style="width: 90px;"
                   type="number"
+                  @change="e => {markerForm.fromValue=Number(e);}"
                   :placeholder="$t('Edb.InputHolderAll.input_number')"
                 />
                 <!-- 至 -->{{$t('Common.to')}}
@@ -137,81 +150,271 @@
                   class="number-input"
                   style="width: 90px;"
                   type="number"
+                  @change="e => {markerForm.toValue=Number(e);}"
                   :placeholder="$t('Edb.InputHolderAll.input_number')"
                 />
 
               </div>
             </template>
-            
-          </el-form-item>
-          <el-form-item :label="$t('EtaChartAddPage.label_line_sty')" prop="dashStyle" v-if="form.markerType==='line'">
-            <el-select 
-              v-model="markerForm.dashStyle"
-              style="width:200px;"
-            >
-              <el-option 
-                v-for="item in dashOptions" 
-                :key="item.value" 
-                :label="item.label" 
-                :value="item.value"
-              >
-                <svg width="60" height="10" viewBox="0 0 60 10" fill="none" xmlns="http://www.w3.org/2000/svg" v-html="item.svg"></svg>
-              </el-option>
-            </el-select>
-          </el-form-item>
-          <el-form-item :label="$t('Chart.Detail.color')" prop="color" style="margin-bottom:8px;">
-            <el-color-picker
-              v-model="markerForm.color"
-              :predefine="predefineColors"
-              show-alpha
-              style="width: 90px"
-            />
-          </el-form-item>
-          <el-form-item :label="$t('Chart.Detail.size')" prop="lineWidth" v-if="form.markerType==='line'">
-            <el-input
-              v-model="markerForm.lineWidth"
-              style="width: 90px"
-              type="number"
-              :min="1"
-            />
-          </el-form-item>
-          <el-form-item :label="form.markerType==='line'?$t('EtaChartAddPage.label_line_intru'):$t('EtaChartAddPage.label_area_intru')" prop="text">
-            <el-input
-              v-model="markerForm.text"
-              style="width: 200px"
-              :placeholder="$t('Chart.InputHolderAll.input_content')"
-            />
-          </el-form-item>
-          <el-form-item :label="$t('EtaChartAddPage.label_text_pos')" prop="textPosition">
-            <el-select 
-              v-model="markerForm.textPosition"
-              style="width:200px;"
-            >
-              <el-option 
-                v-for="item in verticalPositions" 
-                :key="item.value" 
-                :label="item.label" 
-                :value="item.value"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item :label="$t('EtaChartAddPage.label_text_color')" prop="textColor" style="margin-bottom:8px;">
-            <el-color-picker
-              v-model="markerForm.textColor"
-              show-alpha
-              :predefine="predefineColors"
-              style="width: 90px"
-            />
-          </el-form-item>
-          <el-form-item :label="$t('EtaChartAddPage.label_text_size')" prop="textFontSize">
-            <el-input
-              v-model="markerForm.textFontSize"
-              class="number-input"
-              style="width: 90px"
-              type="number"
-              :min="1"
-            />
           </el-form-item>
+
+          <!-- 标识线-指标计算部分 -->
+          <div class="custom-value-setting-wrap" v-if="form.markerType==='line'&&markerForm.markLineType===2">
+            <!-- 指标选择 -->
+            <el-form-item :label="$t('Edb.eta_name')">
+                <div class="edb-box-wrap form-item-content">
+                    <!-- 固定第一个指标 -->
+                    <div class="fixed-edb" style="margin-right: 20px;width:45%;">
+                        <el-radio v-model="markerForm.edbType" :label="0">{{ $t('Chart.Detail.chart_first_edb') }}</el-radio>
+                        <p>{{tableData&&tableData[0].EdbName||''}}</p>
+                    </div>
+                    <!-- 指标/预测指标库的指标 -->
+                    <div class="other-edb">
+                        <el-radio v-model="markerForm.edbType" :label="1" style="margin-right: 20px;">{{$t('Chart.Detail.chart_other_edb')}}</el-radio>
+                        <!-- /datamanage/edb_info/filter_by_es/all -->
+                        <el-select style="width: 200px;"
+                            filterable remote clearable
+                            :placeholder="$t('ToolBox.ForexCalendar.edb_input')"
+                            v-model="searchObj"
+                            :remote-method="searchHandle"
+                            value-key="EdbInfoId"
+                            @click.native="searchHandle('')"
+                            @change="searchChange">
+                            <i slot="prefix" class="el-input__icon el-icon-search"></i>
+                            <el-option
+                                v-for="item in searchOptions"
+                                :key="item.EdbInfoId"
+                                :label="item.EdbName"
+                                :value="item"/>
+                        </el-select>
+                        <p>{{ markerForm.edbType&&markerForm.edbName||'' }}</p>
+                    </div>
+                </div>
+            </el-form-item>
+            <!-- 时间区间选择 -->
+            <el-form-item :label="$t('Chart.Detail.time_interval')">
+                <div class="time-area-wrap">
+                    <el-radio v-model="markerForm.timeInterval" :label="0" :disabled="[7,10].includes(chartInfo.ChartType)">{{ $t('Chart.Detail.follow_chart') }}</el-radio>
+                    <el-radio v-model="markerForm.timeInterval" :label="1">{{ $t('Chart.Detail.custom') }}</el-radio>
+                </div>
+            </el-form-item>
+            <!-- 如果时间区间选择自定义 -->
+            <div class="custom-time-wrap" v-if="markerForm.timeInterval===1">
+                <!-- 起始时间 -->
+                <el-form-item :label="$t('Table.start_time')">
+                    <div class="form-item-content">
+                        <div class="format">
+                            <el-radio v-model="markerForm.startTime.timeType" :label="1" style="margin-right: 0;"><!-- 固定 -->{{ $t('Chart.Detail.edb_time_fix') }}</el-radio>
+                            <el-date-picker
+                                v-model="markerForm.startTime.date"
+                                popper-class="x-range-picker-date"
+                                style="width: 140px;"
+                                placeholder="请输入固定时间"
+                                :clearable="false"
+                                format="yyyy-MM-dd"
+                                value-format="yyyy-MM-dd"
+                            ></el-date-picker>
+                        </div>
+                        <div class="format">
+                            <el-radio v-model="markerForm.startTime.timeType" :label="2" style="margin-left:20px;margin-right:0"><!-- 动态 -->{{ $t('Chart.Detail.edb_time_dyn') }}</el-radio>
+                            <el-tooltip effect="dark" placement="top">
+                                <div slot="content" v-html="$t('EtaChartAddPage.dynamic_time_tip')"></div>
+                                <i class="el-icon-question" style="font-size: 16px;"></i>
+                            </el-tooltip>
+                        </div>
+                    </div>
+                </el-form-item>
+                <!-- 起始时间为动态 -->
+                <div class="start-time-custom-wrap" v-if="markerForm.startTime.timeType===2">
+                    <!-- 基准日期 -->
+                    <el-form-item :label="$t('Chart.Detail.time_base')">
+                        <div class="form-item-content">
+                            <div class="format">
+                                <el-radio v-model="markerForm.startTime.baseDate" :label="0"><!-- 系统日期 -->{{ $t('Chart.Detail.sys_time') }}</el-radio>
+                            </div>
+                            <div class="format" style="display: flex;align-items: center;">
+                                <p>
+                                    <el-radio v-model="markerForm.startTime.baseDate" :label="1" style="margin-right:5px;"><!-- 指标最新日期 -->{{ $t('Chart.Detail.edb_new_time') }}</el-radio>
+                                </p>
+                                <p><!-- 期数前移 -->{{ $t('Chart.Detail.edb_periods') }}{{ $t('Chart.Detail.edb_periods_lead') }}
+                                    <el-input style="width:60px" type="number" class="number-input"
+                                    v-model.number="markerForm.startTime.conf.moveForward" 
+                                    @change="e => {markerForm.startTime.conf.moveForward=Number(e);}"
+                                    />
+                                    <!-- 期 -->{{ $t('Chart.Detail.edb_period') }}
+                                </p>
+                            </div>
+                        </div>
+                        
+                    </el-form-item>
+                    <!-- 日期变换 -->
+                    <dateMoveWaySec ref="startTime"></dateMoveWaySec>
+                   
+                </div>
+                
+                <!-- 结束时间 -->
+                <el-form-item :label="$t('Edb.Detail.e_end_time')">
+                    <div class="form-item-content">
+                        <div class="format">
+                            <el-radio v-model="markerForm.endTime.timeType" :label="3"><!-- 至今 -->{{ $t('Chart.Detail.edb_time_now') }}</el-radio>
+                        </div>
+                        <div class="format">
+                            <el-radio v-model="markerForm.endTime.timeType" :label="1" style="margin-right: 0;"><!-- 固定 -->{{ $t('Chart.Detail.edb_time_fix') }}</el-radio>
+                            <el-date-picker
+                                v-model="markerForm.endTime.date"
+                                popper-class="x-range-picker-date"
+                                style="width: 140px;"
+                                placeholder="请输入固定时间"
+                                :clearable="false"
+                                format="yyyy-MM-dd"
+                                value-format="yyyy-MM-dd"
+                            ></el-date-picker>
+                        </div>
+                        <div class="format">
+                            <el-radio v-model="markerForm.endTime.timeType" :label="2" style="margin-right: 0;"><!-- 动态 -->{{ $t('Chart.Detail.edb_time_dyn') }}</el-radio>
+                            <el-tooltip effect="dark" placement="top">
+                                <div slot="content" v-html="$t('EtaChartAddPage.dynamic_time_tip')"></div>
+                                <i class="el-icon-question" style="font-size: 16px;"></i>
+                            </el-tooltip>
+                        </div>
+                    </div>
+                    
+                </el-form-item>
+                <!-- 结束时间为动态 -->
+                <div class="end-time-custom-wrap" v-if="markerForm.endTime.timeType===2">
+                    <!-- 基准日期 -->
+                    <el-form-item :label="$t('Chart.Detail.time_base')">
+                        <div class="form-item-content">
+                            <div class="format">
+                                <el-radio v-model="markerForm.endTime.baseDate" :label="0"><!-- 系统日期 -->{{ $t('Chart.Detail.sys_time') }}</el-radio>
+                            </div>
+                            <div class="format" style="display: flex;align-items: center;">
+                                <p>
+                                    <el-radio v-model="markerForm.endTime.baseDate" :label="1" style="margin-right:5px;"><!-- 指标最新日期 -->{{ $t('Chart.Detail.edb_new_time') }}</el-radio>
+                                </p>
+                                <p><!-- 期数前移 -->{{ $t('Chart.Detail.edb_periods') }}{{ $t('Chart.Detail.edb_periods_lead') }}
+                                    <el-input style="width:60px" type="number" class="number-input"
+                                    v-model.number="markerForm.endTime.conf.moveForward" 
+                                    @change="e => {markerForm.endTime.conf.moveForward=Number(e);}"
+                                    />
+                                    <!-- 期 -->{{ $t('Chart.Detail.edb_period') }}
+                                </p>
+                            </div>
+                        </div>
+                        
+                    </el-form-item>
+                    <!-- 日期变换 -->
+                    <dateMoveWaySec ref="endTime"></dateMoveWaySec>
+                </div>
+            </div>
+            <!-- 计算方式 -->
+            <el-form-item :label="$t('Chart.Detail.plot_calculation')">
+                <div class="form-item-content">
+                    <!--区间均值-->
+                    <div class="format">
+                        <el-radio v-model="markerForm.calculation" :label="1">{{ $t('Chart.Detail.cal_range_val') }}{{ $t('Chart.Detail.cal_range_mean') }}</el-radio>
+                    </div>
+                    <!--区间均值加N倍标准差-->
+                    <div class="format">
+                        <el-radio v-model="markerForm.calculation" :label="2" style="margin-right:0;">{{ $t('Chart.Detail.cal_range_val') }}{{ $t('Chart.Detail.cal_range_mean') }}</el-radio>
+                        <p style="display:inline-block">{{ $t('Chart.Detail.cal_range_plus') }}
+                            <el-input 
+                            style="width:60px" 
+                            v-model.number="markerForm.calculationValue" 
+                            @change="e => {markerForm.calculationValue=Number(e);}"
+                            type="number" class="number-input"></el-input>{{ $t('Chart.Detail.cal_range_times') }} {{ $t('Chart.Detail.cal_range_std') }}</p>
+                    </div>
+                    <!--区间分位-->
+                    <div class="format">
+                        <el-radio v-model="markerForm.calculation" :label="3" style="margin-right:0;">{{ $t('Chart.Detail.cal_range_val') }}</el-radio>
+                        <p style="display:inline-block">
+                            <el-input style="width:60px" v-model="calculationValue" type="number" class="number-input"></el-input>%
+                            <el-select v-model="calculationType" style="width:80px">
+                                <el-option :label="$t('Chart.Detail.cal_range_count')" :value="3"></el-option>
+                                <el-option :label="$t('Chart.Detail.cal_range_value')" :value="4"></el-option>
+                            </el-select>{{ $t('Chart.Detail.cal_range_quantile') }}
+                        </p>
+                    </div>
+                </div>
+            </el-form-item>
+          </div>
+
+          <!-- 标识线样式 可收起 -->
+          <div class="mark-box" @click="isMarkStyleShow = !isMarkStyleShow;">
+            <span><i :class="isMarkStyleShow?'el-icon-arrow-down':'el-icon-arrow-right'"></i></span><span>{{ $t('Chart.Detail.plot_style') }}</span>
+          </div>
+          <div class="mark-style-wrap" v-show="isMarkStyleShow">
+            <el-form-item :label="$t('EtaChartAddPage.label_line_sty')" prop="dashStyle" v-if="form.markerType==='line'">
+                <el-select 
+                v-model="markerForm.dashStyle"
+                style="width:200px;"
+                >
+                <el-option 
+                    v-for="item in dashOptions" 
+                    :key="item.value" 
+                    :label="item.label" 
+                    :value="item.value"
+                >
+                    <svg width="60" height="10" viewBox="0 0 60 10" fill="none" xmlns="http://www.w3.org/2000/svg" v-html="item.svg"></svg>
+                </el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item :label="$t('Chart.Detail.color')" prop="color" style="margin-bottom:8px;">
+                <el-color-picker
+                v-model="markerForm.color"
+                :predefine="predefineColors"
+                show-alpha
+                style="width: 90px"
+                />
+            </el-form-item>
+            <el-form-item :label="$t('Chart.Detail.size')" prop="lineWidth" v-if="form.markerType==='line'">
+                <el-input
+                v-model="markerForm.lineWidth"
+                style="width: 90px"
+                type="number"
+                @change="e => {markerForm.lineWidth=Number(e);}"
+                :min="1"
+                />
+            </el-form-item>
+            <el-form-item :label="form.markerType==='line'?$t('EtaChartAddPage.label_line_intru'):$t('EtaChartAddPage.label_area_intru')" prop="text">
+                <el-input
+                v-model="markerForm.text"
+                style="width: 200px"
+                :placeholder="$t('Chart.InputHolderAll.input_content')"
+                />
+            </el-form-item>
+            <el-form-item :label="$t('EtaChartAddPage.label_text_pos')" prop="textPosition">
+                <el-select 
+                v-model="markerForm.textPosition"
+                style="width:200px;"
+                >
+                <el-option 
+                    v-for="item in verticalPositions" 
+                    :key="item.value" 
+                    :label="item.label" 
+                    :value="item.value"
+                />
+                </el-select>
+            </el-form-item>
+            <el-form-item :label="$t('EtaChartAddPage.label_text_color')" prop="textColor" style="margin-bottom:8px;">
+                <el-color-picker
+                v-model="markerForm.textColor"
+                show-alpha
+                :predefine="predefineColors"
+                style="width: 90px"
+                />
+            </el-form-item>
+            <el-form-item :label="$t('EtaChartAddPage.label_text_size')" prop="textFontSize">
+                <el-input
+                v-model="markerForm.textFontSize"
+                class="number-input"
+                style="width: 90px"
+                type="number"
+                @change="e => {markerForm.textFontSize=Number(e);}"
+                :min="1"
+                />
+            </el-form-item>
+          </div>
       </el-form>
     </div>
 
@@ -223,8 +426,10 @@
   </el-dialog>
 </template>
 <script>
+import dateMoveWaySec from '@/views/datasheet_manage/components/dateMoveWaySection.vue'
 import { defaultOpts } from '@/utils/defaultOptions';
 import { verticalPositions } from '@/views/system_manage/chartTheme/common/config';
+import {ForexCalendarInterface} from '@/api/modules/toolBoxApi';
 export default {
   props: {
     isShow: {
@@ -241,18 +446,40 @@ export default {
 
     chartInfo: {
       type:Object
+    },
+    tableData:{
+        type:Array
     }
-
+  },
+  components:{
+    dateMoveWaySec
   },
   watch: {
     isShow(nval) {
       if(!nval) return
-
+      this.searchObj = ''
       if(this.form.editIndex) { //表单回显
         this.editIndex = this.form.editIndex;
         this.markerForm = {
           ...this.form.data
         }
+        //标识线特殊处理
+        if(this.form.markerType==='line'){
+            if(!this.markerForm.markLineType){
+                Object.assign(this.markerForm,this.markerExtraConfig)
+                //柱形图 截面散点图禁用时间区间-跟随图表
+                if([7,10].includes(this.chartInfo.ChartType)){
+                    this.markerForm.timeInterval = 1
+                }
+            }else{
+                //重置计算方式的值
+                const {calculation} = this.markerForm
+                if(calculation===3){
+                    this.calculationValue = this.markerForm.calculationValue
+                    this.markerForm.calculationValue = 1
+                }
+            }
+        }
       }else {
         this.editIndex = 0;
         
@@ -262,8 +489,8 @@ export default {
           axis: this.canSelectLeftYaxis?1:0,
           axisName:this.axisLabelMap[this.canSelectLeftYaxis?1:0],
           value: '',
-          from: '',
-          to:'',
+          fromValue: '',
+          toValue:'',
           lineWidth: 2,
           dashStyle: 'ShortDashDot',
           color: '#999',
@@ -273,7 +500,27 @@ export default {
           textFontSize: themeOpt.markerOptions.style.fontSize,
           isShow: true,
         }
+        //标识线特殊处理
+        if(this.form.markerType==='line'){
+           this.markerForm = {
+            ...this.markerForm,
+            ...this.markerExtraConfig
+           }
+            this.calculationValue = 50
+            //柱形图 截面散点图禁用时间区间-跟随图表
+            if([7,10].includes(this.chartInfo.ChartType)){
+                this.markerForm.timeInterval = 1
+            }
+        }
       }
+    },
+    'markerForm.axis':{
+        handler(newval,oldval){
+            //从横轴切换到其他轴/其他轴切换到横轴 清空value值
+            if(oldval===3||newval===3){
+                this.markerForm.value = ''
+            }
+        }
     }
   },
   computed: {
@@ -326,8 +573,53 @@ export default {
         text: '',
         textPosition: 'top',
         textColor: '#999',
-        textFontSize: 12
+        textFontSize: 12,
+        //markerType:'line'
+      },
+      //eta1.9.4新增标识线设置
+      markerExtraConfig:{
+        markLineType:1,//标识线所在刻度 1固定值 2指标计算
+        edbType:0,//指标 0图上第一个指标 1其他指标 -
+        edbInfoId:0,//选择的指标id 图上第一个指标取tableData[0] 其他指标取 searchObj
+        edbName:'',//回显指标用
+        timeInterval:0,//时间区间 0跟随图表 1自定义
+        startTime:{//当timeInterval为1时,有值
+            timeType:1,//起始时间类型 1 固定 2动态
+            date:'2020-01-01',//固定的时间值,timeType为2时为空
+            baseDate:0,//基准日期 0系统日期 1指标最新日期
+            conf:{
+                moveForward:0,//baseTimeType为2时,表示前移的期数
+                dateChange:[
+                    {//和 datasheet_manage/components/dateMoveWaySection 保持一致
+                        ChangeType:1,//1日期位移 2指定频率
+                        Day: 0,
+                        Month: 0,
+                        Year: 0,
+                        Frequency: '本周',
+                        FrequencyDay: '周一'
+                    }
+                ]//日期变换的值,最多两项,最少0项,
+            },
+
+        },
+        endTime:{
+            timeType:3,//起始时间类型 3至今 1 固定 2动态
+            date:'2024-01-01',//固定的时间值,timeType不为1时为空
+            baseDate:0,//基准日期 0系统日期 1指标最新日期
+            conf:{
+                moveForward:0,
+                dateChange:[]
+            },
+        },
+        calculation:1,//计算方式 1区间均值 2区间均值+标准差 3区间百分位个数分位 4区间百分位数值分位
+        calculationValue:1,//计算方式对应值,calculation为2时表示标准差的倍数,为3时表示个数分位的百分数
       },
+      calculationType:3,
+      calculationValue:50,
+     /*  calculationSelect:[
+        {lable:'个数',value:3},
+        {label:'数值',value:4}
+      ], */
 
       axisLabelMap: { //暂时没有横轴的代表key 规定为3好了
         1: '左轴',
@@ -335,6 +627,10 @@ export default {
         2: '右二轴',
         3: '横轴',
       },
+
+      isMarkStyleShow:false,
+      searchObj:'',
+      searchOptions:[]
     }
   },
   mounted(){
@@ -344,15 +640,52 @@ export default {
 
     async saveMarker() {
 
-      if(this.form.markerType==='line'&&!this.markerForm.value) return this.$message.warning(/* '标识线所在刻度不能为空' */this.$t('Chart.Vailds.plotline_msg'))
+      if(this.form.markerType==='line'&&this.markerForm.markLineType===1&&!this.markerForm.value) return this.$message.warning(/* '标识线所在刻度不能为空' */this.$t('Chart.Vailds.plotline_msg'))
 
       else if(this.form.markerType==='area'&&(!this.markerForm.fromValue||!this.markerForm.toValue)) return this.$message.warning(/* '标识区所在范围不能为空' */this.$t('Chart.Vailds.plotarea_msg'))
       
       else if(this.form.markerType==='area'&&this.markerForm.fromValue===this.markerForm.toValue) return this.$message.warning(/* '标识区所在范围不能相同' */this.$t('Chart.Vailds.plotarea_same_msg'))
 
+      //其他判断
+      if(this.form.markerType==='line'){
+        if(this.markerForm.markLineType===2&&this.markerForm.edbType===1&&!this.searchObj){
+            return this.$message.warning(/* '请选择指标' */this.$t('Edb.InputHolderAll.input_select_edb'))
+        }
+        //起始日期为动态 获取日期变换
+        if(this.markerForm.startTime.timeType===2){
+            this.markerForm.startTime.conf.dateChange = this.$refs.startTime.dateChangeArr||[]
+            //key的第一个字母改为小写
+            this.markerForm.startTime.conf.dateChange = this.markerForm.startTime.conf.dateChange.map(i=>{
+                return Object.fromEntries(
+                    Object.keys(i).map(key => [key.charAt(0).toLowerCase() + key.slice(1), i[key]])
+                );
+            })
+        }
+        //结束日期为动态 获取日期变换
+        if(this.markerForm.endTime.timeType===2){
+            this.markerForm.endTime.conf.dateChange = this.$refs.endTime.dateChangeArr||[]
+            this.markerForm.startTime.conf.dateChange = this.markerForm.startTime.conf.dateChange.map(i=>{
+                return Object.fromEntries(
+                    Object.keys(i).map(key => [key.charAt(0).toLowerCase() + key.slice(1), i[key]])
+                );
+            })
+        }
+        if(this.markerForm.edbType===1){
+            this.markerForm.edbInfoId = this.searchObj.EdbInfoId||0
+            this.markerForm.edbName = this.searchObj.EdbName||''
+        }else{
+            this.markerForm.edbInfoId = this.tableData&&this.tableData[0].EdbInfoId||0
+        }
+      }
       
       let item = _.cloneDeep(this.markerForm)
-      
+
+      //格式化某些值
+      //form.calculation+calculationType 共同判断计算方式
+      if(this.markerForm.calculation===3){
+            item.calculation = this.calculationType
+            item.calculationValue = Number(this.calculationValue)
+      }
       this.editIndex 
         ? this.$emit('edit',{
             index: this.editIndex,
@@ -365,13 +698,33 @@ export default {
    
     cancelHandle() {
       this.$emit('update:isShow',false)
-    }
+    },
+    searchHandle(keyword){
+        ForexCalendarInterface.searchEdbInfo({
+            KeyWord:keyword,
+            CurrentIndex:1,
+            PageSize:100,
+        }).then(res=>{
+            if(res.Ret!==200) return 
+            this.searchOptions = res.Data.List||[]
+        })
+    },
+    searchChange(){
+        if(typeof this.searchObj === 'object'){
+            //获取需要的数据
+            this.markerForm.edbInfoId = this.searchObj.EdbInfoId
+            this.markerForm.edbName = this.searchObj.EdbName
+        }else{
+            this.markerForm.edbInfoId = 0
+            this.markerForm.edbName = ''
+        }
+    },
   },
 }
 </script>
 <style scoped lang='scss'>
 .main {
-  padding-left: 20%;
+  padding-left: 5%;
 }
 .bottom {
   margin: 30px 0;
@@ -383,6 +736,28 @@ export default {
 .marker-edit-dialog {
   .el-color-picker__trigger { width: 100%;padding: 0;border-radius: 4px; }
   .number-input .el-input__inner { padding: 0 2px 0 10px; }
+  .form-item-content{
+    display: flex;
+    .format{
+        margin-right: 30px;
+    }
+  }
+  .date-change-ways{
+    margin-bottom: 20px;
+    .header{
+        label{
+            text-align: left !important;
+            width:120px !important;
+        }
+    }
+  }
+  .mark-box{
+    background-color: #EBEFF6;
+    border:1px solid #C8CDD9;
+    padding:12px;
+    cursor: pointer;
+    margin-bottom: 20px;
+  }
 
 }
 .month-day-picker {

+ 319 - 0
src/views/dataEntry_manage/components/addRightEdbDialog.vue

@@ -0,0 +1,319 @@
+<template>
+    <!-- 添加右轴指标 -->
+    <el-dialog
+        :visible.sync="isShow"
+        :close-on-click-modal="false"
+        :append-to-body="true"
+        @close="$emit('close')"
+        custom-class="average-edit-dialog"
+        center
+        width="650px"
+        v-dialogDrag
+        top="8vh"
+        :title="$t('EtaChartAddPage.add_right_edb_btn')"
+    >
+        <div class="container">
+           <div class="type-select">
+                <el-radio-group v-model="rightEdbForm.IndicatorType" @change="indicatorTypeChange">
+                    <el-radio :label="1"><!-- 左轴指标同比 -->{{ $t('EtaChartAddPage.right_edb_type_on_year') }}</el-radio>
+                    <el-radio :label="2"><!-- 指标库 -->{{ $t('EtaChartAddPage.right_edb_type_lib') }}</el-radio>
+                    <el-radio :label="3"><!-- 预测指标 -->{{ $t('EtaChartAddPage.right_edb_type_pred') }}</el-radio>
+                </el-radio-group>
+                <el-select v-if="rightEdbForm.IndicatorType!==1"
+                    v-model="search_txt"
+                    v-loadMore="searchLoad"
+                    ref="searchRef"
+                    :filterable="!search_txt"
+                    remote
+                    clearable
+                    :placeholder="$t('Edb.InputHolderAll.input_name_orid')"
+                    style="width:90%;margin-top: 20px;display: block;"
+                    :remote-method="searchHandle"
+                    @click.native="inputFocusHandle"
+                    @change="selectTarget($event && searchOptions.find(_ => _.EdbInfoId === $event))"
+                >
+                    <i slot="prefix" class="el-input__icon el-icon-search"></i>
+                    <el-option
+                        v-for="item in searchOptions"
+                        :key="item.EdbInfoId"
+                        :label="chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
+                        :value="item.EdbInfoId"
+                        :disabled="!item.HaveOperaAuth"
+                    >
+                        <edbDetailPopover :info="item">
+                            <div slot="reference">
+                                <img 
+                                    :src="$icons.lock_ico2" 
+                                    width="18" 
+                                    height="18" 
+                                    style="vertical-align:middle" 
+                                    v-if="!item.HaveOperaAuth"
+                                />
+                                {{chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName }}
+                            </div>
+                        </edbDetailPopover>
+                    </el-option>
+                </el-select>
+           </div>
+           <div class="form-box">
+            <el-form :model="rightEdbForm" :rules="formRules" hide-required-asterisk
+                label-position="right"
+                label-width="120px">
+                <!-- 生成样式-->
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_gen_style')">
+                    <el-select v-model="rightEdbForm.Style">
+                        <el-option :label="$t('EtaChartAddPage.right_edb_gen_column')" value="column"></el-option>
+                        <el-option :label="$t('EtaChartAddPage.right_edb_gen_mark')" value="mark"></el-option>
+                    </el-select>
+                </el-form-item>
+                <!-- 如果选择标记点 -->
+                <!-- 标记点形状 -->
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_mark_shape')" v-if="rightEdbForm.Style==='mark'">
+                    <el-select v-model="rightEdbForm.Shape">
+                        <el-option 
+                            v-for="markItem in markTypesOpts" 
+                            :key="markItem.value"
+                            :label="markItem.label"
+                            :value="markItem.value"
+                            >
+                            <div style="display: flex;align-items: center;justify-content: center;height: 100%;" v-html="markItem.svg">
+                            </div>
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+                <!-- 柱形/标记点的 颜色及透明度 -->
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_color_set')">
+                    <el-color-picker
+                      style="width: 90px"
+                      v-model="rightEdbForm.ChartColor"
+                      show-alpha
+                      :predefine="predefineColors"
+                    ></el-color-picker>
+                </el-form-item>
+                <!-- 如果选择标记点 -->
+                <!-- 标记点大小 -->
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_mark_size')" v-if="rightEdbForm.Style==='mark'">
+                    <el-input-number 
+                        v-model="rightEdbForm.Size" 
+                        controls-position="right" 
+                        :min="1" 
+                        style="width: 90px"/>
+                </el-form-item>
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_legend')">
+                    <el-input v-model="rightEdbForm.Legend"></el-input>
+                </el-form-item>
+                <!-- 如果选择左轴同比 -->
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_format')" v-if="rightEdbForm.IndicatorType===1">
+                    <el-radio-group v-model="rightEdbForm.NumFormat">
+                        <el-radio :label="1"><!-- 百分数 -->{{ $t('EtaChartAddPage.right_edb_format_per') }}</el-radio>
+                        <el-radio :label="2"><!-- 小数 -->{{ $t('EtaChartAddPage.right_edb_format_dec') }}</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <!-- 如果选择标记点 -->
+                <!-- 标记点连线 -->
+                <el-form-item :label="$t('EtaChartAddPage.right_edb_mark_connect_text')" v-if="rightEdbForm.Style==='mark'">
+                    <el-radio-group v-model="rightEdbForm.IsConnected">
+                        <el-radio :label="0">{{$t('EtaChartAddPage.right_edb_mark_not_connected')}}</el-radio>
+                        <el-radio :label="1">{{ $t('EtaChartAddPage.right_edb_mark_connected') }}</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <!-- 如果选择连线 -->
+                <template v-if="rightEdbForm.IsConnected">
+                    <el-form-item :label="$t('EtaChartAddPage.right_edb_mark_connect_line_color')">
+                        <el-color-picker
+                        style="width: 90px"
+                        v-model="rightEdbForm.LineColor"
+                        show-alpha
+                        :predefine="predefineColors"
+                        ></el-color-picker>
+                    </el-form-item>
+                    <el-form-item :label="$t('EtaChartAddPage.right_edb_mark_connect_line_style')">
+                        <el-select v-model="rightEdbForm.LineStyle">
+                            <el-option v-for="lineItem in lineStylesOpts"
+                                :key="lineItem.value"
+                                :label="lineItem.label"
+                                :value="lineItem.value"
+                            >
+                                <svg width="60" height="10" viewBox="0 0 60 10" fill="none" xmlns="http://www.w3.org/2000/svg" v-html="lineItem.svg">
+                                </svg>
+                            </el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item :label="$t('EtaChartAddPage.right_edb_mark_connect_line_width')">
+                        <el-input-number 
+                            v-model="rightEdbForm.LineWidth" 
+                            controls-position="right" 
+                            :min="1" 
+                            style="width: 90px"/>
+                    </el-form-item>
+                </template>
+            </el-form>
+           </div>
+        </div>
+        <div slot="footer" class="dialog-footer" style="text-align: center;">
+            <el-button @click="$emit('close')">{{$t('Dialog.cancel_btn')}}</el-button>
+            <el-button type="primary" @click="confirmPerson">{{$t('Dialog.confirm_save_btn')}}</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
+import { defaultOpts } from '@/utils/defaultOptions';
+import { markTypesOpts,lineStylesOpts } from '@/views/system_manage/chartTheme/common/config'
+export default {
+    props:{
+        isShow:{
+            type:Boolean,
+            default:false
+        },
+        tableData:{
+            type:Array
+        },
+        formData:{
+            type:Object,
+            default:{}
+        },
+        edbData:{
+            type:Object,
+        }
+    },
+    computed:{
+        formRules(){ //方便英文翻译
+            return {}
+        }
+    },
+    watch:{
+        isShow(newval){
+            if(newval){
+                Object.assign(this.rightEdbForm,this.formData)
+                this.rightEdbData = this.edbData
+                this.search_txt = this.edbData.EdbInfoId||''
+                this.searchOptions = this.edbData&&this.edbData.EdbInfoId?[this.edbData]:[]
+                if(!this.rightEdbForm.Legend){
+                    this.rightEdbForm.Legend = this.$t('EtaChartAddPage.year_on_right')
+                }
+            }
+        }
+    },
+    data() {
+        return {
+            search_page:1,
+            current_search:'',
+            search_txt:'',
+            search_have_more:false,
+            searchOptions:[],
+            rightEdbForm:{
+                IndicatorType:1,//1左轴同比 2指标库 3预测指标
+                Style:'column',//生成样式 column/mark
+                Shape:'circle',//标记点形状
+                ChartColor:'#075EEE',//颜色
+                Size:3,//标记点大小
+                Legend:'',//图例名称
+                NumFormat:1,//数值格式 1百分比 2小数
+                IsConnected:0,//连线 0无 1有
+                LineColor:'rgba(102, 102, 102, 1)',//线条颜色
+                LineWidth:1,//线条粗细
+                LineStyle:'Solid',//线条线型
+            },
+            rightEdbData:{},
+            markTypesOpts,lineStylesOpts,
+            predefineColors: defaultOpts.colors.slice(0, 2),
+        };
+    },
+    methods: {
+        indicatorTypeChange(){
+            //清空指标信息
+            this.search_txt=''
+            this.searchOptions=[]
+            this.rightEdbData={}
+        },
+        /* 搜索 */
+        searchHandle(query) {
+            this.search_page = 1;
+            this.current_search = query;
+            this.searchApi(this.current_search)
+        },
+
+        async searchApi(query,page=1) {
+            let params = {
+                KeyWord:query,
+                CurrentIndex: page,
+            }
+            const res = this.rightEdbForm.IndicatorType === 2
+                ? await dataBaseInterface.targetSearchByPage(params)
+                : await preDictEdbInterface.edbSearch(params)
+
+                if(res.Ret !== 200) return
+                const { List,Paging } = res.Data;
+                this.search_have_more = page < Paging.Pages;
+                this.searchOptions = page === 1 ? List : this.searchOptions.concat(List);
+        },
+
+        /* 聚焦获取当前检索 */
+        inputFocusHandle(e) {
+            this.search_page = 1;
+            this.current_search = e.target.value;
+            this.searchApi(this.current_search);
+        },
+        searchLoad() {
+            if(!this.search_have_more) return;
+            this.searchApi(this.current_search,++this.search_page);
+        },
+        //选择指标,获取详情,保存基本信息
+        async selectTarget(item){
+            if(!item) return 
+            //检查添加指标是否已存在
+            let have_bol = this.tableData.every(i => i.EdbInfoId === item.EdbInfoId);
+            if(have_bol){
+                // this.$message.warning('录入指标已存在');
+                this.search_txt = ''
+                return this.$message.warning(this.$t('Chart.OptMsg.edb_haved_msg'));
+            }
+            //以曲线图的参数获取指标详情
+            let params = {
+                EdbInfoId: item.EdbInfoId,
+                ChartType: 1,
+                Calendar: undefined,
+                DateType: 3,
+                StartYear:0,
+                StartDate: '',
+                EndDate: '',
+            } 
+            const res = await dataBaseInterface.chartInfo(params)
+            if(res.Ret!==200) return 
+            const tableItem = res.Data.EdbInfoList[0]
+            this.rightEdbData = {
+                EdbInfoId: tableItem.EdbInfoId,
+                EdbInfoType:tableItem.EdbInfoType,
+                LeadValue:tableItem.LeadValue,
+                LeadUnit:tableItem.LeadUnit,
+                IsAxis:0,
+            }
+        },
+        confirmPerson(){
+            //校验
+            if(this.rightEdbForm.IndicatorType!==1&&!this.search_txt){
+                return this.$message.warning(/* '请选择指标!' */this.$t('Edb.InputHolderAll.input_select_edb'))
+            }
+            if(!this.rightEdbForm.Legend){
+                return this.$message.warning(/* '请输入图例名称' */this.$t('EtaChartAddPage.legend_placeholder'))
+            }
+            this.$emit('modify',{form:this.rightEdbForm,data:this.rightEdbData})
+        }
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.average-edit-dialog{
+    .type-select{
+        padding-bottom: 30px;
+        border-bottom: 1px solid #C8CDD9;
+    }
+    .form-box{
+        margin-top: 30px;
+    }
+}
+</style>

+ 1 - 3
src/views/dataEntry_manage/components/barOptionSection.vue

@@ -259,10 +259,8 @@ export default {
         this.dateList.push(date_item)
         
         let themeOpt = this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
-        // 看colorsOptions返不返回再说
-        console.log(themeOpt,'themeOpt');
         this.dateList.forEach((item,index) => {
-          item.Color = item.Color || (themeOpt &&themeOpt.lineOptionList[index].color || defaultOpts.colors[index]);
+          item.Color = item.Color || (themeOpt&&themeOpt.colorsOptions[index]||defaultOpts.colors[index]);
         })
       }
       this.cancelDialog()

+ 3 - 2
src/views/dataEntry_manage/components/chartReleationEdbTable.vue

@@ -67,7 +67,8 @@
         width="140"
     >
         <template slot-scope="scope" v-if="scope.row.HaveOperaAuth">
-            <span @click="delTarget(scope.row)" class="deletesty"><!-- 删除 -->{{$t('Table.delete_btn')}}&nbsp;</span>
+            <!-- 如果是季节性图的右轴,隐藏删除按钮 -->
+            <span @click="delTarget(scope.row)" class="deletesty" v-if="!(scope.$index===1&&chartInfo.ChartType===2)"><!-- 删除 -->{{$t('Table.delete_btn')}}&nbsp;</span>
             <span v-permission="permissionBtn.chartLibPermission.chartLib_copyData"
                 class="editsty" @click="copyCode(scope.row)">
                 <i class="el-icon-document-copy" />&nbsp;<!-- 复制数据 -->{{$t('Edb.detail_copydata_btn')}}</span
@@ -151,7 +152,7 @@ export default {
           key: 'SourceName',
         },
       ]
-    }
+    },
   },
   data() {
     return {

+ 245 - 3
src/views/dataEntry_manage/components/markersSection.vue

@@ -1,5 +1,27 @@
 <template>
   <div class="chart-markers-section">
+    <!-- 季节性图升级-添加右轴指标-->
+    <div class="section-item" v-if="chartInfo.ChartType===2">
+        <div class="average-item" v-if="rightEdbForm.IsAdd">
+            <span>{{$t('Chart.Detail.r_axis')}}</span>
+            <div style="flex-shrink:0">
+                <i class="el-icon-view icon" :style="rightEdbForm.IsShow?'color:#0052D9':'color:#999'" @click="rightEdbForm.IsShow=!rightEdbForm.IsShow;previewSeason('updateSeason')"/>
+                <i class="el-icon-edit icon" style="margin:0 6px" @click="isAddRightEdbDialogShow=true"/>
+                <i class="el-icon-delete icon" @click="deleteRightEdb"/>
+            </div>
+        </div>
+        <div v-else
+            class="add-cont"
+            @click="isAddRightEdbDialogShow=true"
+        >
+            <img
+                src="~@/assets/img/set_m/add_ico.png"
+                alt=""
+                style="width: 16px; height: 16px; margin-right: 10px"
+            />
+            <span>{{$t('EtaChartAddPage.add_right_edb_btn')}}</span>
+        </div>
+    </div>
     <!-- 雷达不要 -->
     <template v-if="chartInfo.ChartType!==11">
       <!-- 标示线 -->
@@ -55,6 +77,73 @@
 
       </div>
     </template>
+    <!-- 季节性图升级-同期上下限/均线/标准差-->
+    <template v-if="chartInfo.ChartType===2">
+        <div class="section-item">
+            <div class="average-item" v-if="averageArea.IsAdd">
+                <span>{{ $t('EtaChartAddPage.limits_btn') }}:{{ averageArea.Year||0 }}</span>
+                <div style="flex-shrink:0">
+                    <i class="el-icon-view icon" :style="averageArea.IsShow?'color:#0052D9':'color:#999'" @click="averageArea.IsShow=!averageArea.IsShow;previewSeason('updateSeason')"/>
+                    <i class="el-icon-edit icon" style="margin:0 6px" @click="openAverageDialog(averageArea,1,'edit')"/>
+                    <i class="el-icon-delete icon" @click="deleteAverage(1)"/>
+                </div>
+            </div>
+            <div v-else
+                class="add-cont"
+                @click="openAverageDialog(averageArea,1)"
+            >
+                <img
+                    src="~@/assets/img/set_m/add_ico.png"
+                    alt=""
+                    style="width: 16px; height: 16px; margin-right: 10px"
+                />
+                <span><!-- 添加同期上下限 -->{{$t('Table.add_btn')}}{{$i18n.locale!=='zh'?' ':''}}{{ $t('EtaChartAddPage.limits_btn') }}</span>
+            </div>
+        </div>
+        <div class="section-item">
+            <div class="average-item" v-if="averageLine.IsAdd">
+                <span>{{ $t('EtaChartAddPage.avg_line_btn') }}:{{averageLine.Year||0}}</span>
+                <div style="flex-shrink:0">
+                    <i class="el-icon-view icon" :style="averageLine.IsShow?'color:#0052D9':'color:#999'" @click="averageLine.IsShow=!averageLine.IsShow;previewSeason('updateSeason')"/>
+                    <i class="el-icon-edit icon" style="margin:0 6px" @click="openAverageDialog(averageLine,2,'edit')"/>
+                    <i class="el-icon-delete icon" @click="deleteAverage(2)"/>
+                </div>
+            </div>
+            <div v-else
+                class="add-cont"
+                @click="openAverageDialog(averageLine,2)"
+            >
+                <img
+                    src="~@/assets/img/set_m/add_ico.png"
+                    alt=""
+                    style="width: 16px; height: 16px; margin-right: 10px"
+                />
+                <span><!-- 添加同期均线 -->{{$t('Table.add_btn')}}{{$i18n.locale!=='zh'?' ':''}}{{ $t('EtaChartAddPage.avg_line_btn') }}</span>
+            </div>
+        </div>
+        <div class="section-item">
+            <div class="average-item" v-if="averageStd.IsAdd">
+                <span>{{ $t('EtaChartAddPage.std_btn') }}:{{averageStd.Year||0}}</span>
+                <div style="flex-shrink:0">
+                    <i class="el-icon-view icon" :style="averageStd.IsShow?'color:#0052D9':'color:#999'" @click="averageStd.IsShow=!averageStd.IsShow;previewSeason('updateSeason')"/>
+                    <i class="el-icon-edit icon" style="margin:0 6px" @click="openAverageDialog(averageStd,3,'edit')"/>
+                    <i class="el-icon-delete icon" @click="deleteAverage(3)"/>
+                </div>
+            </div>
+            <div v-else
+                class="add-cont"
+                @click="openAverageDialog(averageStd,3)"
+            >
+                <img
+                    src="~@/assets/img/set_m/add_ico.png"
+                    alt=""
+                    style="width: 16px; height: 16px; margin-right: 10px"
+                />
+                <span><!-- 添加同期标准差 -->{{$t('Table.add_btn')}}{{$i18n.locale!=='zh'?' ':''}}{{ $t('EtaChartAddPage.std_btn') }}</span>
+            </div>
+        </div>
+    </template>
+
 
     <!-- 图表说明 -->
     <div class="section-item">
@@ -93,6 +182,7 @@
         rightIndex: $parent.rightIndex,
         rightTwoIndex: $parent.rightTwoIndex
       }"
+      :tableData="tableData"
       @add="addMarkerItem"
       @edit="editMarkerItem"
     />
@@ -138,17 +228,62 @@
         <el-button @click="chartInductionDiaForm.show=false"><!-- 取消 -->{{$t('Dialog.cancel_btn')}}</el-button>
       </div>
     </m-dialog>
-
+    <!-- 同期上下限/均线/标准差弹窗 -->
+    <addAverageDialog 
+        :isShow="isAddAverageDialogShow"
+        :averageType="averageType"
+        :formData="averageForm"
+        @close="isAddAverageDialogShow=false"
+        @modify="addAverage"
+    />
+    <!-- 右轴指标弹窗 -->
+    <addRightEdbDialog 
+        :isShow="isAddRightEdbDialogShow"
+        :tableData="tableData"
+        :formData="rightEdbForm"
+        :edbData="rightEdbInfo"
+        @close="isAddRightEdbDialogShow=false"
+        @modify="addRightEdb"
+    />
   </div>  
 </template>
 <script>
 import addMarkerDialog from './addMarkerDialog.vue'
 import mDialog from '@/components/mDialog.vue'
+import addAverageDialog from './addAverageDialog.vue'
+import addRightEdbDialog from './addRightEdbDialog.vue'
+
+const baseAverageForm = {
+    Legend:'',//图例名称
+    Year:5,//上下限取数范围/均线取数范围/取数范围
+    Color:'#075EEE',//颜色及透明度
+    LineType:'Solid',//线型
+    LineWidth:1,//线宽
+    Multiple:1,//倍数
+}
+const baseRightForm = {
+    IndicatorType:1,//1左轴同比 2指标库 3预测指标
+    Style:'column',//生成样式 column/mark
+    Shape:'circle',//标记点形状
+    ChartColor:'#075EEE',//颜色
+    Size:3,//标记点大小
+    Legend:'',//图例名称
+    NumFormat:1,//数值格式 1百分比 2小数
+    IsConnected:0,//连线 0无 1有
+    LineColor:'rgba(102, 102, 102, 1)',//线条颜色
+    LineWidth:1,//线条粗细
+    LineStyle:'Solid',//线条线型
+    IsShow:false,
+    IsAdd:false
+}
 export default {
-  components: { addMarkerDialog,mDialog },
+  components: { addMarkerDialog,mDialog, addAverageDialog, addRightEdbDialog },
   props: {
     chartInfo: {
       type: Object
+    },
+    tableData:{
+        type:Array
     }
   },
   data() {
@@ -173,7 +308,26 @@ export default {
       chartInductionDiaForm: {
         show: false,
         text: '',
-      }
+      },
+
+      /* 同期上下限/均线/标准差弹窗 */
+      isAddAverageDialogShow:false,
+      averageType:1,//1同期上下限 2同期均线 3同期标准差
+      averageForm:{},//初始化和回显用
+      averageMap:{
+        0:'',
+        1:{name:'averageArea'},//同期上下限
+        2:{name:'averageLine'},//同期均线
+        3:{name:'averageStd'},//同期标准差
+      },
+      averageArea:{IsAdd:false,IsShow:false},
+      averageLine:{IsAdd:false,IsShow:false},
+      averageStd:{IsAdd:false,IsShow:false},
+
+      /* 右轴指标弹窗 */
+      isAddRightEdbDialogShow:false,
+      rightEdbForm:{},//初始化和回显用
+      rightEdbInfo:{},//右轴不为同比时,有值
     }
   },
   methods:{
@@ -259,6 +413,85 @@ export default {
         color: this.chartInfo.ChartThemeStyle?JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.color:'#333',
         fontSize: this.chartInfo.ChartThemeStyle?JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.fontSize:12
       };
+    },
+    //打开同期弹窗
+    openAverageDialog(data,type,openType='add'){
+        if(openType==='add'){
+            this.averageForm = {
+                ...baseAverageForm,
+                IsAdd:false,
+                IsShow:false
+            }
+            //要默认颜色不一样
+            if(type===1){
+                this.averageForm.Color = 'rgba(153, 153, 153, 0.5)'
+            }
+            if(type===2){
+                this.averageForm.Color = '#ccc'
+                this.averageForm.LineType = 'ShortDash'
+            }
+        }else{
+            this.averageForm = data
+        }
+        this.averageType = type
+        this.isAddAverageDialogShow = true
+    },
+    //添加同期设置
+    addAverage({data,type}){
+        Object.assign(this[this.averageMap[type].name],data)
+        this[this.averageMap[type].name].IsAdd = true
+        this[this.averageMap[type].name].IsShow = true
+        this.isAddAverageDialogShow=false
+        this.previewSeason('previewSeason')
+    },
+    //取消添加同期设置
+    deleteAverage(type){
+        this[this.averageMap[type].name].IsAdd = false
+        this.previewSeason('previewSeason')
+    },
+    //添加右轴指标
+    addRightEdb({form,data}){
+        const tableData = {
+            ...data,
+            IsAxis:0,
+            Unit:form.NumFormat===1?'%':'',
+            UnitEn:''
+
+        }
+        this.rightEdbInfo = tableData
+        Object.assign(this.rightEdbForm,form)
+        this.rightEdbForm.IsAdd = true
+        this.rightEdbForm.IsShow = true
+        this.isAddRightEdbDialogShow = false
+        this.$emit('previewSeasonRight',{rightConfig:this.rightEdbForm,tableData})
+    },
+    //取消添加右轴指标
+    deleteRightEdb(){
+        this.rightEdbForm.IsAdd = false
+        this.rightEdbForm.IsShow = false
+        this.$emit('previewSeasonRight',{rightConfig:this.rightEdbForm,tableData:this.rightEdbInfo})
+        this.rightEdbForm = {}
+        Object.assign(this.rightEdbForm,baseRightForm)
+    },
+    //更新季节性图 同期/右轴
+    //预览图表
+    previewSeason(eventName='previewSeason'){
+        this.$emit(eventName,{
+            SeasonAverageConfig:{
+                MaxMinLimits:this.averageArea,
+                SamePeriodAverage:this.averageLine,
+                SamePeriodStandardDeviation:this.averageStd
+            },
+            SeasonRightEdbConfig:this.rightEdbForm
+        })
+    },
+    //季节性图配置数据回显
+    initSeasonData(data){
+        Object.assign(this.averageArea,data.MaxMinLimits)
+        Object.assign(this.averageLine,data.SamePeriodAverage)
+        Object.assign(this.averageStd,data.SamePeriodStandardDeviation)
+        Object.assign(this.rightEdbForm,data.RightAxis)
+        this.rightEdbInfo = data.RightInfo
     }
   },
 }
@@ -278,6 +511,15 @@ export default {
         padding: 12px 15px;
       }
     }
+    .average-item{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 12px 15px;
+        border: 1px solid #DCDFE6;
+        background: #F0F2F5;
+        margin-bottom: 15px;
+    }
     .icon {font-size: 18px;cursor: pointer;}
     .el-icon-delete{
       color: #f00;

+ 15 - 2
src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue

@@ -54,6 +54,10 @@
 							<el-option :label="item.label" :value="item.value" 
 							v-for="item in THSIndexCodeTypeArr" :key="item.value"></el-option>
 						</el-select>
+						<span class="selectable-option-row" v-if="fromType=='同花顺'">
+							<span>{{ $t('EtaBasePage.option_selectable') }}</span>
+							<el-input v-model="ExtraPars" style="width: 130px;margin-left: 10px;" />
+						</span>
 						<el-checkbox-group v-model="indexCodeSelected">
 							<el-checkbox :label="item.value" v-for="item in indexCodeArr" :key="item.value">{{ item.label }}</el-checkbox>
 						</el-checkbox-group>
@@ -284,6 +288,7 @@ export default {
 			search_company_txt: '',
 			securityCodeText:"",
 			indexCodeText:'',
+			ExtraPars:'',
 			indexCode:[],
 			edbIndexDatas:[],
 			edbTableHeadKey: [
@@ -341,6 +346,7 @@ export default {
 			this.search_company_txt = '';
 			this.wsdAddStep=1
 			this.securityCodeText=""
+			this.ExtraPars=''
 			this.indexCodeText=''
 			this.indexCode=[]
 			this.indexCodeSelected=[]
@@ -460,6 +466,7 @@ export default {
 			if(this.fromDatabase=='1'){
 				this.fromDatabase='0'
 				this.securityCodeText=""
+				this.ExtraPars=''
 				this.indexCodeText=''
 				this.indexCode=[]
 				this.indexCodeSelected=[]
@@ -550,7 +557,8 @@ export default {
 						Source:Number(this.fromCode.get(this.fromType)),
 						SubSource:this.fromDatabase,
 						EdbCode:Array.from(new Set([...this.indexCode,...this.indexCodeSelected])).join(','),
-						StockCode:this.securityCodeText
+						StockCode:this.securityCodeText,
+						ExtraPars:this.ExtraPars
 					}
 					dataBaseInterface.edbExistCheck(params).then(res=>{
 						if(res.Ret == 200){
@@ -584,7 +592,8 @@ export default {
 												Frequency:'日度',
 												EdbName:isCommon?`${item.StockCode}${isCommon.label}`:`${item.StockCode}${item.EdbCode}`,
 												EdbCode:item.EdbCode,
-												StockCode:item.StockCode
+												StockCode:item.StockCode,
+												ApiExtraPars:this.ExtraPars
 											}
 											this.BatchList.push(params)
 											let datas = item.DataList || []
@@ -746,6 +755,10 @@ export default {
 			width:400px;
 			margin-right: 10px;
 		}
+		.selectable-option-row{
+			display: inline-flex;
+			align-items: center;
+		}
 	}
 	.warn_txt {
 		font-size: 16px;

+ 1 - 1
src/views/dataEntry_manage/databaseComponents/batchComputedV2.vue

@@ -52,7 +52,7 @@
                     <el-form-item :label="$t('EtaBasePage.label_calendar')"  style="width:180px">
                         <el-select v-model="formData.calendarType" style="width:120px">
                             <el-option :label="$t('Chart.calendar_gre')" value="公历"></el-option>
-                            <el-option :label="$t('Chart.calendar_lunar')" value="农历"></el-option>
+                            <el-option :label="$t('Chart.calendar_lunar_text')" value="农历"></el-option>
                         </el-select>
                     </el-form-item>
                     </template>

+ 24 - 7
src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue

@@ -110,10 +110,11 @@
 							@change="getDataByPath"
 					>
 							<el-radio-button label="公历">{{$t('Chart.calendar_gre')}}</el-radio-button>
-							<el-radio-button label="农历">{{$t('Chart.calendar_lunar')}}</el-radio-button>
+							<el-radio-button label="农历">{{$t('Chart.calendar_lunar_text')}}</el-radio-button>
 					</el-radio-group>
 				</div>
 			</div>
+			<img src="~@/assets/img/icons/edb-stopping.png" class="stop-mark" v-if="([2,34].includes(chartInfo.Source) || chartInfo.EdbType==2) && chartInfo.NoUpdate==1" />
 		</div>
 		<div class="table-data">
 
@@ -279,6 +280,10 @@ export default {
 						}
 					})
 		},
+		// 切换刷新状态
+		toggleEdbRefreshStatusFun(){
+			this.chartInfo.NoUpdate = 1-this.chartInfo.NoUpdate
+		},
 		//保存指标缩略图
 		async saveEdbImg(EdbInfo){
 			let svg = this.$refs.chartRef.chart.getSVG({
@@ -289,13 +294,16 @@ export default {
 			});
 			let form = new FormData();
 			form.append("Img", svg);
-			let { Data,Ret } = await dataBaseInterface.uploadImgSvg(form);
+			form.append('EdbInfoId',EdbInfo.EdbInfoId)
+      await dataBaseInterface.saveEdbChartThumbnail(form)
+			
+			// let { Data,Ret } = await dataBaseInterface.uploadImgSvg(form);
 
-			if(Ret!==200 || !Data) return 
-			await dataBaseInterface.saveEdbChartImg({
-				EdbInfoId: EdbInfo.EdbInfoId,
-				ImageUrl: Data.ResourceUrl,
-			});
+			// if(Ret!==200 || !Data) return 
+			// await dataBaseInterface.saveEdbChartImg({
+			// 	EdbInfoId: EdbInfo.EdbInfoId,
+			// 	ImageUrl: Data.ResourceUrl,
+			// });
 		},
 
 		/* 获取装置指标数据 */
@@ -844,6 +852,7 @@ export default {
 		}
 	}
 	.min-wrapper {
+		position: relative;
 		.el-input__inner {
 			padding: 0 0 0 5px;
 		}
@@ -867,6 +876,14 @@ export default {
 				}
 			}
 		}
+		.stop-mark{
+			height: 48px;
+			width: 48px;
+			position: absolute;
+			right: 0;
+			top: 0;
+			pointer-events: none;
+		}
 	}
 }
 </style>

+ 1 - 1
src/views/dataEntry_manage/databaseComponents/operationDialog.vue

@@ -476,7 +476,7 @@ export default {
 		calendarOptions(){
 			return [
 				{label: this.$t('Chart.calendar_gre'),key: 1},
-				{label: this.$t('Chart.calendar_lunar'),key: 2},
+				{label: this.$t('Chart.calendar_lunar_text'),key: 2},
 			]
 		}
 	},

+ 55 - 1
src/views/dataEntry_manage/databaseList.vue

@@ -239,7 +239,12 @@
 							</div>
 							<div class="info">
 								{{$t('EtaBasePage.time_show')}}:{{item.CreateTime.substring(0,10)}}
+								<!-- wind和钢联化工的指标、计算指标显示 启用/停用-->
+								<span v-if="([2,34].includes(item.Source) || item.EdbType==2) && isEdbBtnShow('enableOrDisable')" 
+								class="enable-toggle-btn" :style="{'color': item.NoUpdate==1?'#0052D9':'#D54941'}"
+								@click="toggleEdbRefreshStatus(item)">{{item.NoUpdate==1?$t('SystemManage.DataRefresh.enable'):$t('SystemManage.DataRefresh.disable') }}</span>
 							</div>
+							<img src="~@/assets/img/icons/edb-stopping.png" class="stop-mark" v-if="([2,34].includes(item.Source) || item.EdbType==2) && item.NoUpdate==1" />
 						</div>
 					</div>
 					
@@ -259,6 +264,10 @@
 							</el-tab-pane>
 						</el-tabs>
 						<div class="edb-tool-icon edb-tool" style="align-items: center;">
+							<el-button v-if="([2,34].includes(EdbData.Source) || EdbData.EdbType==2) && isEdbBtnShow('enableOrDisable')" 
+								type="text" :style="{'color': EdbData.NoUpdate==1?'#0052D9':'#D54941'}"
+								@click="toggleEdbRefreshStatus(EdbData,'detail')" 
+							>{{EdbData.NoUpdate==1?$t('SystemManage.DataRefresh.enable'):$t('SystemManage.DataRefresh.disable') }}<!-- 启用/停用 --></el-button>
 							<el-button 
 								v-if="isEdbBtnShow('update')"
 								type="text" 
@@ -960,6 +969,7 @@ export default {
 				'checkRelatedChart':edbDataPermission.edbData_checkRelatedChart,//查看关联图表
 				'checkRelatedEdb':edbDataPermission.edbData_checkRelatedEdb,//查看关联指标
 				'checkCalcChart':edbDataPermission.edbData_checkCalcChart,//查看计算指标
+				'enableOrDisable':edbDataPermission.edbData_enableOrDisable,//启用/停用
 			}
 			return checkPermissionBtn(BtnMap[type])
 		},
@@ -1089,6 +1099,29 @@ export default {
 
 			})
 		},
+		// 切换刷新状态
+		async toggleEdbRefreshStatus(item,type='list'){
+			let flag = true
+			if(item.NoUpdate==0){
+				flag=false
+				await this.$confirm(this.$t('SystemManage.DataRefresh.disable_indicator_prompt'),this.$t('Confirm.prompt'),{
+					type:"warning"
+				}).then(res=>{
+					flag=true
+				}).catch(()=>{})
+			}
+			if(!flag) return
+			let ModifyStatus = item.NoUpdate==1?'启用':'暂停'
+			dataBaseInterface.edbRefreshStatusSet({EdbInfoId:item.EdbInfoId,ModifyStatus}).then(res=>{
+				if(res.Ret == 200){
+					item.NoUpdate=1-item.NoUpdate
+					if(type=='detail'){
+						this.$refs.createChart.toggleEdbRefreshStatusFun()
+					}
+					this.$message.success(this.$t('MsgPrompt.operate_success_msg'))
+				}
+			})
+		},
 		//指标图表列表-加载更多
 		loadMoreHandle: _.throttle(function() {
 			let scrollTop = this.$refs.listRef.scrollTop;
@@ -2495,11 +2528,24 @@ export default {
 						border-radius: 4px;
 						border:1px solid #DCDFE6;
 						box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-						.header,.info{
+						position: relative;
+						.header{
 							padding:10px;
 							box-sizing: border-box;
 							text-align: left;
 						}
+						.info{
+							padding:10px;
+							box-sizing: border-box;
+							display: flex;
+							align-items: center;
+							justify-content: space-between;
+							.enable-toggle-btn{
+								cursor: pointer;
+								color: #0052D9;
+								font-size: 14px;
+							}
+						}
 						.header{
 							white-space: nowrap;
 							overflow: hidden;
@@ -2515,6 +2561,14 @@ export default {
 							padding-bottom: 67%;
 							cursor: pointer;
 						}
+						.stop-mark{
+							height: 48px;
+							width: 48px;
+							position: absolute;
+							right: -1px;
+							top: 0;
+							pointer-events: none;
+						}
 					}
 				}
 			}

+ 48 - 5
src/views/dataEntry_manage/editChart.vue

@@ -212,7 +212,8 @@
             <el-collapse-item v-for="(item,index) in tableData" :key="item.EdbInfoId" :disabled="[2,5].includes(chartInfo.ChartType)">
               <template slot="title">
                 <span class="text_oneLine">{{currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName}}</span>
-								<i class="el-icon-delete del-icon" @click.stop="delTarget(item)"></i>
+								<!-- 当为季节性图的第二个轴时,隐藏删除按钮 -->
+								<i class="el-icon-delete del-icon" @click.stop="delTarget(item)" v-if="!(chartInfo.ChartType===2&&index===1)"></i>
               </template>
               <ul class="setting-cont">
 								<!-- 堆叠图 或组合图中的堆叠类型 非第一项隐藏配置 -->
@@ -364,7 +365,11 @@
 						ref="markerSectionRef"
 						:chartType="chartInfo.ChartType"
 						:chartInfo="chartInfo"
+						:tableData="tableData"
 						@update="setChartMarkerInfo"
+						@updateSeason="updateSeasonChart"
+						@previewSeason="previewSeasonChart"
+						@previewSeasonRight="previewSeasonRight"
 					/>
         </div>
 			</div>
@@ -606,7 +611,7 @@
 								@change="getPreviewSplineInfo"
 							>
 								<el-radio-button label="公历">{{$t('Chart.calendar_gre')}}</el-radio-button>
-								<el-radio-button label="农历">{{$t('Chart.calendar_lunar')}}</el-radio-button>
+								<el-radio-button label="农历">{{$t('Chart.calendar_lunar_text')}}</el-radio-button>
 							</el-radio-group>
 
 							<!-- 图表说明 -->
@@ -788,12 +793,31 @@ export default {
 						Unit: ChartInfo.ChartType===7 
 							? (this.currentLang==='en'?BarChartInfo.UnitEn:BarChartInfo.Unit) 
 							: (this.currentLang==='en'?ChartInfo.UnitEn:ChartInfo.Unit),
-						SourcesFromVisable: ChartInfo.SourcesFrom ? JSON.parse(ChartInfo.SourcesFrom).isShow : true
+						SourcesFromVisable: ChartInfo.SourcesFrom ? JSON.parse(ChartInfo.SourcesFrom).isShow : true,
 					};
+					
 					//处理下历史默认来源
 					this.setDefaultSourceFrom();
 
+					//初始化标识线/区/图表说明
 					this.$refs.markerSectionRef.initData(ChartInfo);
+					//季节性图处理SeasonAverageConfig,SeasonRightEdbConfig
+					if(this.chartInfo.ChartType===2){
+						const {MaxMinLimits,SamePeriodAverage,SamePeriodStandardDeviation,RightAxis} = res.Data.DataResp
+						this.chartInfo.SeasonAverageConfig = {MaxMinLimits,SamePeriodAverage,SamePeriodStandardDeviation}
+						this.chartInfo.SeasonRightConfig = RightAxis
+						const tempData = _.cloneDeep(this.chartInfo.SeasonAverageConfig)
+						tempData.RightAxis = _.cloneDeep(RightAxis)
+						tempData.RightInfo = _.cloneDeep((RightAxis.EdbInfoList&&RightAxis.EdbInfoList[0])||{})
+						if(tempData.RightAxis.IndicatorType!==1){
+							tempData.RightInfo = EdbInfoList[1]||{}
+						}
+						delete tempData.MaxMinLimits.List
+						delete tempData.SamePeriodAverage.List
+						delete tempData.SamePeriodStandardDeviation.List
+						delete tempData.RightAxis.EdbInfoList
+						this.$refs.markerSectionRef.initSeasonData(tempData)
+					}
 
 					this.tableData = EdbInfoList;
 					this.updateData = this.tableData.map(item=>{
@@ -892,8 +916,8 @@ export default {
 			this.$refs.diaForm.validate((valid) => {
 				if(valid) {
 					// 季节图只允许添加一个指标
-					if(this.chartInfo.ChartType === 2 && this.tableData.length > 1)  
-						return this.$message.warning(/* '您选择的图表样式为季节性图表,只支持单指标画图' */this.$t('Chart.OptMsg.season_one_msg'));
+					if(this.chartInfo.ChartType === 2 && this.tableData.length > 1) {} 
+						//return this.$message.warning(/* '您选择的图表样式为季节性图表,只支持单指标画图' */this.$t('Chart.OptMsg.season_one_msg'));
 
 					if(this.chartInfo.ChartType === 7 && !this.$refs.BarOptRef.dateList.length)  
 						return this.$message.warning(/*'请添加日期'*/this.$t('ToolBox.CommodityPriceChart.tips_msg06'));
@@ -1011,6 +1035,25 @@ export default {
 							MinMaxSave:Number(hasLimitChange)
 						}
 					}
+					//如果是季节性图,在这里加上同期/右轴的参数
+					if(this.chartInfo.ChartType===2){
+						//const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = this.chartInfo.SeasonAverageConfig||{}
+						const {SeasonRightConfig={}} = this.chartInfo
+						const tempData = _.cloneDeep(this.chartInfo.SeasonAverageConfig||{})
+						const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = tempData||{}
+						delete MaxMinLimits.List
+						delete SamePeriodAverage.List
+						delete SamePeriodStandardDeviation.List
+						const tempConfig = _.cloneDeep(SeasonRightConfig)
+						delete tempConfig.EdbInfoList
+						params.SeasonExtraConfig = {
+							...this.SeasonExtraConfig,
+							MaxMinLimits:MaxMinLimits.IsAdd?MaxMinLimits:{},
+							SamePeriodAverage:SamePeriodAverage.IsAdd?SamePeriodAverage:{},
+							SamePeriodStandardDeviation:SamePeriodStandardDeviation.IsAdd?SamePeriodStandardDeviation:{},
+							RightAxis:SeasonRightConfig.IsAdd?tempConfig:{}//右轴的具体配置
+						}
+					}
 					dataBaseInterface.chartEdit(params).then(res => {
 						if(res.Ret !== 200) return;
 						

+ 180 - 20
src/views/dataEntry_manage/mixins/addOreditMixin.js

@@ -220,7 +220,8 @@ export default {
 				EndDate: this.year_select === 5 ? dateArray[1] : '',
 				IsConvert:Number(IsConvert),
 				ConvertType,ConvertValue:Number(ConvertValue),
-				ConvertUnit,ConvertEnUnit
+				ConvertUnit,ConvertEnUnit,
+				IsAxis:this.tableData[index].IsAxis
 			}).then(res=>{
 				if(res.Ret!==200) return 
 				const {EdbInfoList=[]} = res.Data||{}
@@ -361,6 +362,7 @@ export default {
 
 		},
 
+
 		/* 添加柱形图 /雷达图指标数组 */
 		setBarEdbList(edb) {
 			let have_bol = this.tableData.some(item => item.EdbInfoId === edb.EdbInfoId);
@@ -403,7 +405,8 @@ export default {
 				Sort: {
 					Sort: sort.sort,
 					DateIndex: Number(sort.sortIndex)
-				}
+				},
+				MarkersLines:this.chartInfo.MarkersLines
 			}
 
 			dataBaseInterface.getBarData(params).then(res => {
@@ -433,6 +436,9 @@ export default {
 				
 				//默认来源搞一下
 				this.setDefaultSourceFrom();
+				//标识线回显
+				this.chartInfo.MarkersLines = res.Data.ChartInfo.MarkersLines||''
+				this.$refs.markerSectionRef&&this.$refs.markerSectionRef.initData(res.Data.ChartInfo||{});
 			})
 		},
 
@@ -506,10 +512,25 @@ export default {
 						ConvertType,
 						ConvertValue:Number(ConvertValue),
 						ConvertUnit:IsConvert?ConvertUnit:'',
-						ConvertEnUnit:IsConvert?ConvertEnUnit:''
+						ConvertEnUnit:IsConvert?ConvertEnUnit:'',
+						IsAxis:_.IsAxis
 					}
-				})
-		}
+				}),
+				MarkersLines:this.chartInfo.MarkersLines||''
+			}
+			//季节性图 更改SeasonExtraConfig
+			//如果是季节性图,存储额外参数(同期/右轴)
+			if(this.chartInfo.ChartType===2){
+				const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = this.chartInfo.SeasonAverageConfig||{}
+				const {SeasonRightConfig={}} = this.chartInfo
+				params.SeasonExtraConfig = {
+					...this.SeasonExtraConfig,
+					MaxMinLimits:MaxMinLimits.IsAdd?MaxMinLimits:{},
+					SamePeriodAverage:SamePeriodAverage.IsAdd?SamePeriodAverage:{},
+					SamePeriodStandardDeviation:SamePeriodStandardDeviation.IsAdd?SamePeriodStandardDeviation:{},
+					RightAxis:SeasonRightConfig.IsAdd?SeasonRightConfig:{}
+				}
+			}
 
       const res = await dataBaseInterface.getSplinePreviewData(params)
 
@@ -531,13 +552,18 @@ export default {
 
       this.tableData.forEach((item) => {
         let edbData = EdbInfoList.find(_ => _.EdbInfoId===item.EdbInfoId);
-        item.DataList = edbData.DataList;
-				//更新起始时间和最近更新时间
-        item.StartDate = edbData.StartDate;
-        item.ModifyTime = edbData.ModifyTime;
-				
-        if(edbData.EdbInfoCategoryType===1) item.MoveLatestDate = edbData.MoveLatestDate;
+		if(edbData){
+			item.DataList = edbData.DataList;
+			//更新起始时间和最近更新时间
+			item.StartDate = edbData.StartDate;
+			item.ModifyTime = edbData.ModifyTime;
+			if(edbData.EdbInfoCategoryType===1) item.MoveLatestDate = edbData.MoveLatestDate;
+		}
+        
       });
+			//标识线回显
+			this.chartInfo.MarkersLines = res.Data.ChartInfo.MarkersLines||''
+			this.$refs.markerSectionRef&&this.$refs.markerSectionRef.initData(res.Data.ChartInfo||{});
 		},
 
 		/* 年份改变 重新刷新图表接口  保存当前的图表配置和上下限 只改变图表 */
@@ -632,14 +658,18 @@ export default {
 		setAddChartDefault() {
 
 			let themeOpt = this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
-			console.log(themeOpt,'themeOpt');
 			this.tableData.forEach((item,index) => {
-				item.ChartColor = item.ChartColor || (themeOpt&&themeOpt.colorsOptions[index]||defaultOpts.colors[index]);
-				item.PredictChartColor = item.PredictChartColor || (themeOpt&&themeOpt.colorsOptions[index]||defaultOpts.colors[index]);
-				item.ChartStyle = item.ChartStyle || (themeOpt&&themeOpt.lineOptionList[index].lineType||'spline');
+				//图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const colorIndex = themeOpt ? index%themeOpt.colorsOptions.length : index
+				const defaultOptIndex = index%defaultOpts.colors.length
+				const lineIndex = themeOpt ? index%themeOpt.lineOptionList.length : index
+
+				item.ChartColor = item.ChartColor || (themeOpt&&themeOpt.colorsOptions[colorIndex]||defaultOpts.colors[defaultOptIndex]);
+				item.PredictChartColor = item.PredictChartColor || (themeOpt&&themeOpt.colorsOptions[colorIndex]||defaultOpts.colors[defaultOptIndex]);
+				item.ChartStyle = item.ChartStyle || (themeOpt &&themeOpt.lineOptionList[lineIndex].lineType||'spline');
 				
 				let configLineWid = index===0?3:1;//兼容预测指标绘图无主题配置
-				this.tableData[index].ChartWidth = this.tableData[index].ChartWidth || (themeOpt&&themeOpt.lineOptionList[index].lineWidth||configLineWid);
+				this.tableData[index].ChartWidth = this.tableData[index].ChartWidth || (themeOpt&&themeOpt.lineOptionList[lineIndex].lineWidth||configLineWid);
 			})
 		},
 
@@ -969,12 +999,16 @@ export default {
 
 			let themeOpt = JSON.parse(this.chartInfo.ChartThemeStyle);
 			this.tableData.forEach((item,index) => {
-				item.ChartColor = themeOpt.colorsOptions[index];
-				item.PredictChartColor = themeOpt.colorsOptions[index];
-				item.ChartStyle = themeOpt.lineOptionList[index].lineType||'spline';
+				//图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const colorIndex = themeOpt ? index%themeOpt.colorsOptions.length : index
+				const lineIndex = themeOpt ? index%themeOpt.lineOptionList.length : index
+
+				item.ChartColor = themeOpt && themeOpt.colorsOptions[colorIndex];
+				item.PredictChartColor = themeOpt && themeOpt.colorsOptions[colorIndex];
+				item.ChartStyle = themeOpt && themeOpt.lineOptionList[lineIndex].lineType||'spline';
 				item.isAxis = item.isAxis||1;
 
-				this.tableData[index].ChartWidth = themeOpt.lineOptionList[index].lineWidth;
+				this.tableData[index].ChartWidth = themeOpt && themeOpt.lineOptionList[lineIndex].lineWidth;
 			})
 
 		},
@@ -1060,11 +1094,22 @@ export default {
 			this.chartInfo.MarkersAreas = JSON.stringify(markerAreasArr);
 			this.chartInfo.Instructions = JSON.stringify(chartInstruction);
 
+			//markersLines含有指标计算的部分,调preview
+			if(markerLinesArr.find(i=>i.markLineType===2)){
+				//柱形图单独设置
+				if(this.chartInfo.ChartType===7){
+					this.barDateList.length && this.$refs.BarOptRef.getBarData();
+				}else{
+					this.getPreviewSplineInfo()
+				}
+			}
+
 			this.reLoadChartOption();
 		},
 		
 		//更新标识线,区 重绘图 不用重新获取数据 
 		reLoadChartOption() {
+			console.log('reloadChartOption')
 			if(!this.options.series) return
 			
 			const chartTypeMap = {
@@ -1076,6 +1121,121 @@ export default {
 				? chartTypeMap[this.chartInfo.ChartType]() 
 				: this.setChartOptionHandle(this.tableData);
 		},
+		//更新季节性图额外配置显示隐藏(不重新获取数据)
+		updateSeasonChart({SeasonAverageConfig,SeasonRightEdbConfig}){
+			if(this.chartInfo.SeasonAverageConfig){
+				const {MaxMinLimits,SamePeriodAverage,SamePeriodStandardDeviation} = SeasonAverageConfig
+				this.chartInfo.SeasonAverageConfig.MaxMinLimits.IsShow = MaxMinLimits.IsShow||false
+				this.chartInfo.SeasonAverageConfig.SamePeriodAverage.IsShow = SamePeriodAverage.IsShow||false
+				this.chartInfo.SeasonAverageConfig.SamePeriodStandardDeviation.IsShow = SamePeriodStandardDeviation.IsShow||false
+			}
+			if(this.chartInfo.SeasonRightConfig){
+				this.chartInfo.SeasonRightConfig.IsShow = SeasonRightEdbConfig.IsShow||false
+			}
+			this.reLoadChartOption()
+		},
+		//预览季节性图(请求接口)
+		previewSeasonChart({SeasonAverageConfig={},SeasonRightEdbConfig={IndicatorType:1}}){
+			this.chartInfo.SeasonAverageConfig = SeasonAverageConfig
+			let db_arr = this.tableData.map((_,index) => {
+				const {IsConvert,ConvertType,ConvertValue,ConvertUnit,ConvertEnUnit} = this.updateData[index]
+					return {
+						EdbInfoId: _.EdbInfoId,
+						EdbInfoType: _.EdbInfoType,
+						LeadValue: _.EdbInfoType ? 0 : Number(_.LeadValue),
+						LeadUnit: _.EdbInfoType ? '' : _.LeadUnit,
+						IsConvert:Number(IsConvert),
+						ConvertType,
+						ConvertValue:Number(ConvertValue),
+						ConvertUnit:IsConvert?ConvertUnit:'',
+						ConvertEnUnit:IsConvert?ConvertEnUnit:'',
+						IsAxis:_.IsAxis
+					}
+			})
+			const params = {
+				ChartType:this.chartInfo.ChartType,
+				DateType:this.year_select,
+				StartDate:[5 , 6].includes(this.year_select)? dateArray[0]: '',
+				EndDate:this.year_select === 5 ? dateArray[1]: '',
+				Calendar: this.calendar_type,
+				StartYear:this.count_year || 0,
+				ChartEdbInfoList:SeasonRightEdbConfig.IndicatorType===1?[db_arr[0]]:db_arr,//如果右轴为左轴同比,则只取第一个
+			}
+			const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = SeasonAverageConfig
+			const SeasonExtraConfig = {
+				...this.SeasonExtraConfig,
+				MaxMinLimits:MaxMinLimits.IsAdd?SeasonAverageConfig.MaxMinLimits:{},
+				SamePeriodAverage:SamePeriodAverage.IsAdd?SamePeriodAverage:{},
+				SamePeriodStandardDeviation:SamePeriodStandardDeviation.IsAdd?SamePeriodStandardDeviation:{},
+				RightAxis:SeasonRightEdbConfig.IsAdd?SeasonRightEdbConfig:{}//右轴的具体配置
+			}
+			params.SeasonExtraConfig = SeasonExtraConfig
+			dataBaseInterface.getSplinePreviewData(params).then(res=>{
+				if(res.Ret!==200) return 
+				const {DataResp} = res.Data
+				const {MaxMinLimits,SamePeriodAverage,SamePeriodStandardDeviation,
+						RightAxis={
+							IndicatorType:1,
+							EdbInfoList:[]
+						}} = DataResp
+				//包含同期的具体数据,用于绘图展示和传参
+				this.chartInfo.SeasonAverageConfig = {
+					MaxMinLimits,SamePeriodAverage,SamePeriodStandardDeviation
+				}
+				//更新SearonRightConfig
+				this.chartInfo.SeasonRightConfig = RightAxis
+				//更新chartLimit.rightMin/rightMax
+				const {EdbInfoList=[]} = res.Data
+				let MinData=0,MaxData
+				if(RightAxis.IndicatorType===1){
+					MinData = RightAxis.EdbInfoList[0].MinData||0
+					MaxData = RightAxis.EdbInfoList[0].MaxData||0
+				}else{
+					MinData = EdbInfoList[1]&&EdbInfoList[1].MinData||0
+					MaxData = EdbInfoList[1]&&EdbInfoList[1].MaxData||0
+				}
+				this.chartLimit.rightMin = MinData
+				this.chartLimit.rightMax = MaxData
+				//如果右轴有设置更新tableData&updateData
+				if(RightAxis.IsAdd){
+					this.tableData = EdbInfoList
+					this.updateData = this.tableData.map(item=>{
+						return this.formatUpdateData(item)
+					})
+					//弹窗回显
+					this.$refs.markerSectionRef.rightEdbInfo =RightAxis.IndicatorType!==1? _.cloneDeep(EdbInfoList[1]):{}
+				}else{
+					//右轴为指标时有修改tableData的行为 会重绘图表 而右轴为同比时不会 这里手动重绘一次
+					this.reLoadChartOption()
+				}
+				
+			})
+
+		},
+		//预览季节性图右轴
+		previewSeasonRight({rightConfig,tableData}){
+			this.chartInfo.SeasonRightConfig = rightConfig
+			if(rightConfig.IsAdd){
+				//若为指标/预测指标
+				if(rightConfig.IndicatorType!==1){
+					const tempItem = this.formatUpdateData(tableData)
+					if(rightConfig.IndicatorType!==1){
+						if(this.tableData.length>1){
+							this.tableData[1] = tableData
+						}else{
+							this.tableData.push(tableData)
+							this.updateData.push(tempItem)
+						}
+					}
+				}
+				//若为左轴同比,啥也不做
+			}else{
+				if(rightConfig.IndicatorType!==1){
+					this.delTarget(tableData)
+				}
+			}
+			this.previewSeasonChart({SeasonAverageConfig:this.chartInfo.SeasonAverageConfig,SeasonRightEdbConfig:rightConfig})
+		},
 		//获取图表全局设置
 		async getChartBaseSetting(){
 			//目前是用基本配置的接口,后续有多个配置再改

+ 189 - 41
src/views/dataEntry_manage/mixins/chartPublic.js

@@ -10,6 +10,11 @@ import futuresInterface from '@/api/modules/futuresBaseApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
 import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
 
+//获取RGBA的透明度
+const parseRgbaColor = (color='rgba(51, 51, 51, 1)') => {
+    const arr = color.match(/(\d(\.\d+)?)+/g) || ['','','',1];
+    return parseFloat(arr[3]||1)
+}
 /* 散点x轴 */
 const scatterXAxis = {
   tickPosition: 'inside',
@@ -700,11 +705,11 @@ export const chartSetMixin = {
     /* 切换相关性图中英文 */
     changeRelevanceLang(){
         this.options.yAxis.forEach(item => {
-          item.title.text = this.currentLang == 'zh' ? item.title.textCh : item.title.textEn
+          item.title.text = this.currentLang == 'zh' ? item.title.textCh : item.title.textEn||item.title.textCh
         });
         //图例
         this.options.series.forEach(item => {
-          item.name = this.currentLang == 'zh' ? item.nameCh : item.nameEn
+          item.name = this.currentLang == 'zh' ? item.nameCh : item.nameEn||item.nameCh
         });
         //tooltip
         this.options.tooltip.formatter = this.currentLang == 'zh' ? this.options.tooltip.formatterCh : this.options.tooltip.formatterEn
@@ -842,12 +847,13 @@ export const chartSetMixin = {
           
         //预测指标配置
         let predict_params = item.EdbInfoCategoryType === 1 ? this.getPredictParams(item) : {};
-
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         //数据列
         let obj = {
           data: [],
-          type: (chartTheme&&chartTheme.lineOptionList[index].lineType) || 'spline',
-          dashStyle: (chartTheme&&chartTheme.lineOptionList[index].dashStyle)||'Solid',
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
           yAxis: sameSideIndex,
           name:
             dynamic_arr.length > 1
@@ -858,12 +864,12 @@ export const chartSetMixin = {
           : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
           nameEn:item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:`${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
           color: item.ChartColor,
-          lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptionList[index].lineWidth),
-          marker: chartTheme && chartTheme.lineOptionList[index].dataMark && chartTheme.lineOptionList[index].dataMark!='none'?{
+          lineWidth:Number(item.ChartWidth)|| (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth)||1,
+          marker: chartTheme && chartTheme.lineOptionList[lineIndex].dataMark && chartTheme.lineOptionList[lineIndex].dataMark!='none'?{
             enabled:true,
-            symbol: chartTheme.lineOptionList[index].markType || 'circle',
-            fillColor:chartTheme.lineOptionList[index].markColor,
-            radius: chartTheme.lineOptionList[index].markSize
+            symbol: chartTheme.lineOptionList[lineIndex].markType || 'circle',
+            fillColor:chartTheme.lineOptionList[lineIndex].markColor,
+            radius: chartTheme.lineOptionList[lineIndex].markSize
           }:{},
           ...predict_params
         };
@@ -1047,7 +1053,8 @@ export const chartSetMixin = {
 
         //预测指标配置
         let predict_params = item.EdbInfoCategoryType === 1 ? this.getPredictParams(item,chartStyle) : {};
-
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         //数据列
         let obj = {
           data: [],
@@ -1062,7 +1069,7 @@ export const chartSetMixin = {
           : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
           nameEn:item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:`${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
           color: item.ChartColor,
-          lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptionList[index].lineWidth),
+          lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 1,
           fillColor: (this.chartInfo.ChartType === 3 || (this.chartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
           borderWidth: 1,
           borderColor: item.ChartColor,
@@ -1073,7 +1080,7 @@ export const chartSetMixin = {
         for (let i of item.DataList) {
           obj.data.push([i.DataTimestamp, i.Value]);
         }
-
+        console.log(obj,'obj');
         data.push(obj);
         ydata.push(yItem);
       });
@@ -1107,7 +1114,8 @@ export const chartSetMixin = {
     setSeasonChart(newval) {
       /* 季节性图的图表配置 */
       this.leftIndex = 0;
-      this.rightIndex = -1;
+      const {SeasonRightConfig={}} = this.chartInfo
+      this.rightIndex = SeasonRightConfig.IsShow?1:-1;
       this.rightTwoIndex = -1;
       const chartData = newval[0];
       // 农历数据需要去除第一项  农历和公历处理逻辑一样
@@ -1122,41 +1130,46 @@ export const chartSetMixin = {
       /* 主题样式*/
       const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
       // 跟颜色对应
-      chartTheme.lineOptionList=chartTheme.lineOptionList.reverse().slice(-chartDataHandle.length)
+      chartTheme && (chartTheme.lineOptionList=chartTheme.lineOptionList.reverse().slice(-chartDataHandle.length))
       let seasonYdata = [],
         seasonData = [];
 
         //获取对应轴的上下限
         //预测指标-走势图;图表配置-主题设置;不使用自定义上下限,剔除
         const useTableLimit = ['/predictEdb','/chartThemeSet','/addpredictEdb','/editpredictEdb','/viewBalanceSheet','/editBalanceSheet'].includes(this.$route.path)
-        let minLimit = 0,maxLimit = 0
+        let minLimit = 0,maxLimit = 0,rightMin=0,rightMax=0
         if(useTableLimit){
             minLimit = chartData.MinData
             maxLimit = chartData.MaxData
+            //这几个页面的季节性图没有右轴,若有,取SearonRightConfig.EdbInfoList[0]的MinData/MaxData
         }else{
             minLimit = this.chartLimit.min||0
             maxLimit = this.chartLimit.max||0
+            //加上右轴
+            if(this.rightIndex!=-1){
+                rightMin = this.chartLimit.rightMin||0
+                rightMax = this.chartLimit.rightMax||0
+            }
         }
-
-      //数据列
+      //数据列-常规左轴
       for (let index in chartDataHandle) {
         let j = chartDataHandle[index]
-        // console.log(j,index);
         //预测指标配置
         let predict_params =  chartData.EdbInfoCategoryType === 1 ? this.getSeasonPredictParams(j.CuttingDataTimestamp) : {};
-
+        // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+        const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         let serie_item = {
           data: [],
-          type: (chartTheme&&chartTheme.lineOptionList[index].lineType) || chartData.ChartStyle,
-          dashStyle: (chartTheme&&chartTheme.lineOptionList[index].dashStyle)||'Solid',
+          type: (chartTheme && chartTheme.lineOptionList[lineIndex].lineType) || chartData.ChartStyle,
+          dashStyle: (chartTheme && chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
           yAxis: 0,
           name: this.isPredictorChart?j.Year:j.ChartLegend,
-          lineWidth: (chartTheme&&chartTheme.lineOptionList[index].lineWidth) || 1,
-          marker: chartTheme && chartTheme.lineOptionList[index].dataMark && chartTheme.lineOptionList[index].dataMark!='none'?{
+          lineWidth: (chartTheme && chartTheme.lineOptionList[lineIndex].lineWidth) || 1,
+          marker: chartTheme && chartTheme.lineOptionList[lineIndex].dataMark && chartTheme.lineOptionList[lineIndex].dataMark!='none'?{
             enabled:true,
-            symbol: chartTheme.lineOptionList[index].markType || 'circle',
-            fillColor:chartTheme.lineOptionList[index].markColor,
-            radius: chartTheme.lineOptionList[index].markSize
+            symbol: chartTheme.lineOptionList[lineIndex].markType || 'circle',
+            fillColor:chartTheme.lineOptionList[lineIndex].markColor,
+            radius: chartTheme.lineOptionList[lineIndex].markSize
           }:{},
           ...predict_params
         };
@@ -1167,6 +1180,81 @@ export const chartSetMixin = {
         seasonData.push(serie_item);
       }
 
+      //数据列-同期上下限/均线/标准差
+      const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = this.chartInfo.SeasonAverageConfig||{}
+      if(MaxMinLimits.IsShow&&MaxMinLimits.List&&MaxMinLimits.List.length){
+        let serieItem = {
+            type:'arearange',//上下限是一个范围
+            data:[],
+            name:MaxMinLimits.Legend||'同期上下限',
+            color:MaxMinLimits.Color||'#075EEE' ,
+            fillOpacity:parseRgbaColor(MaxMinLimits.Color||'')>0.75?0.75:parseRgbaColor(MaxMinLimits.Color||'') //透明度最高0.75 
+        }
+        MaxMinLimits.List.forEach(item=>{
+            serieItem.data.push([item.DataTimestamp,item.MinValue,item.MaxValue])
+        })
+        seasonData.push(serieItem)
+      }
+      if(SamePeriodAverage.IsShow&&SamePeriodAverage.List){
+        let serieItem = {
+            type:'line',
+            data:[],
+            lineWidth:SamePeriodAverage.LineWidth,
+            dashStyle:SamePeriodAverage.LineType,
+            name:SamePeriodAverage.Legend||'同期均值',
+            color:SamePeriodAverage.Color||'#075EEE'
+        }
+        SamePeriodAverage.List.forEach(item=>{
+            serieItem.data.push([item.DataTimestamp,item.Value])
+        })
+        seasonData.push(serieItem)
+      }
+      if(SamePeriodStandardDeviation.IsShow&&SamePeriodStandardDeviation.List){
+        let serieItem = {
+            type:'arearange',//标准差也是一个范围
+            data:[],
+            name:SamePeriodStandardDeviation.Legend||'同期标准差',
+            color:SamePeriodStandardDeviation.Color||'#075EEE',
+            fillOpacity:parseRgbaColor(SamePeriodStandardDeviation.Color||'')>0.75?0.75:parseRgbaColor(SamePeriodStandardDeviation.Color||'')
+        }
+        SamePeriodStandardDeviation.List.forEach(item=>{
+            serieItem.data.push([item.DataTimestamp,item.MinValue,item.MaxValue])
+        })
+        seasonData.push(serieItem)
+      }
+      //数据列-右轴
+      if(SeasonRightConfig.IsShow){
+        //右轴的设置
+        let serieConfig = SeasonRightConfig.Style==='column'?{
+            //柱形
+            type:'column',
+            color:SeasonRightConfig.ChartColor
+        }:{
+            //标记点
+            type:'spline',
+            lineWidth:SeasonRightConfig.LineWidth,
+            dashStyle:SeasonRightConfig.LineStyle,
+            color:SeasonRightConfig.IsConnected?SeasonRightConfig.LineColor:'rgba(255, 255, 255, 0)',//没有连线颜色设置为透明
+            marker:{
+                enabled:true,
+                symbol:SeasonRightConfig.Shape,
+                fillColor:SeasonRightConfig.ChartColor,
+                radius:SeasonRightConfig.Size
+            },
+        }
+        let serieItem = {
+            ...serieConfig,
+            name:SeasonRightConfig.Legend||'',
+            data:[],
+            yAxis:1,
+        }
+        const DataList = (SeasonRightConfig.IndicatorType===1?SeasonRightConfig.EdbInfoList[0].DataList:newval[1].DataList)||[]
+        DataList.forEach(item=>{
+            serieItem.data.push([item.DataTimestamp,item.Value])
+        })
+        seasonData.push(serieItem)
+      }
+
       //y轴
       const textZh = chartData.ConvertUnit||chartData.Unit
       const textEn = chartData.ConvertEnUnit||chartData.UnitEn||chartData.ConvertUnit||chartData.Unit
@@ -1203,6 +1291,44 @@ export const chartSetMixin = {
         plotBands: this.setAxisPlotAreas(1),
         plotLines: this.setAxisPlotLines(1)
       }];
+      //如果有右轴,seasonYdata加上右轴
+      if(SeasonRightConfig.IsShow){
+        const rightEdb = (SeasonRightConfig.IndicatorType===1?SeasonRightConfig.EdbInfoList[0]:newval[1])||{Unit:''}
+        //左轴同比:text为空或% 右轴指标:取指标单位
+        if(SeasonRightConfig.IndicatorType===1){
+            rightEdb.Unit = SeasonRightConfig.NumFormat===1?'%':''
+        }else{
+            rightEdb.Unit = newval[1]&&(newval[1].ConvertUnit||newval[1].Unit)||''
+        }
+        seasonYdata.push({
+            ...seasonOptions.yAxis,
+            opposite: true,//右轴
+            labels: {
+                formatter: function () {
+                  let val = this.value;
+                  return val;
+                },
+                align: 'center',
+                style: {
+                  ...chartTheme&&chartTheme.yAxisOptions.style
+                }
+              },
+              title: {
+                text: rightEdb.Unit||'',
+                style:{
+                  ...chartTheme&&chartTheme.yAxisOptions.style
+                },
+                align: 'high',
+                rotation: 0,
+                y: -12,
+                x: -rightEdb.Unit.length*12 ,
+                textAlign: 'right',
+                reserveSpace: false,
+              },
+              max: Number(rightMax),
+              min: Number(rightMin),
+        })
+      }
 
       /* x轴显示月日 */
       const xAxis = {
@@ -1627,18 +1753,19 @@ export const chartSetMixin = {
         //处理首或/尾全是无效数据的以null填充
         let filterData = this.filterInvalidData(item)
         // console.log(filterData)
-      
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         let serie_item = {
           data: filterData,
-          type: (chartTheme&&chartTheme.lineOptionList[index].lineType) || 'spline',
-          dashStyle: (chartTheme&&chartTheme.lineOptionList[index].dashStyle)||'Solid',
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
           yAxis: 0,
           name: item.Name,
           nameCh: item.Name,
           nameEn: item.NameEn,
           color: item.Color,
           chartType: 'linear',
-          lineWidth: (chartTheme&&chartTheme.lineOptionList[index].lineWidth) || 3,
+          lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 3,
           marker: {
             enabled: false
           }
@@ -1876,17 +2003,19 @@ export const chartSetMixin = {
       //处理series
       let seriesData=[]
       this.relevanceChartData.YDataList.forEach((item,index)=>{
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         let serie_item = {
           data: item.Value,
-          type: (chartTheme&&chartTheme.lineOptionList[index].lineType) || 'spline',
-          dashStyle: (chartTheme&&chartTheme.lineOptionList[index].dashStyle)||'Solid',
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
           yAxis: 0,
           name: item.Name,
           nameCh: item.Name,
           nameEn: item.NameEn,
           color: item.Color,
           chartType: 'linear',
-          lineWidth: (chartTheme&&chartTheme.lineOptionList[index].lineWidth) || 3,
+          lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 3,
           marker: {
             enabled: false
           }
@@ -2001,6 +2130,8 @@ export const chartSetMixin = {
       //数据列
       let series = [];
       DataList.forEach((item,index) => {
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         //数据列
         let series_item = {
           data: [],
@@ -2012,7 +2143,7 @@ export const chartSetMixin = {
           chartType: 'linear',
           zIndex:1,
           marker: {
-            radius: (chartTheme&&chartTheme.lineOptionList[index].radius)||5,
+            radius: (chartTheme&&chartTheme.lineOptionList[lineIndex].radius)||5,
           },
         }
         item.EdbInfoList.forEach(_ => {
@@ -2207,17 +2338,19 @@ export const chartSetMixin = {
       //系列
       let series = [];
       YDataList.forEach((item,index) => {
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         let serie_item = {
           data: item.Value,
           pointPlacement: 'on',
-          type: (chartTheme&&chartTheme.lineOptionList[index].lineType) || 'line',
-          dashStyle: (chartTheme&&chartTheme.lineOptionList[index].dashStyle)||'Solid',
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'line',
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
           yAxis: 0,
           name: item.Name || item.Date,
           nameCh: item.Name || item.Date,
           nameEn: item.Date,
           color: item.Color,
-          lineWidth: (chartTheme&&chartTheme.lineOptionList[index].lineWidth) || 1,
+          lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 1,
           chartType: 'linear'
         };
         series.push(serie_item)
@@ -2293,16 +2426,18 @@ export const chartSetMixin = {
           tickWidth: 1,
         }
 
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         let series_item = {
           data: item.Value.map(_ =>[_.X,_.Y]),
-          dashStyle: (chartTheme&&chartTheme.lineOptionList[index].dashStyle)||'Solid',
-          type: (chartTheme&&chartTheme.lineOptionList[index].lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
           yAxis: index,
           name: item.Name,
           nameCh: item.Name,
           nameEn: item.NameEn||item.Name,
           color: item.Color,
-          lineWidth: (chartTheme&&chartTheme.lineOptionList[index].lineWidth)||3,
+          lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth)||3,
           chartType: 'linear',
           zIndex:1
         }
@@ -2987,6 +3122,19 @@ export const chartSetMixin = {
                 this.chartLimit.rightTwoMin = 0
                 this.chartLimit.rightTwoMax = 0
             }
+            //季节性图-右轴为左轴同比,单独处理
+            if(this.chartInfo.ChartType===2){
+                if(this.chartInfo.SeasonRightConfig&&this.chartInfo.SeasonRightConfig.IsAdd&&this.chartInfo.SeasonRightConfig.IsShow){
+                    if(this.chartInfo.SeasonRightConfig.IndicatorType===1){
+                        this.chartLimit.rightMin = this.chartInfo.SeasonRightConfig.EdbInfoList[0].MinData||0
+                        this.chartLimit.rightMax = this.chartInfo.SeasonRightConfig.EdbInfoList[0].MaxData||0
+                    }else{
+                        this.chartLimit.rightMin = this.tableData[1].MinData||0
+                        this.chartLimit.rightMax = this.tableData[1].MaxData||0
+                    }
+                    
+                }
+            }
             console.table([{
                     'y轴': '左轴',
                     '最大值': this.chartLimit.max,

+ 387 - 0
src/views/dataEntry_manage/thirdBase/Wind.vue

@@ -0,0 +1,387 @@
+<template>
+  <div class="Wind-container" id="box">
+    <div class="left-cont" id="left">
+      <div class="scroll-wrap">
+        <el-tree
+          ref="treeRef"
+          class="target_tree"
+          :data="classifyList"
+          node-key="UniqueCode"
+          :props="{
+            label: 'ClassifyName',
+            children: 'Children',
+            isLeaf:'isLeaf'
+          }"
+          :current-node-key="select_node"
+          :default-expanded-keys="defaultShowNodes"
+          :expand-on-click-node="false"
+          check-strictly
+          :empty-text="$t('Common.no_classify_msg')"
+          lazy
+					:load="getLazyTreeData"
+          @node-expand="handleNodeExpand"
+          @node-collapse="handleNodeCollapse"
+          @current-change="nodeChangeHandle"
+        >
+          <span slot-scope="{ node, data }">{{ currentLang==='zh' ? data.ClassifyName : (data.ClassifyNameEn||data.ClassifyName) }}</span>
+        </el-tree>
+      </div>
+    </div>
+
+    <div
+      class="right-cont"
+      id="right"
+      v-loading="dataloading"
+      :element-loading-text="$t('Table.data_loading')"
+    >
+      <div class="right-cont-top">
+        <el-select
+					v-model="search_txt"
+					v-loadMore="searchLoad"
+					ref="searchRef"
+					:filterable="!search_txt"
+					remote
+					clearable
+					:placeholder="$t('Edb.InputHolderAll.input_name_orid')"
+					style="width: 360px;"
+					:remote-method="searchHandle"
+					@click.native="inputFocusHandle"
+				>
+					<i slot="prefix" class="el-input__icon el-icon-search"></i>
+					<el-option
+						v-for="item in searchOptions"
+						:key="item.EdbInfoId"
+						:label="currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
+						:value="item.EdbInfoId"
+					>
+						<div>
+							<img 
+								:src="$icons.lock_ico2" 
+								width="18" 
+								height="18" 
+								style="vertical-align:middle" 
+								v-if="!item.HaveOperaAuth"
+							/>
+							{{currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName}}
+						</div>
+					</el-option>
+				</el-select>
+      </div>
+      <el-table ref="tableRef" :data="tableData" border class="data-source-table" height="calc(100% - 60px)">
+        <!-- 指标Id -->
+        <el-table-column prop="EdbCode" :label="$t('Edb.Detail.e_id')" show-overflow-tooltip>
+          <template slot-scope="scope">
+            {{scope.row.EdbCode}}
+          </template>
+        </el-table-column>
+        <!-- 指标名称 -->
+        <el-table-column prop="EdbName" :label="$t('Edb.Detail.e_name')" show-overflow-tooltip>
+          <template slot-scope="scope">
+            {{currentLang==='en'?scope.row.EdbNameEn:scope.row.EdbName}}
+          </template>
+        </el-table-column>
+        <!-- 频度 -->
+        <el-table-column prop="Frequency" :label="$t('Edb.Detail.e_fre')">
+          <template slot-scope="scope">
+            {{scope.row.Frequency}}
+          </template>
+        </el-table-column>
+        <!-- 单位 -->
+        <el-table-column prop="Unit" :label="$t('Edb.Detail.e_unit')">
+          <template slot-scope="scope">
+            {{currentLang==='en'?scope.row.UnitEn:scope.row.Unit}}
+          </template>
+        </el-table-column>
+        <!-- 目录 -->
+        <el-table-column prop="ClassifyList" :label="$t('Edb.Detail.e_catalogue')" show-overflow-tooltip>
+          <template slot-scope="scope">
+            {{scope.row.ClassifyList.map(cl => cl.ClassifyName).reverse().join('/')+'/'}}
+          </template>
+        </el-table-column>
+        <!-- 起始时间 -->
+        <el-table-column prop="StartDate" :label="$t('Edb.Detail.e_start_time')">
+          <template slot-scope="scope">
+            {{scope.row.StartDate}}
+          </template>
+        </el-table-column>
+        <!-- 更新时间 -->
+        <el-table-column prop="ModifyTime" :label="$t('Edb.Detail.e_update_time')">
+          <template slot-scope="scope">
+            {{scope.row.ModifyTime}}
+          </template>
+        </el-table-column>
+        <!-- 刷新状态 -->
+        <el-table-column prop="NoUpdate" :label="$t('Edb.Detail.e_status')">
+          <template slot-scope="scope">
+            {{scope.row.NoUpdate==0?'启用':'停用'}}
+          </template>
+        </el-table-column>
+        <!-- 创建人 -->
+        <el-table-column prop="SysUserRealName" :label="$t('Edb.Detail.e_creator')">
+          <template slot-scope="scope">
+            {{scope.row.SysUserRealName}}
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { windInterface } from "@/api/modules/thirdBaseApi";
+import { dataBaseInterface } from '@/api/api.js';
+import leftMixin from "./mixins/leftMixin.js";
+export default {
+  name: "Wind",
+  mixins: [leftMixin],
+  components: {},
+  data() {
+    return {
+      dataloading: false,
+      classifyList: [],
+      select_classify: 0,
+      select_edbId: 0, //添加指标后的code,无论是否加载出来,无论是否加载成功
+      select_node: "",
+      defaultShowNodes: [], //展开节点
+      tableData:[],
+
+      search_txt:"",
+      search_page: 1,
+			search_have_more: false,
+			current_search:'',
+      searchOptions:[],
+    };
+  },
+  watch:{
+    select_edbId(newval) {
+			if(newval) {
+				this.getDataList()
+			}
+		},
+    select_classify(newval){
+			if(newval){
+				this.getDataList()
+			}
+		},
+    /* 选中搜索指标 展开目录 选中指标 展示数据 */
+		search_txt(newval) {
+			if (newval) {
+				let [search_obj] = this.searchOptions.filter(
+					(item) => item.EdbInfoId === newval
+				);
+				this.select_node = search_obj.UniqueCode;
+				this.select_edbId = newval;
+				this.select_classify = 0;
+			}
+		},
+  },
+  methods: {
+    /* 获取分类 */
+    getClassify() {
+      windInterface.classifyList().then((res) => {
+        if (res.Ret !== 200) return;
+        this.classifyList = res.Data && res.Data.AllNodes || [];
+        this.select_classify=this.classifyList[0]?this.classifyList[0].ClassifyId||0:0
+        this.select_node=this.classifyList[0]?this.classifyList[0].UniqueCode||'':''
+        this.nodeLocation()
+        this.getDataList()
+      });
+    },
+    //指标懒加载
+    async getLazyTreeData(node,resolve){
+			if(node.level===0){
+				resolve(this.classifyList)
+        this.nodeLocation()
+			}else{
+				let arr=[]
+				const res=await windInterface.classifyList({ParentId:node.data.ClassifyId})
+				if (res.Ret === 200) {
+					const temarr = res.Data.AllNodes || [];
+					arr=temarr.map(item=>{
+						return {
+							...item,
+							isLeaf:item.EdbInfoId?true:false
+						}
+					})
+				}
+				resolve(arr)
+        this.nodeLocation()
+			}
+    },
+
+    /* 获取数据 */
+    getDataList() {
+      this.dataloading = true;
+      windInterface.dataList({
+        ClassifyId:this.select_classify,
+        EdbInfoId:this.select_edbId,
+        PageSize:9999999,
+        CurrentIndex:1
+      }).then((res) => {
+        if (res.Ret !== 200) return;
+        this.tableData=res.Data.List || []
+        if(this.$refs.tableRef && this.$refs.tableRef.$el.querySelector('.el-table__body-wrapper')){
+          this.$refs.tableRef.$el.querySelector('.el-table__body-wrapper').scrollTop=0
+        }
+        // 选中指标对应树节点应该展开的目录
+        if(this.search_txt && this.select_edbId && this.tableData[0]){
+          let classify_arr = this.tableData[0].ClassifyList || [];
+          // 展开目录
+          this.defaultShowNodes=classify_arr.map(item=>item.UniqueCode)
+        }
+      }).finally(()=>{
+        this.dataloading = false;
+      })
+    },
+    /* 改变节点 */
+    nodeChangeHandle(data, node) {
+      if (this.dataloading)
+        return this.$message(this.$t('MsgPrompt.request_frequency'));
+      this.search_txt=''
+      this.select_node = data.UniqueCode;
+      this.select_classify = !data.EdbInfoId?data.ClassifyId:0;
+      this.select_edbId = data.EdbInfoId
+    },
+    // 定位
+    nodeLocation(){
+      this.$nextTick(()=>{
+        setTimeout(() => {
+          this.$refs.treeRef && this.select_node && this.$refs.treeRef.setCurrentKey(this.select_node);
+        }, 100);
+      })
+    },
+    /* 聚焦获取当前检索 */
+		inputFocusHandle(e) {
+			this.search_page = 1;
+			this.current_search = e.target.value;
+			this.searchApi(this.current_search);
+		},
+    searchLoad() {
+			if(!this.search_have_more) return;
+			this.searchApi(this.current_search,++this.search_page);
+		},
+    /* 搜索 */
+		searchHandle(query) {
+			this.search_page = 1;
+			this.current_search = query;
+			this.searchApi(this.current_search)
+		},
+    searchApi(query,page=1) {
+			dataBaseInterface.targetSearchByPage({
+				KeyWord:query,
+				CurrentIndex: page,
+        Source:2, // Wind的
+			}).then(res => {
+				if(res.Ret !== 200) return
+
+				const { List,Paging } = res.Data;
+				this.search_have_more = page < Paging.Pages;
+				this.searchOptions = page === 1 ? List : this.searchOptions.concat(List);
+					
+			})
+		},
+  },
+  computed: {
+    currentLang() {
+      return this.$store.state.lang
+    }
+  },
+  mounted() {
+    this.getClassify();
+  },
+};
+</script>
+<style lang="scss" scoped>
+.Wind-container {
+  display: flex;
+  position: relative;
+  height:calc(100vh - 115px);
+  .left-cont {
+    min-width: 300px;
+    width: 300px;
+    margin-right: 20px;
+    padding: 20px;
+    overflow: hidden;
+    position: relative;
+    height: 100%;
+    background-color: #ffffff;
+    box-sizing: border-box;
+    .scroll-wrap {
+      height: 100%;
+      overflow: hidden auto;
+    }
+    .target_tree {
+      color: #333;
+    }
+  }
+  .right-cont {
+    flex:1;
+    padding: 20px;
+    background-color: #ffffff;
+    box-sizing: border-box;
+    .right-cont-top{
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      margin-bottom: 20px;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.Wind-container {
+  .el-tree-node__content {
+    margin-bottom: 14px !important;
+  }
+
+  .el-tree-node__children {
+    .el-tree-node {
+      margin-bottom: 0px !important;
+      padding-left: 18px;
+    }
+    .el-tree-node__content {
+      margin-bottom: 5px !important;
+      padding-left: 0 !important;
+    }
+  }
+  .expanded.el-icon-caret-right:before {
+    content: url("~@/assets/img/set_m/down.png") !important;
+  }
+  .el-icon-caret-right:before {
+    content: url("~@/assets/img/set_m/slide.png") !important;
+  }
+  .el-tree-node__expand-icon.is-leaf.el-icon-caret-right:before {
+    content: "" !important;
+  }
+  .el-tree-node__expand-icon.expanded {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  .el-tree-node.is-current > .el-tree-node__content {
+    background-color: #f0f4ff !important;
+  }
+  .el-tree-node__content {
+    padding-right: 10px !important;
+  }
+  .right-cont {
+    .data-source-table{
+      .el-table__header{
+        tr{
+          th{
+            background-color: #F0F2F5!important;
+            .cell{
+              font-weight:normal;
+              color:#666666;
+            }
+          }
+        }
+      }
+      .el-table__body{
+        tr{
+          background-color: #ffffff!important;
+        }
+      }
+    }
+  }
+}
+</style>

+ 721 - 0
src/views/dataEntry_manage/thirdBase/components/highFrequency/addHighFrequencyData.vue

@@ -0,0 +1,721 @@
+<template>
+  <div>
+		<el-dialog :visible.sync="isAddShow" :close-on-click-modal="false" :modal-append-to-body='false' 
+    @close="cancelHandle" top="5vh" center :width="addStep==1?'1250px':'1208px'" v-dialogDrag 
+    :title="$t('HighFrequencyData.add_high_frequency_data')">
+      <div class="dialog-container" v-loading="isLoadingData" :element-loading-text="$t('Table.loading')">
+        <div v-if="addStep==1">
+          <div class="data-query-box">
+            <el-input :placeholder="$t('EtaBasePage.stocks_input_pholder')" v-model.trim="securityCodeText" 
+            class="query-index-input" style="margin-bottom: 20px;" @blur="codeInputBlur('stock')"></el-input>
+            <div class="query-index-code">
+              <el-input :placeholder="$t('EtaBasePage.edb_input_pholder')" v-model.trim="indexCodeText" 
+              class="query-index-input" @blur="codeInputBlur('index')"></el-input>
+            </div>
+            <el-checkbox-group v-model="indexCodeSelected" style="margin-bottom: 20px;" @change="indexCodeSelectHandle">
+              <el-checkbox :label="item.value" v-for="item in indexCodeArr" :key="item.value" style="margin-right: 20px;">{{ item.label }}</el-checkbox>
+            </el-checkbox-group>
+            <div class="high-frequency-code-row" style="margin-top: -10px;" v-if="indexCode && indexCode.length>0">
+							<div class="high-frequency-code-item" v-for="item in indexCode" :key="item">
+								<div class="high-frequency-code-item-text">{{ item }}</div>
+								<img src="~@/assets/img/icons/close_icon_black.png" @click="deleteCode(item)" />
+							</div>
+						</div>
+            <div class="time-range-row">
+              <!-- 起始时间 -->
+              <div class="start-time-row">
+                <span>{{ $t('Edb.Detail.e_start_time') }}</span>
+                <el-date-picker
+                  class="date-picker"
+                  v-model="otherParams.startDate"
+                  value-format="yyyy-MM-dd"
+                  type="date"
+                  :placeholder="$t('Edb.InputHolderAll.input_date')">
+                </el-date-picker>
+                <el-time-picker
+                  class="time-picker"
+                  value-format="HH:mm:ss"
+                  v-model="otherParams.startTime"
+                  :placeholder="$t('Edb.InputHolderAll.input_time')">
+                </el-time-picker>
+              </div>
+              <div class="end-time-row"><!-- 截止时间 -->
+                <span>{{ $t('Edb.Detail.e_deadline_time') }}</span>
+                <el-radio v-model="otherParams.deadlineType" label="1">{{ $t('Common.latest') }}</el-radio>
+                <el-radio v-model="otherParams.deadlineType" label="2">{{ $t('Common.fixed') }}</el-radio>
+                <template v-if="otherParams.deadlineType=='2'">
+                  <el-date-picker
+                    class="date-picker"
+                    value-format="yyyy-MM-dd"
+                    v-model="otherParams.deadlineDate"
+                    type="date"
+                    :placeholder="$t('Edb.InputHolderAll.input_date')">
+                  </el-date-picker>
+                  <el-time-picker
+                    class="time-picker"
+                    value-format="HH:mm:ss"
+                    v-model="otherParams.deadlineTime"
+                    :placeholder="$t('Edb.InputHolderAll.input_time')">
+                  </el-time-picker>
+                </template>
+              </div>
+            </div>
+            <div class="time-cycle">
+              <!-- 时间周期 -->
+              <div class="time-cycle-item">
+                <span>{{ $t('HighFrequencyData.period') }}</span>
+                <el-select v-model="otherParams.period" :placeholder="$t('Edb.please_select')">
+                  <el-option
+                    v-for="item in periodList"
+                    :key="item"
+                    :label="item"
+                    :value="item">
+                  </el-option>
+                </el-select>
+              </div>
+              <!-- 复权方式 -->
+              <div class="time-cycle-item">
+                <span>{{ $t('HighFrequencyData.adjustment') }}</span>
+                <el-select v-model="otherParams.adjustment" :placeholder="$t('Edb.please_select')">
+                  <el-option
+                    v-for="item in adjustmentList"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value">
+                  </el-option>
+                </el-select>
+              </div>
+              <!-- 复权基点 -->
+              <div class="time-cycle-item" v-show="otherParams.adjustment!='no'">
+                <span>{{ $t('HighFrequencyData.base_point') }}</span>
+                <el-date-picker
+                  class="date-picker"
+                  v-model="otherParams.basePoint"
+                  value-format="yyyy-MM-dd"
+                  type="date"
+                  :placeholder="$t('Edb.InputHolderAll.input_date')">
+                </el-date-picker>
+              </div>
+            </div>
+            <div class="interval">
+              <span>{{ $t('HighFrequencyData.no_interval_handle') }}</span>
+              <el-select v-model="otherParams.noIntervalHandle" :placeholder="$t('Edb.please_select')">
+                <el-option
+                  v-for="item in noIntervalHandleList"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="dia-bot">
+            <el-button type="primary" @click="nextHandle" :disabled="!isCodeComplete"
+            style="width: 120px;" :loading="isLoadingData" ><!-- 下一步 -->{{$t('EtaBasePage.next_step')}}
+            </el-button>
+          </div>
+        </div>
+        <template v-else>
+          <div class="edb-table-preview">
+            <table width="auto" border="0">
+              <thead>
+                <tr v-for="(item, index) in edbTableHeadKey" :key="item">
+                  <td class="sticky" style="text-align: center;left: 0;text-align: center;position: sticky;z-index: 101;">
+                    {{ edbTableHeadData.get(item) }}
+                    <template v-if="item == 'ClassifyId'">
+                      <br />
+                      <el-radio-group v-model="classifyType" @change="handleClassifyTypeChange" style="margin-top: 5px;">
+                        <el-radio :label="0" style="margin-right: 8px;"><!-- 同目录 -->{{$t('EtaBasePage.directory_radio')}}</el-radio>
+                        <el-radio :label="1"><!-- 分目录 -->{{$t('EtaBasePage.subdirectory_radio')}}</el-radio>
+                      </el-radio-group>
+                    </template>
+                  </td>
+                  <td v-for="(data, sub_index) in edbIndexDatas" :key="sub_index" class="body-td"
+                  :class="highLightIndex.includes(data.IndexName) && item=='IndexName' ?'exist-highlight':''">
+                    <template v-if="item === 'ClassifyId'">
+                      <el-cascader :options="classifyList" v-model="data[item]" :placeholder="$t('Edb.InputHolderAll.input_menu')"
+                       :disabled="(classifyType===0&&sub_index>0)" @change="handleClassifyChange(data)"
+                      :props="{label: 'ClassifyName',
+                        value: 'ClassifyId',
+                        children: 'Children',
+                        checkStrictly: true,
+                        emitPath:false}">
+                      </el-cascader>
+                    </template>
+                    <template v-else-if="item === 'Unit'">
+                      <el-autocomplete
+                        v-model.trim="data[item]"
+                        :fetch-suggestions="querySearchUnit"
+                        :placeholder="$t('Edb.InputHolderAll.input_unit')"
+                        suffix-icon="el-icon-arrow-down"
+                        size="mini"
+                      ></el-autocomplete>
+                    </template>
+                    <template v-else-if="item === 'IndexName'">
+                      <el-input v-model.trim="data[item]" :placeholder="$t('Edb.InputHolderAll.input_name')" size="mini"></el-input>
+                    </template>
+                    <template v-else>
+                      <div style="padding: 0 7px;">{{ data[item] }}</div>
+                    </template>
+                  </td>
+                </tr>
+              </thead>
+              <tbody v-if="edbIndexDatas && edbIndexDatas.length>0">
+                <tr>
+                  <td class="body-td sticky" style="left: 0;text-align: center;height: 330px;text-align: center;position: sticky;z-index: 101;">
+                    <!-- 数据详情 -->{{$t('Edb.data_detail_tab')}}
+                  </td>
+                  <!-- <template > -->
+                    <td class="body-td" style="height: 330px;padding: 0;" v-for="(item,index) in edbIndexDatas" :key="index">
+                      <!-- {{ 'edbIndexDatas[index1].DataList[index].DataTime' }} -->
+                      <div class="td-box">
+                        <div class="data-item" v-for="(item1,index1) in edbIndexDatas[index].DataList">
+                          <span >{{ edbIndexDatas[index].DataList[index1].DataTime }}</span>
+                          <span >{{ edbIndexDatas[index].DataList[index1].Value }}</span>
+                        </div>
+                      </div>
+                    </td>
+                    <!-- <td></td>
+                  </template> -->
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          <div class="dia-bot">
+            <el-button @click="prevHandle" style="width: 120px;"><!-- 上一步 -->{{$t('Dialog.prev_step')}}</el-button>
+            <el-button type="primary" @click="saveHandle" style="width: 120px;margin-left: 50px;"><!-- 保存 -->{{$t('Dialog.confirm_save_btn')}}</el-button>
+          </div>
+        </template>
+      </div>
+
+		</el-dialog>
+    <el-dialog :visible.sync="checkFailShow" :close-on-click-modal="false" :modal-append-to-body='false' 
+			width="600px" :title="$t('Dialog.operation_prompt')">
+			<div class="check-fail-box">
+				<div>
+					<div style="margin-bottom: 20px;">{{$t('EtaBasePage.exist_edb_tips')}}</div>
+					<div v-for="(item,index) in existIndexList" :key="index">
+						{{ index+1+'、'+item.text }}
+					</div>
+				</div>
+				<div class="check-fail-button">
+					<el-button type="primary" @click="checkFailShow=false" style="width: 120px;">{{$t('MsgPrompt.known')}}</el-button>
+				</div>
+			</div>
+		</el-dialog>
+  </div>
+</template>
+
+<script>
+import { highFrequencyDataInterface } from '@/api/api.js'
+  export default {
+    name:"addHighFrequencyData",
+    props: {
+      isAddShow: {
+        type: Boolean,
+        default:false
+      },
+      unitList:{
+        type:Boolean,
+        default:()=>[]
+      },
+      classifyList:{
+        type:Boolean,
+        default:()=>[]
+      }
+    },
+    data() {
+      return {
+        isLoadingData:false,
+        addStep:1,
+        securityCodeText:"",
+        securityCodeLimit:10,
+        indexCodeText:"",
+        indexCode:[],
+        indexCodeLimit:20,
+        indexCodeSelected:[],
+        periodList:[1,3,5,10,15,30,60],
+        otherParams:{
+          startDate:this.$moment(new Date()).subtract(6, 'months').format('YYYY-MM-DD'),
+          startTime:'09:15:00',
+          deadlineType:'1',
+          deadlineDate:this.$moment(new Date()).format('YYYY-MM-DD'),
+          deadlineTime:'09:15:00',
+          period:1,
+          adjustment:'no',
+          basePoint:'1900-01-01',
+          noIntervalHandle:'Original'
+        },
+        edbIndexDatas:[],
+        checkFailShow:false,
+        existIndexList:[],
+        edbTableHeadKey: [
+          "ClassifyId",
+          "Unit",
+          "Frequency",
+          "IndexName",
+          "EdbCode",
+        ],
+        classifyType:0,
+        highLightIndex:[],
+      }
+    },
+    computed:{
+      isCodeComplete(){
+        return this.securityCodeText && (this.indexCode.length>0 || this.indexCodeSelected.length>0) && this.otherParams.startDate && 
+                this.otherParams.startTime && this.otherParams.period && this.otherParams.adjustment && this.otherParams.basePoint && 
+                (this.otherParams.deadlineType=='1' || (this.otherParams.deadlineType=='2' && this.otherParams.deadlineDate && this.otherParams.deadlineTime) )&&
+                this.otherParams.noIntervalHandle
+      },
+      // 常用的指标代码
+      indexCodeArr(){
+        return [
+          {value:'open',label:this.$t('EtaBasePage.op_price')/* "开盘价" */},
+          {value:'high',label:this.$t('EtaBasePage.high_price')/* "最高价" */},
+          {value:'low',label:this.$t('EtaBasePage.low_price')/* "最低价" */},
+          {value:'avgprice',label:this.$t('EtaBasePage.average_price')/* "均价" */},
+          {value:'close',label:this.$t('EtaBasePage.close_price')/* "收盘价" */},
+          {value:'volume',label:this.$t('EtaBasePage.trade_volume')/* "成交量" */},
+          {value:'amt',label:this.$t('EtaBasePage.turnover')/* "成交额" */},
+          {value:'pct_chg',label:this.$t('EtaBasePage.incre_decre')/* "涨跌幅" */},
+          {value:'oi',label:this.$t('EtaBasePage.open_inter')/* "持仓量" */}
+        ]
+      },
+      // currentLang() {
+      //   return this.$store.state.lang
+      // },
+      adjustmentList(){
+        return [
+          {label:this.$t('HighFrequencyData.no_rehabilitation'),value:'no'},
+          {label:this.$t('HighFrequencyData.forward_rehabilitation_1'),value:'forward1'},
+          {label:this.$t('HighFrequencyData.backward_rehabilitation_1'),value:'backward1'},
+          {label:this.$t('HighFrequencyData.forward_rehabilitation_3'),value:'forward3'},
+          {label:this.$t('HighFrequencyData.backward_rehabilitation_3'),value:'backward3'},
+          {label:this.$t('HighFrequencyData.forward_rehabilitation_2'),value:'forward2'},
+          {label:this.$t('HighFrequencyData.backward_rehabilitation_2'),value:'backward2'},
+          {label:this.$t('HighFrequencyData.forward_rehabilitation_4'),value:'forward4'},
+          {label:this.$t('HighFrequencyData.backward_rehabilitation_4'),value:'backward4'},
+        ]
+      },
+      noIntervalHandleList(){
+        return [
+          {label:this.$t('HighFrequencyData.original'),value:'Original'},
+          {label:this.$t('HighFrequencyData.previous'),value:'Previous'},
+          {label:this.$t('HighFrequencyData.blank'),value:'Blank'}
+        ]
+      },
+      edbTableHeadData(){
+        return new Map([
+          ["ClassifyId", /* "所属目录" */this.$t('EtaBasePage.belong_menu')],
+          ["Unit", /* "单位" */this.$t('Edb.Detail.e_unit')],
+          ["Frequency", /* "频度" */this.$t('Edb.Detail.e_fre')],
+          ["IndexName", /* "指标名称" */this.$t('Edb.Detail.e_name')],
+          ["StockCode", /* "证券代码" */this.$t('Edb.Detail.e_stock_code')],
+          ["EdbCode", /* "指标代码" */this.$t('Edb.Detail.e_code')],
+        ])
+      },
+    },
+    methods: {
+      init(){
+        this.isLoadingData=false
+        this.addStep=1
+        this.securityCodeText=""
+        this.indexCodeText=""
+        this.indexCode=[]
+        this.indexCodeSelected=[]
+        this.otherParams={
+          startDate:this.$moment(new Date()).subtract(6, 'months').format('YYYY-MM-DD'),
+          startTime:'09:15:00',
+          deadlineType:'1',
+          deadlineDate:this.$moment(new Date()).format('YYYY-MM-DD'),
+          deadlineTime:'09:15:00',
+          period:1,
+          adjustment:'no',
+          basePoint:'1900-01-01',
+          noIntervalHandle:'Original'
+        }
+      },
+      cancelHandle() {
+        this.init()
+        this.$emit('update:isAddShow',false)
+      },
+      //搜索单位
+      querySearchUnit(queryString, cb){
+        let results = queryString ? this.unitList.filter(item=>item.value.indexOf(queryString) === 0) : this.unitList;
+        // 调用 callback 返回建议列表的数据
+        cb(results);
+      },
+      // 指标代码和证券代码输入失焦
+      codeInputBlur(type){
+        if(type=='stock'){
+          if(!this.securityCodeText) return
+          this.securityCodeText=this.securityCodeText.replaceAll(' ','')
+          let arr = this.securityCodeText.split(',')
+          if(arr.length>this.securityCodeLimit){
+            this.$message.warning(this.$t('HighFrequencyData.stock_code_numer_prompt'))
+            this.securityCodeText=arr.slice(0,this.securityCodeLimit).join(',')
+          }
+        }else{
+          if(!this.indexCodeText) return  
+          this.indexCodeText=this.indexCodeText.replaceAll(' ','')
+          let arr = Array.from(new Set([...this.indexCode,...this.indexCodeText.split(',')]))
+          if(arr.length+this.indexCodeSelected.length>this.indexCodeLimit){
+            this.$message.warning(this.$t('HighFrequencyData.index_code_numer_prompt'))
+            this.indexCode=arr.slice(0,(this.indexCodeLimit-this.indexCodeSelected.length))
+          }else{
+            this.indexCode=arr
+          }
+          this.indexCodeText=''
+        }
+      },
+      deleteCode(code){
+        this.indexCode = this.indexCode.filter(it => it!=code)
+      },
+      indexCodeSelectHandle(){
+        if(this.indexCode.length+this.indexCodeSelected.length>this.indexCodeLimit){
+          this.$message.warning(this.$t('HighFrequencyData.index_code_numer_prompt'))
+          this.indexCodeSelected=this.indexCodeSelected.slice(0,(this.indexCodeLimit-this.indexCode.length))
+        }
+      },
+      nextHandle(){
+        let StartTime = this.otherParams.startDate+" "+this.otherParams.startTime
+        let EndTime = this.otherParams.deadlineType=='2'?this.otherParams.deadlineDate+" "+this.otherParams.deadlineTime:''
+        if(EndTime && !(new Date(EndTime)>new Date(StartTime))){
+          return this.$message.warning(this.$t('HighFrequencyData.start_time_right_end_time'))
+        }
+        setTimeout(()=>{
+          if(this.isCodeComplete){
+            let params={
+              EdbCode:Array.from(new Set([...this.indexCode,...this.indexCodeSelected])).join(','),
+              StockCode:this.securityCodeText,
+              StartTime,
+              EndTime,
+              Interval:+this.otherParams.period,
+              Fill:this.otherParams.noIntervalHandle,
+              CPS:this.otherParams.adjustment,
+              BaseDate:this.otherParams.basePoint
+            }
+            this.isLoadingData=true
+            highFrequencyDataInterface.checkHighFreData(params).then(res=>{
+              if(res.Ret == 200){
+                if(res.Data.ExistIndex && res.Data.ExistIndex.length>0){
+                  // 有重复
+                  this.existIndexList=[]
+                  let existEdbInfo=res.Data.ExistIndex || []
+                  let text=''
+                  existEdbInfo.map(item =>{
+                    text=`${item.IndexName}(${item.IndexCode})`
+                    this.existIndexList.push({text,id:item.IndexId})
+                  })
+                  this.checkFailShow=true
+                  this.isLoadingData=false
+                }else{
+                  // 没有重复
+                  highFrequencyDataInterface.searchHighFreData(params).then(res => {
+                    if(res.Ret == 200){
+                      let stockList = res.Data || []
+                      this.edbIndexDatas=[]
+                      stockList.map((item,index) =>{
+                        let batchParams={
+                          ClassifyId:0,
+                          Unit:'',
+                          Frequency:item.Frequency+'m',
+                          IndexName:item.IndexName,
+                          EdbCode:item.EdbCode,
+                          StockCode:item.StockCode
+                        }
+                        let datas = item.IndexData || []
+                        let datasLength = datas.length
+                        if( datasLength<10){
+                          for (let i = datasLength; i < 10; i++) {
+                            datas.push({DataTime:'',Value:''})													
+                          }
+                        }
+                        this.edbIndexDatas.push({...batchParams,DataList:datas})
+                      })
+
+                      let edbIndexDataLength = this.edbIndexDatas.length
+                      //填充空的列
+                      for (let i = edbIndexDataLength; i < 4; i++) {
+                        this.edbIndexDatas.push({
+                          ClassifyId:0,
+                          Unit:'',
+                          Frequency:'',
+                          IndexName:'',
+                          EdbCode:'',
+                          StockCode:'',
+                          DataList:new Array(10).fill({DataTime:'',Value:''})
+                        })
+                      }
+                      this.highLightIndex=[]
+                      this.classifyType=0
+
+                      this.addStep=2
+                    }
+                  }).finally(()=>{
+                    this.isLoadingData=false
+                  })
+                }
+              }
+            })
+          }
+        },10)
+      },
+      prevHandle(){
+        this.addStep=1
+      },
+      // 同目录修改
+      handleClassifyChange(e,index){
+        if(this.classifyType===0){
+          // 修改所有的指标的目录为第一个
+          this.edbIndexDatas.forEach(item=>{
+            item.ClassifyId=e.ClassifyId
+          })
+        }
+      },
+      handleClassifyTypeChange(){
+        this.handleClassifyChange(this.edbIndexDatas[0])
+      },
+      saveHandle(){
+        let flag = this.edbIndexDatas.some(it => {
+          return (it.StockCode && it.EdbCode) && ((!it.ClassifyId) || (!it.Unit) || (!it.IndexName))
+        })
+        if(flag){
+          this.$message.warning(/* "指标信息未填写完整" */this.$t('BloombergPage.add_edb_check_hint1'))
+          return 
+        }
+        this.isLoadingData=true
+        const IndexList=this.edbIndexDatas.map(data=>{
+          if(data.StockCode && data.EdbCode){
+            return {
+              ClassifyId:data.ClassifyId,
+              StockCode:data.StockCode,
+              EdbCode:data.EdbCode,
+              IndexName:data.IndexName,
+              Frequency:data.Frequency,
+              Unit:data.Unit,
+            }
+          }else{
+            return ''
+          }
+        }).filter(Boolean)
+        let StartTime = this.otherParams.startDate+" "+this.otherParams.startTime
+        let EndTime = this.otherParams.deadlineType=='2'?this.otherParams.deadlineDate+" "+this.otherParams.deadlineTime:''
+        let addParams={
+          IndexList,
+          StartTime,
+          EndTime,
+          Interval:+this.otherParams.period,
+          Fill:this.otherParams.noIntervalHandle,
+          CPS:this.otherParams.adjustment,
+          BaseDate:this.otherParams.basePoint
+        }
+        highFrequencyDataInterface.addHighFreDatas(addParams).then(res=>{
+          console.log(res,'mres');
+          if(res.Ret == 200){
+            this.$message.success(/* "添加指标成功" */this.$t('MsgPrompt.add_msg2'))
+            this.$emit('addSuccessHandle')	
+            this.cancelHandle()	
+          }
+          // else if(res.Ret == 403){
+          //   this.highLightIndex=res.Data?res.Data.ExistEdbName || []:[]
+          // }
+        }).finally(()=>{
+          this.isLoadingData=false
+        })
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+.dialog-container{
+  padding: 0 35px 35px;
+  .data-query-box{
+		padding-top: 20px;
+		.query-index-code{
+			display: flex;
+			align-items: center;
+			margin-bottom: 20px;
+		}
+		.query-index-input{
+			min-width: 490px;
+			width:490px;
+			margin-right: 10px;
+		}
+    .high-frequency-code-row{
+			margin-top: 10px;
+			min-height: 60px;
+			display: flex;
+			align-items: center;
+			flex-wrap: wrap;
+			.high-frequency-code-item{
+				height: 40px;
+				background-color: #EBEFF6;
+				display: flex;
+				align-items: center;
+				margin-right: 10px;
+				padding: 10px;
+				box-sizing: border-box;
+				margin-bottom: 10px;
+				.high-frequency-code-item-text{
+					color: #333333;
+					margin-right: 10px;
+				}
+				img{
+					height: 16px;
+					width: 16px;
+					cursor: pointer;
+				}
+			}
+		}
+    .time-range-row{
+      display: flex;
+      align-items: center;
+      margin-bottom: 20px;
+      .start-time-row{
+        margin-right: 40px;
+      }
+      .start-time-row,.end-time-row{
+        display: flex;
+        align-items: center;
+        span{
+          white-space: nowrap;
+          margin-right: 10px
+        }
+        .date-picker{
+          width: 240px;
+          margin-right: 10px
+        }
+        .time-picker{
+          width: 120px;
+        }
+      }
+      .end-time-row{
+        .el-radio{
+          margin-right: 10px;
+        }
+      }
+    }
+    .time-cycle{
+      display: flex;
+      align-items: center;
+      margin-bottom: 20px;
+      .time-cycle-item{
+        margin-right: 10px;
+        span{
+          margin-right: 10px;
+          white-space: nowrap;
+        }
+        .el-select{
+          width: 140px;
+        }
+        .el-date-editor{
+          width: 240px;
+        }
+      }
+    }
+    .interval{
+      display: flex;
+      align-items: center;
+      margin-bottom: 20px;
+      span{
+        margin-right: 10px;
+        white-space: nowrap;
+      }
+      .el-select{
+        width: 140px;
+      }
+    }
+	}
+  .dia-bot {
+		margin: 60px 0 0;
+		display: flex;
+		justify-content: center;
+	}
+}
+.check-fail-box{
+  padding: 0 0 15px 40px;	
+  color: #333333;
+  .check-fail-button{
+    margin-top: 80px;
+    display: flex;
+    justify-content: flex-end;
+  }
+}
+.edb-table-preview {
+  overflow: auto;
+  height: calc(100% - 124px);
+  &::-webkit-scrollbar {
+    width: 5px !important;
+  }
+  table {
+    border-color: #dcdfe6;
+    border-bottom: 1px solid #dcdfe6;
+    border-right: 1px solid #dcdfe6;
+    border-collapse: separate;
+  }
+  td {
+    height: 30px;
+    // text-align: center;
+    color: #333;
+    box-sizing: border-box;
+    padding: 0 5px;
+    background-color: #fff;
+    border-top: 1px solid #dcdfe6;
+    border-left: 1px solid #dcdfe6;
+  }
+  .body-td{
+    max-width: 217px;
+    min-width: 217px;
+  }
+  thead {
+    position: sticky;
+    z-index: 2;
+    top: 0;
+  }
+  .td-box{
+    height: 100%;
+    width: 100%;
+    overflow: auto;
+    .data-item{
+      border-bottom: 1px solid #dcdfe6;
+      padding: 0 5px;
+      box-sizing: border-box;
+      min-height: 30px;
+      display: flex;
+      align-items: center;
+      flex-wrap: wrap;
+      gap: 8px;
+      span{
+        white-space: nowrap;
+      }
+    }
+  }
+  .exist-highlight{
+    border: red solid 1px;
+  }
+}
+</style>
+<style lang="scss">
+.edb-table-preview{
+  border: 1px solid #dcdfe6;
+  .el-cascader{
+    width: 100%;
+  }
+  .el-autocomplete{
+    width: 100%;
+  }
+  .el-select{
+    width: 100%;
+  }
+  .el-input{
+    width: 100%;
+    input{
+      border: none;
+      padding-left: 7px;
+      font-size: 14px;
+    }
+  }
+}
+</style>

+ 473 - 0
src/views/dataEntry_manage/thirdBase/components/highFrequency/addToIndexDatabaseBatch.vue

@@ -0,0 +1,473 @@
+<template>
+  <el-dialog :visible.sync="isAddShow" :close-on-click-modal="false" :modal-append-to-body='false' 
+  @close="cancelHandle" top="5vh" center width="1090px" v-dialogDrag 
+  :title="$t('HighFrequencyData.add_high_frequency_data')">
+    <div class="dialog-container" v-loading="isLoadingData" :element-loading-text="$t('Table.loading')">
+      <div class="data-set-box" v-if="baseAddStep==1">
+        <div class="zone-title">{{ $t('HighFrequencyData.data_transformation') }} </div>
+        <div class="data-set-row">
+          <!-- 取指定时间的值 -->
+          <el-radio v-model="dataSetParams.getMethod" :label="1">{{ $t('HighFrequencyData.get_point_time') }}</el-radio>
+          <div class="radio-box" v-show="dataSetParams.getMethod==1" style="padding-left: 76px;">
+            <div class="time-item" style="width: 234px;">
+              <el-radio v-model="dataSetParams.pointTimeType" :label="1" 
+              @change="(value)=> radioChangeHandle(value,'pointTimeValue')">{{ $t('HighFrequencyData.today') }}</el-radio>
+              <el-time-picker v-show="dataSetParams.pointTimeType==1"
+                class="time-picker" value-format="HH:mm:ss"
+                v-model="dataSetParams.pointTimeValue"
+                :placeholder="$t('Edb.InputHolderAll.input_time')">
+              </el-time-picker>
+            </div>
+            <div class="time-item">
+              <el-radio v-model="dataSetParams.pointTimeType" :label="2" 
+              @change="(value)=> radioChangeHandle(value,'pointTimeValue')">{{ $t('HighFrequencyData.yesterday') }}</el-radio>
+              <el-time-picker v-show="dataSetParams.pointTimeType==2"
+                class="time-picker" value-format="HH:mm:ss"
+                v-model="dataSetParams.pointTimeValue"
+                :placeholder="$t('Edb.InputHolderAll.input_time')">
+              </el-time-picker>
+            </div>
+          </div>
+        </div>
+        <div class="data-set-row">
+          <el-radio v-model="dataSetParams.getMethod" :label="2">{{ $t('HighFrequencyData.get_range_time') }}</el-radio>
+          <!-- 起始时间 -->
+          <div class="radio-box" v-show="dataSetParams.getMethod==2">
+            <div class="data-set-row-text">{{ $t('Edb.Detail.e_start_time') }}</div>
+            <div class="time-item" style="width: 234px;">
+              <el-radio v-model="dataSetParams.rangeStartTimeType" :label="1"
+              @change="(value)=> radioChangeHandle(value,'rangeStartTimeValue')">{{ $t('HighFrequencyData.today') }}</el-radio>
+              <el-time-picker v-show="dataSetParams.rangeStartTimeType==1"
+                class="time-picker" value-format="HH:mm:ss"
+                v-model="dataSetParams.rangeStartTimeValue"
+                :placeholder="$t('Edb.InputHolderAll.input_time')">
+              </el-time-picker>
+            </div>
+            <div class="time-item">
+              <el-radio v-model="dataSetParams.rangeStartTimeType" :label="2"
+              @change="(value)=> radioChangeHandle(value,'rangeStartTimeValue')">{{ $t('HighFrequencyData.yesterday') }}</el-radio>
+              <el-time-picker v-show="dataSetParams.rangeStartTimeType==2"
+                class="time-picker" value-format="HH:mm:ss"
+                v-model="dataSetParams.rangeStartTimeValue"
+                :placeholder="$t('Edb.InputHolderAll.input_time')">
+              </el-time-picker>
+            </div>
+          </div>
+          <!-- 截止时间 -->
+          <div class="radio-box" v-show="dataSetParams.getMethod==2">
+            <div class="data-set-row-text">{{ $t('Edb.Detail.e_deadline_time') }}</div>
+            <div class="time-item" style="width: 234px;">
+              <el-radio v-model="dataSetParams.rangeDeadlineTimeType" :label="1"
+              @change="(value)=> radioChangeHandle(value,'rangeDeadlineTimeValue')">{{ $t('HighFrequencyData.today') }}</el-radio>
+              <el-time-picker v-show="dataSetParams.rangeDeadlineTimeType==1"
+                class="time-picker" value-format="HH:mm:ss"
+                v-model="dataSetParams.rangeDeadlineTimeValue"
+                :placeholder="$t('Edb.InputHolderAll.input_time')">
+              </el-time-picker>
+            </div>
+            <div class="time-item">
+              <el-radio v-model="dataSetParams.rangeDeadlineTimeType" :label="2"
+              @change="(value)=> radioChangeHandle(value,'rangeDeadlineTimeValue')">{{ $t('HighFrequencyData.yesterday') }}</el-radio>
+              <el-time-picker v-show="dataSetParams.rangeDeadlineTimeType==2"
+                class="time-picker" value-format="HH:mm:ss"
+                v-model="dataSetParams.rangeDeadlineTimeValue"
+                :placeholder="$t('Edb.InputHolderAll.input_time')">
+              </el-time-picker>
+            </div>
+          </div>
+          <!-- 计算方式 -->
+          <div class="radio-box" v-show="dataSetParams.getMethod==2">
+            <div class="data-set-row-text">{{ $t('Edb.Detail.calculation_mode') }}</div>
+            <el-radio v-model="dataSetParams.calculationMode" :label="1" style="margin-right: 20px;">{{ $t('HighFrequencyData.range_average_value') }}</el-radio>
+            <el-radio v-model="dataSetParams.calculationMode" :label="2" style="margin-right: 20px;">{{ $t('HighFrequencyData.range_max_value') }}</el-radio>
+            <el-radio v-model="dataSetParams.calculationMode" :label="3" style="margin-right: 20px;">{{ $t('HighFrequencyData.range_min_value') }}</el-radio>
+          </div>
+        </div>
+      </div>
+      <template v-else>
+        <div class="data-show-box" v-if="baseAddStep==2?(dataList && dataList.length>0):(existDataList && existDataList.length>0)">
+          <div class="zone-title" style="margin-bottom: 10px;">{{ $t('HighFrequencyData.edb_save') }}</div>
+          <el-table :data="baseAddStep==2?dataList:existDataList" border max-height="440px">
+            <el-table-column :label="$t('EtaBasePage.origin_full_metric_name')" align="center" prop="IndexName"/>
+            <el-table-column :label="$t('EtaBasePage.gen_metric_name_label')" align="center" prop="NewIndexName">
+              <template slot-scope="scope">
+                <el-input v-model="scope.row.NewIndexName" size="mini" class="table-input" :placeholder="$t('EtaBasePage.metric_name_input')"/>
+              </template>
+            </el-table-column>
+            <el-table-column :label="$t('Edb.Detail.e_unit')" align="center" width="80px" prop="Unit" />
+            <el-table-column :label="$t('Edb.Detail.e_fre')" align="center" width="80px" prop="NewFrequency" />
+            <el-table-column align="center" width="210px">
+              <template slot="header" slot-scope="scope">
+                <span style="margin-right:8px;display:inline-block"> <!-- 目录 -->{{$t('EtaBasePage.catalogue_directory')}}</span>
+                <el-radio-group v-model="classifyType" @change="handleClassifyTypeChange">
+                  <el-radio :label="0" style="margin-right: 8px;"><!-- 同目录 -->{{$t('EtaBasePage.directory_radio')}}</el-radio>
+                  <el-radio :label="1"><!-- 分目录 -->{{$t('EtaBasePage.subdirectory_radio')}}</el-radio>
+                </el-radio-group>
+              </template>
+              <template slot-scope="{row,$index}">
+                <el-cascader size="mini"
+                  v-model="row.ClassifyId"
+                  :options="classifyOpt"
+                  :props="levelProps"
+                  :placeholder="$t('Edb.InputHolderAll.input_menu')"
+                  :disabled="(classifyType===0&&$index>0)"
+                  @change="handleClassifyChange(row,$index)"/>
+              </template>
+            </el-table-column>
+            <el-table-column align="center" width="50px">
+              <template slot="header" slot-scope="scope">
+                <img src="~@/assets/img/icons/delete-red.png" class="delete-icon" @click="deleteAllHandle"/>
+              </template>
+              <template slot-scope="{row,$index}">
+                <img src="~@/assets/img/icons/delete-red.png" class="delete-icon" @click="deleteHandle(row,$index)"/>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <tableNoData v-else></tableNoData>
+      </template>
+    </div>
+    <div class="dialog-btn">
+      <template v-if="baseAddStep==1">
+        <el-button type="primary" plain @click="cancelHandle" >{{$t('Dialog.cancel_btn')}}</el-button>
+        <el-button type="primary" @click="nextHandle" :disabled="!isCodeComplete"
+          style="min-width: 120px;" :loading="isLoadingData" ><!-- 下一步 -->{{$t('EtaBasePage.next_step')}}
+        </el-button>
+      </template>
+      <template v-else>
+        <el-button @click="prevHandle" style="min-width: 120px;" :loading="isLoadingData"><!-- 上一步 -->{{$t('Dialog.prev_step')}}</el-button>
+        <el-button type="primary" @click="addToDatabase" v-if="baseAddStep!=1" :loading="isLoadingData">{{$t('Dialog.confirm_btn')}}</el-button>
+      </template>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+import { highFrequencyDataInterface } from '@/api/api.js'
+
+  export default {
+    name:"addToIndexDatabaseBatch",
+    props: {
+      isAddShow: {
+        type: Boolean,
+        default:false
+      },
+      IndexIds:{
+        type: Array,
+        default:() =>[]
+      }
+    },
+    data() {
+      return {
+        classifyOpt:[],
+        levelProps: {
+          label: 'ClassifyName',
+          value: 'ClassifyId',
+          children: 'Children',
+          checkStrictly: true,
+          emitPath:false
+        },
+        baseAddStep:1,
+        dataSetParams:{
+          getMethod:1,
+          pointTimeType:1,
+          pointTimeValue:'09:30:00',
+          rangeStartTimeType:1,
+          rangeStartTimeValue:'09:30:00',
+          rangeDeadlineTimeType:1,
+          rangeDeadlineTimeValue:'09:30:00',
+          calculationMode:1
+        },
+        isLoadingData:false,
+        dataList:[],
+        existDataList:[],//重复的数据
+        existDataDeleteIds:[],//重复数据中删除id列表
+        classifyType:0
+      }
+    },
+    watch:{
+      isAddShow(value){
+        if(value){
+          this.getClassifyOpt()
+        }
+      }
+    },
+    computed:{
+      isCodeComplete(){
+        return (this.dataSetParams.getMethod==1 && this.dataSetParams.pointTimeValue && this.dataSetParams.pointTimeType) || 
+              (this.dataSetParams.getMethod==2 && this.dataSetParams.rangeStartTimeValue && this.dataSetParams.rangeStartTimeType 
+                && this.dataSetParams.rangeDeadlineTimeValue && this.dataSetParams.rangeDeadlineTimeType  && this.dataSetParams.calculationMode) 
+      },
+    },
+    methods: {
+      // 获取指标分类
+      async getClassifyOpt(){
+        const res=await dataBaseInterface.menuListV3()
+        if (res.Ret !== 200) return
+        this.filterNodes(res.Data.AllNodes||[]);
+        this.classifyOpt = res.Data.AllNodes || [];
+      },
+      filterNodes(arr) {
+        arr.length &&
+          arr.forEach((item) => {
+            item.Children.length && this.filterNodes(item.Children);
+            if (!item.Children.length) {
+              delete item.Children;
+            }
+          });
+      },
+      radioChangeHandle(value,prop){
+        switch (value) {
+          case 1:
+            this.dataSetParams[prop]="09:30:00"
+            break;
+          case 2:
+            this.dataSetParams[prop]="21:30:00"
+            break;
+          default:
+            break;
+        }
+      },
+      // 同目录修改
+      handleClassifyChange(e,index){
+        if(this.classifyType===0){
+          // 修改所有的指标的目录为第一个
+          this.dataList.forEach(item=>{
+            item.ClassifyId=e.ClassifyId
+          })
+        }
+      },
+      handleClassifyTypeChange(){
+        this.handleClassifyChange(this.dataList[0])
+      },
+      cancelHandle(){
+        this.dataSetParams={
+          getMethod:1,
+          pointTimeType:1,
+          pointTimeValue:'09:30:00',
+          rangeStartTimeType:1,
+          rangeStartTimeValue:'09:30:00',
+          rangeDeadlineTimeType:1,
+          rangeDeadlineTimeValue:'09:30:00',
+          calculationMode:1
+        }
+        this.baseAddStep=1
+        this.dataList=[]
+        this.isLoadingData=false
+        this.existDataList=[]
+        this.existDataDeleteIds=[]
+        this.classifyType=0
+        this.$emit('update:isAddShow',false)
+      },
+      nextHandle(){
+        if(this.dataSetParams.getMethod==2){
+          let StartTime = this.$moment('2024-07-10 '+this.dataSetParams.rangeStartTimeValue).subtract(this.dataSetParams.rangeStartTimeType-1,'days') .format('YYYY-MM-DD HH:mm:ss')
+          let EndTime = this.$moment('2024-07-10 '+this.dataSetParams.rangeDeadlineTimeValue).subtract(this.dataSetParams.rangeDeadlineTimeType-1,'days') .format('YYYY-MM-DD HH:mm:ss')
+          if(!(new Date(EndTime)>new Date(StartTime))){
+            return this.$message.warning(this.$t('HighFrequencyData.start_time_right_end_time'))
+          }
+        }
+        setTimeout(()=>{
+          if(this.isCodeComplete){
+            let params={
+              ConvertRule:{
+                ConvertType:this.dataSetParams.getMethod,
+                ConvertFixed:{
+                  FixedDay:this.dataSetParams.pointTimeType,
+                  FixedTime:this.dataSetParams.pointTimeValue,
+                },
+                ConvertArea:{
+                  StartDay:this.dataSetParams.rangeStartTimeType,
+                  StartTime:this.dataSetParams.rangeStartTimeValue,
+                  EndDay:this.dataSetParams.rangeDeadlineTimeType,
+                  EndTime:this.dataSetParams.rangeDeadlineTimeValue,
+                  CalculateType:this.dataSetParams.calculationMode
+                },
+              },
+              IndexIds:this.IndexIds
+            }
+            // console.log(params,'params');
+            this.isLoadingData=true
+            highFrequencyDataInterface.highFreDataSavePre(params).then(res=>{
+              if(res.Ret == 200){
+                this.dataList=res.Data||[]
+                this.baseAddStep=2
+              }
+            }).finally(()=>{
+              this.isLoadingData=false
+            })
+          }
+        },10)
+      },
+      prevHandle(){
+        this.baseAddStep = this.baseAddStep-1 || 1
+      },
+      deleteHandle(row,index){
+        if(this.baseAddStep==2){
+          this.dataList.splice(index,1)
+        }else{
+          this.existDataDeleteIds.push(row.IndexId)
+          this.existDataList.splice(index,1)
+        }
+      },
+      deleteAllHandle(){
+        if(this.baseAddStep==2){
+          this.dataList=[]
+        }else{
+          this.existDataDeleteIds=this.existDataList.map(it => it.IndexId)
+          this.existDataList=[]
+        }
+      },
+      addToDatabase(){
+        for (let i = 0; i < this.dataList.length; i++) {
+          const element = this.dataList[i];
+          if(!element.NewIndexName){
+            return this.$message.warning(this.$t('EtaBasePage.metric_name_input'))
+          }
+          if(!element.ClassifyId){
+            return this.$message.warning(this.$t('Edb.InputHolderAll.input_menu'))
+          }
+        }
+        if(this.existDataDeleteIds && this.existDataDeleteIds.length>0){
+          // 处理重复数据时,删除掉了部分
+          this.dataList = this.dataList.filter(it => !this.existDataDeleteIds.includes(it.IndexId))
+        }
+        (this.existDataList && this.existDataList.length>0) && this.dataList.map(item =>{
+          let existItem = this.existDataList.find(it => it.IndexId == item.IndexId)
+          if(existItem){
+            item.NewIndexName=existItem.NewIndexName
+            item.ClassifyId=existItem.ClassifyId
+          }
+        })
+        // console.log(this.dataList,'this.dataList');
+        let params={
+          ConvertRule:{
+            ConvertType:this.dataSetParams.getMethod,
+            ConvertFixed:{
+              FixedDay:this.dataSetParams.pointTimeType,
+              FixedTime:this.dataSetParams.pointTimeValue,
+            },
+            ConvertArea:{
+              StartDay:this.dataSetParams.rangeStartTimeType,
+              StartTime:this.dataSetParams.rangeStartTimeValue,
+              EndDay:this.dataSetParams.rangeDeadlineTimeType,
+              EndTime:this.dataSetParams.rangeDeadlineTimeValue,
+              CalculateType:this.dataSetParams.calculationMode
+            },
+          },
+          NewIndexes:this.dataList
+        }
+        this.isLoadingData=true
+        highFrequencyDataInterface.highFreDataSave(params).then(res=>{
+          if(res.Ret == 200){
+            let resData = res.Data||{}
+            this.existDataList=[]
+            this.existDataDeleteIds=[]
+            let allSuccess=true
+            if(resData.Exist && resData.Exist.length>0){
+              // 已存在              
+              this.existDataList = [...this.existDataList,...resData.Exist]
+              this.baseAddStep=3
+              this.$message.warning(this.$t('HighFrequencyData.index_has_exist_prompt'))
+              allSuccess=false
+            }
+            if(resData.Fail && resData.Fail.length>0){
+              let message = '';
+              resData.Fail.forEach(item => {
+                message+=`${item.NewIndexName}:${this.$t('MsgPrompt.add_fail_msg')}</br>`
+              })
+              // 失败的
+              this.existDataList = [...this.existDataList,...resData.Fail]
+              this.baseAddStep=3
+              this.$message.error(message)
+              allSuccess=false
+            }
+            if(allSuccess){
+              this.$message.success(this.$t('MsgPrompt.add_msg2'))
+              this.cancelHandle()	
+            }
+          }
+        }).finally(()=>{
+          this.isLoadingData=false
+        })
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+.dialog-container{
+  padding: 0 35px 35px;
+  .zone-title{
+    font-size: 16px;
+    line-height: 24px;
+    font-weight: bold;
+    color: #333333;
+  }
+  .data-set-box{
+    .data-set-row{
+      padding-top: 10px;
+      .radio-box{
+        margin-top: 20px;
+        display: flex;
+        align-items: center;
+        .data-set-row-text{
+          margin-right: 20px;
+        }
+        .time-item{
+          margin-right: 40px;
+          display: flex;
+          align-items: center;
+          .el-radio{
+            margin-right: 10px;
+          }
+          .el-input{
+            width: 172px;
+          }
+        }
+      }
+    }
+  }
+  .data-show-box{
+    margin-top: 20px;
+  }
+}
+.dialog-btn{
+  text-align: center;
+  padding: 40px 0 25px;
+  .el-button{
+    min-width: 120px;
+  }
+}
+.delete-icon{
+  height: 16px;
+  width: 16px;
+  cursor: pointer;
+}
+</style>
+<style lang="scss">
+.data-show-box{
+  .el-input{
+    width: 100%;
+    input{
+      border: none;
+      text-align: center;
+    }
+  }
+  .table-input{
+    input{
+      padding: 0;
+    }
+  }
+  .el-table tr{
+    background-color: #fff !important;
+    &:hover>td{
+        background-color: transparent !important; /* 或者其他想要的颜色值 */
+    }
+  }
+  .el-table td{
+    padding: 10px 0;
+  }
+}
+</style>

+ 635 - 0
src/views/dataEntry_manage/thirdBase/components/highFrequency/classifySetting.vue

@@ -0,0 +1,635 @@
+<template>
+  <div>
+    <el-dialog :visible.sync="showIt" :close-on-click-modal="false" append-to-body v-dialogDrag top="5vh"
+    width="600px" :title="$t('HighFrequencyData.classify_setting')" @close="classifySetClose">
+      <div class="dialog-container">
+        <el-tree
+          ref="treeRef"
+          class="target_tree"
+          :data="classify"
+          node-key="UniqueCode"
+          :props="defaultProp"
+          :allow-drag="canDragHandle"
+          :allow-drop="canDropHandle"
+          :current-node-key="select_node"
+          :default-expanded-keys="defaultShowNodes"
+          draggable
+          :expand-on-click-node="false"
+          check-strictly
+          :empty-text="$t('Common.no_classify_msg')"
+          lazy
+          :load="getLazyTreeData"
+          @node-expand="handleNodeExpand"
+          @node-collapse="handleNodeCollapse"
+          @current-change="nodeChange"
+          @node-drop="dropOverHandle"
+          @node-drag-end="dropMouseLeave"
+          @node-drag-leave="dropMouseLeave"
+          @node-drag-enter="dropMouseOver"
+        >
+          <span class="custom-tree-node" slot-scope="{ node, data }">
+            <el-input
+              ref="editVal"
+              class="label-input"
+              v-model="new_label"
+              v-if="data.isEdit"
+              @blur="changeValue(node, data)"
+            />
+            <span
+              @dblclick.stop="editNodeLabel(node, data)"
+              v-else
+              class="text_oneLine node_label"
+              :id="`node${data.UniqueCode}`"
+            > 
+              <span v-if="data.IndexId">{{ data.IndexName }}</span>
+              <span v-else>{{ currentLang==='en' ? (data.ClassifyNameEn || data.ClassifyName) : data.ClassifyName }}</span>
+            </span>
+            <span
+              style="display: flex; align-items: center"
+              v-if="select_node === data.UniqueCode"
+            >
+              <img
+                src="~@/assets/img/data_m/move_ico.png"
+                alt=""
+                style="width: 14px; height: 14px; margin-right: 8px"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_classify_move"
+              />
+              <!-- 添加子项 -->
+              <img
+                v-if="!data.IndexId && data.Level<6"
+                src="~@/assets/img/set_m/add.png"
+                style="width: 14px; height: 14px; margin-right: 8px"
+                @click.stop="addNode(node, data)"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_classify_editAdd"
+              />
+              <!-- 编辑子项 -->
+              <img
+                v-if="!data.IndexId"
+                src="~@/assets/img/set_m/edit.png"
+                style="width: 15px; height: 14px; margin-right: 8px"
+                @click.stop="editNode(node, data)"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_classify_editAdd"
+              />
+              <!-- 删除子项 -->
+              <img
+                v-if="!data.IndexId"
+                slot="reference"
+                src="~@/assets/img/set_m/del.png"
+                style="width: 14px; height: 14px"
+                @click.stop="removeNode(node, data)"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_classify_delete"
+              />
+            </span>
+          </span>
+        </el-tree>
+        <div class="add-top-classify" @click="addLevelOneHandle" v-permission="permissionBtn.dataSourcePermission.highFrequency_classify_editAdd">
+          <img
+            src="~@/assets/img/sand_new/add_ico.png"
+            alt=""
+            style="width: 16px; height: 16px; margin-right: 10px"
+          />
+          <span>{{$t('EtaBasePage.add_first_menu_btn')}}</span>
+        </div>
+      </div>
+    </el-dialog>
+    <!-- 新增、编辑目录 -->
+    <el-dialog
+      :visible.sync="isOpenDialog"
+      :close-on-click-modal="false"
+      append-to-body 
+      @close="cancelHandle"
+      custom-class="dialog"
+      center
+      width="560px"
+      v-dialogDrag>
+        <div slot="title" style="display:flex;align-items:center;">
+          <img :src="title=='添加'?$icons.add:title=='编辑'?$icons.edit:''" style="color:#fff;width:16px;height:16px;margin-right:5px;">
+          <span style="font-size:16px;">{{title==='添加' ? $t('Table.add_btn') : $t('Table.edit_btn')}}</span>
+        </div>
+        <div class="dialog-main">
+          <el-form
+          ref="diaForm"
+          label-position="left"
+          hide-required-asterisk
+          label-width="120px"
+          :model="dialogForm"
+          :rules="formRules">
+              <el-form-item :label="$t('EtaBasePage.parent_menu')" v-if="dialogForm.level>0">
+                <el-tooltip class="item" effect="dark" :content="getParentName" placement="top">
+                      <span class="parentStr">{{getParentName}}</span>
+                  </el-tooltip>
+              </el-form-item>
+              <el-form-item :label="$t('EtaBasePage.menu_name')" prop="levelVal">
+                <el-input
+                v-model="dialogForm.levelVal"
+                style="width: 80%"
+                :placeholder="$t('Dialog.require_vaild')"></el-input>
+              </el-form-item>
+          </el-form>
+        </div>
+        <div class="dia-bot">
+          <el-button type="primary" style="margin-right:20px" @click="saveHandle"><!-- 保存 -->{{$t('Dialog.confirm_save_btn')}}</el-button>
+          <el-button type="primary" plain @click="cancelHandle"><!-- 取消 -->{{$t('Dialog.cancel_btn')}}</el-button>
+        </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { highFrequencyDataInterface } from '@/api/api.js'
+  export default {
+    name:'classifySetting',
+    props:{
+      showIt:{
+        Type:Boolean,
+        default:false
+      }
+    },
+    computed:{
+      currentLang() {
+        return this.$store.state.lang
+      },
+      getParentName(){
+        const arr=this.dialogForm.parentArr||[]
+        let strArr=arr.reverse().map(item=>{
+          return this.currentLang==='en'?item.classifyNameEn:item.classifyName
+        })
+        
+        return strArr.join('/')
+      }
+    },
+    data() {
+      return {
+        classify:[],
+        defaultProp: {
+          label: 'ClassifyName',
+          children: 'Children',
+          isLeaf:'isLeaf'
+        },//树结构配置项
+        select_node:'',//当前选中的节点
+        defaultShowNodes:[], //默认展开的节点
+        new_label: '',//新的节点label值
+        formRules: {
+          levelVal:[
+            { required: true, message: this.$t('EtaBasePage.input_menu_msg'), trigger: 'blur' },
+          ]
+        },
+        dialogForm:{
+          level:''
+        },
+        title:"",
+
+        requestDataList:false, //是否需要请求数据列表 修改分类名名称 移动分类、指标位置
+        requestClassifyList:false,//是否需要请求分类列表(筛选项中的) 新增、修改、删除、移动分类位置
+      }
+    },
+    watch:{
+      showIt(value){
+        if(value){
+          this.requestDataList=false
+          this.requestClassifyList=false
+          this.getClassify()
+        }
+      }
+    },
+    methods: {
+      //控制页面按钮权限
+      canBtnShow(type){
+        const {dataSourcePermission,checkPermissionBtn}=this.permissionBtn
+        const BtnMap = {
+          'editAddClassify':dataSourcePermission.highFrequency_classify_editAdd,//编辑/添加分类
+          'moveClassify':dataSourcePermission.highFrequency_classify_move,//移动分类
+        }
+        return checkPermissionBtn(BtnMap[type])
+      },
+      getClassify(){
+        highFrequencyDataInterface.classifyList({ParentId:0}).then(res=>{
+          if(res.Ret == 200){
+            this.classify=res.Data||[]
+            this.classify.map(cl => cl.Children || (cl.Children=[]))
+            console.log(this.classify,'classify');
+          }
+        })
+      },
+      //绑定el-tree的load属性
+      async getLazyTreeData (node,resolve){
+        console.log(node);
+        if(node.level===0){
+          resolve(this.classify)
+        }else{
+          let arr=[]
+          const res=await highFrequencyDataInterface.classifyList({ParentId:node.data.ClassifyId})
+          if (res.Ret === 200) {
+            const temarr = res.Data || [];
+            arr=temarr.map(item=>{
+              return {
+                ...item,
+                isLeaf:item.IndexId?true:false,
+                Children:[]
+              }
+            })
+          }
+          resolve(arr)
+        }
+        this.select_node && this.$refs.treeRef && this.$nextTick(() => {
+          this.$refs.treeRef.setCurrentKey(this.select_node);
+          let node = document.getElementById(`node${this.select_node}`)||{}
+          let parent = document.getElementsByClassName('target_tree')[0];
+          //parent可视区间:[scrollTop,scrollTop+offsetHeight]
+          //node位置:node.offsetTop
+          const overTop = node.offsetTop+node.clientHeight+30<parent.scrollTop
+          const overBottom = node.offsetTop+node.clientHeight+30>parent.scrollTop+parent.offsetHeight
+          if(overTop){
+            parent.scrollTop = node.offsetTop-60
+          }
+          if(overBottom){
+            parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
+          }
+        });
+      },
+      // 树节点展开
+      handleNodeExpand (data) {
+        // 保存当前展开的节点
+        let flag = this.defaultShowNodes.some((item) => item === data.UniqueCode);
+        if (!flag) { // 不存在则存到数组里
+          this.defaultShowNodes.push(data.UniqueCode)
+        }
+      },
+      // 树节点关闭
+      handleNodeCollapse (data) {
+        this.defaultShowNodes.some((item, index) => {
+          if (item === data.UniqueCode) {
+            // 删除关闭节点
+            this.defaultShowNodes.length = index
+          }
+        })
+      },
+      /* 节点变化时 */
+      nodeChange(data,node) {
+        this.select_node = data.UniqueCode;
+      },
+      /* 判断节点是否能被拖拽 */
+      canDragHandle({data}) {
+        return this.canBtnShow('moveClassify')
+      },
+      /* 判断节点是否能被拖入 */
+      canDropHandle(draggingNode, dropNode, type) {
+        let canDrop=false
+        
+        // 如果拖动的是指标
+        if(draggingNode.data.IndexId){
+          if(!(dropNode.level===1&&type!=='inner')){
+            canDrop=true
+          }
+        }else{//拖动的是目录
+          // console.log(dropNode.level,draggingNode.level);
+          //目录层级不能改变
+          if((dropNode.level+1==draggingNode.level&&type==='inner'&&!dropNode.data.IndexId)||(dropNode.level===draggingNode.level&&type!=='inner')){
+            canDrop=true
+          }
+        }
+        return canDrop
+      },
+      /* 拖拽完成 */
+      dropOverHandle(b,a,i,e) {
+        // 被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置
+        console.log(b,a,i);
+        const isIndex=b.data.IndexId?true:false
+        let list=a.parent.childNodes;
+        let targetIndex=0,PrevClassifyId=0,NextClassifyId=0,ParentClassifyId=0;
+        let ClassifyId=0,ItemId=0,PrevItemId=0,NextItemId=0;
+
+        ClassifyId=isIndex?0:b.data.ClassifyId
+        ItemId=isIndex?b.data.IndexId:0
+        
+
+        if(i!=='inner'){
+          ParentClassifyId=a.parent.data.ClassifyId||0
+          list.forEach((item,index)=>{
+            if(isIndex){
+              if(item.data.IndexId===b.data.IndexId){
+                targetIndex=index
+              }
+            }else{
+              if(item.data.ClassifyId===b.data.ClassifyId){
+                targetIndex=index
+              }
+            }
+            
+          })
+
+          console.log(targetIndex);
+          
+          if(targetIndex===0){
+            const data=list[targetIndex+1].data
+            NextClassifyId=data.EdbCode?0:data.ClassifyId
+            NextItemId=data.EdbCode?data.IndexId:0
+          }else if(targetIndex===list.length-1){
+            const data=list[targetIndex-1].data
+            PrevClassifyId=data.EdbCode?0:data.ClassifyId
+            PrevItemId=data.EdbCode?data.IndexId:0
+          }else{
+            const pData=list[targetIndex-1].data
+            PrevClassifyId=pData.EdbCode?0:pData.ClassifyId
+
+            PrevItemId=pData.EdbCode?pData.IndexId:0
+
+            const nData=list[targetIndex+1].data
+            NextClassifyId=nData.EdbCode?0:nData.ClassifyId
+            NextItemId=nData.EdbCode?nData.IndexId:0
+          }
+        }else{
+          ParentClassifyId=a.data.ClassifyId||0
+        }
+
+        const params={
+          ClassifyId,
+          ParentClassifyId,
+          ItemId,
+          PrevClassifyId,
+          NextClassifyId,
+          PrevItemId,
+          NextItemId
+        }
+        // console.log(params);
+        highFrequencyDataInterface.classifyMove(params).then(res=>{
+          if(res.Ret===200){
+            this.$message.success(this.$t('MsgPrompt.move_sort_success'))
+          }
+          this.requestDataList=true
+          !isIndex && (this.requestClassifyList=true)
+          if(i=='inner'){
+            let code = a.data.UniqueCode
+            let flag = 	this.defaultShowNodes.some((item) => {
+              return item === code
+            });
+            code && !flag && this.defaultShowNodes.push(code);
+          }
+
+
+          this.getClassify() 
+        })
+      },
+      /* 拖拽覆盖添加背景色 */
+      dropMouseOver(node1,node2,e) {
+        // console.log(e.layerY);
+        // 被拖拽节点对应的 Node、所进入节点对应的 Node、event
+        if(!node2.data.IndexId&&(node1.level>node2.level||(node1.data.IndexId>0&&!node2.data.IndexId)) && (e.target.childNodes[0].className.includes('el-tree-node__content') 
+        || e.target.className.includes('el-tree-node__content'))) {
+          // console.log(e.target.childNodes[0])
+          e.target.childNodes[0].className.includes('el-tree-node__content') 
+          ? e.target.childNodes[0].style.backgroundColor = '#409eff' 
+          : e.target.style.backgroundColor = '#409eff';
+        }
+      },
+      /* 拖拽离开/拖拽完成重置背景色 */
+      dropMouseLeave(node1,node2,e) {
+        let arrs = $('.el-tree-node__content');
+        for( let a of arrs ) {
+          a.style.backgroundColor = 'transparent';
+        }
+      },
+      /* 双击label出现input修改框 */
+      editNodeLabel(node, data) {
+        //目录名称可以双击修改 指标不能
+        if(!data.IndexId &&this.canBtnShow('editAddClassify')) {
+          this.$set(data,'isEdit',true)
+          this.new_label = this.currentLang==='en' ? data.ClassifyNameEn : data.ClassifyName;
+          this.$nextTick(() => {
+            this.$refs.editVal.focus();
+          });
+        }
+      },
+      /* input失去焦点恢复node 修改最新的值*/
+      changeValue(node, data) {
+        this.$set(data,'isEdit',false)
+        if(!this.new_label) return this.$message.warning(this.$t('MsgPrompt.name_none'))
+        if(this.new_label!=(this.currentLang==='en' ? data.ClassifyNameEn : data.ClassifyName)) {
+          highFrequencyDataInterface.classifyEdit({
+            ClassifyId: data.ClassifyId,
+            ClassifyName: this.new_label
+          }).then(res => {
+            if(res.Ret === 200) {
+              this.getClassify();
+            }
+          })
+        }
+      },
+      /* 添加节点 */
+      addNode(node,data) {
+        this.title = '添加';
+        let arr=[]
+        arr=this.getNodeParentData(node,arr)
+        /* 添加目录 */
+        this.dialogForm = {
+          parentArr:arr,
+          parent_id: data.ClassifyId,
+          level: node.level,
+          levelVal:'',
+          uniqueCode:data.UniqueCode
+        }
+        this.isOpenDialog = true;
+      },
+      // 递归节点
+      getNodeParentData(data,arr){
+        if(data.level===0) return
+        arr.push({classifyName:this.currentLang==='en'?data.data.ClassifyNameEn:data.data.ClassifyName,classifyId:data.data.ClassifyId})
+        this.getNodeParentData(data.parent,arr)
+        return arr
+      },
+      /* 编辑节点 */
+      editNode(node,data) {
+        this.title = '编辑';
+        let arr=[]
+        arr=this.getNodeParentData(node.parent,arr)
+        /* 编辑目录 */
+        this.dialogForm = {
+          parentArr:arr,
+          levelVal: this.currentLang==='en'?data.ClassifyNameEn:data.ClassifyName,
+          classify_id: data.ClassifyId,
+          level: node.level-1,
+          uniqueCode:data.UniqueCode
+        }
+        this.isOpenDialog = true;
+      },
+      /* 删除节点校验 */
+      removeNode(node,data) {
+        this.$confirm(
+          this.$t('Edb.MsgPrompt.del_menu_confirm'),
+          /* 提示 */this.$t('Dialog.warn_tit'),
+          {
+          confirmButtonText: /* '确定' */this.$t('Dialog.confirm_btn'),
+          cancelButtonText: /* '取消' */this.$t('Dialog.cancel_btn'),
+          type: 'warning'
+        }).then(() => {
+          highFrequencyDataInterface.classifyDelete({
+            ClassifyId: data.ClassifyId,
+          }).then(res => {
+            if(res.Ret === 200) {
+            this.$message.success(this.$t('MsgPrompt.delete_msg'));
+            this.getClassify();
+            this.requestClassifyList=true
+          }
+          })
+        }).catch(() => {});
+      },
+      /* 添加一级目录 */
+      addLevelOneHandle() {
+        this.title = '添加';
+        this.dialogForm = {
+          parent_id: '',
+          level: 0,
+          levelVal:'',
+        }
+        this.isOpenDialog = true;
+      },
+      async saveHandle(){
+        await this.$refs.diaForm.validate();
+        let res = null;
+        if(this.title==='添加') {
+          res = await highFrequencyDataInterface.classifyAdd({
+            ClassifyName: this.dialogForm.levelVal||'',
+            ParentId:this.dialogForm.parent_id || 0,
+            Level: this.dialogForm.level
+          })
+        }else if(this.title==='编辑') {
+          res = await highFrequencyDataInterface.classifyEdit({
+            ClassifyName: this.dialogForm.levelVal||'',
+            ClassifyId:this.dialogForm.classify_id || 0
+          })
+        }
+        if(res.Ret !== 200) return
+        this.$message.success(res.Msg);
+        this.getClassify();
+        if(this.title==='添加'){
+          //新增分类完成之后,展开父节点显示刚新增的分类,若已展开节点则不做处理
+          let code = this.dialogForm.uniqueCode
+          let flag = 	this.defaultShowNodes.some((item) => {
+            return item === code
+          });
+          code && !flag && this.defaultShowNodes.push(code);
+        }else if(this.title==='编辑'){
+          this.requestDataList=true
+        }
+        this.requestClassifyList=true
+        this.cancelHandle()
+      },
+      cancelHandle(){
+        this.isOpenDialog=false
+        this.dialogForm={
+          level:''
+        }
+        this.$refs.diaForm.clearValidate();
+      },
+      classifySetClose(){
+        this.$emit('closeHandle',{requestClassifyList:this.requestClassifyList,requestDataList:this.requestDataList})
+      }
+    },
+    mounted(){
+      this.getClassify()
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .dialog-container{
+    padding: 0 35px 25px;
+  }
+  .parentStr{
+		display: block;
+		width: 304px;
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+	}
+	.dialog-main {
+		padding-left: 50px;
+	}
+	.el-cascader .el-input {
+		width: 100%;
+	}
+	.dia-bot {
+		margin: 52px 0 30px;
+		display: flex;
+		justify-content: center;
+
+	}
+</style>
+<style lang="scss">
+@import "~@/styles/theme-vars.scss";
+.target_tree {
+  color: #333;
+  height: 630px; 
+  overflow: auto;
+  .label-input .el-input__inner {
+    height: 25px;
+    line-height: 25px;
+  }
+  .el-input{
+    width: 100%;
+    padding-right: 10px;
+  }
+  .custom-tree-node {
+    display: flex !important;
+    justify-content: space-between;
+    align-items: center;
+    display: block;
+    flex: 1;
+    width: calc(100% - 30px);
+    .node_label {
+      margin-right: 2px;
+    }
+    .el-icon-view {
+      color: #409eff;
+      font-size: 18px;
+      margin-left: 5px;
+    }
+  }
+  .el-tree__drop-indicator{
+    height:3px;
+    background-color:$theme-color;
+  }
+  .el-tree-node__content {
+    margin-bottom: 10px !important;
+  }
+  .el-tree-node__children {
+    .el-tree-node {
+      margin-bottom: 0px !important;
+      padding-left: 18px;
+    }
+    .el-tree-node__content {
+      margin-bottom: 5px !important;
+      padding-left: 0 !important;
+    }
+  }
+  .expanded.el-icon-caret-right:before {
+    content: url('~@/assets/img/set_m/down_black.png') !important;
+  }
+  .el-icon-caret-right:before {
+    content: url('~@/assets/img/set_m/slide_black.png') !important;
+  }
+  .el-tree-node__expand-icon.is-leaf.el-icon-caret-right:before {
+    content: '' !important;
+  }
+  .el-tree-node__expand-icon.expanded {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  .el-tree-node.is-current > .el-tree-node__content {
+    background-color: #f0f4ff !important;
+  }
+  .el-tree-node__content {
+    padding-right: 10px !important;
+  }
+}
+.add-top-classify {
+  margin: 20px 0 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: $theme-color;
+  font-size: 16px;
+  cursor: pointer;
+}
+		
+</style>

+ 1022 - 0
src/views/dataEntry_manage/thirdBase/highFrequencyData.vue

@@ -0,0 +1,1022 @@
+<template>
+    <div class="hight-frequency-data-container">
+        <div class="top-box">
+            <div class="select-box">
+                <span>{{$t('SystemManage.DataRefresh.select_source')}}</span>
+                <el-select :placeholder="$t('SystemManage.DataRefresh.select_source_pld')" v-model="Source" @change="handleSourceChange">
+                    <el-option v-for="item in SourceList" :key="item.Source" 
+                    :label="$i18nt.locale==='zh'?item.SourceName:item.SourceNameEn||item.SourceName" :value="item.Source"/>
+                </el-select>
+                <el-select v-model="Sequence" @change="handleSequenceChange">
+                    <el-option v-for="item in SequenceList" :key="item.Sequence" 
+                    :label="$i18nt.locale==='zh'?item.SequenceName:item.SequenceNameEn||item.SequenceName" :value="item.Sequence"/>
+                </el-select>
+                <!-- 添加高频数据 -->
+                <el-button type="primary" @click="addHighFrequencyDiaShow" v-permission="permissionBtn.dataSourcePermission.highFrequency_adds"
+                >{{$t('HighFrequencyData.add_high_frequency_data')}}</el-button>
+            </div>
+        </div>
+        <div class="table-box">
+          <div class="table-select">
+            <div class="select-list">
+              <el-cascader :placeholder="$t('HighFrequencyData.select_classify_prompt')"
+                v-model="classifyArr" @change="searchListDelay" :options="classifyListTree" 
+                style="max-width: 160px;"
+                key="isAssociativeSub"
+                v-if="searchParams.isAssociativeSub"
+                :show-all-levels="false" collapse-tags
+                :props="classifyProps" 
+                clearable/>
+              <el-cascader :placeholder="$t('HighFrequencyData.select_classify_prompt')"
+                v-model="classifyArr" @change="searchListDelay" :options="classifyListTree" 
+                style="max-width: 160px;" v-else key="noIsAssociativeSub"
+                :show-all-levels="false" collapse-tags
+                :props="classifyProps" 
+                clearable/>
+              <div class="associative-box">
+                <span>{{$t('HighFrequencyData.associative_sub_classify')}}</span>
+                <el-switch v-model="searchParams.isAssociativeSub" @change="changeAssociativeSub"></el-switch>
+                <span class="span-button" @click="setClassify" 
+                v-permission="[permissionBtn.dataSourcePermission.highFrequency_classify_move,permissionBtn.dataSourcePermission.highFrequency_classify_delete,
+                  permissionBtn.dataSourcePermission.highFrequency_classify_editAdd,'or']"
+                >{{$t('HighFrequencyData.classify_setting')}}</span>
+              </div>
+              <el-select :placeholder="$t('Edb.InputHolderAll.input_fre')" v-model="frequencyArr" @change="searchListDelay" multiple collapse-tags clearable>
+                <el-option v-for="i in frequencyList" :key="i.value"
+                    :label="i.label" :value="i.value"
+                />
+              </el-select>
+              <el-cascader
+                :placeholder="$t('Edb.InputHolderAll.select_creator')" v-model="userArr" @change="searchListDelay"
+                :props="{
+                    value: 'ItemId',
+                    label: 'ItemName',
+                    children: 'Children',
+                    emitPath: false,
+                    multiple:true,
+                }"
+                :options="userList"
+                collapse-tags
+                :show-all-levels="false"
+                clearable
+                filterable 
+              />
+              <el-input :placeholder="$t('Edb.InputHolderAll.input_name_orid')" prefix-icon="el-icon-search" clearable
+              v-model="searchParams.keyWord" @input="searchList"></el-input>
+            </div>
+            <div class="select-other">
+              <el-checkbox :indeterminate="isIndeterminate" v-model="isCheckAll" @change="listCheckAllChange">{{$t('SystemManage.DataRefresh.all_list')}}</el-checkbox>
+              <!-- 批量添加到指标库 -->
+              <el-button type="primary" @click="batchAddToDatabaseOpen"
+                :disabled="!selectedTotal>0" :loading="batchLoading"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_addTo_database"
+              >{{$t('HighFrequencyData.add_to_eta_indicators')}}</el-button>
+              <!-- 批量操作 -->
+              <el-button type="primary" @click="openBatchOperationDia"
+                :disabled="!selectedTotal>0" :loading="batchLoading"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_operations"
+              >{{$t('HighFrequencyData.batch_operation')}}</el-button>
+            </div>
+          </div>
+          <el-table :data="tableData" border ref="edbDataRef"
+            @selection-change="selectionChange"
+            @select="selectHandle" 
+            @select-all="selectAllHandle"
+            @sort-change="handleSortChange"
+          >
+            <!-- 多选 -->
+            <el-table-column
+                align="center"
+                type="selection"
+                width="55">
+            </el-table-column>
+            <!-- 指标ID -->
+            <el-table-column prop="IndexCode" :label="$t('Edb.Detail.e_id')" align="center" show-overflow-tooltip>
+              <template slot-scope="{row}">
+                <span>{{row.IndexCode}}</span>
+              </template>
+            </el-table-column>
+            <!-- 指标名称 -->
+            <el-table-column prop="IndexName" :label="$t('Edb.Detail.e_name')" align="center" show-overflow-tooltip>
+              <template slot-scope="{row}">
+                <span>{{row.IndexName}}</span>
+              </template>
+            </el-table-column>
+            <!-- 频度 -->
+            <el-table-column prop="Frequency" :label="$t('Edb.Detail.e_fre')" align="center">
+              <template slot-scope="{row}">
+                <span>{{row.Frequency}}</span>
+              </template>
+            </el-table-column>
+            <!-- 单位 -->
+            <el-table-column prop="Unit" :label="$t('Edb.Detail.e_unit')" align="center">
+              <template slot-scope="{row}">
+                <span>{{row.Unit}}</span>
+              </template>
+            </el-table-column>
+            <!-- 指标开始时间 -->
+            <el-table-column prop="StartDate" :label="$t('Edb.Detail.e_start_time_whole')" align="center" sortable="custom">
+              <template slot-scope="{row}">
+                <span>{{row.StartDate}}</span>
+              </template>
+            </el-table-column>
+            <!-- 指标最新时间 -->
+            <el-table-column prop="EndDate" :label="$t('Edb.Detail.e_latest_time_whole')" align="center" sortable="custom">
+              <template slot-scope="{row}">
+                <span>{{row.EndDate}}</span>
+              </template>
+            </el-table-column>
+            <!-- 更新时间 -->
+            <el-table-column prop="ModifyTime" :label="$t('Edb.Detail.e_update_time')" align="center" sortable="custom">
+              <template slot-scope="{row}">
+                <span>{{row.ModifyTime}}</span>
+              </template>
+            </el-table-column>
+            <!-- 最新值 -->
+            <el-table-column prop="LatestValue" :label="$t('Edb.Detail.e_latest_value')" align="center" sortable="custom">
+              <template slot-scope="{row}">
+                <span>{{row.LatestValue}}</span>
+              </template>
+            </el-table-column>
+            <!-- 数据源分类 -->
+            <el-table-column prop="ClassifyPath" :label="$t('HighFrequencyData.data_source_classify')" align="center" show-overflow-tooltip>
+              <template slot-scope="{row}">
+                <span>{{row.ClassifyPath}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="Operation" :label="$t('Table.column_operations')" align="center">
+              <template slot-scope="{row}">
+                <span class="table-operation-item" @click="detailIndexHandle(row)" 
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_operation_detail">{{ $t('Table.detail_btn') }}</span>
+                <span class="table-operation-item" @click="refreshIndexHandle(row)"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_operation_refresh">{{ $t('Table.refresh_btn') }}</span>
+                <span class="table-operation-item del-item" @click="deleteIndexHandle(row)"
+                v-permission="permissionBtn.dataSourcePermission.highFrequency_operation_delete">{{ $t('Table.delete_btn') }}</span>
+              </template>
+            </el-table-column>
+          </el-table>
+          <el-pagination 
+            :current-page="searchParams.currentPage"
+            :page-size="searchParams.pageSize"
+            :total="total"
+            @current-change="handleCurrentChange"
+          />
+        </div>
+        <!-- 数据详情 -->
+        <el-dialog custom-class="custom-dialog"
+          :title="$t('Edb.data_detail_tab')"
+          :visible.sync="detailDiaShow"
+          :close-on-click-modal="false"
+          :modal-append-to-body="false"
+          @close="detailDiaShow=false"
+          width="980px"
+          top="5vh"
+          v-dialogDrag
+          center
+        >
+          <div class="dialog-container">
+            <div class="detail-date-select-zone">
+              <span>{{ $t('HighFrequencyData.data_date') }}</span>
+              <el-date-picker v-model="detailRequestParams.DataDate" type="date" :clearable="false" @change="getIndexDetailFun"
+                :placeholder="$t('EtaBasePage.input_date_msg')" style="max-width:240px" value-format="yyyy-MM-dd"></el-date-picker>
+            </div>
+            <div class="detail-data-zone">
+              <div class="detail-data-zone-header">
+                <table border class="header-table">
+                    <tr>
+                      <td>{{ $t('Edb.Detail.e_name') }}</td>
+                      <td>
+                        <el-input v-model.trim="indexDetail.IndexName" :placeholder="$t('Edb.InputHolderAll.input_name')" size="mini"></el-input>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td>{{ $t('Edb.Detail.e_stock_code') }}</td>
+                      <td>{{ indexDetail.ZqCode }}</td>
+                    </tr>
+                    <tr>
+                      <td>{{ $t('Edb.Detail.e_indicator_code') }}</td>
+                      <td>{{ indexDetail.ZbCode }}</td>
+                    </tr>
+                </table>
+                <table border class="header-table">
+                    <tr>
+                      <td>{{ $t('HighFrequencyData.belong_to_classify') }}</td>
+                      <td>
+                        <el-cascader :options="classifyListTree" v-model="indexDetail.ClassifyId" 
+                        size="mini"
+                        :props="{label: 'ClassifyName',
+                          value: 'ClassifyId',
+                          children: 'Children',
+                          checkStrictly: true,
+                          emitPath:false}">
+                        </el-cascader>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td>{{ $t('Edb.Detail.e_unit') }}</td>
+                      <td>
+                        <el-autocomplete
+                          v-model.trim="indexDetail.Unit"
+                          :fetch-suggestions="querySearchUnit"
+                          :placeholder="$t('Edb.InputHolderAll.input_unit')"
+                          suffix-icon="el-icon-arrow-down"
+                          size="mini"
+                        ></el-autocomplete>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td>{{ $t('Edb.Detail.e_fre') }}</td>
+                      <td>{{indexDetail.Frequency}}</td>
+                    </tr>
+                </table>
+              </div>
+              <div class="detail-data-list" ref="detailDataListRef">
+                <table class="body-table" >
+                  <template v-if="indexDetail.DataList && indexDetail.DataList.length>0">
+                    <tr v-for="(item,index) in indexDetail.DataList" :key="index">
+                      <td>{{ item.DataTime }}</td>
+                      <td>{{ item.Value }}</td>
+                    </tr>
+                  </template>
+                  <tableNoData v-else></tableNoData>
+                </table>
+              </div>
+            </div>
+          </div>
+          <!-- 弹窗按钮 -->
+          <div class="dialog-btn">
+            <el-button type="primary" plain @click="detailDiaShow=false">{{$t('Dialog.cancel_btn')}}</el-button>
+            <el-button type="primary" @click="editDataHandle">{{$t('Dialog.confirm_btn')}}</el-button>
+          </div>
+        </el-dialog>
+        <!-- 批量操作 -->
+        <el-dialog custom-class="custom-dialog"
+          :title="$t('HighFrequencyData.batch_operation')"
+          :visible.sync="batchOperationDialogShow"
+          :close-on-click-modal="false"
+          :modal-append-to-body="false"
+          @close="batchOperationClose"
+          width="600px"
+          top="5vh"
+          v-dialogDrag
+        >
+          <div class="dialog-container">
+            <div class="batch-option-row">
+              <el-radio v-model="batchOperationData.type" :label="1">{{ $t('HighFrequencyData.move_to_new_classify') }}</el-radio>
+              <el-cascader :options="classifyListTree" v-model="batchOperationData.newClassify" 
+              style="width: 160px;"
+              :placeholder="$t('HighFrequencyData.select_classify_prompt')"
+              :props="{label: 'ClassifyName',
+              value: 'ClassifyId',
+              children: 'Children',
+              checkStrictly: true,
+              emitPath:false}">
+              </el-cascader>
+            </div>
+            <div class="batch-option-row">
+              <el-radio v-model="batchOperationData.type" :label="2" style="margin-right: 10px;">{{ $t('Edb.detail_del_btn') }}</el-radio>
+            </div>
+            <div class="batch-option-row">
+              <el-radio v-model="batchOperationData.type" :label="3">{{ $t('Edb.detail_refresh_btn') }}</el-radio>
+              <div class="radio-box" v-show="batchOperationData.type==3">
+                <el-radio v-model="batchOperationData.refreshType" :label="1">{{ $t('HighFrequencyData.last_six_hours') }}</el-radio>
+                <el-radio v-model="batchOperationData.refreshType" :label="2">{{ $t('HighFrequencyData.refresh_all') }}</el-radio>
+              </div>
+            </div>
+          </div>
+          <!-- 弹窗按钮 -->
+          <div class="dialog-btn">
+            <el-button type="primary" plain @click="batchOperationDialogShow=false">{{$t('Dialog.cancel_btn')}}</el-button>
+            <el-button type="primary" @click="batchOpeartion">{{$t('Dialog.confirm_btn')}}</el-button>
+          </div>
+        </el-dialog>
+        <!-- 分类设置 -->
+        <classifySetting :showIt.sync="classifySettingShow" @closeHandle="classifyCloseHandle" />
+        <!-- 添加高频数据 -->
+        <addHighFrequencyData :isAddShow.sync="addHighFrequencyShow" :unitList="unitList" :classifyList="classifyListTree"  @addSuccessHandle="addHighFrequencySuccess" />
+        <!-- 批量添加到到指标库 -->
+        <addToIndexDatabaseBatch :isAddShow.sync="batchAddToDatabaseShow" :IndexIds="choiceIdList"/>
+    </div>
+</template>
+
+<script>
+import {dataRefreshInterface,dataAuthInterface} from '@/api/modules/dataApi.js';
+import { dataInterence,highFrequencyDataInterface } from '@/api/api.js'
+import classifySetting from './components/highFrequency/classifySetting.vue';
+import addHighFrequencyData from './components/highFrequency/addHighFrequencyData.vue'
+import addToIndexDatabaseBatch from './components/highFrequency/addToIndexDatabaseBatch.vue';
+
+  export default {
+    name:'highFrequencyData',
+    components:{classifySetting,addHighFrequencyData,addToIndexDatabaseBatch},
+    data() {
+        return {
+            Source:'',
+            SourceList:[],
+            Sequence:'',
+            SequenceList:[],
+
+            classifyListTree:[],
+            userList:[],
+            unitList:[],
+            searchParams:{
+              classify:'',//分类
+              isAssociativeSub:true,//是否关联子分类
+              frequency:'',//频度
+              user:'',//创建人
+              keyWord:'',//关键字
+              sortType:'',//升序降序
+              sortParam:'',//排序字段
+              pageSize:10,
+              currentPage:1,
+            },
+            classifyArr:[],
+            frequencyArr:[],
+            userArr:[],
+            tableData: [],
+            tableDataIds:[],
+            total:0,
+
+            //全部全选
+            isIndeterminate:false,
+            isCheckAll:false,
+            isSelectAll:false,//为true时,selectList是剔除的指标,为false时selectList是已选择的指标
+            //已选择/已剔除的指标id
+            selectList:[],//监听table的select-all select
+            choiceIdList:[], //后端返回的选中的列表
+
+            detailDiaShow:false,
+            indexDetail:{},
+            detailRequestParams:{
+              IndexId:0,
+              DataDate:''
+            },
+
+            classifySettingShow:false,
+
+            addHighFrequencyShow:false,
+
+            batchOperationDialogShow:false,
+            batchOperationData:{
+              type:1,
+              newClassify:0,
+              refreshType:1
+            },
+
+            batchAddToDatabaseShow:false,
+            batchLoading:false
+        };
+    },
+    computed:{
+      selectedTotal(){
+        if(this.isSelectAll){
+          return this.total - (this.selectList ? this.selectList.length : 0)
+        }else{
+          return this.selectList ? this.selectList.length : 0
+        }
+      },
+      frequencyList() {
+        return [
+          {value: "1m",label: "1m"},
+          {value: "3m",label: '3m'},
+          {value: "5m",label: "5m"},
+          {value: "10m",label: "10m"},
+          {value: "15m",label: "15m"},
+          {value: "30m",label: "30m"},
+          {value: "60m",label: "60m"}
+        ];
+      },
+      classifyProps(){
+        return {
+          checkStrictly:(!this.searchParams.isAssociativeSub),
+          value:'ClassifyId',
+          label:'ClassifyName',
+          children:'Children',
+          emitPath:this.searchParams.isAssociativeSub,
+          multiple:true
+        }
+      }
+    },
+    watch:{
+      classifyArr(value){
+        if(value && value.length>0){
+          const classifyIds = [...new Set(value.join(',').split(','))]
+          this.searchParams.classify=classifyIds.join(',')
+        }else{
+          this.searchParams.classify=''
+        }
+      },
+      frequencyArr(value){
+        if(value && value.length>0){
+          this.searchParams.frequency=value.join(',')
+        }else{
+          this.searchParams.frequency=''
+        }
+      },
+      userArr(value){
+        if(value && value.length>0){
+          this.searchParams.user=value.join(',')
+        }else{
+          this.searchParams.user=''
+        }
+      },
+    },
+    methods: {
+        //添加高频数据
+        addHighFrequencyDiaShow(){
+          this.addHighFrequencyShow=true
+        },
+        addHighFrequencySuccess(){
+          this.searchParams.currentPage = 1
+          this.getTableData()
+        },
+        //获取数据源列表
+        getSourceList(){
+          this.SourceList=[{Source: 1,SourceName: "同花顺",SourceNameEn: "同花顺"}]
+          this.Source = this.SourceList[0].Source
+        },
+        getSequenceList(){
+          this.SequenceList=[{Sequence: 1,SequenceName: "高频序列",SequenceNameEn: "高频序列"}]
+          this.Sequence = this.SequenceList[0].Sequence
+        },
+        //数据源改变
+        handleSourceChange(){
+        },
+        // 序列改变
+        handleSequenceChange(){
+        },
+        //获取分类列表
+        async getClassifyList(){
+          const res = await highFrequencyDataInterface.classifyListTree()
+          if(res.Ret!==200) return 
+          this.classifyListTree = res.Data||[]
+        },
+        //获取用户列表
+        getUserList() {
+          dataAuthInterface.userSearch({
+              KeyWord: ''
+          }).then(res => {
+              if(res.Ret !== 200) return 
+              this.userList = res.Data||[]
+          })
+        },
+        // 获取指标单位
+        async getUnitList(){
+          let res=await dataInterence.getTargetUnitList()
+          if(res.Ret===200){
+            this.unitList=res.Data&&res.Data.map(item=>{
+              return {value:item}
+            })
+          }
+        },
+        //搜索单位
+        querySearchUnit(queryString, cb){
+          let results = queryString ? this.unitList.filter(item=>item.value.indexOf(queryString) === 0) : this.unitList;
+          // 调用 callback 返回建议列表的数据
+          cb(results);
+        },
+        changeAssociativeSub(value){
+          // 清空
+          this.classifyArr=[]
+          this.searchListDelay()
+        },
+        searchListDelay(){
+          setTimeout(()=>{
+            this.searchList()
+          },0)
+        },
+        //表格筛选项改变时触发
+        searchList(){
+          this.searchParams.currentPage = 1
+          this.getTableData('search')
+        },
+        handleCurrentChange(page){
+            this.searchParams.currentPage = page
+            this.getTableData()
+        },
+        async getTableData(type){
+          const {frequency,user,classify,keyWord,sortParam,sortType,currentPage,pageSize,isAssociativeSub} = this.searchParams
+          let params={
+            ClassifyId:classify,
+            IncludeChild:isAssociativeSub,
+            SysAdminId:user,
+            Frequency:frequency,
+            Keywords:keyWord,
+            SortField:sortParam,
+            SortType:sortType,
+            PageSize:Number(pageSize) || 10,
+            CurrentIndex:Number(currentPage)||1
+          }
+          // console.log(params,'params');
+          const res = await highFrequencyDataInterface.getTableDataApi(params)
+          if(res.Ret!==200) return 
+          const {Paging,List} = res.Data||{}
+          this.tableData = List||[]
+          if(this.tableData.length === 0 && this.searchParams.currentPage>1 && Paging.Pages){
+            // 最后一页的最后一个被删除了 当前页码没数据 去最后一页 非要改
+            this.searchParams.currentPage > Paging.Pages ?
+            (this.searchParams.currentPage =  Paging.Pages || 1) :
+            (this.searchParams.currentPage--)
+            this.getTableData(type)
+            return 
+          }
+          this.total = Paging.Totals||0
+          if(this.tableData.length>0){
+            this.tableDataIds = this.tableData.map(it => it.IndexId)
+          }else{
+            this.tableDataIds = []
+          }
+          if(type==='search'){
+              //如果是表格筛选项改变导致重新请求数据
+              //清除所选
+              this.selectList = []
+              this.listCheckAllChange(false)
+          }else{
+              //若不是,数据获取完成后,查询列表全选的值
+              //若当页有数据在selectList内,则勾选/剔除
+              this.adjustSelection()
+          }
+        },
+        //勾选/取消勾选表格项
+        adjustSelection(){
+            if(!this.isSelectAll){
+              this.tableData.map(it =>{
+                    let row = this.selectList.includes(it.IndexId)?it:''
+                    if(row){
+                        this.$nextTick(()=>{
+                          this.$refs.edbDataRef.toggleRowSelection(row,true)
+                        })
+                    }
+                })
+            }else{
+              this.tableData.map(it =>{
+                let row = this.selectList.includes(it.IndexId)?'':it
+                if(row){
+                  this.$nextTick(()=>{
+                    this.$refs.edbDataRef.toggleRowSelection(row,true)
+                  })
+                }
+              })
+            }
+        },
+        //列表全选改变
+        listCheckAllChange(value){
+            this.selectList = []
+            this.isSelectAll = value
+            this.$refs.edbDataRef && this.$refs.edbDataRef.clearSelection()
+            if(value){
+                this.$refs.edbDataRef && this.$refs.edbDataRef.toggleAllSelection()
+            }
+        },
+        selectionChange(selection){
+            // selectAllHandle的触发在selectionChange后面,将selectionChange的逻辑延迟一下
+            setTimeout(()=>{
+                // 去重
+                let duplicateArr = Array.from(new Set(this.selectList))
+                //isSelectAll为true时,selectList表示需要剔除的项
+                //isSelectAll为false时,selectList表示需要勾选的项
+                //全选
+                if((duplicateArr.length == this.total && (!this.isSelectAll))|| (duplicateArr.length == 0 && this.isSelectAll)){
+                    this.isCheckAll = true
+                    this.isIndeterminate=false
+                //全不选
+                }else if((duplicateArr.length == 0 && (!this.isSelectAll))|| (duplicateArr.length == this.total && this.isSelectAll)){
+                    this.isCheckAll = false
+                    this.isIndeterminate=false
+                //半选
+                }else{
+                    this.isCheckAll = false
+                    this.isIndeterminate=true
+                }
+            },1)
+        },
+        selectHandle(selection,row){
+            let check = false; 
+            if(selection.some(it => it.IndexId == row.IndexId)){
+                // 勾选
+                if(this.isSelectAll){
+                    check=false
+                }else{
+                    check=true
+                }
+            }else{
+                // 取消勾选
+                if(this.isSelectAll){
+                    check=true
+                }else{
+                    check=false
+                }
+            }
+            if(check){
+              this.selectList.push(row.IndexId)
+            }else{
+              this.selectList=this.selectList.filter(it => it!=row.IndexId)
+            }
+        },
+        selectAllHandle(selection){
+          let check = false; 
+          if(selection && selection.length>0){
+              // 全选
+              if(this.isSelectAll){
+                  check=false
+              }else{
+                  check=true
+              }
+          }else{
+              // 全不选
+              if(this.isSelectAll){
+                  check=true
+              }else{
+                  check=false
+              }
+          }
+          if(check){
+              this.selectList =  [...this.selectList,...this.tableDataIds]
+          }else{
+              this.selectList = this.selectList.filter(it => !this.tableDataIds.includes(it))
+          }
+        },
+        handleSortChange({prop,order}){
+          let propMap = new Map([
+            ["StartDate",1],
+            ["EndDate",2],
+            ["ModifyTime",3],
+            ["LatestValue",4]
+          ])
+          if(order){
+            this.searchParams.sortParam = propMap.get(prop)
+            this.searchParams.sortType = order==='ascending'?1:2
+          }else{
+            this.searchParams.sortParam = ''
+            this.searchParams.sortType = ''
+          }
+          this.searchList()
+        },
+        // 详情
+        async detailIndexHandle(row){
+          this.detailRequestParams.IndexId = row.IndexId
+          this.detailRequestParams.DataDate = ''
+          await this.getIndexDetailFun()
+          this.detailDiaShow=true
+          this.$nextTick(()=>{
+            this.$refs.detailDataListRef && (this.$refs.detailDataListRef.scrollTop=0)
+          })
+        },
+        async getIndexDetailFun(){
+          await highFrequencyDataInterface.highFreDataDetail(this.detailRequestParams).then(res=>{
+            if(res.Ret == 200){
+              let resData = res.Data||{}
+              let indexData = resData.Index || {}
+              this.detailRequestParams.DataDate = resData.DataDate
+              this.indexDetail={
+                IndexId:indexData.IndexId,
+                IndexName:indexData.IndexName,
+                ZqCode:indexData.StockCode,
+                ZbCode:indexData.Indicator,
+                ClassifyId:indexData.ClassifyId,
+                Unit:indexData.Unit,
+                Frequency:indexData.Frequency,
+                DataList:resData.DataList||[]
+              }
+            }
+          })
+        },
+        editDataHandle(){
+          if(!(this.indexDetail.IndexName && this.indexDetail.ClassifyId && this.indexDetail.Unit)){
+            return this.$message.warning(this.$t('MsgPrompt.please_complete'))
+          }
+          let params={
+            IndexId:this.indexDetail.IndexId,
+            IndexName:this.indexDetail.IndexName,
+            ClassifyId:this.indexDetail.ClassifyId,
+            Unit:this.indexDetail.Unit,
+          }
+          highFrequencyDataInterface.highFreDataEdit(params).then(res=>{
+            if(res.Ret == 200){
+              this.$message.success(this.$t('MsgPrompt.operate_success_msg'))
+              this.detailDiaShow=false
+              this.getTableData()
+            }
+          })
+        },
+        // 刷新
+        refreshIndexHandle(row){
+          highFrequencyDataInterface.highFreDataRefresh({
+            IndexId:row.IndexId
+          }).then(res=>{
+            if(res.Ret!==200) return
+            this.$message.success(/* "刷新成功"  */this.$t('MsgPrompt.refresh_success_msg'))
+            this.getTableData()
+          })
+        },
+        // 删除
+        deleteIndexHandle(row){
+          this.$confirm(this.$t('Edb.MsgPrompt.del_edb_confirm'),this.$t('Dialog.warn_tit'),{
+            confirmButtonText:/* "确定" */this.$t('Dialog.confirm_btn'),
+            cancelButtonText:/* "取消" */this.$t('Dialog.cancel_btn'),
+            type:"warning"
+          }).then(()=>{
+            highFrequencyDataInterface.highFreDataDelete({
+              IndexId:row.IndexId
+            }).then(res=>{
+              if(res.Ret!==200) return
+              this.$message.success(/* "删除成功"  */this.$t('MsgPrompt.delete_msg'))
+              this.selectList=this.selectList.filter(it => it!=row.IndexId)
+              this.getTableData()
+            })
+          }).catch(()=>{})
+        },
+        setClassify(){
+          this.classifySettingShow=true
+        },
+        classifyCloseHandle({requestClassifyList,requestDataList}){
+          if(requestDataList) this.getTableData('search')
+          if(requestClassifyList) this.getClassifyList()
+          this.classifySettingShow=false
+        },
+        async openBatchOperationDia(){
+          if(this.selectedTotal>500){
+            return this.$message.warning(this.$t('HighFrequencyData.batch_operation_limit'))
+          }
+          this.batchLoading = true
+          let flag = await this.getHighFreDataChoiceList()
+          this.batchLoading = false
+          this.batchOperationDialogShow=!!flag
+        },
+        async getHighFreDataChoiceList(){
+          let params={
+            ClassifyId:this.searchParams.classify,
+            IncludeChild:this.searchParams.isAssociativeSub,
+            Frequency:this.searchParams.frequency,
+            SysAdminId:this.searchParams.user,
+            Keywords:this.searchParams.keyWord,
+            ListIds:this.selectList.join(','),
+            SelectAll:this.isSelectAll,
+          }
+          return await highFrequencyDataInterface.highFreDataChoice(params).then(res=>{
+            if(res.Ret == 200){
+              const choiceList = res.Data || []
+              this.choiceIdList=choiceList.map(cl=> cl.IndexId)
+              return true 
+            }else{
+              return false
+            }
+          })
+        },
+        batchOperationClose(){
+          this.batchOperationDialogShow=false
+          this.batchOperationData={
+            type:1,
+            newClassify:0,
+            refreshType:1
+          }
+        },
+        batchOpeartion(){
+          if(this.batchOperationData.type==1 && !this.batchOperationData.newClassify) return this.$message.warning(this.$t('HighFrequencyData.select_classify_prompt'))
+          let params={
+            IndexIds:this.choiceIdList,
+            OptType:this.batchOperationData.type,
+            MoveClassifyId:this.batchOperationData.newClassify,
+            RefreshType:this.batchOperationData.refreshType
+          }
+          highFrequencyDataInterface.highFreDataBatchOperation(params).then(res=>{
+            if(res.Ret == 200){
+              if(this.batchOperationData.type==2){
+                // 批量删除
+                let deleteFails=res.Data.Fail || []
+                let deleteSuccess=res.Data.Success || []
+                if(deleteSuccess.length) this.$message.success(this.$t('MsgPrompt.operate_success_msg'))
+
+                if(deleteFails){
+                  let message = '';
+                  deleteFails.forEach(item => {
+                    message+=`${item.IndexName}:${this.$t('HighFrequencyData.indicator_been_referenced_prompt')}</br>`
+                  })
+                  // 和成功提示错开
+                  this.$nextTick(()=>{
+                    this.$message({
+                      dangerouslyUseHTMLString: true,
+                      message,
+                      type: 'error'
+                    })
+                  })
+                }
+                // 删除之后 调整选中
+                this.listCheckAllChange(false)
+              }else{
+                this.$message.success(this.$t('MsgPrompt.operate_success_msg'))
+              }
+              this.getTableData()
+              this.batchOperationDialogShow=false
+            }
+          })
+        },
+        async batchAddToDatabaseOpen(){
+          if(this.selectedTotal>500){
+            return this.$message.warning(this.$t('HighFrequencyData.batch_operation_limit'))
+          }
+          this.batchLoading = true
+          let flag = await this.getHighFreDataChoiceList()
+          this.batchLoading = false
+          this.batchAddToDatabaseShow=!!flag
+        }
+    },
+    mounted(){
+        this.getSourceList()
+        this.getSequenceList()
+        this.getClassifyList()
+        this.getUserList()
+        this.getUnitList()
+        this.getTableData()
+    }
+  }
+</script>
+
+<style scoped lang="scss">
+.hight-frequency-data-container{
+    min-height: calc(100vh - 120px);
+    display: flex;
+    flex-direction: column;
+    .top-box{
+        box-sizing: border-box;
+        margin-bottom: 16px;
+        display: flex;
+        .select-box{
+          span{
+            margin-right:10px;
+          }
+          .el-select{
+            margin-right:10px;
+            width:160px;
+          }
+        }
+    }
+    .table-box{
+      flex:1;
+      .el-select{
+          min-width:180px;
+      }
+      .table-select{
+          display: flex;
+          justify-content: space-between;
+          .select-list{
+            flex:1;
+            display: flex;
+            flex-wrap: wrap;
+            gap:10px;
+            .el-select,.el-cascader,.el-input{
+              max-width: 210px;
+            }
+            .associative-box{
+              display: flex;
+              align-items: center;
+              gap: 10px;
+              color: #333333;
+              .span-button{
+                color:#0052D9 ;
+                cursor: pointer;
+              }
+            }
+          }
+          .select-other{
+            margin-left: 10px;
+            .el-button{
+                margin-left:10px;
+            }
+          }
+      }
+      .el-table{
+          margin:20px 0;
+      }
+      .el-pagination{
+        text-align: right;
+        background-color: white;
+        padding: 10px 0;
+      }
+      .table-operation-item{
+        padding: 0 3px;
+        cursor: pointer;
+        color: #0052D9;
+        white-space: nowrap;
+      }
+      .del-item{
+        color: #D54941;
+      }
+    }
+    .custom-dialog{
+      .dialog-container{
+        overflow: hidden;
+        padding: 0 35px;
+        .detail-date-select-zone{
+          display:flex;
+          margin-bottom: 30px;
+          align-items:center;
+          span{
+            margin-right: 20px;
+          }
+          .el-input{
+            width: 240px;
+          }
+        }
+        .detail-data-zone{
+          display: flex;
+          flex-direction: column;
+          justify-content: center;
+          .detail-data-zone-header{
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .header-table{
+              font-size: 14px;
+              border:solid 1px #C8CDD9;
+              box-sizing: border-box;
+              tr{
+                box-sizing: border-box;
+                td{
+                  padding: 10px;
+                  width: 270px;
+                  color: #666666;
+                  box-sizing: border-box;
+                  &:first-child{
+                      width: 150px;
+                      text-align: center;
+                      font-weight: bold;
+                      color: #333333;
+                  }
+                }
+              }
+            }
+          }
+          .detail-data-list{
+            height: 260px;
+            overflow: auto;
+            margin: 40px auto 30px auto;
+            .body-table{
+              border-left: solid 1px #C8CDD9;
+              border-right: solid 1px #C8CDD9;
+              tr{
+                box-sizing: border-box;
+                td{
+                  min-width: 150px;
+                  text-align: center;
+                  padding: 8px 10px;
+                  color: #666666;
+                  box-sizing: border-box;
+                  &:first-child{
+                    width: 260px;
+                    border-right:solid 1px #C8CDD9;
+                  }
+                }
+              }
+            }
+          }
+        }
+        // 批量操作
+        .batch-option-row{
+          margin-bottom: 20px;
+          .radio-box{
+            margin-top: 20px;
+            padding-left: 50px;
+            .el-radio{
+              margin-right: 20px;
+            }
+          }
+        }
+      }
+      .dialog-btn{
+        text-align: center;
+        padding: 40px 0 25px;
+        .el-button{
+          min-width: 120px;
+        }
+      }
+    }
+}
+</style>
+<style lang="scss">
+.custom-dialog{
+  .el-input{
+    width: 100%!important;
+  }
+}
+
+.detail-data-zone-header{
+  .el-cascader{
+    width: 100%;
+  }
+  .el-autocomplete{
+    width: 100%;
+  }
+  .el-select{
+    width: 100%;
+  }
+  .el-input{
+    width: 100%;
+    input{
+      border: none;
+      padding: 0;
+      font-size: 14px;
+    }
+  }
+}
+</style>

+ 2 - 2
src/views/dataEntry_manage/thirdBase/selfDataBase.vue

@@ -80,11 +80,11 @@
           >
             <template slot-scope="{row}">
               <template v-if="item.key==='handle'">
-                <span 
+                <span v-permission="permissionBtn.dataSourcePermission.selfData_detail"
                   class="editsty"
                   @click="lookDataHandle(row)"
                 >
-                  <!-- 查看数据 -->{{$t('Edb.detail_lookdata_btn')}}
+                  <!-- 查看详情 -->{{$t('Edb.detail_lookdata2_btn')}}
                 </span>
 
                 <span 

+ 7 - 5
src/views/dataEntry_manage/thirdBase/steelChemicalbase.vue

@@ -169,7 +169,7 @@
               :tableOption="tableOption"
               tableType="header"
               ref="table"
-              source="gl"
+              source="glhg"
             />
           </div>
           <div class="data-cont" v-if="dateArr.length">
@@ -177,7 +177,7 @@
               :tableOption="tableOption"
               tableType="data"
               :dateArr="dateArr"
-              source="gl"
+              source="glhg"
             />
           </div>
           <div v-else class="nodata"></div>
@@ -379,7 +379,8 @@ export default {
                 IndexCode:this.index_code,
                 FrequencyName:'',
                 UnitName:'',
-                UpdateTime:''
+                UpdateTime:'',
+                IsStop:'',
               }]
               //为了美观
               for (let i = 0; i < 6; i++) {
@@ -388,7 +389,8 @@ export default {
                   IndexCode:'',
                   FrequencyName:'',
                   UnitName:'',
-                  UpdateTime:''
+                  UpdateTime:'',
+                  IsStop:'',
                 })
               }
               //为了美观
@@ -485,7 +487,7 @@ export default {
     /* 改变节点 */
     nodeChangeHandle(data, node) {
       if (this.dataloading)
-        return this.$message("请求频繁,请数据加载完成后再试!");
+        return this.$message(this.$t('MsgPrompt.request_frequency'));
       this.dynamicNode = node;
       this.select_node = data.UniqueCode;
       this.select_classify = data.BaseFromMysteelChemicalClassifyId;

+ 70 - 32
src/views/datasheet_manage/common/customTable.js

@@ -70,32 +70,51 @@ export function splitString(str) {
 }
 
 //选中整行整列样式
-export function selectMoreCellStyle(e,type=null) {
+export function selectMoreCellStyle(e) {
   let table = document.querySelector('.table');
   resetStyle();
-
+  let tableRect = table.getBoundingClientRect()
   if($(e.target).hasClass('th-col')) { //点击列
-    // 指标列 日期列显示显示有所区分
-    const columnIndex = Array.from(e.target.parentNode.children).indexOf(e.target);
-    table.rows.forEach((cell,index)=> {
-
-      if(index !==0) {
-        if(type === 1) index === 2 ? $(cell.children[columnIndex-1]).addClass('td-col-select') : $(cell.children[columnIndex]).addClass('td-col-select');
+    let eRect = e.target.getBoundingClientRect()
+    // console.log(eRect,tableRect);
+    $(table.querySelector('#row-col-select')).css({
+      'top':`${eRect.height}px`,
+      'left':`${eRect.x - tableRect.x}px`,
+      'visibility':`visible`,
+      'height':`${tableRect.height-eRect.height-1}px`,
+      'width':`${eRect.width}px`,
+      'border-width':'0 1px 0 1px'})
+    // if(!type){
+    //   $(e.target).addClass('td-col-select-new');
+    // }
 
-        if(type === 2) index === 1 ? $(cell.children[columnIndex-1]).addClass('td-col-select') : $(cell.children[columnIndex]).addClass('td-col-select');
-
-        if(!type) $(cell.children[columnIndex]).addClass('td-col-select');
-      }
-    })
+    // 指标列 日期列显示显示有所区分
+    // const columnIndex = Array.from(e.target.parentNode.children).indexOf(e.target);
+    // table.rows.forEach((cell,index)=> {
+    //   if(index !==0) {
+    //     if(type === 1) index === 2 ? $(cell.children[columnIndex-1]).addClass('td-col-select') : $(cell.children[columnIndex]).addClass('td-col-select');
+
+    //     if(type === 2) index === 1 ? $(cell.children[columnIndex-1]).addClass('td-col-select') : $(cell.children[columnIndex]).addClass('td-col-select');
+        
+    //     if(!type) $(cell.children[columnIndex]).addClass('td-col-select');
+    //   }
+    // })
   }else if($(e.target).hasClass('th-row')) { //点击行
-    e.target.parentNode.children.forEach((cell,index)=> {
-      if(index !==0) {
-        index === 2 ? $(cell).addClass('td-row-select') : $(cell).addClass('td-row-select');
-      }
-    })
+    let eRect = e.target.getBoundingClientRect()
+    // e.target.parentNode.children.forEach((cell,index)=> {
+    //   console.log(cell,index,'index');
+    //   if(index !==0) {
+    //     index === 2 ? $(cell).addClass('td-row-select') : $(cell).addClass('td-row-select');
+    //   }
+    // })
+    $(table.querySelector('#row-col-select')).css({
+      'top':`${eRect.y - tableRect.y}px`,
+      'left':`${eRect.width}px`,
+      'visibility':`visible`,
+      'height':`${eRect.height}px`,
+      'width':`${tableRect.width-eRect.width-1}px`,
+      'border-width':'1px 0 1px 0'})
   }
-
-
 }
 
 // 选中格子样式
@@ -119,15 +138,21 @@ export function resetStyle() {
   table.querySelectorAll(".td-chose").forEach(el => {
     el.classList.remove('td-chose')
   })
-  table.querySelectorAll(".td-col-select").forEach(el => {
-    el.classList.remove('td-col-select')
-  })
-  table.querySelectorAll(".td-row-select").forEach(el => {
-    el.classList.remove('td-row-select')
-  })
+  // table.querySelectorAll(".td-col-select").forEach(el => {
+  //   el.classList.remove('td-col-select')
+  // })
+  // table.querySelectorAll(".td-row-select").forEach(el => {
+  //   el.classList.remove('td-row-select')
+  // })
   table.querySelectorAll(".td-relation").forEach(el => {
     el.classList.remove('td-relation')
   })
+  $(table.querySelector('#row-col-select')).css({
+    'top':0,
+    'left':0,
+    'visibility':`hidden`,
+    'height':0,
+    'width':0})
 }
 
 //单击聚焦
@@ -146,11 +171,19 @@ export function setCellBg(e) {
   e.target.parentNode.parentNode.nodeName==='TD' && $(e.target.parentNode.parentNode).addClass("insert")
 }
 
-//右键菜单
-export function getRightClickMenu(pos,canEdit=false,isStaticTable=false) {
-  // 如果是静态表则只有清空功能
+/**
+ * 右键菜单
+ * @param {*} pos 类型 cell-单元格 selection-选区 col-列头 row-行头
+ * @param {*} canEdit 单元格是否可编辑
+ * @param {*} isStaticTable 是否是静态表 -- 平衡表中
+ * @param {*} extraConfig 额外的配置 cellMerged-是否合并了单元格
+ * @returns 
+ */
+export function getRightClickMenu(pos,canEdit=false,isStaticTable=false,extraConfig={}) {
+  // 如果是静态表则有清空功能、清除单元格
   if(isStaticTable){
-    return [{ label: bus.$i18nt ? bus.$i18nt.t('SystemManage.ReportApprove.clear_btn'):"清空", key: "reset" }]
+    return [{ label: bus.$i18nt ? bus.$i18nt.t('ETable.Btn.unmerge_cell') : '取消合并单元格',key: 'cell-unmerge',hidden:!extraConfig.cellMerged },
+      { label: bus.$i18nt ? bus.$i18nt.t('SystemManage.ReportApprove.clear_btn'):"清空", key: "reset" }].filter(me => !me.hidden)
   }
 
   let cellMenu = [
@@ -178,6 +211,7 @@ export function getRightClickMenu(pos,canEdit=false,isStaticTable=false) {
         { label: bus.$i18nt ? bus.$i18nt.t('Edb.CalculatesAll.day_mean') : '日均值',source: 16,fromEdbKey:75 },
       ]
     },
+    { label: bus.$i18nt ? bus.$i18nt.t('ETable.Btn.unmerge_cell') : '取消合并单元格',key: 'cell-unmerge',hidden:!extraConfig.cellMerged },
     { label: bus.$i18nt ? bus.$i18nt.t('SystemManage.ReportApprove.clear_btn'):"清空", key: "reset" },
   ]
 
@@ -193,8 +227,12 @@ export function getRightClickMenu(pos,canEdit=false,isStaticTable=false) {
       { label: bus.$i18nt ? bus.$i18nt.t('ETable.Btn.delete_btn') : "删除", key: "del" },
     ],
     'cell': canEdit 
-      ? [{ label: bus.$i18nt ? bus.$i18nt.t('ETable.Btn.edit_btn') : '编辑',key: 'cell-edit' },...cellMenu]
-      : cellMenu
+      ? [{ label: bus.$i18nt ? bus.$i18nt.t('ETable.Btn.edit_btn') : '编辑',key: 'cell-edit' },...cellMenu.filter(me => !me.hidden)]
+      : cellMenu.filter(me => !me.hidden),
+    'selection':[
+      extraConfig.cellMerged ? { label: bus.$i18nt ? bus.$i18nt.t('ETable.Btn.unmerge_cell') : '取消合并单元格',key: 'cell-unmerge' }:
+      { label: bus.$i18nt ? bus.$i18nt.t('ETable.Btn.merge_cell') : '合并单元格',key: 'cell-merge' }
+    ]
   }
 
   return menuMap[pos];

+ 1 - 1
src/views/datasheet_manage/components/BalanceAddChart.vue

@@ -360,7 +360,7 @@
               <!-- 公历 -->
               <el-radio-button label="公历">{{$t('Chart.calendar_gre')}}</el-radio-button>
               <!-- 农历 -->
-              <el-radio-button label="农历">{{$t('Chart.calendar_lunar')}}</el-radio-button>
+              <el-radio-button label="农历">{{$t('Chart.calendar_lunar_text')}}</el-radio-button>
             </el-radio-group>
           </div>
           <!-- 季节图设置图例名称按钮 -->

+ 7 - 5
src/views/datasheet_manage/components/BalanceSheetChartItem.vue

@@ -119,12 +119,14 @@ export default {
             });
             let form = new FormData();
             form.append('Img', svg);
-            let { Data } = await dataBaseInterface.uploadImgSvg(form);
+            // let { Data } = await dataBaseInterface.uploadImgSvg(form);
 
-            await dataBaseInterface.setChartImage({
-                ChartInfoId: this.chartInfo.ChartInfoId,
-                ImageUrl: Data.ResourceUrl,
-            });
+            // await dataBaseInterface.setChartImage({
+            //     ChartInfoId: this.chartInfo.ChartInfoId,
+            //     ImageUrl: Data.ResourceUrl,
+            // });
+            form.append('ChartInfoId',this.chartInfo.ChartInfoId)
+            await dataBaseInterface.setChartThumbnail(form)
         },
 
         handleAddMyChart(){

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