Browse Source

Merge branch 'master' of http://8.136.199.33:3000/eta_front/eta_front into eta1.9.4

cxmo 11 months ago
parent
commit
b5b778de5c
100 changed files with 10413 additions and 683 deletions
  1. 6 2
      src/api/api.js
  2. 37 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. 4 4
      src/lang/modules/ReportManagement/CategoryList.js
  29. 117 9
      src/lang/modules/ReportManagement/ReportList.js
  30. 4 4
      src/lang/modules/ReportManagement/SmartReport.js
  31. 4 2
      src/lang/modules/Slides/pptPresent.js
  32. 73 2
      src/lang/modules/StatisticAnalysis/ChartRelevance.js
  33. 59 0
      src/lang/modules/systemManage/DataRefresh.js
  34. 2 2
      src/lang/modules/systemManage/ReportApprove.js
  35. 5 2
      src/mixins/reportApproveConfig.js
  36. 11 0
      src/routes/modules/chartRoutes.js
  37. 16 0
      src/routes/modules/dataRoutes.js
  38. 28 16
      src/routes/modules/oldRoutes.js
  39. 7 0
      src/styles/global.scss
  40. 21 1
      src/utils/buttonConfig.js
  41. 12 0
      src/utils/common.js
  42. 2 3
      src/views/Home.vue
  43. 1 1
      src/views/Login.vue
  44. 4 4
      src/views/approve_manage/approveDetail.vue
  45. 14 8
      src/views/approve_manage/approveEdit.vue
  46. 2 2
      src/views/approve_manage/components/flowNode/approveNode.vue
  47. 1 1
      src/views/approve_manage/mixins/approveMixins.js
  48. 61 19
      src/views/chartRelevance_manage/components/chartCard.vue
  49. 10 2
      src/views/chartRelevance_manage/components/explainText.js
  50. 111 0
      src/views/chartRelevance_manage/components/saveChartSetting.vue
  51. 44 8
      src/views/chartRelevance_manage/components/saveChartTobaseDia.vue
  52. 2 2
      src/views/chartRelevance_manage/components/saveEdbToBaseDia.vue
  53. 5 0
      src/views/chartRelevance_manage/components/selectTarget.vue
  54. 7 6
      src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue
  55. 4 1
      src/views/chartRelevance_manage/css/index.scss
  56. 18 8
      src/views/chartRelevance_manage/mixins/classifyMixin.js
  57. 210 0
      src/views/chartRelevance_manage/relevance/components/batchSelectFormula.vue
  58. 257 0
      src/views/chartRelevance_manage/relevance/components/batchSelectTable.vue
  59. 38 0
      src/views/chartRelevance_manage/relevance/components/formMixin.js
  60. 137 0
      src/views/chartRelevance_manage/relevance/components/modifyClassifyDialog.vue
  61. 616 0
      src/views/chartRelevance_manage/relevance/components/multipleIndForm.vue
  62. 268 0
      src/views/chartRelevance_manage/relevance/components/singleIndForm.vue
  63. 294 23
      src/views/chartRelevance_manage/relevance/list.vue
  64. 1089 0
      src/views/chartRelevance_manage/relevance/relevanceChartEditorV2.vue
  65. 111 0
      src/views/chartRelevance_manage/relevance/utils/config.js
  66. 70 0
      src/views/chartRelevance_manage/relevance/utils/index.js
  67. 28 14
      src/views/classify_manage/chapterSettingV2.vue
  68. 11 2
      src/views/classify_manage/classifyEnlistV2.vue
  69. 142 29
      src/views/classify_manage/classifylistV2.vue
  70. 8 7
      src/views/dataEntry_manage/addChart.vue
  71. 10 8
      src/views/dataEntry_manage/chartSetting.vue
  72. 46 2
      src/views/dataEntry_manage/codecount/index.vue
  73. 17 4
      src/views/dataEntry_manage/components/SaveChartOther.vue
  74. 1 3
      src/views/dataEntry_manage/components/barOptionSection.vue
  75. 15 2
      src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue
  76. 23 6
      src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue
  77. 55 1
      src/views/dataEntry_manage/databaseList.vue
  78. 17 9
      src/views/dataEntry_manage/mixins/addOreditMixin.js
  79. 48 36
      src/views/dataEntry_manage/mixins/chartPublic.js
  80. 387 0
      src/views/dataEntry_manage/thirdBase/Wind.vue
  81. 721 0
      src/views/dataEntry_manage/thirdBase/components/highFrequency/addHighFrequencyData.vue
  82. 473 0
      src/views/dataEntry_manage/thirdBase/components/highFrequency/addToIndexDatabaseBatch.vue
  83. 635 0
      src/views/dataEntry_manage/thirdBase/components/highFrequency/classifySetting.vue
  84. 1022 0
      src/views/dataEntry_manage/thirdBase/highFrequencyData.vue
  85. 2 2
      src/views/dataEntry_manage/thirdBase/selfDataBase.vue
  86. 7 5
      src/views/dataEntry_manage/thirdBase/steelChemicalbase.vue
  87. 70 32
      src/views/datasheet_manage/common/customTable.js
  88. 7 5
      src/views/datasheet_manage/components/BalanceSheetChartItem.vue
  89. 742 85
      src/views/datasheet_manage/components/BalanceTable.vue
  90. 43 39
      src/views/datasheet_manage/components/CustomTable.vue
  91. 651 97
      src/views/datasheet_manage/components/MixedTable.vue
  92. 116 40
      src/views/datasheet_manage/components/toolBarSection.vue
  93. 4 2
      src/views/datasheet_manage/sheetList.vue
  94. 12 15
      src/views/edbHistoryPage.vue
  95. 7 6
      src/views/futures_manage/chartEditor.vue
  96. 8 6
      src/views/futures_manage/commodityChartBase.vue
  97. 27 11
      src/views/mychart_manage/components/chartDetailDia.vue
  98. 48 35
      src/views/ppt_manage/mixins/mixins.js
  99. 12 1
      src/views/ppt_manage/mixins/pptEditorMixins.js
  100. 23 15
      src/views/ppt_manage/mixins/pptMixins.js

+ 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等

+ 37 - 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 
@@ -965,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'
     }
-    
   },
   
   /* 公示说明 */

+ 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;

+ 8 - 7
src/views/dataEntry_manage/addChart.vue

@@ -937,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({

+ 10 - 8
src/views/dataEntry_manage/chartSetting.vue

@@ -1852,7 +1852,7 @@ export default {
         const {SeasonRightConfig={}} = this.chartInfo
         params.SeasonExtraConfig = {
             ...this.SeasonExtraConfig,
-            MaxMinLimits:MaxMinLimits.IsAdd?SeasonAverageConfig.MaxMinLimits:{},
+            MaxMinLimits:MaxMinLimits.IsAdd?MaxMinLimits:{},
             SamePeriodAverage:SamePeriodAverage.IsAdd?SamePeriodAverage:{},
             SamePeriodStandardDeviation:SamePeriodStandardDeviation.IsAdd?SamePeriodStandardDeviation:{},
             RightAxis:SeasonRightConfig.IsAdd?SeasonRightConfig:{}
@@ -2403,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 => {

+ 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()

+ 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;

+ 23 - 6
src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue

@@ -114,6 +114,7 @@
 					</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>

+ 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;
+						}
 					}
 				}
 			}

+ 17 - 9
src/views/dataEntry_manage/mixins/addOreditMixin.js

@@ -669,14 +669,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);
 			})
 		},
 
@@ -1006,12 +1010,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;
 			})
 
 		},

+ 48 - 36
src/views/dataEntry_manage/mixins/chartPublic.js

@@ -682,11 +682,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
@@ -824,12 +824,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
@@ -840,12 +841,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
         };
@@ -1029,7 +1030,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: [],
@@ -1044,7 +1046,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,
@@ -1055,7 +1057,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);
       });
@@ -1105,7 +1107,7 @@ 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 = [];
 
@@ -1131,19 +1133,20 @@ export const chartSetMixin = {
         let j = chartDataHandle[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
         };
@@ -1727,18 +1730,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
           }
@@ -1964,17 +1968,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
           }
@@ -2089,6 +2095,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: [],
@@ -2100,7 +2108,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(_ => {
@@ -2295,17 +2303,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)
@@ -2381,16 +2391,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
         }

+ 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];

+ 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(){

File diff suppressed because it is too large
+ 742 - 85
src/views/datasheet_manage/components/BalanceTable.vue


+ 43 - 39
src/views/datasheet_manage/components/CustomTable.vue

@@ -12,7 +12,7 @@
 
       <!-- 日期行表格 -->
       <div class="table-wrapper" v-if="config.type === 1">
-        <table width="auto" border="0" class="table" :style="disabled ? 'width:100%':''">
+        <table width="auto" border="0" class="table" :style="disabled ? 'width:100%':''" style="position: relative;">
           <thead>
             <tr>
               <!-- 行头 -->
@@ -143,13 +143,16 @@
               </td>
             </tr>
           </tbody>
+          <!-- 行列选中样式 -->
+          <div ref="rowColSelectRef" id="row-col-select" 
+          style="position: absolute;border-color: #18ad18;border-style: solid;background-color: transparent;visibility: hidden;z-index: 1;pointer-events: none;"></div>
         </table>
       </div>
       
 
       <!-- 日期列表格 -->
       <div class="table-wrapper" v-else>
-        <table width="auto" border="0" class="table" :style="disabled ? 'width:100%':''">
+        <table width="auto" border="0" class="table" :style="disabled ? 'width:100%':''" style="position: relative;">
           <thead>
             <tr>
               <!-- 行头 -->
@@ -312,6 +315,9 @@
         
             </tr>
           </tbody>
+          <!-- 行列选中样式 -->
+          <div ref="rowColSelectRef" id="row-col-select" 
+          style="position: absolute;border-color: #18ad18;border-style: solid;background-color: transparent;visibility: hidden;z-index: 1;pointer-events: none;"></div>
         </table>
       </div>
 
@@ -429,15 +435,6 @@ export default {
         resetStyle();
       })
     },
-    // 'config.data':{
-    //   handler(value){
-    //     console.log(value,'valuevaluevalue');
-    //     if(!this.disabled && this.hasInit){
-    //       this.$emit("autoSave")
-    //     }
-    //   },
-    //   deep:true
-    // },
     'config.textRowData':{
       handler(value){
         if(!this.disabled && this.hasInit){
@@ -705,7 +702,7 @@ export default {
 			dom.style.left = e.clientX-3 + 'px';
 			dom.style.top = e.clientY-3 + 'px';
       
-      selectMoreCellStyle(e,this.config.type)
+      selectMoreCellStyle(e)
     },
 
     /*  */
@@ -732,6 +729,10 @@ export default {
           this.config.textRowData.forEach(row => {
             row.splice(index+1,1)
           })
+          // 删除的是最后一列
+          if(!(index < this.config.data[0].length)){
+            resetStyle()
+          }
       }else if(cindex === '-1') { //删除行
         console.log('删除行',rindex)
 
@@ -746,7 +747,10 @@ export default {
             _.Data.splice(index,1)
           })
         }
-
+        // 删除的是最后一行
+        if(!(index < this.config.data.length)){
+          resetStyle()
+        }
         
       }
       if(!this.disabled && this.hasInit){
@@ -926,32 +930,32 @@ export default {
       border: 2px solid #0033FF;
       box-shadow: 0 0 5px rgba(73, 177, 249, .5)
     }
-    &.td-col-select::after {
-      position: absolute;
-      top: 0;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      content: "";
-      display: block;
-      outline: 0;
-      border: 1px solid rgb(24, 173, 24);
-      border-bottom: none;
-      border-top: none;
-    }
-    &.td-row-select::after {
-      position: absolute;
-      top: 0;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      content: "";
-      display: block;
-      outline: 0;
-      border: 1px solid rgb(24, 173, 24);
-      border-left: none;
-      border-right: none;
-    }
+    // &.td-col-select::after {
+    //   position: absolute;
+    //   top: 0;
+    //   left: 0;
+    //   right: 0;
+    //   bottom: 0;
+    //   content: "";
+    //   display: block;
+    //   outline: 0;
+    //   border: 1px solid rgb(24, 173, 24);
+    //   border-bottom: none;
+    //   border-top: none;
+    // }
+    // &.td-row-select::after {
+    //   position: absolute;
+    //   top: 0;
+    //   left: 0;
+    //   right: 0;
+    //   bottom: 0;
+    //   content: "";
+    //   display: block;
+    //   outline: 0;
+    //   border: 1px solid rgb(24, 173, 24);
+    //   border-left: none;
+    //   border-right: none;
+    // }
     &.insert {
       background: #FFEFDD;
     }

+ 651 - 97
src/views/datasheet_manage/components/MixedTable.vue

@@ -3,7 +3,8 @@
     <template v-if="config.data.length">
 
       <!-- 工具栏 -->
-      <toolBarSection v-if="!disabled" :cell="selectCell" @updateCell="updateCellStyle"/>
+      <toolBarSection v-if="!disabled" :cell="selectCell?selectCell:selectedCells" @cellMerge="toolCellMergeFun"
+        :echoParameter="{hasMergedCell}"/>
       
       <!-- 公式显示区 -->
       <div class="formula-wrapper" v-if="!disabled">
@@ -20,6 +21,9 @@
         border="0"
         class="table"
         :style="disabled ? 'width:100%' : ''"
+        ref="tableRef"
+        style="position: relative;"
+        @mousedown="selectCellHandle"
       >
         <thead>
           <tr>
@@ -57,7 +61,12 @@
               :key="`${index}_${cell_index}`"
               :data-rindex="rowHeader[index]"
               :data-cindex="columnHeader[cell_index]"
+              :data-datarindex="index"
+              :data-datacindex="cell_index"
               :data-key="cell.Uid"
+              v-show="!cell.merData || cell.merData.type!=='merged'"
+              :colspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.colspan || 1:1"
+              :rowspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.rowspan || 1:1"
               @click="clickCell($event, cell)"
               @dblclick="dblClickCellHandle($event,cell)"
               @contextmenu.prevent="rightClickHandle($event,cell)"
@@ -99,6 +108,8 @@
                   slot="reference"
                   :data-rindex="rowHeader[index]"
                   :data-cindex="columnHeader[cell_index]"
+                  :data-datarindex="index"
+                  :data-datacindex="cell_index"
                   :data-key="cell.Uid"
                 >{{ cell.ShowStyle?cell.ShowFormatValue:cell.ShowValue }}</span>
               </el-popover>
@@ -108,6 +119,8 @@
                 v-else-if="cell.ShowStyle"
                 :data-rindex="rowHeader[index]"
                 :data-cindex="columnHeader[cell_index]"
+                :data-datarindex="index"
+                :data-datacindex="cell_index"
                 :data-key="cell.Uid"
               >
                 {{cell.ShowFormatValue}}
@@ -116,6 +129,8 @@
               <span
                 :data-rindex="rowHeader[index]"
                 :data-cindex="columnHeader[cell_index]"
+                :data-datarindex="index"
+                :data-datacindex="cell_index"
                 :data-key="cell.Uid"
                 v-else
               >{{ cell.ShowValue }}</span>
@@ -129,6 +144,8 @@
                 :data-key="cell.Uid"
                 :data-rindex="rowHeader[index]"
                 :data-cindex="columnHeader[cell_index]"
+                :data-datarindex="index"
+                :data-datacindex="cell_index"
                 :fetch-suggestions="searchTarget"
                 @change.native="changeVal($event, cell)"
                 @keydown.native="keyEnterHandle($event,cell)"
@@ -152,6 +169,12 @@
             </td>
           </tr>
         </tbody>
+        <!-- 选区 -->
+        <div ref="selectionRef" id="selection-id"
+        style="position: absolute;border: 2px solid #0052D9;background-color: rgba(0, 82, 217, 0.1);visibility: hidden;z-index: 1;pointer-events: none;"></div>
+        <!-- 行列选中样式 -->
+        <div ref="rowColSelectRef" id="row-col-select" 
+        style="position: absolute;border-color: #18ad18;border-style: solid;background-color: transparent;visibility: hidden;z-index: 1;pointer-events: none;"></div>
       </table>
 
       <!-- 右键菜单 -->
@@ -239,7 +262,8 @@ import {
   toUpperCase,
   findCellKeyByFactor,
   isNumberVal,
-  transDecimalPlace
+  transDecimalPlace,
+  resetStyle
 } from "../common/customTable";
 import * as sheetInterface from "@/api/modules/sheetApi.js";
 import { dataBaseInterface } from '@/api/api.js';
@@ -301,6 +325,16 @@ export default {
       },
       deep:true
     },
+    'endCell.row':{
+      handler(newVal){
+        this.setSelectionStyle()
+      }
+    },
+    'endCell.column':{
+      handler(newVal){
+        this.setSelectionStyle()
+      }
+    }
   },
   data() {
     return {
@@ -349,8 +383,40 @@ export default {
       isInsertCalculateDate: false,//日期计算弹窗
       insertCalculateDateInfo: {},//日期计算info
 
-      activeNames: []
-
+      activeNames: [],
+      // 合并单元格data
+      isSelectionStart:false, //选区开始
+      startCell:{// 选区时鼠标开始的单元格
+        row:null,
+        column:null
+      }, 
+      endCell:{// 选区时鼠标结束的单元格
+        row:null,
+        column:null
+      },
+      selectionStart:{// 选区范围的左上角单元格
+        row:null,
+        rowSpan:0,
+        column:null,
+        colSpan:0
+      },
+      selectionEnd:{// 选区范围的右下角角单元格
+        row:null,
+        rowSpan:0,
+        column:null,
+        colSpan:0
+      },
+      hasMergedCell:false,// 选区内是否有合并的单元格
+      selectedCells:[],
+      // 选区有'值'单元格 因为超一个单元格有值不让合并,所以记录一个就行
+      hasValueCellItem:{
+        cellNumber:0, //有几个
+        row:null,
+        column:null
+      },
+      // 做个缓存
+      cacheKey:'',
+      cacheCellDom:{}
     };
   },
   mounted() {
@@ -390,8 +456,9 @@ export default {
       if(this.disabled) return
 
       selectCellStyle(e);
+      this.clearSelection()
+      this.hasMergedCell = !!(cell && cell.merData)
       this.selectCell = cell;
-      
       setFocus(e);
 
       //是插值单元格时寻找关联依赖的单元格 设置选框
@@ -399,7 +466,6 @@ export default {
         const { key } = e.target.dataset;
         if(!this.insertRelationArr.find(_ => _.key===key)) return
         let { relation_date,relation_edb } = this.insertRelationArr.find(_ => _.key===key)
-
         relation_date.key && setRelationStyle(relation_date)
         relation_edb.key && setRelationStyle(relation_edb)
       }
@@ -519,26 +585,25 @@ export default {
     },
 
     /* 选择指标 单元格类型为2 已经是指标单元格了就重置单元格 否则就视为选择指标*/
-    selectTarget(e,cell) {
-      const { EdbName,EdbInfoId }  = e;
-
-      //如果已经是指标单元格了再次点击就清空
-      if(cell.DataType===2&&cell.EdbInfoId) {
-        this.clearCell()
-      }else {
-        cell.DataType = 2;
-        cell.DataTime = '';
-        cell.ShowValue = EdbName;
-        cell.Value = EdbName;
-        cell.EdbInfoId = EdbInfoId;
-      }
-
-      this.checkCellRelation(cell)
-    },
+    // selectTarget(e,cell) {
+    //   const { EdbName,EdbInfoId }  = e;
+
+    //   //如果已经是指标单元格了再次点击就清空
+    //   if(cell.DataType===2&&cell.EdbInfoId) {
+    //     this.clearCell()
+    //   }else {
+    //     cell.DataType = 2;
+    //     cell.DataTime = '';
+    //     cell.ShowValue = EdbName;
+    //     cell.Value = EdbName;
+    //     cell.EdbInfoId = EdbInfoId;
+    //   }
+
+    //   this.checkCellRelation(cell)
+    // },
 
     /* 输入框失焦 设置单元格类型 处理关联关系 */
     async changeVal(e, cell) {
-
       // 是日期格式 DataType为1
       // 自定义内容 DataType 3
       //有=号为输入公式 DataType 6
@@ -563,14 +628,13 @@ export default {
           cell.DataTime = dateFormat;
           cell.Value = dateFormat;
         }else if(value.startsWith('=')) { //公式单元格
+          cell.Value = value;
           cell.DataType = 6;
           let calculateVal = await this.getValueByFormula(value);
           if(!calculateVal) return
           cell.ShowValue = calculateVal;
           //处理公式关系
           this.$set(cell,'Extra',this.dealFormulaConstruction(value))
-          
-
         }else {//自定义值
           cell.DataType = 3;
           cell.ShowValue = value;
@@ -637,7 +701,11 @@ export default {
       let relationIndex = this.insertRelationArr.findIndex(_ => _.key===key)
       this.insertRelationArr.splice(relationIndex,1)
     },
-
+    // 替换关联关系
+    replaceCellRelation(originKey,replaceKey){
+      if(!this.insertRelationArr.length) return
+      this.insertRelationArr = JSON.parse(JSON.stringify(this.insertRelationArr).replaceAll(originKey,replaceKey))
+    },
     /* 单元格更新时去更新有依赖关系单元格的值 目前只更4 5 7*/
     updateRelationCell(relation,cell) {
       const cellTypeMap = {
@@ -770,7 +838,6 @@ export default {
 
       // 提取因数数组
       let factors = extractFactorsFromFormula(val)
-      console.log(factors)
       
       //根据因数找单元格
       let isAllCell = factors.some(_ => findCellByFactorMixed(this.config.data,_)===null||isNaN(findCellByFactorMixed(this.config.data,_)))
@@ -785,7 +852,7 @@ export default {
           TagMap[_] = Number(findCellByFactorMixed(this.config.data,_))
         }
       });
-
+      
       const res = await sheetInterface.calculateCustomCellData({
         CalculateFormula: val,
         TagMap
@@ -803,10 +870,12 @@ export default {
     rightClickHandle(e,cell) {
       if(this.disabled) return
 
-      const { rindex,cindex,key } = e.target.dataset;
+      const { rindex,cindex,key,datacindex,datarindex } = e.target.dataset;
       this.rightClickCell = {
         rindex,
         cindex,
+        datarindex,
+        datacindex,
         key
       }
 
@@ -817,12 +886,20 @@ export default {
         pos = 'col'
       }else if(cindex==='-1') { //行头
         pos = 'row'
+      }else if( datarindex>=this.selectionStart.row && datarindex<=this.selectionEnd.row &&
+      datacindex>=this.selectionStart.column && datacindex<=this.selectionEnd.column &&
+      (this.selectionEnd.row-this.selectionStart.row>0||this.selectionEnd.column-this.selectionStart.column>0)){
+        // 选区
+        pos = 'selection'
       }else {//单元格
         pos = 'cell'
       }
+
+      pos==='cell' && this.clickCell(e,cell);
+
       this.config.contextMenuOption = pos === 'cell' 
-        ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||[5,7,8].includes(cell.DataType))
-        : getRightClickMenu(pos)
+        ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||[5,7,8].includes(cell.DataType),false,{cellMerged:this.hasMergedCell})
+        : getRightClickMenu(pos,false,false,{cellMerged:this.hasMergedCell})
 
       this.$nextTick(() => {
         let dom = $('#contextMenu-wrapper')[0];
@@ -835,9 +912,10 @@ export default {
           dom.style.top = e.clientY-3 + 'px';
         }
 
-        ['col','row'].includes(pos) && selectMoreCellStyle(e);
-        pos==='cell' && this.clickCell(e,cell);
-
+        if(['col','row'].includes(pos)){
+          this.clearSelection()
+          selectMoreCellStyle(e);
+        }
       })
       
     },
@@ -872,7 +950,9 @@ export default {
         // 'insert-edb-date': this.insertDateOpen,//导入指标日期
         'insert-date-calculate': this.insertDateCalculateOpen,//日期计算弹窗
         'reset': this.clearCell, //清空
-        'cell-edit': this.selectCell ? editHandlesMap[this.selectCell.DataType] : null
+        'cell-edit': this.selectCell ? editHandlesMap[this.selectCell.DataType] : null,
+        'cell-merge':this.mergeCellFun,
+        'cell-unmerge':this.unmergeCellsFun
       }
       keyMap[key] && keyMap[key](key)
       
@@ -929,22 +1009,38 @@ export default {
 
     },
 
-    /* 清除单元格内容 格式 关联关系 */
-    clearCell() {
-      if([4,5].includes(this.selectCell.DataType)) resetRelationStyle();
+    /* 
+      清除单元格内容 格式 关联关系 
+      config:{
+        single:true 清除单个,不考虑合并单元格的联系
+      }
+    */
+    clearCell(c) {
+      const isCell = c && typeof(c)=='object' && c.Uid
+      const cell = isCell ? c: this.selectCell
+
+      if([4,5].includes(cell.DataType)) resetRelationStyle();
+
+      cell.DataType = 3;
+      cell.ShowValue = '';
+      cell.Value = '';
+      cell.DataTime = '';
+      cell.DataTimeType = 0;
+      cell.EdbInfoId = 0;
+      cell.ShowStyle = '';
+      cell.ShowFormatValue = '';
+      cell.Extra && (cell.Extra = '');
 
-      this.selectCell.DataType = 3;
-      this.selectCell.ShowValue = '';
-      this.selectCell.Value = '';
-      this.selectCell.DataTime = '';
-      this.selectCell.DataTimeType = 0;
-      this.selectCell.EdbInfoId = 0;
-      this.selectCell.ShowStyle = '';
-      this.selectCell.ShowFormatValue = '';
+      this.checkCellRelation(cell)
 
-      this.checkCellRelation(this.selectCell)
     },
-
+    findDataByStartKey(key){
+      if(!key) return {data:{},row:-1,col:-1}
+      let mergeCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
+      let row = +mergeCellDom.dataset.datarindex
+      let col = +mergeCellDom.dataset.datacindex
+      return {data:this.config.data[row][col],row,col}
+    },
     /* 删除行列 */
     delColOrRow() {
       let { rindex,cindex } = this.rightClickCell;
@@ -956,23 +1052,113 @@ export default {
 
         let index = this.columnHeader.findIndex(_ => _ === cindex);
 
+        // 处理删除列对合并单元格的影响
+        let startMainKey=''
+        this.config.data.map((row,rowInd) => {
+          let rowEle=row[index]
+          if(rowEle.merData){
+            let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
+            let r = row
+            let c = col
+            let rs = data.merData.mer.rowspan
+            let cs = data.merData.mer.colspan
+            if(cs == 1) return //只有一列
+
+            if(rowEle.merData.type == 'merged'){
+              // 每个大单元格只处理一次
+              if(startMainKey != rowEle.merData.mer.sKey){
+                if(data.merData.mer.colspan==2 && data.merData.mer.rowspan==1){
+                  //删除这一列之后,只有一个单元格了
+                  data.merData=null
+                  return
+                }
+                data.merData.mer.colspan--
+                startMainKey = rowEle.merData.mer.sKey
+              }
+            }else{
+              // 右一列的单元格作为新的左上角单元格
+              const newStartCell = this.config.data[r][c+1]
+              if(rowEle.merData.mer.colspan==2 && rowEle.merData.mer.rowspan==1){
+                //删除这一列之后,只有一个单元格了
+                newStartCell.merData=null
+                return
+              }
+              newStartCell.merData=rowEle.merData
+              newStartCell.merData.mer.sKey = newStartCell.Uid
+              newStartCell.merData.mer.colspan--
+              for (let i = r; i < (r+rs); i++) {
+                for (let j = c+1; j < (c+cs); j++) {
+                  const element = this.config.data[i][j];
+                  if(element.merData.type == 'merged'){
+                    element.merData.mer.sKey = newStartCell.Uid
+                  }
+                }                  
+              }
+            }
+          }
+        })
         //删除时清除关系
         if(this.insertRelationArr.length) {
           let delCellIds = this.config.data.map(row => row[index].Uid);
-          
           this.clearRelationInsertCell(delCellIds);
         }
-
         this.config.data.forEach(row => {
           row.splice(index,1)
         })
+        // 删除的是最后一列
+        if(!(index < this.config.data[0].length)){
+          resetStyle()
+        }
       }else if(cindex === '-1') { //删除行
         console.log('删除行',rindex)
 
         if(this.rowHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_row_msg') )
 
         let index = this.rowHeader.findIndex(_ => _ === rindex)
-        
+        // 处理删除行对合并单元格的影响
+        let startMainKey=''
+        this.config.data[index].map((rowEle,rowInd) => {
+          if(rowEle.merData){
+            let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
+            let r = row
+            let c = col
+            let rs = data.merData.mer.rowspan
+            let cs = data.merData.mer.colspan
+            if(rs == 1) return //只有一行
+
+            if(rowEle.merData.type == 'merged'){
+              // 每个大单元格只处理一次
+              if(startMainKey != rowEle.merData.mer.sKey){
+                if(data.merData.mer.colspan==1 && data.merData.mer.rowspan==2){
+                  //删除这一行之后,只有一个单元格了
+                  data.merData=null
+                  return
+                }
+                data.merData.mer.rowspan--
+                startMainKey = rowEle.merData.mer.sKey
+              }
+            }else{
+              // 下一行的单元格作为新的左上角单元格
+              const newStartCell = this.config.data[r+1][c]
+              if(rowEle.merData.mer.colspan==1 && rowEle.merData.mer.rowspan==2){
+                //删除这一行之后,只有一个单元格了
+                newStartCell.merData=null
+                return
+              }
+              newStartCell.merData=rowEle.merData
+              newStartCell.merData.mer.sKey = newStartCell.Uid
+              newStartCell.merData.mer.rowspan--
+              for (let i = r+1; i < (r+rs); i++) {
+                for (let j = c; j < (c+cs); j++) {
+                  const element = this.config.data[i][j];
+                  if(element.merData.type == 'merged'){
+                    element.merData.mer.sKey = newStartCell.Uid
+                  }
+                }                  
+              }
+            }
+          }
+        })
         if(this.insertRelationArr.length) {
           //删除时清除关系
           let delCellIds = this.config.data[index].map(cell => cell.Uid);
@@ -981,7 +1167,10 @@ export default {
         }
 
         this.config.data.splice(index,1)
-
+        // 删除的是最后一行
+        if(!(index < this.config.data.length)){
+          resetStyle()
+        }
       }
     },
 
@@ -1003,18 +1192,30 @@ export default {
       let { cindex } = this.rightClickCell;
       
       let index = this.columnHeader.findIndex(_ => _ === cindex);
-
+      let checkIndex = key==='insert-col-left'?index-1:index+1
+      let startMainKey=''
       this.config.data.forEach((row,rindex) => {
+        let isEnlargeCell = !!(row[index].merData && row[checkIndex] && row[checkIndex].merData)
+        if(isEnlargeCell && startMainKey != row[index].merData.mer.sKey){
+          const data = row[index].merData.type == 'merge'?row[index]:this.findDataByStartKey(row[index].merData.mer.sKey).data
+          data.merData.mer.colspan++
+          startMainKey = row[index].merData.mer.sKey
+        }
         row.splice(key==='insert-col-left'?index:index+1,0,{
           ShowValue: "",
           Value: "",
           DataType: 3,
           DataTime: "",
           EdbInfoId: 0,
-          Uid: md5.hex_md5(`${new Date().getTime()}${rindex}`)
+          Uid: md5.hex_md5(`${new Date().getTime()}${rindex}`),
+          merData:isEnlargeCell?{
+            type:'merged',
+            mer:{
+              sKey:row[index].merData.mer.sKey,//左上角第一个单元格的Uid
+            }
+          }:null
         })
       })
-      
     },
 
     /* 插入行 */
@@ -1022,15 +1223,35 @@ export default {
       let { rindex } = this.rightClickCell;
       
       let index = this.rowHeader.findIndex(_ => _ === rindex)
+      let checkIndex = key==='insert-row-up'?index-1:index+1
+      let startMainKey=''
+
+      let row = new Array(this.columnHeader.length).fill("").map((_,cindex) => {
+
+        let isEnlargeCell = !!(this.config.data[index][cindex].merData && this.config.data[checkIndex][cindex] && this.config.data[checkIndex][cindex].merData)
+        if(isEnlargeCell && startMainKey != this.config.data[index][cindex].merData.mer.sKey){
+          const data = this.config.data[index][cindex].merData.type == 'merge'?
+                      this.config.data[index][cindex]:
+                      this.findDataByStartKey(this.config.data[index][cindex].merData.mer.sKey).data
+          data.merData.mer.rowspan++
+          startMainKey = this.config.data[index][cindex].merData.mer.sKey
+        }
 
-      let row = new Array(this.columnHeader.length).fill("").map((_,cindex) => ({
-        ShowValue: "",
-        Value: "",
-        DataType: 3,
-        DataTime: "",
-        EdbInfoId: 0,
-        Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`)
-      }));
+        return {
+          ShowValue: "",
+          Value: "",
+          DataType: 3,
+          DataTime: "",
+          EdbInfoId: 0,
+          Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`),
+          merData:isEnlargeCell?{
+            type:'merged',
+            mer:{
+              sKey:this.config.data[index][cindex].merData.mer.sKey,//左上角第一个单元格的Uid
+            }
+          }:null
+        }
+      });
 
       this.config.data.splice( key==='insert-row-up'?index:index+1,0,row)
 
@@ -1083,7 +1304,6 @@ export default {
 
     /* 插入系统/指标日期 */
     insertDatehandle({insertValue,dataTimeType,str,sourceName}) {
-
       this.updateSourceFrom(sourceName)
 
       this.insertTargetCell.DataType = 1;
@@ -1202,7 +1422,7 @@ export default {
             DataTimeType: 0,
             DataTime: "",
             EdbInfoId:0,
-            Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`)
+            Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`),
           }));
         });
       }
@@ -1241,6 +1461,7 @@ export default {
         cell.EdbInfoId = this.copyCellItem.EdbInfoId;
         cell.ShowStyle = this.copyCellItem.ShowStyle;
         cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
+        cell.Extra = this.copyCellItem.Extra;
       }else {
         cell.DataType = 3;
         cell.ShowValue = this.copyCellItem.ShowValue;
@@ -1298,12 +1519,11 @@ export default {
       }
     },
 
-    /* 改变单元格显示文本 */
-    updateCellStyle({ShowStyle,ShowFormatValue}) {
-      
-      this.$set(this.selectCell,'ShowStyle',ShowStyle)
-      this.$set(this.selectCell,'ShowFormatValue',ShowFormatValue)
-    },
+    // /* 改变单元格显示文本 */
+    // updateCellStyle({ShowStyle,ShowFormatValue}) {
+    //   this.$set(this.selectCell,'ShowStyle',ShowStyle)
+    //   this.$set(this.selectCell,'ShowFormatValue',ShowFormatValue)
+    // },
     // 更新数据来源
     updateSourceFrom(source){
       if(!source) return
@@ -1311,6 +1531,339 @@ export default {
       let sourceStr = Array.from(new Set(concatSourceArr)).join(',');
       this.sourceFrom.text=sourceStr
       this.$emit('updateSourceName')
+    },
+    // ==================================================合并单元格
+    // 选区开始
+    selectCellHandle(e) {
+      // 不是左键的mousedown事件
+      if(e.button!==0) return
+      if(this.disabled) return
+      this.isSelectionStart=true
+      
+      let startTd;
+      if(e.target.nodeName==='TD'){
+        startTd = e.target
+      }else if(e.target.parentNode.nodeName==='TD'){
+        startTd = e.target.parentNode
+      }else if(e.target.parentNode.parentNode.nodeName==='TD'){
+        startTd = e.target.parentNode.parentNode
+      }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
+        startTd = e.target.parentNode.parentNode.parentNode
+      }
+
+      if(!startTd) return
+
+      this.startCell={
+        row:+startTd.dataset.datarindex,
+        column:+startTd.dataset.datacindex
+      }
+      document.addEventListener('mousemove',this.selectZoneHandle)
+      document.addEventListener('mouseup',this.selectCellEndHandle)
+    },
+    // 选取
+    selectZoneHandle(e) {
+      if(!this.isSelectionStart) return 
+      if(this.disabled) return
+      const selection = window.getSelection();
+      if (selection.rangeCount>0) {
+        // 清除选中的文本范围
+        selection.removeAllRanges();
+      }
+
+      let tableRect=this.$refs.tableRef.getBoundingClientRect()
+      const mouseX = e.pageX;
+      const mouseY = e.pageY;
+
+      let endTd;
+
+      if(mouseX >= tableRect.left && mouseX <= tableRect.right &&
+      mouseY >= tableRect.top && mouseY <= tableRect.bottom){
+        // 表格内
+        if(e.target.nodeName==='TD'){
+          endTd = e.target
+        }else if(e.target.parentNode.nodeName==='TD'){
+          endTd = e.target.parentNode
+        }else if(e.target.parentNode.parentNode.nodeName==='TD'){
+          endTd = e.target.parentNode.parentNode
+        }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
+          endTd = e.target.parentNode.parentNode.parentNode
+        }
+        if(!endTd) return 
+
+        this.endCell={
+          row:+endTd.dataset.datarindex,
+          column:+endTd.dataset.datacindex
+        }
+      }
+    },
+    // 选区结束
+    selectCellEndHandle(){
+      this.isSelectionStart=false
+      // click事件走在mouseup事件前面,延迟下
+      setTimeout(()=>{
+        if((this.selectionStart.row || this.selectionStart.row==0) 
+      && (this.selectionEnd.row || this.selectionEnd.row==0)
+      && (this.selectionStart.column || this.selectionStart.column==0)
+      && (this.selectionEnd.column || this.selectionEnd.column==0)){
+          this.selectedCells=[]
+          resetStyle()
+          this.selectCell=null
+          // 选区
+          for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
+            for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
+              this.selectedCells.push(this.config.data[i][j])
+            }        
+          }
+        }else{
+          this.selectedCells=[]
+        }
+      },1)
+      document.removeEventListener('mousemove',this.selectZoneHandle)
+      document.removeEventListener('mouseup',this.selectCellEndHandle)
+    },
+    findCellDom(key){
+      if(!key) return null
+      if(key !== this.cacheKey){
+        // 重新找
+        this.cacheCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
+        this.cacheKey=key
+      }
+      return this.cacheCellDom
+    },
+    // 确定选区范围和设置选区样式
+    setSelectionStyle(){
+     if(!this.isSelectionStart) return
+      // 开始的单元格没有
+      if(!( (this.startCell.row || this.startCell.row==0) && 
+        (this.startCell.column || this.startCell.column==0))) return 
+      // 结束的单元格没有
+      if(!( (this.endCell.row || this.endCell.row==0) && 
+        (this.endCell.column || this.endCell.column==0))) return
+
+      // 递归确定选区范围
+      const findZone = ({sR,eR,sC,eC})=>{
+        this.hasValueCellItem.cellNumber=0
+        
+        for (let i = sR; i < eR+1; i++) {
+          for (let j = sC; j < eC+1; j++) {
+            const element = this.config.data[i][j]
+            if(element.Value){
+              this.hasValueCellItem.cellNumber++
+              this.hasValueCellItem.row=i
+              this.hasValueCellItem.column=j
+            }
+
+            if(element.merData && element.merData.type==='merge'){
+              if(i+element.merData.mer.rowspan-1 > eR){
+                // 该单元格的行有合并 重新规定选取范围
+                return findZone({sR,eR:i+element.merData.mer.rowspan-1,sC,eC})
+              }
+              if(j+element.merData.mer.colspan-1 > eC){
+                // 该单元格的列有合并 重新规定选取范围
+                return findZone({sR,eR,sC,eC:j+element.merData.mer.colspan-1})
+              }
+              this.hasMergedCell=true
+            }
+            
+            if(element.merData && element.merData.type==='merged' ){
+              let item = this.findCellDom(element.merData.mer.sKey)
+              let row = +item.dataset.datarindex
+              let col = +item.dataset.datacindex
+              if(row < sR){
+                // 该单元格的行有被合并 重新规定选取范围
+                return findZone({sR:row,eR,sC,eC})
+              }
+              if(col < sC){
+                // 该单元格的行有被合并 重新规定选取范围
+                return findZone({sR,eR,sC:col,eC})
+              }
+              this.hasMergedCell=true
+            }
+          }
+        }
+        // 防止选中的区域不是整个的单元格(合并后的),后面确定selectionRef 区域大小有问题
+        if(this.config.data[eR][eC].merData && this.config.data[eR][eC].merData.type==='merged'){
+          let item = this.findCellDom(this.config.data[eR][eC].merData.mer.sKey) 
+          let row = +item.dataset.datarindex
+          let col = +item.dataset.datacindex
+          eR=row
+          eC=col
+          this.hasMergedCell=true
+        }
+        return {startR:sR,
+                endR:eR,
+                startC:sC,
+                endC:eC}
+      }
+
+      // 看是否是从下往上、从右往左选的
+      let rowReverse = this.startCell.row > this.endCell.row
+      let colReverse = this.startCell.column > this.endCell.column
+      let postion={
+        sR:rowReverse?this.endCell.row:this.startCell.row,
+        eR:rowReverse?this.startCell.row:this.endCell.row,
+        sC:colReverse?this.endCell.column:this.startCell.column,
+        eC:colReverse?this.startCell.column:this.endCell.column
+      }
+
+      this.hasMergedCell=false
+      const zone = findZone(postion)
+
+      let start = this.config.data[zone.startR][zone.startC]
+      let end = this.config.data[zone.endR][zone.endC]
+
+      this.selectionStart.row = zone.startR
+      this.selectionStart.column = zone.startC
+      this.selectionStart.rowSpan = start.merData?start.merData.mer.rowspan:1
+      this.selectionStart.colSpan = start.merData?start.merData.mer.colspan:1
+
+      this.selectionEnd.row = zone.endR
+      this.selectionEnd.column = zone.endC
+      this.selectionEnd.rowSpan = end.merData?end.merData.mer.rowspan:1
+      this.selectionEnd.colSpan = end.merData?end.merData.mer.colspan:1
+
+      let tableRect = this.$refs.tableRef.getBoundingClientRect()
+      let startTd = this.$refs.tableRef.querySelector(`[data-key="${start.Uid}"]`)
+      let endTd = this.$refs.tableRef.querySelector(`[data-key="${end.Uid}"]`)
+      if(!(startTd && endTd)) return
+      let startRect = startTd.getBoundingClientRect()
+      let endRect = endTd.getBoundingClientRect()
+
+      this.$refs.selectionRef.style.left = startRect.left-tableRect.left+'px'
+      this.$refs.selectionRef.style.top = startRect.top-tableRect.top+'px'
+      let width = Math.abs(endRect.right - startRect.right) + startRect.width
+      let height = Math.abs(endRect.bottom - startRect.bottom) + startRect.height
+      this.$refs.selectionRef.style.width = width+'px'
+      this.$refs.selectionRef.style.height = height + 'px'
+      this.$refs.selectionRef.style.visibility='visible'
+    },
+    clearSelection(){
+      this.$refs.selectionRef.style.width = 0
+      this.$refs.selectionRef.style.height = 0
+      this.$refs.selectionRef.style.visibility='hidden'
+      this.selectionStart={
+        row:null,
+        rowSpan:0,
+        column:null,
+        colSpan:0
+      }
+      this.selectionEnd={
+        row:null,
+        rowSpan:0,
+        column:null,
+        colSpan:0,
+      }
+      this.selectedCells=[]
+    },
+    mergeCellFun(){
+      // 无选区
+      if(!((this.selectionStart.row || this.selectionStart.row==0) 
+      && (this.selectionEnd.row || this.selectionEnd.row==0)
+      && (this.selectionStart.column || this.selectionStart.column==0)
+      && (this.selectionEnd.column || this.selectionEnd.column==0))) return
+
+      if(this.hasValueCellItem.cellNumber>1 || this.hasValueCellItem.cellNumber<0){
+        return this.$message.warning(this.$t('ETable.Msg.merge_cell_fail_msg'))
+      }
+      const firstCell = this.config.data[this.selectionStart.row][this.selectionStart.column]
+      if(this.hasValueCellItem.cellNumber!=0 && (this.hasValueCellItem.row!=this.selectionStart.row || this.hasValueCellItem.column!=this.selectionStart.column)){
+
+        const reserveCell=this.config.data[this.hasValueCellItem.row][this.hasValueCellItem.column]
+        // 将原本有值的单元格 移给左上角第一个单元格
+        firstCell.ShowValue=reserveCell.ShowValue
+        firstCell.ShowStyle=reserveCell.ShowStyle
+        firstCell.ShowFormatValue=reserveCell.ShowFormatValue
+        firstCell.Value=reserveCell.Value
+        firstCell.DataType=reserveCell.DataType
+        firstCell.DataTimeType=reserveCell.DataTimeType
+        firstCell.DataTime=reserveCell.DataTime
+        firstCell.EdbInfoId=reserveCell.EdbInfoId
+        reserveCell.CanEdit && (firstCell.CanEdit=reserveCell.CanEdit)
+        reserveCell.Extra && (firstCell.Extra=reserveCell.Extra)
+        // 处理合并后的依赖关系 就是替换
+        this.replaceCellRelation(reserveCell.Uid,firstCell.Uid)
+        // 清空
+        this.clearCell(reserveCell)
+      }
+
+
+      this.$set(firstCell,'merData',{
+        type:'merge',
+        mer:{
+          sKey:firstCell.Uid,//保留的单元格的Uid
+          rowspan: this.selectionEnd.row - this.selectionStart.row+1,
+          colspan: this.selectionEnd.column - this.selectionStart.column+1,
+        }
+      })
+
+      for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
+        for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
+          const element = this.config.data[i][j]
+          if(i == this.selectionStart.row && j == this.selectionStart.column){
+            continue
+          }
+          element.merData={
+            type:'merged',
+            mer:{
+              sKey:firstCell.Uid,//左上角第一个单元格的Uid
+            }
+          }
+        }        
+      }
+
+      let startCell = this.config.data[this.selectionStart.row][this.selectionStart.column]
+      let target = this.$refs.tableRef.querySelector(`[data-key="${startCell && startCell.Uid}"]`)
+      // 触发单元格的点击事件
+      target.click()
+    },
+    unmergeCellsFun(){
+      if((this.selectionStart.row || this.selectionStart.row==0) 
+      && (this.selectionEnd.row || this.selectionEnd.row==0)
+      && (this.selectionStart.column || this.selectionStart.column==0)
+      && (this.selectionEnd.column || this.selectionEnd.column==0)){
+        // 选区
+        for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
+          for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
+            this.unmergeCellFun(this.config.data[i][j])
+          }        
+        }
+      }else{
+        // 单个单元格
+        this.selectCell && this.unmergeCellFun(this.selectCell)
+      }
+      this.hasMergedCell=false
+      // 取消合并后,调整选区(有的话)
+      if((this.selectionStart.row || this.selectionStart.row==0) 
+      && (this.selectionEnd.row || this.selectionEnd.row==0)
+      && (this.selectionStart.column || this.selectionStart.column==0)
+      && (this.selectionEnd.column || this.selectionEnd.column==0)){
+        this.selectionStart.rowSpan=1
+        this.selectionStart.colSpan=1
+
+        this.selectionEnd.row += (this.selectionEnd.rowSpan-1)
+        this.selectionEnd.column += (this.selectionEnd.colSpan-1)
+        this.selectionEnd.rowSpan=1
+        this.selectionEnd.colSpan=1
+      }
+
+    },
+    unmergeCellFun(cell){
+      if(!(cell.merData && cell.merData.type=='merge')) return
+      let {row,col} = this.findDataByStartKey(cell.merData.mer.sKey)
+      const sRow = row,
+          sCol = col,
+          eRow = row+cell.merData.mer.rowspan-1,
+          eCol = col+cell.merData.mer.colspan-1
+
+      for (let i = sRow; i < eRow+1; i++) {
+        for (let j = sCol; j < eCol+1; j++) {
+          this.config.data[i][j].merData=null
+        }
+      }
+    },
+    toolCellMergeFun(){
+      if(this.hasMergedCell) this.unmergeCellsFun()
+      else this.mergeCellFun()
     }
   },
 };
@@ -1325,6 +1878,7 @@ export default {
 .table-wrapper {
   width: 100%;
   overflow: auto;
+  * { box-sizing: border-box; }
 
   .formula-wrapper {
     height: 42px;
@@ -1375,32 +1929,32 @@ export default {
       border: 2px dashed #0033ff;
       box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
     }
-    &.td-col-select::after {
-      position: absolute;
-      top: 0;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      content: "";
-      display: block;
-      outline: 0;
-      border: 1px solid rgb(24, 173, 24);
-      border-bottom: none;
-      border-top: none;
-    }
-    &.td-row-select::after {
-      position: absolute;
-      top: 0;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      content: "";
-      display: block;
-      outline: 0;
-      border: 1px solid rgb(24, 173, 24);
-      border-left: none;
-      border-right: none;
-    }
+    // &.td-col-select::after {
+    //   position: absolute;
+    //   top: 0;
+    //   left: 0;
+    //   right: 0;
+    //   bottom: 0;
+    //   content: "";
+    //   display: block;
+    //   outline: 0;
+    //   border: 1px solid rgb(24, 173, 24);
+    //   border-bottom: none;
+    //   border-top: none;
+    // }
+    // &.td-row-select::after {
+    //   position: absolute;
+    //   top: 0;
+    //   left: 0;
+    //   right: 0;
+    //   bottom: 0;
+    //   content: "";
+    //   display: block;
+    //   outline: 0;
+    //   border: 1px solid rgb(24, 173, 24);
+    //   border-left: none;
+    //   border-right: none;
+    // }
     &.td-choose-insert-target::after {
       position: absolute;
       top: 0;

+ 116 - 40
src/views/datasheet_manage/components/toolBarSection.vue

@@ -2,7 +2,7 @@
   <!-- 混合表格顶部工具栏 -->
   <div class="toolbar-wrapper">
     <div 
-      class="tool-btn-item" v-for="tool in toolIcons" 
+      class="tool-btn-item" v-for="tool in toolIcons.filter(ic => tools.split(',').includes(ic.tool))" 
       :key="tool.key" 
       @click="dealToolHandles(tool)"
     >
@@ -11,6 +11,11 @@
         <template v-if="tool.type==='icon'">
           <span class="icon-wrap" v-html="tool.icon"></span>
         </template>
+        
+        <div class="icon-box" v-if="tool.type=='icon-text'">
+          <span class="icon-wrap" v-html="tool.icon"></span>
+          <span class="icon-txt">{{tool.title}}</span>
+        </div>
 
         <template v-if="tool.type==='select'">
           <el-select 
@@ -18,7 +23,7 @@
             style="width: 90px" 
             size="small" 
             v-if="tool.key==='cell-type-edit'"
-            @change="changeCellType"
+            @change="changeCellsType"
           >
             <el-option
               v-for="item in numberTypeOptions"
@@ -40,15 +45,35 @@ export default {
     cell: {
       type: Object,
     },
+    /**工具
+     * cell-point-type(数字/百分位显示切换) 
+     * cell-merge(合并单元格)
+    */
+    tools:{
+      type:'String',
+      default:'cell-point-type,cell-merge',
+    },
+    // 回显参数
+    echoParameter:{
+      type:Object,
+      default:()=>{
+        return {}
+      },
+    }
   },
   watch: {
     cell(nval) {
-      if(nval&&nval.ShowStyle) {
-        this.option = {
-          ...JSON.parse(nval.ShowStyle)
+      if(nval) {
+        this.cellArray = Array.isArray(nval)?nval:[nval]
+        this.option = this.cellArray[0].ShowStyle?{
+          ...JSON.parse(this.cellArray[0].ShowStyle)
+        }:{
+          nt: "",//numberType
+          pn: 0,//ponitNum
         }
-      }else {
-        this.option = {
+      }else{
+        this.cellArray=[]
+        this.option ={
           nt: "",//numberType
           pn: 0,//ponitNum
         }
@@ -61,8 +86,7 @@ export default {
         nt: "",//numberType  number percent
         pn: 0,//ponitNum
       },
-
-
+      cellArray:[],
     };
   },
   computed:{
@@ -83,7 +107,8 @@ export default {
           </svg>`,
           key: "add-point",
           type: 'icon',
-          title: this.$t('ETableChildren.number_increase_title') 
+          title: this.$t('ETableChildren.number_increase_title') ,
+          tool:'cell-point-type'
         },
         { 
           icon: `<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
@@ -100,13 +125,25 @@ export default {
           </svg>`, 
           key: "del-point", 
           type: 'icon',
-          title: this.$t('ETableChildren.number_reduce_title') 
+          title: this.$t('ETableChildren.number_reduce_title'),
+          tool:'cell-point-type'
         },
         { 
           icon: '',
           key: 'cell-type-edit',
           type:'select',
-          title:'' 
+          title:'' ,
+          tool:'cell-point-type'
+        },
+        { 
+          icon: `<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+            <path d="M17.9 1.45H2.1C1.55 1.45 1.1 1.9 1.1 2.45V18.25C1.1 18.8 1.55 19.25 2.1 19.25H17.9C18.45 19.25 18.9 18.8 18.9 18.25V2.45C18.9 1.9 18.45 1.45 17.9 1.45ZM17.7 6.54H12.87V2.65H17.7V6.54ZM7.15 6.54V2.65H11.68V6.54H7.15ZM5.95 2.65V6.54H2.3V2.65H5.95ZM5.95 12.23H2.3V7.74H5.95V12.23ZM2.3 13.43H5.95V18.06H2.3V13.43ZM7.15 18.05V7.74H17.7V18.05H7.15Z" fill="#333333"/>
+            </svg>
+            `,
+          key: 'cell-merge',
+          type:'icon-text',
+          title:this.echoParameter.hasMergedCell?this.$t('ETable.Btn.unmerge'):this.$t('ETable.Btn.merge_cell'),
+          tool:'cell-merge'
         }
       ]
     },
@@ -119,54 +156,71 @@ export default {
   },
   methods: {
     dealToolHandles({key}) {
-      //单元格不是数字就不用转了
-      if(!isNumberVal(this.cell.ShowValue)) return
 
       const handlesMap = {
-        'add-point': this.changeCellPoint,
-        'del-point': this.changeCellPoint,
+        'add-point': this.changeCellsPoint,
+        'del-point': this.changeCellsPoint,
+        'cell-merge': this.cellMergeHandle,
       }
 
       handlesMap[key]&&handlesMap[key](key)
     },
-
+    changeCellsPoint(key){
+      this.cellArray.map(item =>{
+        if(!item.merData || item.merData.type=='merge'){
+          this.changeCellPoint(key,item)
+        }
+      })
+    },
     /* 处理小数点位数 */
-    changeCellPoint(key) {
-      let value = _.cloneDeep(this.cell.ShowValue)
-      key==='add-point' ? this.option.pn++ : this.option.pn--;
+    changeCellPoint(key,cell) {
+      //单元格不是数字就不用转了
+      if( !isNumberVal(cell.ShowValue)) return
+      let cellValueStyle = cell.ShowStyle?JSON.parse(cell.ShowStyle):{
+        nt: "",//numberType
+        pn: 0,//ponitNum
+      }
+      key==='add-point' ? cellValueStyle.pn++ : cellValueStyle.pn--;
       
       //判断小数点后尾数 整数最小pn为0 小数最小为负位数
-      if(this.option.pn <= parseInt(`-${getDecimalPlaces(value)}`)) {
-        this.option.pn = parseInt(`-${getDecimalPlaces(value)}`)
+      if(cellValueStyle.pn <= parseInt(`-${getDecimalPlaces(cell.ShowValue)}`)) {
+        cellValueStyle.pn = parseInt(`-${getDecimalPlaces(cell.ShowValue)}`)
       }
 
       //百分比格式的话 pn最小为位数-2
-      if(this.option.nt==='percent' && this.option.pn <= parseInt(`-${getDecimalPlaces(value)-2}`)) {
-        this.option.pn = parseInt(`-${getDecimalPlaces(value)-2}`)
+      if(cellValueStyle.nt==='percent' && cellValueStyle.pn <= parseInt(`-${getDecimalPlaces(cell.ShowValue)-2}`)) {
+        cellValueStyle.pn = parseInt(`-${getDecimalPlaces(cell.ShowValue)-2}`)
       }
 
-      let nval = transDecimalPlace(value,this.option)
+      cell.ShowFormatValue = transDecimalPlace(cell.ShowValue,{...cellValueStyle,pn:cellValueStyle.pn})
+      cell.ShowStyle = JSON.stringify({...cellValueStyle,pn:cellValueStyle.pn})
       // console.log(nval)
-
-      this.$emit('updateCell',{
-        ShowStyle: JSON.stringify(this.option),
-        ShowFormatValue: nval
+      // this.$emit('updateCell',{
+      //   ShowStyle: JSON.stringify({...this.option,cellValueStyle.pn}),
+      //   ShowFormatValue: nval
+      // })
+    },
+    changeCellsType(){
+      this.cellArray.map(item =>{
+        if(!item.merData || item.merData.type=='merge'){
+          this.changeCellType(item)
+        }
       })
     },
-
     /* 处理百分位或数字格式 */
-    changeCellType() {
-      if(!isNumberVal(this.cell.ShowValue)) return
+    changeCellType(item) {
+      if(!isNumberVal(item.ShowValue)) return
       this.option.pn = 0
 
-      let value = _.cloneDeep(this.cell.ShowValue)
-
-      let nval = transNumPercentType(value,this.option.nt)
-
-      this.$emit('updateCell',{
-        ShowStyle: JSON.stringify(this.option),
-        ShowFormatValue: nval
-      })
+      item.ShowFormatValue = transNumPercentType(item.ShowValue,this.option.nt)
+      item.ShowStyle = JSON.stringify(this.option)
+      // this.$emit('updateCell',{
+      //   ShowStyle: JSON.stringify(this.option),
+      //   ShowFormatValue: nval
+      // })
+    },
+    cellMergeHandle(){
+      this.$emit('cellMerge')
     }
   },
 };
@@ -197,6 +251,28 @@ export default {
         height: 20px;
         display: inline-block;
       }
+      .icon-box{
+        display: flex;
+        align-items: center;
+        padding: 6px;
+        border: 1px solid #C8CDD9;
+        border-radius: 4px;
+        .icon-wrap{
+          width: 18px;
+          height: 18px;
+          display: inline-block;
+        }
+        .icon-txt{
+          white-space: nowrap;
+          font-size: 14px;
+          color: #333333;
+          margin-left: 4px;
+        }
+        &:hover {
+          background: #F4F8FE;
+        }
+      }
+
     }
   }
 }

+ 4 - 2
src/views/datasheet_manage/sheetList.vue

@@ -582,7 +582,10 @@ export default {
     },
     /* 表格id */
     select_id(newval,oldVlue) {
-      newval && this.getDetailHandle();
+      if(newval){
+        this.sheetDetailInfo = {}
+        this.getDetailHandle()
+      }
       this.markFinishStatus(oldVlue)
     },
 
@@ -753,7 +756,6 @@ export default {
       this.select_classify = !ExcelInfoId ? ExcelClassifyId : 0;
       if (this.select_id !== ExcelInfoId) {
         this.select_id = ExcelInfoId || 0;
-        this.sheetDetailInfo = {};
       }
       this.resetNodeStyle(node);
       this.dynamicNode = node;

+ 12 - 15
src/views/edbHistoryPage.vue

@@ -162,9 +162,7 @@ export default {
             this.mould = document.getElementById('mould')
             this.mouldText = document.getElementById('mould-text')
 
-            let edbName=this.treeData.EdbName+(this.treeData.IsStop?'(暂停更新)':'')
-            let edbNameEn=this.treeData.EdbNameEn+(this.treeData.IsStop?'(Pause Updates)':'')
-            this.mouldText.innerText=edbName
+            this.mouldText.innerText=this.treeData.EdbName
             let node = this.graph.createNode({
                 shape: 'vue-shape',
                 component: 'custom-rect',
@@ -179,8 +177,8 @@ export default {
                     },
                 },
                 data:{
-                    EdbName:edbName,
-                    EdbNameEn:edbNameEn,
+                    EdbName:this.treeData.EdbName,
+                    EdbNameEn:this.treeData.EdbNameEn,
                     RuleTitle:this.treeData.RuleTitle,
                     RuleTitleEn:this.treeData.RuleTitleEn,
                     routeQuery:{ 
@@ -191,9 +189,8 @@ export default {
                     },
                     isRoot:true,
                     isLeaf:(this.treeData.Child && this.treeData.Child.length>0)?false:true,
-                    style:{
-                        color:this.treeData.IsStop?"red!important":'#ffffff!important',
-                    },
+                    isStop:this.treeData.IsStop,
+                    style:{color:'#ffffff!important'},
                 }
             })
             let cells = [node,...this.createCells(this.treeData.Child,node)]
@@ -207,9 +204,8 @@ export default {
             }
             let dataList = []
             list.forEach(element => {
-                let edbName=element.EdbName+(element.IsStop?'(暂停更新)':'')
-                let edbNameEn=element.EdbNameEn+(this.treeData.IsStop?'(Pause Updates)':'')
-                this.mouldText.innerText=edbName
+
+                this.mouldText.innerText=element.EdbName
                 let node = this.graph.createNode({
                     shape: 'vue-shape',
                     component: 'custom-rect',
@@ -226,10 +222,10 @@ export default {
                     data:{
                         style:{
                             backgroundColor:'#f2f6fa',
-                            color:element.IsStop?"red!important":'#000000',
+                            color:'#000000',
                         },
-                        EdbName:edbName,
-                        EdbNameEn:edbNameEn,
+                        EdbName:element.EdbName,
+                        EdbNameEn:element.EdbNameEn,
                         RuleTitle:element.RuleTitle,
                         RuleTitleEn:element.RuleTitleEn,
                         routeQuery:{ 
@@ -239,7 +235,8 @@ export default {
                             EdbInfoType:element.EdbInfoType
                         },
                         isRoot:false,
-                        isLeaf:(element.Child && element.Child.length>0)?false:true
+                        isLeaf:(element.Child && element.Child.length>0)?false:true,
+                        isStop:element.IsStop,
                     }
                 })
                 let side = this.graph.createEdge({

+ 7 - 6
src/views/futures_manage/chartEditor.vue

@@ -576,12 +576,13 @@ export default {
     },
     
     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.chart_code ? this.$t('MsgPrompt.add_msg2')||'添加成功' : this.$t('MsgPrompt.saved_msg')||'保存成功');
 			this.$router.replace({
 				path: '/commordityChartBase',

+ 8 - 6
src/views/futures_manage/commodityChartBase.vue

@@ -575,12 +575,14 @@ export default {
     },
 
     async setImageHandle(form) {
-      let { Data } = await dataBaseInterface.uploadImgSvg(form);
-
-      await dataBaseInterface.setChartImage({
-        ChartInfoId: this.selected_chartid,
-        ImageUrl: Data.ResourceUrl,
-      });
+      // let { Data } = await dataBaseInterface.uploadImgSvg(form);
+
+      // await dataBaseInterface.setChartImage({
+      //   ChartInfoId: this.selected_chartid,
+      //   ImageUrl: Data.ResourceUrl,
+      // });
+			form.append('ChartInfoId',this.selected_chartid)
+			await dataBaseInterface.setChartThumbnail(form)
     },
 
 		copyChartConfirm(type) {

+ 27 - 11
src/views/mychart_manage/components/chartDetailDia.vue

@@ -639,7 +639,9 @@ export default {
           this.refreshLoading = false;
           if (res.Ret !== 200) return;
           this.chartInfo = res.Data.ChartInfo;
-          
+
+          this.chartInfo.SeasonExtraConfig && (this.SeasonExtraConfig = JSON.parse(this.chartInfo.SeasonExtraConfig))
+
           if(!this.chartInfo.HaveOperaAuth) return
 
           if([1,11].includes(this.chartInfo.Source)) {
@@ -685,11 +687,15 @@ export default {
                   {
                     Value: res.Data.YDataList[0].Value,
                     Color:'#00f',
-                    Name:res.Data.ChartInfo.ChartName,
-                    NameEn:res.Data.ChartInfo.ChartNameEn
+                    Name:res.Data.YDataList[0].Name||res.Data.ChartInfo.ChartName,
+                    NameEn:res.Data.YDataList[0].NameEn||res.Data.ChartInfo.ChartNameEn
                   }
                 ]
             }
+            //多因子
+            if(res.Data.CorrelationChartInfo.AnalysisMode===1){
+                this.relevanceChartData.YDataList = res.Data.YDataList
+            }
             
             this.initRelevanceChartData()
             this.tableData = res.Data.EdbInfoList
@@ -1229,12 +1235,14 @@ 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.chartInfo.ChartInfoId,
-        ImageUrl: Data.ResourceUrl,
-      });
+      // let { Data } = await dataBaseInterface.uploadImgSvg(form);
+      // // let { Data } = await dataBaseInterface.uploadImg(form);
+      // await dataBaseInterface.setChartImage({
+      //   ChartInfoId: this.chartInfo.ChartInfoId,
+      //   ImageUrl: Data.ResourceUrl,
+      // });
+      form.append('ChartInfoId',this.chartInfo.ChartInfoId)
+			await dataBaseInterface.setChartThumbnail(form)
     },
 
     /* 点击表格行展开配置项 */
@@ -1323,12 +1331,19 @@ export default {
     editChartHandle() {
       
       let path = '';
+      let type = '';
       if(this.chartInfo.Source === 1){
         path='/editchart'
       }else if([2,5].includes(this.chartInfo.Source)){
         path='/addCommodityChart'
       }else if([3,4].includes(this.chartInfo.Source)){
-        path='/relevancechartEditor'
+        //path='/relevancechartEditor'
+        path='/relevancechartEditorV2'
+        if(this.chartInfo.Source===3){
+            type = this.relevanceChartData.CorrelationChartInfo&&this.relevanceChartData.CorrelationChartInfo.AnalysisMode||0
+        }else{//滚动相关性也是单因子
+            type = 0
+        }
       }else if(this.chartInfo.Source===6){
         path='/fittingEquationChartEditor'
       }else if([7,8,9].includes(this.chartInfo.Source)) {
@@ -1342,7 +1357,8 @@ export default {
         path,
         query: {
           code: this.chartInfo.UniqueCode,
-          from: 'mychart'
+          from: 'mychart',
+          type,
         }
       })
       window.open(href,'_blank');

+ 48 - 35
src/views/ppt_manage/mixins/mixins.js

@@ -207,22 +207,25 @@ export default {
         ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
         : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`
         const nameEn = item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
+
+        //图表可配置的线条数就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:nameCh,
           nameCh:nameCh,
           nameEn:nameEn,
           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
         };
@@ -383,7 +386,8 @@ export default {
 
         //预测指标配置
         let predict_params = item.EdbInfoCategoryType === 1 ? this.getPredictParams(item,chartStyle) : {};
-        
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         //中英文名称
         const nameCh = dynamic_arr.length > 1
         ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
@@ -399,7 +403,7 @@ export default {
           nameCh:nameCh,
           nameEn:nameEn,
           color: item.ChartColor,
-          lineWidth: Number(item.ChartWidth),
+          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,
@@ -456,7 +460,7 @@ export default {
       temChartDataList
 
       // 跟颜色对应
-      chartTheme.lineOptionList=chartTheme.lineOptionList.reverse().slice(-chartDataHandle.length)
+      chartTheme && (chartTheme.lineOptionList=chartTheme.lineOptionList.reverse().slice(-chartDataHandle.length))
 
       let seasonYdata = [],
         seasonData = []
@@ -475,19 +479,20 @@ export default {
         let j = chartDataHandle[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: 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
         };
@@ -1025,18 +1030,19 @@ export default {
       data.forEach((item,index) => {
         //处理首或/尾全是无效数据的以null填充
         let filterData = this.filterInvalidData(item)
-
+        //图表可配置的线条数就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
           }
@@ -1237,21 +1243,22 @@ export default {
         opposite: false,
         tickWidth: 1,
       }
-
       //处理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
           }
@@ -1364,7 +1371,10 @@ export default {
 
       //数据列
       let series = [];
-      DataList.forEach(item => {
+      DataList.forEach((item,index) => {
+
+        //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+				const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
         //数据列
         let series_item = {
           data: [],
@@ -1377,7 +1387,7 @@ export default {
           chartType: 'linear',
           zIndex:1,
           marker: {
-            radius: (chartTheme&&chartTheme.lineOptionList.radius)||5,
+            radius: (chartTheme&&chartTheme.lineOptionList[lineIndex].radius)||5,
           },
         }
         item.EdbInfoList.forEach(_ => {
@@ -1540,17 +1550,18 @@ export default {
           max: index===0? Number(LeftMaxValue):Number(RightMaxValue),
           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
         }
@@ -1806,17 +1817,19 @@ export default {
       //系列
       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)

+ 12 - 1
src/views/ppt_manage/mixins/pptEditorMixins.js

@@ -88,7 +88,18 @@ export default{
     }
   },
   methods:{
-    testInput(e,item){
+    handlePaste(e,item){
+        //不触发input
+        e.preventDefault()
+        //只获取文字
+        const text = e.clipboardData.getData('text/plain')
+        if(!text.trim().length){
+            this.$message.warning(this.$t('Slides.title_paste_hint'))
+        }
+        e.target.innerHTML += text.trim()
+        item.title += text.trim()
+    },
+    handleInput(e,item){
         const text = e.target.innerHTML
         item.title = text
     },

+ 23 - 15
src/views/ppt_manage/mixins/pptMixins.js

@@ -216,7 +216,8 @@ export default {
             PublishTime,
             Editor,
             CoverContent,
-            TitleSetting
+            TitleSetting,
+            AdminId
         } = res.Data
         const pptDate = formatPPTDate(this.currentLang, PptDate)
         let legalContent = JSON.parse(Content)
@@ -248,7 +249,8 @@ export default {
             PublishTime,
             Editor,
             CoverContent,
-            TitleSetting:legalTitleSetting
+            TitleSetting:legalTitleSetting,
+            AdminId
         }
       }else{
         this.result = {status:'',content:'获取ppt数据失败!'}
@@ -311,17 +313,21 @@ export default {
       }else if([3].includes(this.chartInfo.Source)){//相关性
         this.relevanceChartData={
             ChartInfo:res.Data.ChartInfo,
-						EdbInfoList:res.Data.EdbInfoList,
-						XEdbIdValue:this.chartInfo.Source === 3 ? res.Data.XEdbIdValue : res.Data.DataResp.XDateTimeValue,
-						CorrelationChartInfo:res.Data.CorrelationChartInfo,
-						YDataList:[
-							{
-								Value:this.chartInfo.Source === 3 ? res.Data.YDataList[0].Value : res.Data.DataResp.YDataList[0].Value,
-								Color:'#00f',
-								Name:res.Data.ChartInfo.ChartName,
-								NameEn:res.Data.ChartInfo.ChartNameEn
-							}
-						]
+            EdbInfoList:res.Data.EdbInfoList,
+            XEdbIdValue:this.chartInfo.Source === 3 ? res.Data.XEdbIdValue : res.Data.DataResp.XDateTimeValue,
+            CorrelationChartInfo:res.Data.CorrelationChartInfo,
+            YDataList:[
+                {
+                    Value:this.chartInfo.Source === 3 ? res.Data.YDataList[0].Value : res.Data.DataResp.YDataList[0].Value,
+                    Color:res.Data.YDataList[0].Color||'#00f',
+                    Name:res.Data.YDataList[0].Name||res.Data.ChartInfo.ChartName,
+                    NameEn:res.Data.YDataList[0].NameEn||res.Data.ChartInfo.ChartNameEn
+                }
+            ]
+        }
+        //多因子重新赋值YDataList
+        if(res.Data.CorrelationChartInfo.AnalysisMode===1){
+            this.relevanceChartData.YDataList = res.Data.YDataList
         }
         this.initRelevanceChartData()
         this.changeRelevanceOptions(currentLang)
@@ -860,11 +866,13 @@ export default {
                 })
             let  parser = new DOMParser();
             let svgDoc = parser.parseFromString(svgData, 'image/svg+xml');
-
+            //console.log('plotBackgroundColor',plotBackgroundColor)
             // 查找class为'background'的rect元素并修改fill属性
             let rectElement = svgDoc.querySelector('rect.highcharts-plot-background');
             if (rectElement) {
-                rectElement.setAttribute('fill', plotBackgroundColor);
+                //transparent(生成的图表背景会变黑) -> rgba(255, 255, 255, 0)
+                let currentColor = plotBackgroundColor==='transparent'?'rgba(255, 255, 255, 0)':plotBackgroundColor
+                rectElement.setAttribute('fill', currentColor);
             }
             // 将修改后的SVG文档转换回字符串
             let serializer = new XMLSerializer();

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