浏览代码

Merge branch 'master' into ETA1.4.2

jwyu 1 年之前
父节点
当前提交
064ba899d1
共有 100 个文件被更改,包括 7173 次插入409 次删除
  1. 0 1
      index.html
  2. 5 5
      src/api/crypto.js
  3. 1 1
      src/api/http.js
  4. 23 1
      src/api/modules/chartApi.js
  5. 338 1
      src/api/modules/chartRelevanceApi.js
  6. 1 1
      src/api/modules/dataApi.js
  7. 66 0
      src/api/modules/dataSource.js
  8. 10 0
      src/api/modules/pptApi.js
  9. 10 0
      src/api/modules/pptEnApi.js
  10. 21 0
      src/api/modules/sheetApi.js
  11. 9 0
      src/api/modules/thirdBaseApi.js
  12. 二进制
      src/assets/img/add-quadrate-blue.png
  13. 二进制
      src/assets/img/data_m/icon01.png
  14. 二进制
      src/assets/img/data_m/move_ico2.png
  15. 二进制
      src/assets/img/data_m/set_icon.png
  16. 二进制
      src/assets/img/delete-minus-red.png
  17. 二进制
      src/assets/img/icons/ai_Company.png
  18. 二进制
      src/assets/img/icons/ai_avatar.png
  19. 二进制
      src/assets/img/icons/close_icon_black.png
  20. 二进制
      src/assets/img/icons/email-login-type.png
  21. 二进制
      src/assets/img/icons/gpt-4-turbo.png
  22. 二进制
      src/assets/img/icons/gpt-4.png
  23. 22 10
      src/components/chart/chartDetailHandlesWrap.vue
  24. 8 4
      src/components/chart/chartListWrap.vue
  25. 1 1
      src/components/lzTable.vue
  26. 21 7
      src/routes/modules/chartRoutes.js
  27. 19 0
      src/routes/modules/dataSource.js
  28. 6 0
      src/routes/modules/oldRoutes.js
  29. 24 1
      src/utils/buttonConfig.js
  30. 7 4
      src/utils/parseData.js
  31. 8 7
      src/utils/svgToblob.js
  32. 11 1
      src/views/Home.vue
  33. 81 6
      src/views/Login.vue
  34. 2 1
      src/views/chartFrame_manage/index.vue
  35. 1 1
      src/views/chartRelevance_manage/components/chartCard.vue
  36. 24 0
      src/views/chartRelevance_manage/components/explainText.js
  37. 32 5
      src/views/chartRelevance_manage/components/selectTarget.vue
  38. 670 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue
  39. 208 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/chartFormSection.vue
  40. 140 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/edbTableSection.vue
  41. 182 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/tagRelationDialog.vue
  42. 203 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/tagSetDialog.vue
  43. 570 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/list.vue
  44. 5 2
      src/views/chartRelevance_manage/css/index.scss
  45. 8 6
      src/views/chartRelevance_manage/fittingEquation/fittingEquationChartEditor.vue
  46. 3 3
      src/views/chartRelevance_manage/fittingEquation/fittingEquationList.vue
  47. 35 21
      src/views/chartRelevance_manage/mixins/classifyMixin.js
  48. 5 5
      src/views/chartRelevance_manage/relevance/list.vue
  49. 9 10
      src/views/chartRelevance_manage/relevance/relevanceChartEditor.vue
  50. 7 8
      src/views/chartRelevance_manage/statistic/statisticFeatureChartEditor.vue
  51. 3 3
      src/views/chartRelevance_manage/statistic/statisticFeatureList.vue
  52. 2 1
      src/views/dataEntry_manage/addChart.vue
  53. 38 9
      src/views/dataEntry_manage/chartSetting.vue
  54. 26 4
      src/views/dataEntry_manage/coal/index.vue
  55. 8 2
      src/views/dataEntry_manage/components/LegendEditDia.vue
  56. 8 2
      src/views/dataEntry_manage/components/SaveChartOther.vue
  57. 7 1
      src/views/dataEntry_manage/components/insertData.vue
  58. 46 12
      src/views/dataEntry_manage/components/setEnNameDia.vue
  59. 22 0
      src/views/dataEntry_manage/css/baseTargetPage.scss
  60. 11 1
      src/views/dataEntry_manage/css/exchangedata.scss
  61. 26 6
      src/views/dataEntry_manage/dataEntry.vue
  62. 555 56
      src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue
  63. 1 1
      src/views/dataEntry_manage/databaseComponents/dataAssociateChart.vue
  64. 47 1
      src/views/dataEntry_manage/databaseComponents/util.js
  65. 22 16
      src/views/dataEntry_manage/databaseList.vue
  66. 2 1
      src/views/dataEntry_manage/editChart.vue
  67. 240 24
      src/views/dataEntry_manage/mixins/chartPublic.js
  68. 1 1
      src/views/dataEntry_manage/targetList.vue
  69. 19 5
      src/views/dataEntry_manage/thirdBase/BAIINFOTargetbase.vue
  70. 19 2
      src/views/dataEntry_manage/thirdBase/NationalDataBase.vue
  71. 18 2
      src/views/dataEntry_manage/thirdBase/SCITargetbase.vue
  72. 9 1
      src/views/dataEntry_manage/thirdBase/chinaFinancialFutures.vue
  73. 288 0
      src/views/dataEntry_manage/thirdBase/components/batchAddEdbDia.vue
  74. 23 17
      src/views/dataEntry_manage/thirdBase/components/targetDialog.vue
  75. 9 1
      src/views/dataEntry_manage/thirdBase/dlExchangeData.vue
  76. 22 3
      src/views/dataEntry_manage/thirdBase/elaSteoBase.vue
  77. 27 5
      src/views/dataEntry_manage/thirdBase/glTargetbase.vue
  78. 28 7
      src/views/dataEntry_manage/thirdBase/lzTargetbase.vue
  79. 14 4
      src/views/dataEntry_manage/thirdBase/mixins/leftMixin.js
  80. 9 1
      src/views/dataEntry_manage/thirdBase/shEnergy.vue
  81. 9 1
      src/views/dataEntry_manage/thirdBase/shFutures.vue
  82. 65 14
      src/views/dataEntry_manage/thirdBase/smmTargetbase.vue
  83. 108 15
      src/views/dataEntry_manage/thirdBase/steelChemicalbase.vue
  84. 9 1
      src/views/dataEntry_manage/thirdBase/zzExchangeData.vue
  85. 162 0
      src/views/dataSource_manage/accountList.vue
  86. 177 0
      src/views/dataSource_manage/components/DelEDBTable.vue
  87. 313 0
      src/views/dataSource_manage/components/DetailTable.vue
  88. 183 0
      src/views/dataSource_manage/components/EDBInfoChangeTable.vue
  89. 158 0
      src/views/dataSource_manage/components/EditAccount.vue
  90. 137 0
      src/views/dataSource_manage/components/GLRefreshFailDetail.vue
  91. 123 0
      src/views/dataSource_manage/components/SetTableCols.vue
  92. 186 0
      src/views/dataSource_manage/components/StatisticTable.vue
  93. 108 0
      src/views/dataSource_manage/dataSourceListGL.vue
  94. 4 0
      src/views/dataSource_manage/utils/config.js
  95. 1 1
      src/views/datasheet_manage/addSheet.vue
  96. 43 8
      src/views/datasheet_manage/common/customTable.js
  97. 38 3
      src/views/datasheet_manage/components/CustomTable.vue
  98. 458 64
      src/views/datasheet_manage/components/MixedTable.vue
  99. 24 0
      src/views/datasheet_manage/components/SheetExcel.vue
  100. 521 0
      src/views/datasheet_manage/components/calculateEdbDia.vue

+ 0 - 1
index.html

@@ -12,7 +12,6 @@
 	<link rel="icon" type="image/x-icon" href="./static/fa.ico" id="icon"/>
 	<script src="./static/js/vue.js"></script>  <!-- 开发版,开发过程中使用此方案-->
 	<script src="./static/js/main.js"></script>  <!-- 生产版,打包的时候使用此方案 -->
-	<script src="./static/base_config.js"></script>  <!-- key -->
 	<!-- 引入组件库 -->
 	
 	<!-- oss SDK -->

+ 5 - 5
src/api/crypto.js

@@ -1,16 +1,16 @@
-const key = window.key||'6WpHp4vSvLVQK8SLioNZ7WMq'; //eta
-// const key = 'cJ3b1I4YBlTc85vnxy36xip2'; //逸诺
-// const key = 'bvS3kVp7QIZoD70fPk1wk41n'; //试用
+let key = ''; //eta
 
 class CryptoJS {
 	// 3DES加密,CBC/PKCS5Padding
-	static Des3Encrypt (input) {
+	static Des3Encrypt (input,keyVal) {
+		key=keyVal
 		let genKey = genkey(key, 0, 24);
 		return base64encode(des(genKey.key, input, 1, 1, key.substr(0, 8), 1));
 	}
 
 	// 3DES解密,CBC/PKCS5Padding
-	static Des3Decrypt (input) {
+	static Des3Decrypt (input,keyVal) {
+		key=keyVal
 		let genKey = genkey(key, 0, 24);
 		return des(genKey.key, base64decode(input), 0, 1, key.substr(0, 8), 1);
 	}

+ 1 - 1
src/api/http.js

@@ -44,7 +44,7 @@ function checkStatus(response) {
   //处理响应数据
   if (response && response.status === 200) {
     // loading,如果http状态码正常,则直接返回数据
-    let res = bus.$parseData(response.data);
+    let res = bus.$parseData(response);
     if (!res) {
       bus.$message.error("服务器开了个小差");
       return false;

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

@@ -396,7 +396,20 @@ const dataBaseInterface = {
 		return http.get('/datamanage/edb_source/list/python')
 	},
 
-
+	/**
+	 * 新增指标 检验指标是否存在接口
+	 * @param {*} params Source SubSource EdbCode StockCode
+	 */
+	edbExistCheck: params => {
+		return http.get('/datamanage/edb_info/exist/check',params)
+	},
+	/**
+	 * 批量新增指标
+	 * @param {*} params BatchList[{Source,EdbName,Frequency,Unit,ClassifyId,StockCode,EdbCode}]
+	 */
+	edbAddBatch: params => {
+		return http.post('/datamanage/edb_info/batch/add',params)
+	},
 	//========================================chart
 	// /**
 	//  * 
@@ -911,6 +924,15 @@ const dataBaseInterface = {
 	 */
 	saveEdbChartImg:(params)=>{
 		return http.post('/datamanage/edb_info/image/set',params)
+	},
+
+	/** 
+	 * 获取图表批量刷新结果
+	 *   Source ReportId ReportChapterId
+	 * 
+	 */
+	getReportrefreshStatus: params => {
+		return http.post('/datamanage/chart_info/batch_refresh/result',params)
 	}
 	
 }

+ 338 - 1
src/api/modules/chartRelevanceApi.js

@@ -635,7 +635,19 @@ export const statisticFeatureInterface = {
 
   /**
    * 设置英文
-   * @param {*} params  ChartInfoId ChartNameEn
+   * @param {*} params  ChartInfoId ChartNameEn 
+   * "TagList": [
+      {
+        "ChartTagId": 1,
+        "TagNameEn": "宏观en"
+      }
+    ],
+    "VarietyList": [
+      {
+        "ChartVarietyId": 2,
+        "VarietyNameEn": "甲醇en"
+      }
+    ]
    * @returns 
    */
   editChartEn: params => {
@@ -682,4 +694,329 @@ export const statisticFeatureInterface = {
     previewSpline: params => {
       return http.post('/line_feature/preview_cure',params)
     }
+}
+
+/* 跨品种分析 */
+export const crossVarietyInterface = {
+  /**
+   * 分类列表
+   * @param {*} params 
+   * @returns 
+   */
+  classifyList: params => {
+    return http.get('/cross_variety/classify/list',params)
+  },
+
+  /**
+   * 分类添加
+   * @param {*} params ChartClassifyName
+   * @returns 
+   */
+  classifyAdd: params => {
+    return http.post('/cross_variety/classify/add',params)
+  },
+
+  /**
+   * 分类编辑
+   * @param {*} params ChartClassifyName ChartClassifyId
+   * @returns 
+   */
+  classifyEdit: params => {
+    return http.post('/cross_variety/classify/edit',params)
+  },
+
+  /**
+   * 分类移动
+   * @param {*} params 
+   * "ClassifyId": 269,
+    "PrevClassifyId": 0,
+    "NextClassifyId": 227,
+   * @returns 
+   */
+  classifyMove: params => {
+    return http.post('/cross_variety/classify/move',params)
+  },
+
+   /**
+   * 图表拖动
+   * @param {*} params 
+   * "ChartInfoId": 844,
+    "PrevChartInfoId": 0,
+    "NextChartInfoId": 839,
+    "ChartClassifyId": 270
+   * @returns 
+   */
+    chartMove: params => {
+      return http.post('/cross_variety/chart_info/move',params)
+    },
+  
+    /**
+     * 获取图表列表
+     * @param {*} params 
+     * CurrentIndex PageSize ChartClassifyId Keyword IsShowMe
+     * @returns 
+     */
+    getChartList: params => {
+      return http.get('/cross_variety/chart_info/list',params)
+    },
+  
+    /**
+     * 图表详情
+     * @param {*} params  ChartInfoId
+     * @returns 
+     */
+    chartDetail: params => {
+      return http.get('/cross_variety/chart_info/detail',params)
+    },
+
+    /**
+     * 添加图表
+     * @param {*} params 
+     * "ChartName": "跨品种分析图标名称",
+      "TagX": 1,
+      "TagY": 2,
+      "CalculateValue": 6,
+      "CalculateUnit": "月",
+      "DateConfigList": [
+        {
+          "DateType": 2,
+          "Num": 60
+        }
+      ],
+      "VarietyList": [2,5]
+     * @returns 
+     */
+    chartAdd: params => {
+      return http.post('/cross_variety/chart_info/add',params)
+    },
+
+    /**
+     * 编辑图表
+     * @param {*} params 
+     * ChartInfoId
+     * "ChartName": "跨品种分析图标名称",
+      "TagX": 1,
+      "TagY": 2,
+      "CalculateValue": 6,
+      "CalculateUnit": "月",
+      "DateConfigList": [
+        {
+          "DateType": 2,
+          "Num": 60
+        }
+      ],
+      "VarietyList": [2,5]
+     * @returns 
+     */
+    chartEdit: params => {
+      return http.post('/cross_variety/chart_info/edit',params)
+    },
+
+    /**
+     * 删除图表
+     * @param {*} params ChartInfoId
+     * @returns 
+     */
+    chartDel: params => {
+      return http.post('/cross_variety/chart_info/delete',params)
+    },
+
+    /**
+     * 预览图表
+     * @param {*} params 
+     *  "TagX": 1,
+        "TagY": 2,
+        "CalculateValue": 6,
+        "CalculateUnit": "月",
+        "DateConfigList": [
+          {
+            "DateType": 1,
+            "Num": 0
+          }
+        ],
+        "VarietyList": [2,5]
+     * @returns 
+     */
+    chartPreview: params => {
+      return http.post('/cross_variety/chart_info/preview',params)
+    },
+
+    /**
+     * 设置英文
+     * @param {*} params  ChartInfoId ChartNameEn
+     * "TagList": [
+        {
+          "ChartTagId": 1,
+          "TagNameEn": "宏观en"
+        }
+      ],
+      "VarietyList": [
+        {
+          "ChartVarietyId": 2,
+          "VarietyNameEn": "甲醇en"
+        }
+      ]
+     */
+    editChartEn: params => {
+      return http.post('/cross_variety/chart_info/en/edit',params)
+    },
+
+    /**
+     * 图表搜索
+     * @param {*} params Keyword
+     * @returns 
+     */
+    searchChart: params => {
+      return http.get('/cross_variety/chart_info/search_by_es',params)
+    },
+
+    /**
+     * 刷新图表
+     * @param {*} params ChartInfoId
+     * @returns 
+     */
+    refreshChart: params => {
+      return http.get('/cross_variety/chart_info/refresh',params)
+    },
+
+    /**
+     * 图表另存为
+     * @param {*} params ChartInfoId ChartName
+     * @returns 
+     */
+    saveOtherChart: params => {
+      return http.post('/cross_variety/chart_info/copy',params)
+    },
+    
+    /**
+     * 编辑英文名称
+     * @param {*} params 
+     * @returns 
+     */
+    editChartEn: params => {
+      return http.post('/cross_variety/chart_info/en/edit',params)
+    },
+
+    /**
+     * 图表设置语言配置信息
+     * @param {*} params  ChartInfoId
+     * @returns 
+     */
+    chartLangOption: params => {
+      return http.get('/cross_variety/chart_info/relation',params)
+    },
+    
+    /**
+     * 品种列表
+     * @param {*} params 
+     */
+    getVarietyList: params => {
+      return http.get('/cross_variety/variety/list',params)
+    },
+
+    /**
+     * 添加品种
+     * @param {VarietyName} params 
+     * @returns 
+     */
+    varietyAdd: params => {
+      return http.post('/cross_variety/variety/add',params)
+    },
+    
+    /**
+     * 编辑品种
+     * @param {VarietyName ChartVarietyId} params 
+     * @returns 
+     */
+    varietyEdit: params => {
+      return http.post('/cross_variety/variety/edit',params)
+    },
+    
+    /**
+     * 删除品种检测
+     * @param {ChartVarietyId} params 
+     * @returns 
+     */
+    varietyDelCheck: params => {
+      return http.post('/cross_variety/variety/delete/check',params)
+    },
+    
+    /**
+     * 删除品种
+     * @param {ChartVarietyId} params 
+     * @returns 
+     */
+    varietyDel: params => {
+      return http.post('/cross_variety/variety/delete',params)
+    },
+
+    /**
+     * 标签列表
+     * @param {*} params 
+     */
+    getTagList: params => {
+      return http.get('/cross_variety/tag/list',params)
+    },
+
+    /**
+     * 添加标签
+     * @param {TagName} params 
+     * @returns 
+     */
+    tagAdd: params => {
+      return http.post('/cross_variety/tag/add',params)
+    },
+
+    /**
+     * 编辑标签
+     * @param {TagName ChartTagId} params 
+     * @returns 
+     */
+    tagEdit: params => {
+      return http.post('/cross_variety/tag/edit',params)
+    },
+
+    /**
+     * 删除标签检测
+     * @param {ChartTagId} params 
+     * @returns 
+     */
+    tagDelCheck: params => {
+      return http.post('/cross_variety/tag/delete/check',params)
+    },
+
+    /**
+     * 添加标签
+     * @param {ChartTagId} params 
+     * @returns 
+     */
+    tagDel: params => {
+      return http.post('/cross_variety/tag/delete',params)
+    },
+
+    /**
+     * 设置标签关联品种对应信息
+     * @param {
+        "ChartTagId": 1,
+        "VarietyEdb": [
+            {
+                "ChartVarietyId": 2,
+                "EdbInfoId": 103407
+            },
+        ]
+     * } params 
+     * @returns 
+     */
+    setTagRelationVariety: params => {
+      return http.post('/cross_variety/tag/variety_edb/save',params)
+    },
+
+
+    /**
+     * 获取标签关联的品种信息
+     * @param {ChartTagId} params 
+     */
+    getTagRelation: params => {
+      return http.get('/cross_variety/tag/variety_edb/list',params)
+    }
 }

+ 1 - 1
src/api/modules/dataApi.js

@@ -191,7 +191,7 @@ const dataInterence = {
 
 	// 谷歌出行指数 获取数据
 	getGoogleTravelData:params=>{
-		return http.get('	/datamanage/visitors_covid/list',params)
+		return http.get('/datamanage/visitors_covid/list',params)
 	},
 	
 	// 上海国际能源交易中心

+ 66 - 0
src/api/modules/dataSource.js

@@ -0,0 +1,66 @@
+import http from "@/api/http.js"
+
+// 数据源管理模块
+const apiDataSource={
+    //获取数据源列表列配置项
+    //列表类型ColumnType:1数据源明细表,2数据源统计表,3删除指标列表,4指标信息变更表"
+    GLTableColOpts:params=>{
+        return http.get('/data_stat/source_column',params)
+    },
+
+    //编辑自定义列
+    GLTableColEdit:params=>{
+        return http.post('/data_stat/source_column/edit',params)
+    },
+
+    //数据源明细表
+    GLDetailTableList:params=>{
+        return http.get('/data_stat/edb_update_stat',params)
+    },
+
+    //数据源统计
+    GLStatisticTableList:params=>{
+        return http.get('/data_stat/source_stat',params)
+    },
+
+    //删除指标列表数据
+    GLDelTableList:params=>{
+        return http.get('/data_stat/edb_delete_log',params)
+    },
+
+    //指标信息变更列表数据
+    GLEdbInfoTableList:params=>{
+        return http.get('/data_stat/edb_update_log',params)
+    },
+
+    //刷新失败指标详情
+    GLRefreshFailDetail:params=>{
+        return http.get('data_stat/edb_update_stat/failed',params)
+    },
+
+    // 新增/编辑终端账号
+    accountSave:params=>{
+        return http.post('/data_stat/terminal/save',params)
+    },
+
+    //终端账号列表
+    accountList:params=>{
+        return http.get('/data_stat/terminal/list',params)
+    },
+
+    //启用/禁用终端账号
+    accountSet:params=>{
+        return http.post('/data_stat/terminal/status/set',params)
+    },
+
+    // 获取终端编码数据
+    terminalCodeArr:params=>{
+        return http.get('/data_stat/terminal/code',{})
+    }
+    
+
+}
+
+export {
+    apiDataSource
+}

+ 10 - 0
src/api/modules/pptApi.js

@@ -256,6 +256,16 @@ export default{
      */
     transCatalogtoEn:params=>{
       return http.post('pptv2/batchToEn',params)
+    },
+    /**
+     * PPT编辑加锁
+     * @param {*} params 
+     * @param {Number} params.PptId 
+     * @param {Number} params.Status :0仅查看,1编辑中,2编辑完成
+     * @returns 
+     */
+    pptEditLock:params=>{
+        return http.post('pptv2/editing',params)
     }
 
 }

+ 10 - 0
src/api/modules/pptEnApi.js

@@ -217,6 +217,16 @@ export const pptEnInterface = {
      */
     transPPTtoReport:params => {
       return http.post('/ppt_english/toReport',params)
+    },
+    /**
+     * PPT编辑加锁
+     * @param {*} params 
+     * @param {Number} params.PptId 
+     * @param {Number} params.Status :0仅查看,1编辑中,2编辑完成
+     * @returns 
+     */
+    pptEditLock:params=>{
+        return http.post('ppt_english/editing',params)
     }
 
 }

+ 21 - 0
src/api/modules/sheetApi.js

@@ -266,6 +266,27 @@ export const getDateLatelyData = params => {
 	return http.get('/datamanage/edb_info/date_data/before_after',params)
 }
 
+/**
+ * 获取系统日期
+ * @param {*} params 
+ * "DataTimeType": 1,
+    "Value": "{\"Source\":3,\"Frequency\":\"本周\",\"Day\":\"周日\",\"CalculateNum\":0,\"CalculateFrequency\":\"\"}"
+ * @returns 
+ */
+export const getSystemDate = params => {
+	return http.post('/datamanage/excel_info/get_system_date',params)
+}
+
+/**
+ * 混合表格指标计算
+ * @param {*} params 
+ * EdbInfoId Source Formula Frequency Calendar MoveType MoveFrequency
+ * @returns 
+ */
+export const getMixedCalculateData = params => {
+	return http.post('/datamanage/excel_info/mixed/calculate',params)
+}
+
 
 /* =====自定义分析==== */
 

+ 9 - 0
src/api/modules/thirdBaseApi.js

@@ -81,6 +81,10 @@ const smmDataInterface = {
 	classifyList: params => {
 		return http.get('/datamanage/smm/classify',params);
 	},
+	// 分类下的指标列表
+	edbListForClassify:params=>{
+		return http.get('/datamanage/smm/index/list',params)
+	},
 	/**
 	 * 获取指标目录详情
 	 * @param {ClassifyId}  分类id
@@ -235,6 +239,11 @@ const steelInterface = {
 		return http.get('/datamanage/mysteel_chemical/classify')
 	},
 
+	//指标懒加载
+	edbListForClassify:params=>{
+		return http.get('/datamanage/mysteel_chemical/index/list',params)
+	},
+
 	/**
 	 * 编辑分类 ClassifyName BaseFromMysteelChemicalClassifyId ParentId  Level
 	 * @param {*} params 

二进制
src/assets/img/add-quadrate-blue.png


二进制
src/assets/img/data_m/icon01.png


二进制
src/assets/img/data_m/move_ico2.png


二进制
src/assets/img/data_m/set_icon.png


二进制
src/assets/img/delete-minus-red.png


二进制
src/assets/img/icons/ai_Company.png


二进制
src/assets/img/icons/ai_avatar.png


二进制
src/assets/img/icons/close_icon_black.png


二进制
src/assets/img/icons/email-login-type.png


二进制
src/assets/img/icons/gpt-4-turbo.png


二进制
src/assets/img/icons/gpt-4.png


+ 22 - 10
src/components/chart/chartDetailHandlesWrap.vue

@@ -162,20 +162,32 @@ export default {
             enNameSetting:checkPermissionBtn(productPricePermission.goodsPrice_incomeLine_enNameSetting),
             del:checkPermissionBtn(productPricePermission.goodsPrice_incomeLine_del),
         }
-        //相关性分析
-        if(path==='/chartrelevance'){
-            return chartrelevanceMap[btn]
+
+         const crossVarietyBtnMap = {
+            share:checkPermissionBtn(statisticPermission.crossVariety_share),
+            addMyChart:checkPermissionBtn(statisticPermission.crossVariety_addMyChart),
+            refresh:checkPermissionBtn(statisticPermission.crossVariety_refresh),
+            otherSave:checkPermissionBtn(statisticPermission.crossVariety_otherSave),
+            edit:checkPermissionBtn(statisticPermission.crossVariety_edit),
+            copyOffice:checkPermissionBtn(statisticPermission.crossVariety_copyOffice),
+            copyWechat:checkPermissionBtn(statisticPermission.crossVariety_copyWechat),
+            enNameSetting:checkPermissionBtn(statisticPermission.crossVariety_enNameSetting),
+            del:checkPermissionBtn(statisticPermission.crossVariety_del),
         }
+        //相关性分析
+        if(path==='/chartrelevance') return chartrelevanceMap[btn]
+
         //拟合方程曲线
-        if(path==='/fittingEquationList'){
-            return fittingEquationMap[btn]
-        }
+        else if(path==='/fittingEquationList') return fittingEquationMap[btn]
+        
         //统计特性
-        if(path==='/statisticFeatureList'){
-            return statisticFeatureMap[btn]
-        }
+        else if(path==='/statisticFeatureList') return statisticFeatureMap[btn]
+
+        //跨品种分析
+        else if(path==='/crossVarietyChartList') return crossVarietyBtnMap[btn]
+
         //商品价格曲线
-        if(path==='/commordityChartBase'){
+        else if(path==='/commordityChartBase'){
             const {Source,ChartType} = this.chartInfo
             if(Source===2&&ChartType===8){//是商品价格曲线
                 return priceLineMap[btn]

+ 8 - 4
src/components/chart/chartListWrap.vue

@@ -8,7 +8,7 @@
     >
       <el-col
         :span="6"
-        style="margin-bottom: 20px; padding-right: 20px"
+        style="margin-bottom: 20px; padding-right: 20px;min-width: 270px;"
         v-for="chart in list"
         :key="chart.ChartInfoId"
       >
@@ -67,15 +67,19 @@ export default {
             return checkPermissionBtn(statisticPermission.corrAnalysis_addMyChart)
         }
         //拟合方程曲线
-        if(path==='/fittingEquationList'){
+        else if(path==='/fittingEquationList'){
             return checkPermissionBtn(statisticPermission.fittingEq_addMyChart)
         }
         //统计特性
-        if(path==='/statisticFeatureList'){
+        else if(path==='/statisticFeatureList'){
             return checkPermissionBtn(statisticPermission.statisticFeature_addMyChart)
         }
+        //跨品种分析
+        else if(path==='/crossVarietyChartList') {
+          return checkPermissionBtn(statisticPermission.crossVariety_addMyChart)
+        }
         //商品价格曲线
-        if(path==='/commordityChartBase'){
+        else if(path==='/commordityChartBase'){
             const {Source,ChartType} = item
             if(Source===2&&ChartType===8){//是商品价格曲线
                 return checkPermissionBtn(productPricePermission.goodsPrice_priceLine_addMyChart)

+ 1 - 1
src/components/lzTable.vue

@@ -38,7 +38,7 @@
 			>
 				<th>{{date}}</th>
 				<td v-for="(data, sub_index) in tableOption" :key="sub_index">
-					{{data.DataList.find(item => date === item.DataTime) ? 
+					{{data.DataList && data.DataList.find(item => date === item.DataTime) ? 
 					data.DataList.find(item => date === item.DataTime)[dynamic_key]
 					: ''}}
 				</td>

+ 21 - 7
src/routes/modules/chartRoutes.js

@@ -229,17 +229,17 @@ export default [
 			{
 				path: 'chartrelevance',
 				name: '相关性分析',
-				component:()=>import('@/views/chartRelevance_manage/list.vue')
+				component:()=>import('@/views/chartRelevance_manage/relevance/list.vue')
 			},
 			{
 				path: 'fittingEquationList',
 				name: '拟合方程曲线',
-				component:()=>import('@/views/chartRelevance_manage/fittingEquationList.vue')
+				component:()=>import('@/views/chartRelevance_manage/fittingEquation/fittingEquationList.vue')
 			},
 			{
 				path: 'fittingEquationChartEditor',
 				name: '添加图表',
-				component: () => import('@/views/chartRelevance_manage/fittingEquationChartEditor.vue'),
+				component: () => import('@/views/chartRelevance_manage/fittingEquation/fittingEquationChartEditor.vue'),
 				meta: { 
 					pathFrom: "fittingEquationList",
           			pathName: "拟合方程曲线",
@@ -248,7 +248,7 @@ export default [
 			{
 				path: 'relevancechartEditor',
 				name: '编辑图表',
-				component:()=>import('@/views/chartRelevance_manage/relevanceChartEditor.vue'),
+				component:()=>import('@/views/chartRelevance_manage/relevance/relevanceChartEditor.vue'),
 				meta: { 
 					pathFrom: "chartrelevance",
           			pathName: "相关性图表",
@@ -257,17 +257,31 @@ export default [
 			{
 				path: 'statisticFeatureList',
 				name: '统计特征',
-				component: () => import('@/views/chartRelevance_manage/statisticFeatureList.vue')
+				component: () => import('@/views/chartRelevance_manage/statistic/statisticFeatureList.vue')
 			},
 			{
 				path: 'statisticFeatureChartEditor',
 				name: '编辑图表',
-				component:()=>import('@/views/chartRelevance_manage/statisticFeatureChartEditor.vue'),
+				component:()=>import('@/views/chartRelevance_manage/statistic/statisticFeatureChartEditor.vue'),
 				meta: { 
 					pathFrom: "statisticFeatureList",
           			pathName: "统计特征",
 				}
-			}
+			},
+			{
+				path: 'crossVarietyChartList',
+				name: '跨品种分析',
+				component: () => import('@/views/chartRelevance_manage/crossVarietyAnalysis/list.vue')
+			},
+			{
+				path: 'crossVarietyChartEditor',
+				name: '编辑图表',
+				component:()=>import('@/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue'),
+				meta: { 
+					pathFrom: "crossVarietyChartList",
+          pathName: "跨品种分析",
+				}
+			},
 		]
 	},
 

+ 19 - 0
src/routes/modules/dataSource.js

@@ -0,0 +1,19 @@
+const home = r => require.ensure([], () => r(require('@/views/Home.vue')), 'Home'); //主页
+
+export default [
+    //
+    {
+        path: "/",
+        component: home,
+        name: "数据报表管理",
+        hidden: false,
+        icon_path: require("@/assets/img/home/data_ic.png"),
+        children: [
+            {
+                path: "dataSourceGL",
+                name: "数据源管理",
+                component: () => import("@/views/dataSource_manage/dataSourceListGL.vue"),
+            },
+        ]
+    }
+]

+ 6 - 0
src/routes/modules/oldRoutes.js

@@ -323,6 +323,12 @@ export default [
         name: "外部链接配置",
         hidden: true,
       },
+      {
+        path: "dataSourceAccountList",
+        component: () => import("@/views/dataSource_manage/accountList.vue"),
+        name: "数据源终端管理",
+        hidden: true,
+      },
     ],
   },
   // 外部链接

+ 24 - 1
src/utils/buttonConfig.js

@@ -232,8 +232,13 @@ export const dataSourcePermission = {
     /*--------EIA  STEO报告---- */
     eiaData_export:'eiaData:export',
     /*--------国家统计局---- */
-    gjtjjData_export:'gjtjjData:export'
+    gjtjjData_export:'gjtjjData:export',
 
+    /*--------数据报表管理---- */
+    /*--------数据源终端管理---- */
+    dataSource_account_add:'dataSourceAccount:add',//新增终端账号
+    dataSource_account_edit:'dataSourceAccount:edit',//编辑
+    dataSource_account_enable:'dataSourceAccount:enable',//禁用/启用
 }
 
 /*
@@ -508,6 +513,24 @@ export const statisticPermission = {
     fittingEq_refresh:'fittingEq:refresh',
     fittingEq_addMyChart:'fittingEq:addMyChart',
     fittingEq_share:'fittingEq:share',
+
+    /* 跨品种分析 */
+    crossVariety_addChart:'crossVariety:addChart',//添加图表按钮
+    crossVariety_onlyMine:'crossVariety:onlyMine',//只看我的
+    crossVariety_classifyOpt_edit:'crossVariety:classifyOpt:edit',//添加编辑分类
+    crossVariety_classifyOpt_delete:'crossVariety:classifyOpt:delete',//删除分类
+    crossVariety_variety_edit: 'crossVariety:variety:edit',//品种管理
+    crossVariety_tag_edit: 'crossVariety:tag:edit',//标签管理
+        /*---图表操作栏--- */
+    crossVariety_del:'crossVariety:del',
+    crossVariety_enNameSetting:'crossVariety:enNameSetting',
+    crossVariety_copyWechat:'crossVariety:copyWechat',
+    crossVariety_copyOffice:'crossVariety:copyOffice',
+    crossVariety_edit:'crossVariety:edit',
+    crossVariety_otherSave:'crossVariety:otherSave',
+    crossVariety_refresh:'crossVariety:refresh',
+    crossVariety_addMyChart:'crossVariety:addMyChart',
+    crossVariety_share:'crossVariety:share',
 }
 /*
  * --------------------------------------------------------------------------供应分析------------------------------------------------

+ 7 - 4
src/utils/parseData.js

@@ -1,8 +1,11 @@
 import ParserData from '@/api/crypto.js';
 /* 解密数据处理 */
-export function parseData(res) {
-  let result = process.env.NODE_ENV === "production"
-  ? JSON.parse(ParserData.Des3Decrypt(res))
-  : res;
+export function parseData(response) {
+  const headKeyStr=response.headers.dk
+  sessionStorage.setItem('dk',headKeyStr);
+  const desKey=ParserData.Des3Decrypt(headKeyStr,'JMCqSoUrTAmyNNIRb0TtlrPk')
+  let result = process.env.NODE_ENV == "production"
+  ? JSON.parse(ParserData.Des3Decrypt(response.data,desKey))
+  : response.data;
   return result
 }

+ 8 - 7
src/utils/svgToblob.js

@@ -46,11 +46,12 @@ export const svgToBase64 = (svg) => {
 
 /* 不受粘贴板对象影响的粘贴 */
 export function copyFit(value) {
-  const input = document.createElement('input')
-  input.setAttribute('readonly','readonly')
-  input.value = value
-  document.body.appendChild(input)
-  input.select();
-  document.execCommand('copy');
-  document.body.removeChild(input);
+  if(navigator.clipboard) {
+    navigator.clipboard.writeText(value)
+  }else {
+    setTimeout(() => {
+      bus.$copyText(value)
+    })
+  }
+
 }

+ 11 - 1
src/views/Home.vue

@@ -105,7 +105,7 @@
                       :style="`display: flex;align-items:center;color:${
                         child.path === activePath ? $setting.theme_color : '#666'
                       }`"
-                      @click="(e) => e.preventDefault()"
+                      @click="handleClickSubMenuItem(child,$event)"
                     >
                       <svg t="1689672247666" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7676" width="30" height="30"><path d="M640 499.2v25.6a21.333333 21.333333 0 0 1-21.333333 21.333333h-213.333334a21.333333 21.333333 0 0 1-21.333333-21.333333v-25.6a21.333333 21.333333 0 0 1 21.333333-21.333333h213.333334a21.333333 21.333333 0 0 1 21.333333 21.333333z"  p-id="7677" :fill="child.path === activePath ? $setting.theme_color : '#666'"></path></svg>
                       <span style="margin-left:15px;">{{ child.name }}</span>
@@ -490,6 +490,16 @@ export default {
     this.getPublicSettings();
   },
   methods: {
+    handleClickSubMenuItem(item,e){
+      e.preventDefault();
+      if(item.path==='AIQA'){
+        e.stopPropagation();
+        let { href } = this.$router.resolve({
+          path:'/'+item.path
+        });
+        window.open(href, '_blank')
+      }
+    },
     // 获取商家Code
     getBusinessCodeFun(){
       getBusinessCode().then(res=>{

+ 81 - 6
src/views/Login.vue

@@ -80,9 +80,9 @@
 							:areaCode="areaCode"
 						/>
 					</el-tab-pane>
-					<el-tab-pane label="邮箱登录" name="emailModel">
-						<EmailModel ref="emailModel"/>
-					</el-tab-pane>
+					<!-- <el-tab-pane label="邮箱登录" name="emailModel"> -->
+						<EmailModel ref="emailModel" v-show="activeModel=='emailModel'"/>
+					<!-- </el-tab-pane> -->
 				</el-tabs>
 				<el-button
 					type="primary"
@@ -91,6 +91,19 @@
 					:loading="logining"
 					class="submit_btn"
 					>登录</el-button>
+                <div class="another-login-type">
+                    <div class="another-type-hint">
+                        <div class="type-hint-line"></div>
+                        <div class="type-hint-text">其他登录方式</div>
+                        <div class="type-hint-line"></div>
+                    </div>
+                    <div class="another-type">
+                        <!-- <div class="login-type-item"
+                        > -->
+                            <img src="~@/assets/img/icons/email-login-type.png" @click="activeModel='emailModel';handleClick({name:'emailModel'})" />
+                        <!-- </div> -->
+                    </div>
+                </div>
 			</div>
 			<div class="login-box" v-else>
 				<ForgetPassModel 
@@ -342,10 +355,13 @@ export default {
         },
         ordinaryModelLogin(){
             const {account,checkPass,checked} = this.$refs.ordinaryModel.form
+            const t=new Date().getTime()
+            const md5key='MiQM9yusNA9T2uIH'
             departInterence.userLogin({
                 LoginType:1,
                 Username:account,
-                Password:md5.hex_md5(checkPass)
+                Password: `${md5.hex_md5(md5.hex_md5(checkPass)+md5key+t)}`,
+                ReqTime:`${t}`
             }).then(res=>{
                 //this.logining = false
                 //账号异常 将accountCheck置为true
@@ -532,7 +548,7 @@ export default {
 	height: 100%;
 	background: #fff;
 	position: relative;
-	overflow: hidden;
+	// overflow: hidden;
 	#login_wrapper {
 		width: 100%;
 		height: 100%;
@@ -566,7 +582,7 @@ export default {
 			box-sizing: border-box;
 			border-radius: 10px;
 			position: absolute;
-			top: 27%;
+			top: 18%;
 			right: 12%;
 			z-index: 100;
 			input::-webkit-input-placeholder {
@@ -582,6 +598,48 @@ export default {
 				font-size: 20px;
 				border-radius: 5px;
 			}
+            .another-login-type{
+				margin-top: 45px;
+				.another-type-hint{
+					display: flex;
+					align-items: center;
+					.type-hint-line{
+						flex: 1;
+						height: 1px;
+						background-color: #C0C4CC;
+					}
+					.type-hint-text{
+						font-size: 18px;
+						color: #999999;
+						padding: 0 20px;
+					}
+				}
+				.another-type{
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    img{
+                        margin-top: 20px;
+                        height: 72px;
+                        width: 64px;
+                        cursor: pointer;
+                        // margin-bottom: 4px;
+                    }
+					// .login-type-item{
+					// 	display: flex;
+					// 	flex-direction: column;
+					// 	justify-content: center;
+					// 	align-items: center;
+					// 	margin-top: 20px;
+					// 	cursor: pointer;
+	
+					// 	span{
+					// 		font-size: 16px;
+					// 		color: #666666;
+					// 	}
+					// }
+				}
+			}
 			.el-input input {
 				width: 100%;
 				height: 40px;
@@ -640,6 +698,23 @@ export default {
 			}
 			#login-container ,.login-box{
 				width: 70%;
+				top:15%;
+			}
+		}
+		@media screen and (max-width:1440px){
+			#login-container ,.login-box{
+				.login-title{
+					font-size: 32px;
+				}
+			}
+			
+		}
+		@media screen and (max-height:720px) {
+			#login-container ,.login-box{
+				top:20%;
+				.login-title{
+					margin-bottom: 30px;
+				}
 			}
 		}
 	}

+ 2 - 1
src/views/chartFrame_manage/index.vue

@@ -533,12 +533,13 @@ export default {
                 PageSize:1200,
                 CurrentIndex:1,
                 MyChartClassifyId: Number(id),
+                IsShared:true,
             }).then(res=>{
                 if(res.Ret!==200) return 
                 if(res.Data&&res.Data.List){
                     if(res.Data.List.length){
                         this.chartClassify = id
-                        this.classifyUserId = nodeLink.AdminId||0
+                        this.classifyUserId = nodeLink?nodeLink.AdminId||0:0
                         this.chartCode = res.Data.List[0].UniqueCode
                         this.chartArr = res.Data.List.map(item => item.UniqueCode)
                         this.myETADetailDialogShow = true

+ 1 - 1
src/views/chartRelevance_manage/components/chartCard.vue

@@ -4,7 +4,7 @@
       <div class="title text_twoLine">
          <span>{{cardTitle}}</span>
       </div>
-      <div style="flex-shrink: 0">
+      <div style="flex-shrink: 0;align-self: flex-start;">
         <template v-if="isHaveEdbHandle">
           <el-dropdown 
             v-show="isEdbAdd" 

+ 24 - 0
src/views/chartRelevance_manage/components/explainText.js

@@ -35,4 +35,28 @@ export const statisticFeatureListTextArr = [
     <p>2、根据频段数划分多个间距相同的区间(左闭右开,最后一个区间为左闭右闭),统计数据值落在每个区间的数据个数;</p>
     <p>3、频率=落在某区间数据个数/所选时间段内数据总个数;</p>
     <p>4、累计频率为从最小值所在区间对应的频率开始累加;</p>`
+]
+
+//跨品种分析
+export const crossVarietyAnalisisTextArr = [
+    `<p style="font-weight:bold;">一、处理逻辑</p>
+    <p>1、百分位计算公式:对所选时间范围内的数据,取最大值Max,最小值Min,计算Max-Min,百分位=(现值-Min)/(Max-Min),Max=Min时不计算</p>
+    <p>2、取值方式:</p>
+    <p>(1)通过“选择日期”和“时间长度”,时间范围为“选择日期”至选择的日期往过去推“时间长度”,在这个时间段找出指标最大值和最小值,进行百分位计算。</p>
+    <p>(2)若在(1)的时间范围下找不到值,则继续往过去找,直到找到值。</p>
+    <p>3、图表说明:</p>
+    <p> (1)某个品种会有多个坐标点(坐标点的数量取决于设置的日期数量);</p>
+    <p> (2)坐标点的X、Y值取实际日期与值。</p>`,
+
+    `<p style="font-weight:bold;">二、相关配置</p>
+    <p>1、基本配置</p>
+    <p>(1)管理员进行品种管理、标签管理;</p>
+    <p>(2)使用者对标签的品种关联指标。</p>
+    <p>2、计算配置</p>
+    <p>(1)时间长度:默认显示6个月;</p>
+    <p>(2)选择日期:最多支持选择5个日期;</p>
+    <p>(3)X轴坐标:选择标签;</p>
+    <p>(4)Y轴坐标:选择标签;</p>
+    <p>(5)图表名称:X轴坐标和Y轴坐标的拼接。</p>`
+
 ]

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

@@ -5,7 +5,7 @@
       v-model="targetType"
       placeholder="请选择指标种类"
       @change="targetTypeChange"
-      v-if="selectStyleType===1"
+      v-if="selectStyleType===1&&filter"
     >
       <el-option
         v-for="item in etaTypeOpt"
@@ -15,7 +15,7 @@
       />
     </el-select>
 
-    <div v-else-if="selectStyleType===2" class="database-choose">
+    <div v-else-if="selectStyleType===2&&filter">
       <label>选择指标:</label>
       <el-radio-group v-model="targetType" @change="targetTypeChange">
         <el-radio  
@@ -26,7 +26,7 @@
       </el-radio-group>
     </div>
 
-    <div v-else-if="selectStyleType===3" style="display:flex;align-items:center">
+    <div v-else-if="selectStyleType===3&&filter" style="display:flex;align-items:center">
       <el-select
         v-model="targetType"
         placeholder="请选择指标种类"
@@ -73,7 +73,7 @@
       remote
       clearable
       placeholder="请选择指标名称"
-      style="width: 100%; margin-top: 20px"
+      :style="`width: 100%; ${filter?'margin-top: 20px':''}`"
       :remote-method="searchHandle"
       @click.native="inputFocusHandle"
       @change="handleSelectTarget"
@@ -96,6 +96,7 @@
 <script>
 import { dataBaseInterface } from '@/api/api.js';
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
+import * as sheetInterface from "@/api/modules/sheetApi.js";
 export default {
     props:{
       defaultId:{
@@ -109,6 +110,9 @@ export default {
       },
       selectStyleType: {
         default: 1
+      },
+      filter: { //是否要预测和eta的筛选
+        default: true
       }
     },
     watch:{
@@ -152,7 +156,30 @@ export default {
                 KeyWord: query,
                 CurrentIndex: page,
             }
-            const res = this.targetType=='1'?await dataBaseInterface.targetSearchByPage(params):await preDictEdbInterface.edbSearch(params)
+
+            let res;
+            if(this.filter) {
+               res = this.targetType=='1'?await dataBaseInterface.targetSearchByPage(params):await preDictEdbInterface.edbSearch(params)
+            }else {
+              const filterMap = {
+                1: 2,
+                8: 3,
+                14: 6
+              }
+
+              let FilterSource = (this.$route.path==='/addMixedSheet' && this.$parent.isCalculateDia)
+                ? filterMap[this.$parent.formData.source]||1 
+                : 1;
+              let Frequency = (this.$route.path==='/addMixedSheet' && this.$parent.isCalculateDia && this.$parent.formData.source===2)
+                ? '季度' 
+                : ''
+              res = await sheetInterface.searchTarget({
+                ...params,
+                FilterSource,
+                Frequency
+              })
+            }
+            
 
             if (res.Ret !== 200) return
             const { List, Paging } = res.Data;

+ 670 - 0
src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue

@@ -0,0 +1,670 @@
+<template>
+  <div class="crossVariety-edit-page" id="box">
+    <span
+      class="slide-icon slide-right"
+      @click="isSlideLeft = !isSlideLeft"
+      v-show="isSlideLeft"
+    >
+      <i class="el-icon-d-arrow-right"></i>
+    </span>
+    <div class="left-cont" v-show="!isSlideLeft" id="left">
+      <div class="left-top">
+        <div>
+          <el-button type="primary" @click="saveChartHandle">保存</el-button>
+          <el-button type="primary" plain @click="$router.back()">取消</el-button>
+
+        </div>
+        <div style="color:#409EFF;font-size: 16px;cursor: pointer;" @click="showExplain = true">
+            <i class="el-icon-document" style="font-size:22px;"></i>
+            操作说明
+        </div>
+      </div>
+
+      <div class="left-min">
+        <section class="section-item">
+          <div class="top">
+            <label>选择品种</label>
+            <el-button
+              v-permission="permissionBtn.statisticPermission.crossVariety_variety_edit"
+              type="text" 
+              @click="setDialogOpen('variety')"
+            >品种管理</el-button>
+          </div>
+          <div class="list" v-if="varietyOptions.length">
+            <el-tag 
+              size="small" 
+              :class="['tag',{'act':checkedVarietys.includes(item.ChartVarietyId)}]"
+              v-for="item in varietyOptions"
+              :key="item.ChartVarietyId"
+              @click="checkVarietyHandle(item)"
+            >{{item.ChartVarietyName}}</el-tag>
+          </div>
+
+          <tableNoData v-else text="暂无品种" size="mini"/>
+        </section>
+
+        <el-divider/>
+
+        <section class="section-item">
+          <div class="top">
+            <label>标签配置</label>
+            <el-button
+              v-permission="permissionBtn.statisticPermission.crossVariety_tag_edit"
+              type="text" 
+              @click="setDialogOpen('tag')"
+            >标签管理</el-button>
+          </div>
+          <div class="list" v-if="tagOptions.length">
+            <el-tag 
+              size="small" 
+              :class="item.VarietyTotal?'act tag':'tag'"
+              v-for="item in tagOptions"
+              :key="item.ChartTagId"
+              @click="setTagRelationOpen(item)"
+            >{{item.ChartTagName}}</el-tag>
+          </div>
+
+          <tableNoData text="暂无标签" size="mini" v-else/>
+        </section>
+
+      </div>
+      
+      <span
+        class="move-btn resize"
+        v-drag
+        id="resize"
+      ></span>
+      <span class="slide-icon slide-left" @click="isSlideLeft = !isSlideLeft">
+        <i class="el-icon-d-arrow-left"></i>
+      </span>
+    </div>
+    <div
+      class="right-cont"
+      id="right"
+      :style="isSlideLeft ? 'width:100%' : `width:80%`"
+    >
+      <div
+        class="chart-min-cont"
+      >
+        <div class="chart-wrapper" v-if="options.series&&options.series.length">
+          <div class="chart-show-cont"  v-if="!chartInfo.WarnMsg">
+            <div style="position:relative;">
+              <h2 class="chart-title">{{ chartInfo.ChartName }}</h2>
+              <Chart 
+                :options="options"
+                minHeight="400px" 
+                height="450px"
+                ref="chartRef"
+              />
+              <span class="chart-author">作者:{{ chartInfo.SysUserRealName || accountName}}</span>
+
+              <!-- 上下限 -->
+              <template>	
+                <div class="range-cont left">
+                  <el-input
+                    style="width: 60px; display: block"
+                    size="mini"
+                    type="number"
+                    :min="0"
+                    :max="100"
+                    placeholder="上限"
+                    v-model="chartLimit.max"
+                    @change="changeLimit"
+                  />
+                  <el-input
+                    class="min-data-input"
+                    size="mini"
+                    type="number"
+                    :min="0"
+                    :max="100"
+                    placeholder="下限"
+                    v-model="chartLimit.min"
+                    @change="changeLimit"
+                  />
+                </div>
+                <!-- x轴上下限 -->
+                <div class="range-cont bottom" > 
+                  <el-input
+                    class="left"
+                    size="mini"
+                    type="number"
+                    :min="0"
+                    :max="100"
+                    placeholder="下限"
+                    v-model="chartLimit.x_min"
+                    @change="changeLimit"
+                  />
+                  <el-input
+                    class="left"
+                    size="mini"
+                    type="number"
+                    :min="0"
+                    :max="100"
+                    placeholder="上限"
+                    v-model="chartLimit.x_max"
+                    @change="changeLimit"
+                  />
+                </div>
+              </template>
+              
+            </div>
+          </div>
+
+          <!-- 异常显示 -->
+          <p class="error-tip" style="min-height: 400px;" v-if="chartInfo.WarnMsg">{{chartInfo.WarnMsg}}</p>
+        </div>
+
+        <div class="nodata" v-else>
+          <tableNoData text="暂无信息"/>
+        </div>
+
+        <div class="bottom-wrapper">
+          <!-- 图表相关配置 -->
+          <chartFormSection
+            :tagList="tagOptions"
+            :chartInfo="chartInfo"
+            ref="chartFormRef"
+            @getData="getChartPreviewData"
+          />
+
+          <!-- 指标列表 -->
+          <edbTableSection :tableData="tableData"/>
+        </div>
+
+      </div> 
+
+    </div>
+
+    <!-- 管理弹窗 -->
+    <tagSetDialog
+      :isShow.sync="isShowSetDia"
+      :type="dialogType"
+      :dataList="dialogType==='variety'?varietyOptions:tagOptions"
+      @refresh="dialogType==='tag'?getTagList():getVarietyList();"
+    />
+
+    <!-- 标签指标配置 -->
+    <tagRelationDialog
+      :isShow.sync="isShowTagRelationDia"
+      :varietyList="varietyOptions"
+      :info="tagRelationInfo"
+      @refresh="getTagList"
+    />
+
+    <!-- 操作说明 -->
+    <ExplainDialog 
+        textArrName="crossVarietyAnalisisTextArr"
+        :show-explain="showExplain"
+        @close="showExplain = false"
+    />
+  </div>
+</template>
+
+<script>
+import { crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
+import { dataBaseInterface } from '@/api/api';
+import { chartSetMixin } from '@/views/dataEntry_manage/mixins/chartPublic';
+import Chart from '@/views/dataEntry_manage/components/chart';
+import ExplainDialog from '../components/explainDialog.vue';
+import chartFormSection from './components/chartFormSection.vue';
+import tagSetDialog from './components/tagSetDialog.vue';
+import tagRelationDialog from './components/tagRelationDialog.vue';
+import edbTableSection from './components/edbTableSection.vue'
+export default {
+  components: {
+    ExplainDialog,
+    Chart,
+    chartFormSection,
+    tagSetDialog,
+    tagRelationDialog,
+    edbTableSection
+  },
+  directives: {
+    drag(el, bindings) {
+      el.onmousedown = function (e) {
+        var init = e.clientX;
+        // console.log(init);
+        var box = $('#box')[0];
+        // console.log(box.clientWidth)
+        let total_wid = box.offsetWidth;
+        var left = $('#left')[0];
+        var right = $('#right')[0];
+        var initWidth = left.offsetWidth;
+        document.onmousemove = function (e) {
+          var end = e.clientX;
+          var newWidth = end - init + initWidth;
+          left.style.width = newWidth + 'px';
+          right.style.width = newWidth > 300 ? total_wid - newWidth + 'px' : total_wid - 320 + 'px';
+        };
+        document.onmouseup = function () {
+          document.onmousemove = document.onmouseup = null;
+          e.releaseCapture && e.releaseCapture();
+        };
+        e.setCapture && e.setCapture();
+        return false;
+      };
+    },
+  },
+  mixins: [ chartSetMixin ],
+  computed: {
+    accountName() {
+      return localStorage.getItem('userName')
+    }
+  },
+  data() {
+    return {
+      chart_code: this.$route.query.code || '',
+      isSlideLeft: false,
+      chartInfo: {
+        Source: 10,
+        ChartName: '',
+        SysUserRealName: ''
+      },
+
+      showExplain: false,
+
+      checkedVarietys: [], //选中的品种
+      varietyOptions: [],
+      tagOptions: [],
+
+      isShowSetDia: false,//管理弹窗
+      dialogType: '',
+
+      isShowTagRelationDia: false,//标签指标管理弹窗
+      tagRelationInfo: {
+        tagName:'',
+        id: 0
+      }
+    };
+  },
+  methods: {
+
+    /* 获取图表详情 */
+    async getChartDetail() {
+      if(!this.chart_code) return 
+
+      let res = await dataBaseInterface.getChartByCode({
+				UniqueCode: this.chart_code
+			})
+
+      if(res.Ret !== 200) return
+
+      const { ChartInfo,DataResp,EdbInfoList } = res.Data;
+      let configSet = JSON.parse(ChartInfo.ExtraConfig);
+      this.checkedVarietys = configSet.VarietyList;
+      this.$refs.chartFormRef.initData(configSet);
+
+      this.chartInfo = ChartInfo;
+      this.tableData = EdbInfoList;
+      this.crossVarietyChartData = DataResp;
+      this.chartLimit = {
+        min: DataResp.YMinValue,
+        max: DataResp.YMaxValue ,
+        x_min: DataResp.XMinValue,
+        x_max: DataResp.XMaxValue,
+      }
+
+      this.setCrossVarietyChart()
+    },
+
+    checkParmas(type='') {
+      if(!this.checkedVarietys.length || !this.$refs.chartFormRef.form.CalculateValue || !this.$refs.chartFormRef.form.TagX ||!this.$refs.chartFormRef.form.TagY){
+        
+        type && this.dealWarnings()
+        return false
+      }
+      return true
+    },
+
+    dealWarnings() {
+      const {CalculateValue,TagX,TagY } = this.$refs.chartFormRef.form;
+      let message = '';
+      
+      if(!this.checkedVarietys.length) message = '请选择品种'
+      else if(!CalculateValue) message = '请输入时间长度'
+      else if(!TagX) message = '请选择X轴坐标'
+      else if(!TagY) message = '请选择Y轴坐标'
+
+      this.$message.warning(message)
+    },
+
+    /* 获取标签列表 */
+    async getTagList() {
+      let res = await crossVarietyInterface.getTagList()
+
+      if(res.Ret !== 200) return
+      this.tagOptions = res.Data.List || []
+    },
+
+    async getVarietyList() {
+      let res = await crossVarietyInterface.getVarietyList()
+
+      if(res.Ret !== 200) return
+      this.varietyOptions = res.Data.List || []
+    },
+
+    /* 预览数据 */
+    async getChartPreviewData() {
+      if(!this.checkParmas()) return;
+
+      let params = {
+        VarietyList: this.checkedVarietys,
+        ...this.$refs.chartFormRef.form
+      }
+      let res = await crossVarietyInterface.chartPreview(params)
+
+      if(res.Ret !== 200) return
+
+      const { DataResp,EdbInfoList } = res.Data;
+      this.tableData = EdbInfoList;
+      
+      this.chartLimit = {
+        min: Number(DataResp.YMinValue),
+        max: Number(DataResp.YMaxValue),
+        x_min: Number(DataResp.XMinValue),
+        x_max: Number(DataResp.XMaxValue)
+      }
+      this.crossVarietyChartData = DataResp;
+      this.setCrossVarietyChart()
+    },
+    
+    /* 选择品种 */
+    checkVarietyHandle(item) {
+      this.checkedVarietys.includes(item.ChartVarietyId) 
+        ? this.checkedVarietys.splice(this.checkedVarietys.indexOf(item.ChartVarietyId),1) 
+        : this.checkedVarietys.push(item.ChartVarietyId)
+
+      this.getChartPreviewData();
+    },
+
+    /* 打开标签关联弹窗 */
+    setTagRelationOpen(item) {
+      this.tagRelationInfo = {
+        tagName: item.ChartTagName,
+        id: item.ChartTagId
+      }
+      this.isShowTagRelationDia = true;
+    },
+
+    /* 标签管理 */
+    setDialogOpen(type) {
+      this.dialogType = type;
+      this.isShowSetDia = true;
+    },
+
+    /* 保存图表 */
+    async saveChartHandle() {
+      if(!this.checkParmas('warning')) return;
+
+      let { min,max,x_min,x_max } = this.chartLimit;
+      let params = {
+        VarietyList: this.checkedVarietys,
+        ...this.$refs.chartFormRef.form,
+        XMinValue: String(x_min),
+				XMaxValue: String(x_max),
+				YMinValue: String(min),
+				YMaxValue: String(max),
+      }
+      let res = this.chart_code 
+        ? await crossVarietyInterface.chartEdit({...params,ChartInfoId: this.chartInfo.ChartInfoId})
+        : await crossVarietyInterface.chartAdd(params)
+
+      if(res.Ret !== 200) return
+      this.setChartImage(res.Data);
+    },
+
+     /* 设置图表封面图片 */
+    setChartImage(data) {
+      let svg = this.$refs.chartRef.chart.getSVG({
+        chart: {
+          width: 340,
+          height: 230,
+        }
+      });
+      let form = new FormData();
+      form.append('Img', svg);
+      this.setImageHandle(form,data);
+    },
+    async setImageHandle(form,{ UniqueCode,ChartInfoId }) {
+      let { Data } = await dataBaseInterface.uploadImgSvg(form);
+      await dataBaseInterface.setChartImage({
+        ChartInfoId: ChartInfoId,
+        ImageUrl: Data.ResourceUrl,
+      });
+
+			this.$message.success('保存成功');
+			this.$router.replace({
+				path: '/crossVarietyChartList',
+				query: {
+					code: UniqueCode,
+					id: ChartInfoId
+				}
+			})
+
+    },
+   
+    reloadRightWid() {
+      let total_wid = $('#box')[0].offsetWidth;
+      let left = $('#left')[0].offsetWidth;
+      let rigtWid = total_wid - left - 20 + 'px';
+      $('#right')[0].style.width = rigtWid;
+    },
+
+  },
+  mounted() {
+    this.getVarietyList();
+    this.getTagList();
+    this.getChartDetail();
+    window.addEventListener('resize', this.reloadRightWid);
+  },
+  destroyed() {
+    window.removeEventListener('resize', this.reloadRightWid);
+  },
+  beforeRouteEnter(to, from, next) {
+    if(to.query.code){
+      to.matched[1].name='编辑图表'
+    }else{
+      to.matched[1].name='添加图表'
+    }
+    next()
+  }
+};
+</script>
+<style lang="scss" scoped>
+.crossVariety-edit-page {
+  $font-small: 12px;
+  $font-normal: 14px;
+  display: flex;
+  * {
+    box-sizing: border-box;
+  }
+
+  .slide-icon {
+    padding: 20px 0;
+    /* display: block; */
+    box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.3);
+    border-radius: 5px;
+    cursor: pointer;
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+    z-index: 99;
+    &:hover {
+      background-color: rgba(0, 0, 0, 0.05);
+    }
+    &.slide-left {
+      right: 0;
+    }
+    &.slide-right {
+      left: 0;
+    }
+  }
+  .left-cont {
+    width: 380px;
+    min-width: 380px;
+    background: #fff;
+    margin-right: 20px;
+    border: 1px solid #ececec;
+    border-radius: 4px;
+    box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
+    height: calc(100vh - 113px);
+    overflow: hidden;
+    position: relative;
+    box-sizing: border-box;
+    .left-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;
+      justify-content: space-between;
+    }
+    .left-min {
+      padding: 0 20px;
+      max-height: calc(100vh - 190px);
+      overflow-y: auto;
+      
+      .section-item{
+        padding: 20px 0;
+        .top {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          margin-bottom: 15px;
+
+        }
+        .list {
+          display: flex;
+          flex-wrap: wrap;
+          gap: 10px;
+          .tag {
+            color: #333;
+            background: #fff;
+            border-color: transparent;
+            cursor: pointer;
+            &.act {
+              color: #0052D9;
+              background-color: #e6eefb;
+              border-color: #ccdcf7;
+            }
+          }
+        }
+      }
+
+      .left-bottom {
+        margin-top: 20px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+     
+    }
+    .move-btn {
+      height: 100%;
+      width: 4px;
+      position: absolute;
+      right: 0px;
+      top: 0;
+      &:hover {
+        cursor: col-resize;
+      }
+    }
+  }
+  .right-cont {
+    width: 80%;
+    overflow-x: auto;
+    .chart-min-cont {
+      background: #fff;
+      min-width: 880px;
+      height: calc(100vh - 118px);
+      overflow-y: auto;
+      display: flex;
+      flex-wrap: wrap;
+      .chart-wrapper {
+				padding: 30px 0;
+        width: 100%;
+				/* =================== */
+				.chart-show-cont {
+					min-height: 400px;
+					padding: 0 100px 50px;
+					position: relative;
+					.chart-title {
+						font-size: 16px;
+						font-weight: normal;
+						text-align: center;
+						margin-bottom: 10px;
+					}
+					.chart-author {
+						font-size: 14px;
+						color: #333;
+						position: absolute;
+						bottom: -50px;
+						right: -70px;
+					}
+          .range-cont {
+            position: absolute;
+            top: 15%;
+            .min-data-input {
+              width: 60px;
+              display: block;
+            }
+            &.left {
+              left: -70px;
+            }
+            &.bottom {
+              width: 100%;
+              display: flex;
+              justify-content: space-between;
+              top: auto;
+              right: 0;
+              bottom: -4%;
+              .left {
+                width: 60px;
+                display: block;
+                flex-shrink: 0;
+              }
+            }
+          }
+				}
+				.options-cont {
+					display: flex;
+					flex-wrap: wrap;
+					justify-content: space-between;
+				}
+			}
+
+      @media screen and (min-width: 1711px) {
+        .min-data-input {
+          margin-top: 290px;
+        }
+      }
+      @media screen and (max-width: 1710px) {
+        .min-data-input {
+          margin-top: 250px;
+        }
+      }
+
+    }
+    .nodata {
+      background-color: #fff;
+      text-align: center;
+      font-size: 16px;
+      color: #666;
+      width: 100%;
+      padding: 100px 0;
+    }
+    .bottom-wrapper {
+      width: 100%;
+      padding: 20px;
+      border-top: 1px solid #ebeff6;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.crossVariety-edit-page {
+  .el-input--mini .el-input__inner {
+		padding: 0 0 0 4px;
+	}
+}
+</style>

+ 208 - 0
src/views/chartRelevance_manage/crossVarietyAnalysis/components/chartFormSection.vue

@@ -0,0 +1,208 @@
+<template>
+  <div class="form-cont">
+    <el-form
+      ref="diaForm"
+      label-position="left"
+      label-width="80px"
+      :model="form"
+      :rules="formRules"
+    >
+      <el-form-item label="时间长度" prop="CalculateValue">
+        <el-input
+          v-model="form.CalculateValue"
+          style="width: 140px"
+          :step="1"
+          type="number"
+          @change="(val) => {form.CalculateValue = Number(val);changeParams()}"
+        />
+        <el-select
+          v-model="form.CalculateUnit"
+          placeholder="请选择"
+          style="width: 100px"
+          @change="changeParams"
+        >
+          <el-option
+            v-for="item in unitOpt"
+            :key="item.val"
+            :label="item.label"
+            :value="item.val"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="X轴坐标" prop="TagX">
+        <el-select
+          v-model="form.TagX"
+          style="width: 240px"
+          placeholder="请选择"
+          @change="changeSeries"
+        >
+          <el-option
+            v-for="item in tagList"
+            :key="item.ChartTagId"
+            :label="item.ChartTagName"
+            :value="item.ChartTagId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="Y轴坐标" prop="TagY">
+        <el-select
+          v-model="form.TagY"
+          placeholder="请选择"
+          style="width: 240px"
+          @change="changeSeries"
+        >
+          <el-option
+            v-for="item in tagList"
+            :key="item.ChartTagId"
+            :label="item.ChartTagName"
+            :value="item.ChartTagId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="图表名称" prop="ChartName">
+        <el-input
+          v-model="form.ChartName"
+          style="width: 240px"
+          placeholder="请输入图表名称"
+          @change="changeParams"
+        />
+      </el-form-item>
+    </el-form>
+
+    <div class="date-section">
+      <label class="el-form-item__label">选择日期</label>
+      <ul>
+        <li class="date-li" v-for="(item,index) in form.DateConfigList" :key="index">
+          <el-select
+            v-model="item.DateType"
+            style="width: 150px"
+            placeholder="请选择"
+            @change="changeParams"
+          >
+            <el-option
+              v-for="item in dateOptions"
+              :key="item.val"
+              :label="item.label"
+              :value="item.val"
+            />
+          </el-select>
+
+          <el-input
+            v-model="item.Num"
+            v-if="item.DateType===2"
+            style="width: 140px"
+            :step="1"
+            type="number"
+            @change="(val) => {item.Num = Number(val);changeParams()}"
+          />
+
+          <el-button type="text" v-if="index===0" @click="addDateHandle">
+            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 -2 16 16" fill="none">
+              <path d="M5.23966 8.48046H7.51966V10.7605C7.51966 10.8265 7.57366 10.8805 7.63966 10.8805H8.35966C8.42566 10.8805 8.47966 10.8265 8.47966 10.7605V8.48046H10.7597C10.8257 8.48046 10.8797 8.42646 10.8797 8.36046V7.64046C10.8797 7.57446 10.8257 7.52046 10.7597 7.52046H8.47966V5.24046C8.47966 5.17446 8.42566 5.12046 8.35966 5.12046H7.63966C7.57366 5.12046 7.51966 5.17446 7.51966 5.24046V7.52046H5.23966C5.17366 7.52046 5.11966 7.57446 5.11966 7.64046V8.36046C5.11966 8.42646 5.17366 8.48046 5.23966 8.48046Z" fill="#0052D9"/>
+              <path d="M13.52 2H2.48C2.2145 2 2 2.2145 2 2.48V13.52C2 13.7855 2.2145 14 2.48 14H13.52C13.7855 14 14 13.7855 14 13.52V2.48C14 2.2145 13.7855 2 13.52 2ZM12.92 12.92H3.08V3.08H12.92V12.92Z" fill="#0052D9"/>
+            </svg>添加日期
+          </el-button>
+
+          <i 
+            v-else 
+            class="el-icon-delete" 
+            style="cursor:pointer;color:#f00;"
+            @click="() => {form.DateConfigList.splice(index,1);changeParams()}"
+          />
+
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    tagList: {
+      type: Array,
+    },
+    chartInfo: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      form: {
+        ChartName:'',
+        Source: 10,
+        CalculateValue: 6,
+        CalculateUnit: '月',
+        TagX: '',
+        TagY: '',
+        DateConfigList: [
+          { DateType: 1,Num: 0 },
+        ],
+      },
+      unitOpt: [
+        { label: "年", val: "年" },
+        { label: "季", val: "季" },
+        { label: "月", val: "月" },
+        { label: "周", val: "周" },
+        { label: "天", val: "天" },
+      ],
+
+      dateOptions: [
+        { label: '最新日期',val: 1 },
+        { label: 'N天前',val: 2 },
+      ]
+    };
+  },
+  methods: {
+    addDateHandle() {
+      if(this.form.DateConfigList.length === 5) return this.$message.warning('日期数量已达上限')
+
+      this.form.DateConfigList.push({
+        DateType: 1,Num: 1
+      })
+      
+      this.changeParams()
+    },
+
+    initData(data) {
+      const { ChartName,CalculateValue,CalculateUnit,TagX,TagY,DateConfigList } = data;
+      this.form = {
+        ChartName,
+        CalculateValue,
+        CalculateUnit,
+        TagX,
+        TagY,
+        DateConfigList
+      }
+    },
+
+    changeSeries() {
+      let xName = this.tagList.find(_ => _.ChartTagId===Number(this.form.TagX))?this.tagList.find(_ => _.ChartTagId===Number(this.form.TagX)).ChartTagName:'';
+      let yName = this.tagList.find(_ => _.ChartTagId===Number(this.form.TagY))?this.tagList.find(_ => _.ChartTagId===Number(this.form.TagY)).ChartTagName:'';
+
+      this.form.ChartName = (xName&&yName) ? `${xName}百分位和${yName}百分位` : '';
+      this.changeParams()
+    },
+
+    changeParams() {
+      this.$emit('getData')
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.form-cont {
+  width: 100%;
+  display: flex;
+  gap: 50px;
+
+  .date-section {
+    display: flex;
+    .date-li {
+      display: flex;
+      align-items: center;
+      gap: 10px;
+      margin-bottom: 20px;
+    }
+  }
+}
+</style>

+ 140 - 0
src/views/chartRelevance_manage/crossVarietyAnalysis/components/edbTableSection.vue

@@ -0,0 +1,140 @@
+<template>
+  <el-table
+    :data="tableData"
+    ref="tableRef"
+    highlight-current-row
+    border
+    >
+      <el-table-column
+        v-for="item in tableColums"
+        :key="item.label"
+        :label="item.label"
+        :width="item.widthsty"
+        :min-width="item.minwidthsty"
+        align="center"
+      >
+        <template slot-scope="scope">
+          <span>{{ scope.row[item.key] }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" key="Copy" align="center" width="140">
+        <template slot-scope="scope">
+          <span class="editsty" @click="copyCode(scope.row)">
+          <i class="el-icon-document-copy" />&nbsp;复制数据</span
+        ><br />
+        <span class="editsty" @click="viewTarget(scope.row)">查看数据</span>
+      </template>
+    </el-table-column>
+    <div slot="empty">
+      <tableNoData text="暂无指标" size="mini"/>
+    </div>
+  </el-table>
+</template>
+<script>
+import { dataBaseInterface } from '@/api/api';
+import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
+export default {
+  props: {
+    tableData: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      tableColums: [
+        {
+          label: '指标名称',
+          key: 'EdbName',
+          enKey:'EdbNameEn',
+					inputTip:'点击输入英文指标名称',
+          minwidthsty: '150px',
+        },
+        {
+          label: '指标ID',
+          key: 'EdbCode',
+          widthsty: '120px',
+        },
+        {
+          label: '更新频度',
+          key: 'Frequency',
+          enKey:'FrequencyEn',
+          minwidthsty: '60px',
+        },
+        {
+          label: '单位',
+          key: 'Unit',
+          enKey:'UnitEn',
+					inputTip:'英文单位',
+          minwidthsty: '50px',
+        },
+        {
+          label: '起始时间',
+          key: 'StartDate',
+          minwidthsty: '100px',
+        },
+        {
+          label: '最新日期',
+          key: 'LatestDate',
+          minwidthsty: '90px',
+        },
+        {
+          label: '最新值',
+          key: 'LatestValue',
+          minwidthsty: '90px',
+        },
+        {
+          label: '最近更新',
+          key: 'ModifyTime',
+          minwidthsty: '100px',
+        },
+        {
+          label: '数据来源',
+          key: 'SourceName',
+        },
+      ],//表格列
+    }
+  },
+  methods:{
+    /* 用于复制指标 */
+    async copyCode({EdbInfoId, EdbInfoCategoryType}) {
+      let params = {
+        PageSize: 100000,
+        CurrentIndex: 1,
+        EdbInfoId: EdbInfoId,
+      }
+      const res = EdbInfoCategoryType === 1 
+        ? await preDictEdbInterface.edbDataInfo(params)
+        : await dataBaseInterface.targetList(params);
+      if (res.Ret !== 200) return
+
+      let arr = res.Data.Item.DataList || [];
+
+      let str = '日期\t 值\n';
+      arr.forEach((item) => (str += `${item.DataTime}\t${item.Value}\n`));
+      this.$copyText(str).then(
+        (res) => {
+          this.$message.success('已成功复制!');
+        },
+        (err) => {
+          this.$message.error('复制失败!');
+        }
+      );
+    },
+
+    /* 查看数据 跳转指标库展开具体指标 */
+    viewTarget({ UniqueCode,EdbInfoId,EdbInfoCategoryType,ClassifyId }) {
+      let path = EdbInfoCategoryType ? '/predictEdb' : '/database';
+      let {href} = this.$router.resolve({path, query: {
+        code: UniqueCode,
+        id: EdbInfoId,
+        classifyId:ClassifyId
+      }});
+			window.open(href,'_blank');
+    },
+  },
+}
+</script>
+<style scoped lang='scss'>
+
+</style>

+ 182 - 0
src/views/chartRelevance_manage/crossVarietyAnalysis/components/tagRelationDialog.vue

@@ -0,0 +1,182 @@
+<template>
+  <el-dialog
+    :visible.sync="isShow"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    :title="`${info.tagName}指标配置`"
+    @close="cancelHandle"
+    custom-class="tag-relation-dialog"
+    center
+    width="650px"
+    v-dialogDrag
+  >
+    <div class="dialog-min">
+      <ul class="list-ul">
+        <li class="list-li" v-for="(item,index) in list" :key="index">
+          <label class="variety-name">{{item.varietyName}}</label>
+
+          <selectTarget
+            :defaultId="item.edbInfoId"
+            :defaultOpt="searchOptions"
+            @select="e => selectTargetHandle(e,item)"  
+            :filter="false"
+            style="max-width: 200px;"
+          />
+          <el-date-picker
+            v-model="item.endDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            disabled
+            style="width:140px;"
+            placeholder="最新日期"
+          />
+
+          <el-input
+            v-model="item.endValue"
+            style="width: 100px;"
+            disabled
+            placeholder="最新值"
+          />
+
+        </li>
+      </ul>
+
+      <div class="dialog-bot">
+        <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+          >保存</el-button
+        >
+        <el-button type="primary" plain @click="cancelHandle">取消</el-button>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import { crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
+import selectTarget from '@/views/chartRelevance_manage/components/selectTarget.vue';
+export default {
+  components: { selectTarget },
+  props: {
+    isShow: {
+      type: Boolean
+    },
+    info: {
+      type:  Object
+    },
+    varietyList: {
+      type: Array
+    }
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+
+      this.getRelationList() 
+    }
+  },
+  data() {
+    return {
+      list: [],
+      searchOptions: []
+    }
+  },
+  methods:{
+    selectTargetHandle(e,item) {
+      if(!e){
+        item.edbName = '';
+        item.edbInfoId = '';
+        item.endDate = '';
+        item.endValue = '';
+        return
+      } 
+      const { EndDate,EndValue,EdbName,EdbInfoId } = e;
+      
+      item.edbName = EdbName;
+      item.edbInfoId = EdbInfoId;
+      item.endDate = EndDate;
+      item.endValue = EndValue;
+    },
+
+    /* 获取标签关联品种列表 */
+    async getRelationList() {
+      let res = await crossVarietyInterface.getTagRelation({ ChartTagId: this.info.id })
+      if(res.Ret!==200) return
+
+      let relationArr = res.Data.List || [];
+
+      this.list = this.varietyList.map(_ => {
+        let relationItem = relationArr.length ? relationArr.find(item => item.ChartVarietyId===_.ChartVarietyId) : undefined
+
+        return {
+          varietyName: _.ChartVarietyName,
+          varietyId: _.ChartVarietyId,
+          edbName: relationItem?relationItem.EdbName:'',
+          edbInfoId: relationItem?relationItem.EdbInfoId:0,
+          endDate: relationItem?relationItem.EndDate:'',
+          endValue: relationItem?relationItem.EndValue:''
+        }
+      })
+
+      this.searchOptions = this.list.map(_ => ({
+        EdbName: _.edbName,
+        EdbInfoId: _.edbInfoId
+      }))
+    },
+
+    /* 保存`` */
+    saveHandle: _.debounce(async function() {
+      let params = {
+        ChartTagId: this.info.id,
+        VarietyEdb: this.list.map(_ => ({
+          ChartVarietyId: _.varietyId,
+          EdbInfoId: _.edbInfoId
+        })).filter(_ => _.EdbInfoId)
+      }
+      let res = await crossVarietyInterface.setTagRelationVariety(params)
+
+      if(res.Ret!==200) return
+      this.$message.success('配置保存成功')
+      this.$emit('refresh')
+      this.cancelHandle()
+    },300),
+
+    cancelHandle() {
+      this.list = [];
+      this.searchOptions=[];
+      this.$emit('update:isShow',false)
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.dialog-min {
+  padding: 30px 0 50px;
+  .list-ul{
+    padding: 0 15px;
+    max-height: calc(100vh - 500px);
+    min-height: 300px;
+    overflow-y: auto;
+    .list-li {
+      display: flex;
+      align-items: center;
+      gap: 20px;
+      margin-bottom: 20px;
+      .variety-name {
+        /* margin-right: 20px; */
+        width: 100px;
+      }
+    }
+  }
+  .dialog-bot {
+    display: flex;
+    margin-top: 30px;
+    justify-content: center;
+  }
+}
+</style>
+<style lang="scss">
+  /* .tag-relation-dialog .el-dialog__body {
+    max-height: calc(100vh - 350px);
+    min-height: 300px;
+    overflow-y: auto;
+  } */
+</style>

+ 203 - 0
src/views/chartRelevance_manage/crossVarietyAnalysis/components/tagSetDialog.vue

@@ -0,0 +1,203 @@
+<template>
+  <el-dialog
+    :visible.sync="isShow"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    :title="type==='tag'?'标签管理':'品种管理'"
+    @close="cancelHandle"
+    custom-class="dialog"
+    center
+    width="560px"
+    v-dialogDrag
+  >
+    <div class="dialog-min">
+      <el-input
+        v-model="searchTxt"
+        placeholder="请输入名称"
+        prefix-icon="el-icon-search"
+        size="medium"
+        clearable 
+        @change="filterList"
+      />
+      <div class="tag-list">
+        <div
+          v-for="(item,index) in showList"
+          :key="item.id"
+          class="el-tag"
+          :style="item.isEdit&&'padding:0;border:none;'"
+          @dblclick="editTagOpen(item,index)"
+        >
+
+          <el-input
+            v-model="item.label"
+            v-if="item.isEdit"
+            class="input-edit"
+            :ref="`inputRef${index}`"
+            size="small"
+            @change="editItemHandle(item)"
+          />
+          <span v-else>
+            {{ item.label }}
+            <el-popconfirm
+              :title="`是否确认删除该${type==='tag'?'标签':'品种'}`"
+              @onConfirm="closeItemHandle(item)"
+            >
+              <i
+                slot="reference"
+                class="el-tag__close el-icon-close" 
+              />
+                <!-- @click.stop="closeItemHandle(item)" -->
+            </el-popconfirm>
+          </span>
+        </div>
+
+        <el-input
+          class="input-edit"
+          v-if="inputVisible"
+          v-model="inputValue"
+          ref="saveTagInput"
+          size="small"
+          @change="addNewTagHandle"
+        >
+        </el-input>
+        <el-button v-else size="small" @click="addNewItem">+ 标签</el-button>
+
+      </div>
+    </div>
+
+  </el-dialog>
+</template>
+<script>
+import { crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
+export default {
+  props: {
+    isShow: {
+      type: Boolean
+    },
+    type: { //tag  variety
+      type: String
+    },
+    dataList: {
+      type: Array,
+      default: () => []
+    }
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+      this.initData()
+    },
+
+    dataList(nval) {
+      this.initData();
+    }
+  },
+  computed: {
+    showList() {
+      return this.list.length ? this.list.filter(_ => _.label.includes(this.searchTxt)) : []
+    }
+  },
+  data() {
+    return {
+      searchTxt: '',
+      inputVisible: false,
+      inputValue: '',
+      list: []
+    }
+  },
+  mounted(){
+
+  },
+  methods:{
+    /* 关闭标签 */
+    closeItemHandle(item) {
+      this.delItem(item)
+    },
+
+    async delItem(item) {
+      let res = this.type==='tag' 
+        ? await crossVarietyInterface.tagDel({ChartTagId:item.id})
+        : await crossVarietyInterface.varietyDel({ChartVarietyId:item.id})
+
+      if(res.Ret !== 200) return
+      this.$message.success('删除成功')
+      // let index = this.list.findIndex(_ => _.id === item.id);
+      // this.list.splice(index,1)
+      
+      this.refreshData()
+    },
+
+    addNewItem() {
+      this.inputValue = '';
+      this.inputVisible = true;
+      this.$nextTick(_ => {
+        this.$refs.saveTagInput.$refs.input.focus();
+      });
+    },
+
+    /* 新增标签 */
+    async addNewTagHandle() {
+      this.inputVisible = false;
+      if(!this.inputValue) return
+
+      let res = this.type==='tag' 
+        ? await crossVarietyInterface.tagAdd({ TagName: this.inputValue})
+        : await crossVarietyInterface.varietyAdd({ VarietyName: this.inputValue})
+        
+      if(res.Ret!==200) return
+      this.refreshData()
+      
+    },
+
+    editTagOpen(item,index) {
+      this.$set(item,'isEdit',true)
+      this.$nextTick(_ => {
+        this.$refs[`inputRef${index}`][0].$refs.input.focus();
+      });
+    },
+
+    /* 编辑标签 */
+    async editItemHandle(item) {
+      let res = this.type==='tag' 
+        ? await crossVarietyInterface.tagEdit({ TagName: item.label,ChartTagId:item.id})
+        : await crossVarietyInterface.varietyEdit({ VarietyName: item.label,ChartVarietyId:item.id})
+      if(res.Ret !== 200) return
+
+      item.isEdit = false;
+      this.refreshData()
+    },
+
+    refreshData() {
+      this.searchTxt = ''
+      this.$emit('refresh')
+    },
+
+    initData() {
+      this.list = this.dataList.map(_ => ({
+        label: _.ChartTagName || _.ChartVarietyName,
+        id:  _.ChartTagId || _.ChartVarietyId,
+        ..._
+      }))
+    },
+
+    cancelHandle() {
+      this.searchTxt = ''
+      this.$emit('update:isShow',false)
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.dialog-min {
+  padding: 0 0 60px;
+  .tag-list { 
+    margin-top: 30px;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+  }
+  .input-edit {
+    width: 100px;
+  }
+}
+</style>

+ 570 - 0
src/views/chartRelevance_manage/crossVarietyAnalysis/list.vue

@@ -0,0 +1,570 @@
+<template>
+	<div class=" pub-chart-box" v-if="showData">
+		<span
+			class="slide-icon slide-right"
+			@click="isSlideLeft = !isSlideLeft"
+			v-show="isSlideLeft"
+		>
+			<i class="el-icon-d-arrow-right"></i>
+		</span>
+
+		<div class="data-sheet-main" id="box">
+      <div class="main-left left" id="left" v-show="!isSlideLeft">
+				<div class="datasheet_top">
+						<el-button v-permission="permissionBtn.statisticPermission.crossVariety_addChart"
+							 type="primary" @click="goAddChart">添加图表</el-button>
+				</div>
+
+				<div class="search-cont">
+					<el-checkbox v-model="isShowMe"  
+						v-permission="permissionBtn.statisticPermission.crossVariety_onlyMine"
+						@change="() => { getTreeData();getPublicList() }">只看我的</el-checkbox>
+					<el-select
+						v-model="search_txt"
+						v-loadMore="searchLoad"
+						:filterable="!search_txt"
+						remote
+						clearable
+						placeholder="请输入图表名称"
+						style="width: 100%; margin-top: 20px"
+						: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.ChartInfoId"
+							:label="item.ChartName"
+							:value="item.ChartInfoId"
+						>
+						</el-option>
+					</el-select>
+				</div>
+				<div class="tree-cont">
+					<el-tree
+						ref="treeRef"
+						class="target_tree"
+						:data="treeData"
+						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="暂无分类"
+						@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"
+								style="width: 90px"
+								placeholder="请输入值"
+								class="label-input"
+								v-model="new_label"
+								v-if="data.isEdit&&permissionBtn.isShowBtn('statisticPermission','crossVariety_classifyOpt_edit')"
+								@blur="changeValue(data)"
+							/>
+							<span
+								@dblclick.stop="handleDblClick(data)"
+								v-else
+								class="text_oneLine node_label"
+								:style="`width:${
+									(select_node === data.UniqueCode && node.Nodewidth) || ''
+								}`"
+							>
+								<span>{{ data.ChartClassifyName }}</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"
+								/>
+								<img
+									src="~@/assets/img/set_m/edit.png"
+									alt=""
+									style="width: 15px; height: 14px; margin-right: 8px"
+									@click.stop="editNode(node, data)"
+									v-if="!data.ChartInfoId&&permissionBtn.isShowBtn('statisticPermission','crossVariety_classifyOpt_edit')"
+								/>
+								<!-- <img
+									slot="reference"
+									src="~@/assets/img/set_m/del.png"
+									alt=""
+									style="width: 14px; height: 14px"
+									@click.stop="removeNode(node, data)"
+									v-if="!data.ChartInfoId&&permissionBtn.isShowBtn('statisticPermission','crossVariety_classifyOpt_delete')"
+								/> -->
+							</span>
+						</span>
+					</el-tree>
+
+				</div>
+				<span
+					class="move-btn resize"
+					v-drag
+					id="resize"
+					@mousemove="dynamicNode && resetNodeStyle(dynamicNode)"
+				></span>
+				<span class="slide-icon slide-left" @click="isSlideLeft = !isSlideLeft">
+					<i class="el-icon-d-arrow-left"></i>
+				</span>
+      </div>
+
+			<div class="main-right" id="right" :style="isSlideLeft ? 'width:100%' : 'width:80%'">
+
+				<!-- 图表详情 -->
+				<div class="chart-detail-wrapper" v-if="chartInfo.ChartInfoId">
+					<el-row class="bottom-min">
+              <el-col
+                :span="21"
+                style="padding: 20px 0;"
+              >
+                <div class="chartEn-mark" v-show="chartInfo.IsEnChart" style="top: 0;left: 0;">En</div>
+                <div class="chart-show-cont"  v-if="!chartInfo.WarnMsg">
+                  <div class="chartWrapper" id="chartWrapper">
+                    <h2 class="chart-title">{{ chartInfo.ChartName }}</h2>
+                    <Chart 
+											:options="options"
+											minHeight="440px" 
+											height="500px"
+											ref="chartRef"
+										/>
+                  </div>
+                  <span class="chart-author">作者:{{ chartInfo.SysUserRealName}}</span>
+                </div>
+
+                <!-- 异常显示 -->
+                <p class="error-tip" style="min-height: 400px;" v-if="chartInfo.WarnMsg">{{chartInfo.WarnMsg}}</p>
+              </el-col>
+              <el-col :span="3" style="position: absolute;height: 100%;right: 0;">
+								<!-- 操作 -->
+								<chartHandlesWrap
+									:chartInfo="chartInfo"
+									:linkUrl="linkUrl"
+									@copyChartConfirm="copyChartConfirm"
+									@addMychartHandle="addMychartHandle"
+									@refreshHandle="refreshHandle"
+									@saveChartOtherHandle="saveChartOtherHandle"
+									@editChartHandle="editChartHandle"
+									@openEnNameDia="openEnNameDia"
+									@delChartHandle="delChartHandle"
+								/>
+              </el-col>
+          </el-row>
+
+					<!-- 指标列表 -->
+					<edbTableSection :tableData="tableData"/>
+
+				</div>
+				<!-- 列表 -->
+				<chartListWrap
+          v-else 
+          :total="chart_total"
+          :list="chartList" 
+          @loadMoreHandle="loadMoreHandle"
+          @detailShowHandle="detailShowHandle"
+          @addMychartHandle="addMychartHandle"
+          ref="chartListWrap"
+        />
+			</div>
+		</div>
+
+
+		<!-- 分类弹窗 -->
+		<classify-dia
+			:isOpenDialog.sync="classifyDia"
+			:title="dialog_title"
+			:form="classifyForm"
+			@successCallback="getTreeData"
+		/>
+
+		 <!-- 加入我的图库弹窗 -->
+    <addMyClassifyDia
+      :isAddMyDialog="isAddMyChart"
+      :add_id="add_chart_id"
+      :add_ids="add_ids"
+      @cancel="isAddMyChart = false"
+      @addSuccess="addMySuccess"
+    />
+
+		 <!-- 图表另存 -->
+    <SaveChartOther 
+      :show.sync="isShowSaveOther" 
+      fromType="chartsetting"
+			source="cross_variety"
+      :data="chartInfo"
+      @ensure="getTreeData"
+    />
+
+		<!-- 输入英文指标弹窗 -->
+		<set-en-name-dia 
+			:isOpenDialog="setEnName" 
+		  :formData="formItemArray"
+			@cancel="setEnName=false"
+   	  @updateEnName="updateEnName"
+		/>
+
+	</div>
+</template>
+
+<script>
+import { crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
+import leftMixin from '../mixins/classifyMixin';
+import Chart from '@/views/dataEntry_manage/components/chart';
+import classifyDia from '@/views/datasheet_manage/components/sheetClassifyDia.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 edbTableSection from './components/edbTableSection.vue';
+export default {
+	components: {
+		classifyDia,
+		Chart,
+		addMyClassifyDia,
+		SaveChartOther,
+		setEnNameDia,
+		edbTableSection
+	},
+	mixins:[ leftMixin,chartSetMixin ],
+	computed: {
+		/* 分享地址 */
+    linkUrl() {
+      const LINK_CHART_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow';
+      return `${LINK_CHART_URL}?code=${this.chartInfo.UniqueCode}&fromType=share?&lang=${this.currentLang}`
+    }
+	},
+	data () {
+		return {
+			showData: false,
+			refreshLoading: false,
+			isShowMe: false,
+			search_txt: '',
+			searchOptions:[],
+			isSlideLeft: false,//左侧分类收起
+
+			select_node: '',//节点唯一标识code
+			select_classify: '',
+			new_label:'',//双击修改的value
+			treeData: [], //分类数据
+      defaultShowNodes: [], //展开节点
+      defaultProp: {
+        label: 'ChartClassifyName',
+        children: 'Children',
+      }, //树结构配置项
+			dynamicNode: null,
+
+			/* 分类弹窗 */
+			dialog_title:'',
+			classifyDia: false, //
+			classifyForm: {},
+
+			select_id: '',//选中的图表id
+			chartInfo: {},
+			chart_title:'',//图表标题 双击标题修改时来存储最新值
+
+			isAddMyChart: false, //加入图库弹窗
+      add_chart_id: 0, //要加入的图表
+			add_ids:[],//加入时已有的分类
+
+			/* 图表列表 */
+			publicHaveMove: true,//是否还有列表数据
+			chartList: [],
+			chart_total: 0,
+			chart_page: 1,
+			chart_pages_size: 16,
+
+			search_page: 1,
+			search_have_more: false,
+			current_search:'',
+		};
+	},
+	methods: {
+
+		/* 添加图表 */
+		goAddChart() {
+			this.$router.push({ path: '/crossVarietyChartEditor' });
+		},
+
+		/* 获取分类 */
+		getTreeData(params=null) {
+			crossVarietyInterface.classifyList({IsShowMe:this.isShowMe}).then(res => {
+				const { Ret,Data } = res;
+				if(Ret !== 200) return
+
+				this.showData = true;
+				this.treeData = Data.AllNodes || [];
+				this.$nextTick(() => {
+					/* 新增完成后 处理树展开和选中 */
+					params && this.selectCurrentNode(params);
+				});
+
+			})
+		},
+
+		/* 搜索 */
+		searchHandle(query) {
+			this.search_page = 1;
+			this.current_search = query;
+			this.searchApi(this.current_search)
+		},
+
+		searchApi(query,page=1) {
+      /* 查找列表 */
+      crossVarietyInterface
+        .searchChart({
+          Keyword: query,
+          IsShowMe:this.isShowMe,
+          CurrentIndex: page
+        })
+        .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,...List];
+        });
+		},
+
+		/* 聚焦获取当前检索 */
+		inputFocusHandle(e) {
+			this.search_page = 1;
+			this.current_search = e.target.value;
+      if(this.current_search) {
+        this.searchApi(this.current_search)
+      }else {
+        this.searchOptions = [];
+      }
+		},
+
+		searchLoad() {
+			if(!this.search_have_more) return;
+			this.searchApi(this.current_search,++this.search_page);
+		},
+
+		/* 选中分类变化时 */
+		nodeChange({ UniqueCode,ChartInfoId,ChartClassifyId },node) {
+			this.search_txt = '';
+			this.select_node = UniqueCode;
+			this.select_classify = !ChartInfoId ? ChartClassifyId : 0;
+			this.select_id = ChartInfoId || 0;
+			this.resetNodeStyle(node);
+			this.dynamicNode = node;
+		},
+
+
+    /* 编辑节点 */
+    editNode(node, { ChartClassifyName,ChartClassifyId }) {
+
+      this.dialog_title = '编辑图表分类';
+      /* 编辑目录 */
+      this.classifyForm = {
+        classify_name: ChartClassifyName,
+        classify_id: ChartClassifyId,
+      };
+      this.classifyDia = true;
+    },
+
+		 /* 删除方法 */
+    delApi(ChartInfoId) {
+      crossVarietyInterface.chartDel({
+				ChartInfoId
+			})
+      .then((res) => {
+				if (res.Ret !== 200) return
+				this.$message.success(res.Msg);
+
+				if (!res.Data.ChartInfoId) this.select_id = '';
+
+				//删除自动显示下一张
+				res.Data.ChartInfoId
+					? this.getTreeData({
+							code: res.Data.UniqueCode,
+							id: res.Data.ChartInfoId
+						})
+					: this.getTreeData();
+			});
+    },
+
+		/* 分类成功回调 */
+		classifyCallback(type) {
+			this.getTreeData();
+
+			if (type === 'add') {
+        //新增分类完成之后,展开父节点显示刚新增的分类,若已展开节点则不做处理
+        let code = this.add_parent_id;
+        let flag = this.defaultShowNodes.some(item => item === code);
+        // console.log(flag)
+        !flag && this.defaultShowNodes.push(code);
+        this.add_parent_id = '';
+
+      }
+		},
+
+		/* 获取图表列表 */
+		getPublicList() {
+			crossVarietyInterface.getChartList({
+				CurrentIndex: this.chart_page,
+				PageSize: this.chart_pages_size,
+        ChartClassifyId: this.select_classify || 0,
+				IsShowMe: this.isShowMe
+			}).then(res => {
+				if(res.Ret !== 200) return
+
+				this.publicHaveMove = res.Data
+            ? this.chart_page < res.Data.Paging.Pages
+            : false;
+          this.chartList = res.Data
+            ? this.chart_page === 1
+              ? res.Data.List
+              : [...this.chartList, ...res.Data.List]
+            : [];
+        this.chart_total = res.Data ? res.Data.Paging.Totals : 0;
+			})
+		},
+
+		getChartInfo() {
+			this.getDetailHandle();
+		},
+
+		/* 获取图表详情 */
+		getDetailHandle() {
+			crossVarietyInterface.chartDetail({
+				ChartInfoId: this.select_id
+			}).then(res => {
+				if(res.Ret !== 200) return
+
+				const { ChartInfo,DataResp,EdbInfoList } = res.Data;
+
+				this.chartInfo = ChartInfo;
+				this.tableData = EdbInfoList;
+				this.crossVarietyChartData = DataResp;
+				this.chartLimit = {
+					min: DataResp.YMinValue,
+					max: DataResp.YMaxValue ,
+					x_min: DataResp.XMinValue,
+					x_max: DataResp.XMaxValue,
+				}
+
+				this.setCrossVarietyChart()
+			})
+		},
+
+		/* 删除图表 */
+		delChartHandle() {
+			const { ChartClassifyId,ChartInfoId } = this.chartInfo;
+			this.$confirm('删除后该图表将不能再引用,确认删除吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      })
+        .then(() => {
+          this.delApi(ChartInfoId)
+        })
+        .catch(() => {});
+		},
+
+		/* 刷新图表 */
+		refreshHandle() {
+			this.refreshLoading = this.$loading({
+        lock: true,
+        target: '.main-right',
+        text: '刷新图表中...',
+        spinner: 'el-icon-loading',
+        background: 'rgba(255, 255, 255, 0.8)',
+      });
+      crossVarietyInterface.refreshChart({
+          ChartInfoId: this.chartInfo.ChartInfoId,
+      }).then((res) => {
+				this.refreshLoading.close();
+				if (res.Ret === 200) {
+					this.getDetailHandle();
+					this.$message.success(res.Msg);
+				}
+			});
+		},
+
+		/* 编辑图表 */
+		editChartHandle() {
+			this.$router.push({
+        path: '/crossVarietyChartEditor',
+        query: {
+          code: this.chartInfo.UniqueCode,
+					id: this.chartInfo.ChartInfoId
+        }
+      })
+		},
+
+		copyChartHandle:_.debounce(function(type){
+      let chartsName = this.currentLang=='ch'?this.chartInfo.ChartName:this.chartInfo.ChartNameEn
+      let { heightNum, widthNum , newTitle , dynamic_copyOptions} = this.dynamicWidthAndHeight(type,this.chartInfo.ChartType,chartsName,1)
+      const chartType = 'seasonLegend';
+      // 英文转SVG设置变动
+      if(this.currentLang == 'en'){
+        // 如果竖轴坐标单位为'英文单位',表示客户没填,转成svg时置为空
+        this.$refs.chartRef.chart.options.yAxis.forEach(it => {
+          if(it.title.text == '英文单位') it.title.text='' 
+        });
+      }
+      let svg = this.$refs.chartRef.chart.getSVG({
+        chart:{
+          width:widthNum,
+          height:heightNum,
+          backgroundColor:"rgba(255, 255, 255, 0)",
+        },
+        title: {
+          text: newTitle,
+          margin: 10,
+          style: {
+            fontSize: '18px'
+          }
+        },
+        legend:{
+          ...copyOtherOptions[chartType],
+          ...dynamic_copyOptions[chartType]
+          }
+      });
+      this.copyBlobItem(widthNum,heightNum,svg,type);
+    },500),
+    
+		handleDblClick(data){
+			if(!this.permissionBtn.isShowBtn('statisticPermission','crossVariety_classifyOpt_edit')) return 
+			this.editNodeLabel(data)
+		}
+	},
+	mounted() {
+
+		if(this.$route.query.code) {
+      this.getTreeData({code: this.$route.query.code,id: Number(this.$route.query.id)})
+    } else {
+      this.getTreeData();
+      this.getPublicList();
+    }
+
+		window.addEventListener('resize', this.reloadRightWid);
+	},
+	destroyed() {
+		window.removeEventListener('resize', this.reloadRightWid);
+	}
+}
+</script>
+<style lang='scss' scoped>
+@import '../css/index.scss';
+</style>
+
+<style lang="scss">
+@import '../css/pub.scss';
+</style>

+ 5 - 2
src/views/chartRelevance_manage/css/index.scss

@@ -28,7 +28,7 @@ $normal-font: 14px;
     display: flex;
 
     .main-left {
-      width: 400px;
+      width: 300px;
       min-width: 300px;
       background: #fff;
       margin-right: 20px;
@@ -46,6 +46,8 @@ $normal-font: 14px;
         border: 1px solid #ececec;
         box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
         margin-bottom: 20px;
+        display: flex;
+        justify-content: space-between;
       }
       .search-cont {
         padding: 0 20px;
@@ -78,6 +80,7 @@ $normal-font: 14px;
       }
       .target_tree {
         color: #333;
+        overflow: hidden;
         .custom-tree-node {
           display: flex !important;
           justify-content: space-between;
@@ -133,7 +136,7 @@ $normal-font: 14px;
           margin-bottom: 20px;
 
           .chart-show-cont {
-            padding: 0 160px 0 120px;
+            padding: 0 160px 0 100px;
             position: relative;
             min-height: 400px;
             .chart-title {

+ 8 - 6
src/views/chartRelevance_manage/fittingEquationChartEditor.vue → src/views/chartRelevance_manage/fittingEquation/fittingEquationChartEditor.vue

@@ -174,10 +174,10 @@
 import { fittingEquationInterface } from '@/api/modules/chartRelevanceApi';
 import { yearSelector } from '@/utils/defaultOptions';
 import Chart from '@/views/dataEntry_manage/components/chart';
-import selectTarget from './components/selectTarget.vue';
-import fittingEquationSaveDia from './components/fittingEquationSaveDia.vue';
-import chartCard from './components/chartCard.vue';
-import ExplainDialog from './components/explainDialog.vue';
+import selectTarget from '../components/selectTarget.vue';
+import fittingEquationSaveDia from '../components/fittingEquationSaveDia.vue';
+import chartCard from '../components/chartCard.vue';
+import ExplainDialog from '../components/explainDialog.vue';
 export default {
   components: { Chart,selectTarget,fittingEquationSaveDia,chartCard,ExplainDialog },
 	directives: {
@@ -416,7 +416,7 @@ export default {
 	}
   .left-cont {
     width: 400px;
-    min-width: 300px;
+    min-width: 310px;
     background: #fff;
     margin-right: 20px;
     border: 1px solid #ececec;
@@ -496,9 +496,11 @@ export default {
 			display: flex;
 			flex-wrap: wrap;
 			.card-wrapper {
-				width: 50%;
+				width: 48%;
         margin-bottom: 20px;
         min-height: 350px;
+        min-width: 410px;
+        margin-right: 15px;
 				.card-item {
 					padding: 20px;
 					.top {

+ 3 - 3
src/views/chartRelevance_manage/fittingEquationList.vue → src/views/chartRelevance_manage/fittingEquation/fittingEquationList.vue

@@ -243,7 +243,7 @@
 
 <script>
 import { fittingEquationInterface } from '@/api/modules/chartRelevanceApi';
-import leftMixin from './mixins/classifyMixin';
+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';
@@ -634,9 +634,9 @@ export default {
 }
 </script>
 <style lang='scss' scoped>
-@import './css/index.scss';
+@import '../css/index.scss';
 </style>
 
 <style lang="scss">
-@import './css/pub.scss';
+@import '../css/pub.scss';
 </style>

+ 35 - 21
src/views/chartRelevance_manage/mixins/classifyMixin.js

@@ -1,5 +1,5 @@
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi.js';
-import { fittingEquationInterface,statisticFeatureInterface } from '@/api/modules/chartRelevanceApi';
+import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
 import { dataBaseInterface } from '@/api/api.js';
 
 export default {
@@ -117,7 +117,6 @@ export default {
     resetNodeStyle: _.debounce(function(node) {
 			const tree = $('.target_tree')[0];
 			let width = tree.offsetWidth;
-			// let label_wid = width > 500 ? 'auto' : (width <= 300 && width < 360) ?  100 : 0.7*width;
 			let label_wid =
 				width > 500
 					? 'auto'
@@ -143,26 +142,34 @@ export default {
       if(!this.new_label) return this.$message.warning('名称不能为空');
       this.$set(data,'isEdit',false)
 
-      if(this.new_label !== data.ClassifyName) {
-        let res = this.$route.path === '/fittingEquationList'
-          ? await fittingEquationInterface.classifyEdit({
-              ChartClassifyId: data.ChartClassifyId,
-              ChartClassifyName: this.new_label
-            })
-          : this.$route.path === '/statisticFeatureList'
-          ? await statisticFeatureInterface.classifyEdit({
-              ChartClassifyId: data.ChartClassifyId,
-              ChartClassifyName: this.new_label
-            })
-          :await chartRelevanceApi.classifyEdit({
-              ChartClassifyId: data.ChartClassifyId,
-              ChartClassifyName: this.new_label
-            })
-
-        if(res.Ret !== 200) return
-  
-        this.getTreeData();
+      if(this.new_label === data.ClassifyName) return 
+      
+      let res;
+      if(this.$route.path === '/fittingEquationList') {
+        res = await fittingEquationInterface.classifyEdit({
+                ChartClassifyId: data.ChartClassifyId,
+                ChartClassifyName: this.new_label
+              })
+      }else if(this.$route.path === '/statisticFeatureList') {
+        res = await statisticFeatureInterface.classifyEdit({
+                ChartClassifyId: data.ChartClassifyId,
+                ChartClassifyName: this.new_label
+              })
+      }else if(this.$route.path === '/chartrelevance') {
+        res = await chartRelevanceApi.classifyEdit({
+                ChartClassifyId: data.ChartClassifyId,
+                ChartClassifyName: this.new_label
+              })
+      }else if(this.$route.path === '/crossVarietyChartList') {
+        res = await crossVarietyInterface.classifyEdit({
+          ChartClassifyId: data.ChartClassifyId,
+          ChartClassifyName: this.new_label
+        })
       }
+
+      if(res.Ret !== 200) return
+
+      this.getTreeData();
     },
 
     /* 拖拽完成 */
@@ -214,6 +221,8 @@ export default {
         res=await fittingEquationInterface.classifyMove(params)
       }else if(this.$route.path === '/statisticFeatureList') {
         res=await statisticFeatureInterface.classifyMove(params)
+      }else if(this.$route.path === '/crossVarietyChartList') {
+        res=await crossVarietyInterface.classifyMove(params)
       }
 
       if (res.Ret !== 200) return;
@@ -264,6 +273,8 @@ export default {
         res=await fittingEquationInterface.chartMove(params)
       }else if(this.$route.path === '/statisticFeatureList') {
         res=await statisticFeatureInterface.chartMove(params)
+      }else if(this.$route.path === '/crossVarietyChartList') {
+        res=await crossVarietyInterface.chartMove(params)
       }
       
       if (res.Ret !== 200) return;
@@ -335,6 +346,9 @@ export default {
           (dropNode.level === 2 && type !== "inner")
         ) {
           canDrop = true;
+          
+          //跨品种分析不允许跨分类拖
+          if(draggingNode.data.ChartClassifyId !== dropNode.data.ChartClassifyId)  canDrop = false;
         }
       }
 

+ 5 - 5
src/views/chartRelevance_manage/list.vue → src/views/chartRelevance_manage/relevance/list.vue

@@ -189,7 +189,7 @@
             </el-col>
             <el-col
               :span="3"
-              style="position: absolute; height: 100%; right: 0"
+              style="position: absolute; height: 100%; right: 0;min-width: 115px;"
             >
               <!-- 操作 -->
               <chartHandlesWrap
@@ -302,7 +302,7 @@
 
 <script>
 import chartRelevanceApi from "@/api/modules/chartRelevanceApi.js";
-import leftMixin from "./mixins/classifyMixin";
+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";
@@ -745,10 +745,10 @@ export default {
   },
 };
 </script>
-<style lang='scss' scoped>
-@import './css/index.scss';
+<style lang="scss" scoped>
+@import '../css/index.scss';
 </style>
 
 <style lang="scss">
-@import './css/pub.scss';
+@import '../css/pub.scss';
 </style>

+ 9 - 10
src/views/chartRelevance_manage/relevanceChartEditor.vue → src/views/chartRelevance_manage/relevance/relevanceChartEditor.vue

@@ -283,7 +283,6 @@
     <div
       class="right-cont"
       id="right"
-      :style="isSlideLeft ? 'width:100%' : `width:80%`"
     >
       <div
         class="chart-min-cont"
@@ -374,12 +373,12 @@ import { dataBaseInterface } from '@/api/api.js';
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
 import {yearSelector} from '@/utils/defaultOptions';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
-import selectTarget from './components/selectTarget.vue'
-import chartCard from './components/chartCard.vue';
+import selectTarget from '../components/selectTarget.vue'
+import chartCard from '../components/chartCard.vue';
 import SaveChartOther from '@/views/dataEntry_manage/components/SaveChartOther';
-import saveChartToBase from './components/saveChartTobaseDia.vue';
-import saveEdbToBase from './components/saveEdbToBaseDia.vue'
-import ExplainDialog from './components/explainDialog.vue';
+import saveChartToBase from '../components/saveChartTobaseDia.vue';
+import saveEdbToBase from '../components/saveEdbToBaseDia.vue'
+import ExplainDialog from '../components/explainDialog.vue';
 export default {
   components: { selectTarget, chartCard, SaveChartOther, saveChartToBase, saveEdbToBase, ExplainDialog },
   directives: {
@@ -867,7 +866,7 @@ export default {
     }
   }
   .right-cont {
-    width: 80%;
+    flex:1;
     /* =================== */
     .chart-min-cont {
       /* background: #fff; */
@@ -882,9 +881,9 @@ export default {
         background: #fff;
         margin-bottom: 20px;
         min-height: 350px;
-        &:nth-child(2n) {
-          margin-left: 15px;
-        } 
+        min-width:410px;
+        margin-right: 15px;
+        
         .card-item {
           padding: 20px;
           .top {

+ 7 - 8
src/views/chartRelevance_manage/statisticFeatureChartEditor.vue → src/views/chartRelevance_manage/statistic/statisticFeatureChartEditor.vue

@@ -289,12 +289,12 @@ import { dataBaseInterface } from '@/api/api.js';
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
 import {yearSelector} from '@/utils/defaultOptions';
 import {statisticFeatureInterface} from '@/api/modules/chartRelevanceApi';
-import selectTarget from './components/selectTarget.vue'
-import chartCard from './components/chartCard.vue';
+import selectTarget from '../components/selectTarget.vue'
+import chartCard from '../components/chartCard.vue';
 import SaveChartOther from '@/views/dataEntry_manage/components/SaveChartOther';
-import saveChartToBase from './components/saveChartTobaseDia.vue';
-import saveEdbToBase from './components/saveEdbToBaseDia.vue';
-import ExplainDialog from './components/explainDialog.vue';
+import saveChartToBase from '../components/saveChartTobaseDia.vue';
+import saveEdbToBase from '../components/saveEdbToBaseDia.vue';
+import ExplainDialog from '../components/explainDialog.vue';
 export default {
   components: { selectTarget,chartCard,SaveChartOther,saveChartToBase,saveEdbToBase,ExplainDialog },
   directives: {
@@ -739,9 +739,8 @@ export default {
         width: 48%;
         margin-bottom: 20px;
         min-height: 350px;
-        &:nth-child(2n) {
-          margin-left: 15px;
-        } 
+        min-width:410px;
+        margin-right: 15px;
         .card-item {
           padding: 20px;
           background: #fff;

+ 3 - 3
src/views/chartRelevance_manage/statisticFeatureList.vue → src/views/chartRelevance_manage/statistic/statisticFeatureList.vue

@@ -229,7 +229,7 @@
 <script>
 
 import { statisticFeatureInterface } from '@/api/modules/chartRelevanceApi';
-import leftMixin from './mixins/classifyMixin';
+import leftMixin from '../mixins/classifyMixin';
 import Chart from '@/views/dataEntry_manage/components/chart';
 import classifyDia from '@/views/datasheet_manage/components/sheetClassifyDia.vue';
 import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyDia';
@@ -602,9 +602,9 @@ export default {
 }
 </script>
 <style lang='scss' scoped>
-@import './css/index.scss';
+@import '../css/index.scss';
 </style>
 
 <style lang="scss">
-@import './css/pub.scss';
+@import '../css/pub.scss';
 </style>

+ 2 - 1
src/views/dataEntry_manage/addChart.vue

@@ -152,6 +152,7 @@
 					></el-date-picker>
 					<el-checkbox label="跨年" v-model="isSpanYear" :disabled="isSpanYearDisable"
 					style="margin-top: 12px;" @change="changeIsSpanYear"></el-checkbox>
+					<br />
 					<div class="legend-set-text" @click="openLegendEditDia">
 						<span>图例名称设置</span>
 						<img src="~@/assets/img/icons/edit-blue.png" />
@@ -835,7 +836,7 @@ export default {
 				.legend-set-text{
 					font-size: 15px;
 					color: #1B7BDE;
-					display: flex;
+					display: inline-flex;
 					align-items: center;
 					justify-content: flex-start;
 					margin-top: 20px;

+ 38 - 9
src/views/dataEntry_manage/chartSetting.vue

@@ -496,7 +496,7 @@
                 <!-- 异常显示 -->
                 <p class="error-tip" style="min-height: 400px;" v-if="chartInfo.WarnMsg">{{chartInfo.WarnMsg}}</p>
               </el-col>
-              <el-col :span="3" style="position: absolute;height: 100%;right: 0;">
+              <el-col :span="3" style="position: absolute;height: 100%;right: 0;min-width: 115px;">
                 <ul class="right-actions">
                     <li>操作</li>
                     <li
@@ -637,7 +637,32 @@
             ref="listChartPage"
             @scroll="loadMorePublicChart"
           >
-            <el-col
+            <div class="chart-list-item-wrap">
+                <div class="chart-list-item" v-for="chart in chartPublicList" :key="chart.ChartInfoId">
+                    <div class="chart-item-top" style="position:relative;">
+                        <div class="chartEn-mark" v-show="chart.IsEnChart">En</div>
+                        <span class="text_oneLine" :style="{'padding-left':chart.IsEnChart?'24px':''}">{{ currentLang === 'en' ? (chart.ChartNameEn||chart.ChartName) : chart.ChartName }}</span>
+                    </div>
+                    <div class="chart-item-img" @click="detailShowHandle(chart)"
+                    :style="chart.ChartImage?{background: `no-repeat top/cover url('${chart.ChartImage}')`}:{}"></div>
+                    <div class="chart-item-bottom">
+                        <span>创建时间: {{ chart.CreateTime.slice(0,10) }}</span>
+                        <span v-permission="permissionBtn.chartLibPermission.chartLib_addMy"
+                            class="join_txt"
+                            @click="addMychartHandle(chart)"
+                        >
+                            <img
+                            :src="$icons.chart_join_ico"
+                            alt=""
+                            style="width: 13px; height: 12px; vertical-align: middle"
+                            />
+                            加入我的图库
+                        </span>
+                    </div>
+                </div>
+            </div>
+            
+            <!-- <el-col
               :span="6"
               style="margin-bottom: 20px; padding-right: 20px"
               v-for="chart in chartPublicList"
@@ -669,7 +694,7 @@
                   </span>
                 </div>
               </el-card>
-            </el-col>
+            </el-col> -->
           </div>
           <div v-if="!public_total" class="nodata">
             <tableNoData text="暂无图表"/>
@@ -1954,8 +1979,6 @@ export default {
       this.year_select = item.value;
       this.select_date = '';
       this.dateTip = '请选择时间段';
-      //保存表格配置和上下限 曲线图需要保存表格配置 季节图就不用了
-      // this.saveNowOptions();
       // 图表已存在
       this.selected_chartid && this.getPreviewChartInfo();
     },
@@ -2011,8 +2034,6 @@ export default {
           this.dateTip = `${data.start_date}~至今`;
         }
       }
-
-      // this.saveNowOptions();
       this.getPreviewChartInfo();
     },
 
@@ -2127,7 +2148,6 @@ export default {
 
     /* 季节图切换年份  保持当前配置 */
     seasonYearChange() {
-      // this.saveNowOptions();
       this.getPreviewChartInfo();
     },
     /* 一键刷新 超长等待..*/
@@ -2484,6 +2504,7 @@ export default {
       margin-bottom: 20px;
       .right-actions {
         /* max-width: 160px; */
+        min-width: 115px;
         height: 100%;
         padding: 20px 10px;
         border-left: 1px solid #DCDFE6;
@@ -2567,6 +2588,14 @@ export default {
           }
         }
       }
+      .chart-list-item{
+          width:23%;
+          min-width:230px;
+          .chart-item-top,.chart-item-bottom{
+              display: flex;
+              justify-content: space-between;
+          }
+      }
     }
   }
   .nodata {
@@ -2733,7 +2762,7 @@ export default {
         }
       }
       .main-right {
-        width: 80%;
+        flex:1;
         .mx-datepicker {
           width: 220px !important;
         }

+ 26 - 4
src/views/dataEntry_manage/coal/index.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="lzTarget-container">
-    <div class="left-cont minHeight">
+    <span
+        class="slide-btn-icon"
+        :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" v-show="isLeftWrapShow">
       <div class="left-top">
         <!-- <el-button type="primary" plain size="medium" @click="exportClick" :loading="btnload">导出Excel</el-button> -->
         <el-button
@@ -135,6 +142,7 @@ export default {
   },
   data() {
     return {
+      isLeftWrapShow:true,
       dataloading: false,
       rightShow: false,
       exportBase: process.env.VUE_APP_API_ROOT + "/entry/export/coalList", //中国煤炭网数据导出接口
@@ -526,6 +534,15 @@ export default {
 <style lang="scss" scoped>
 .lzTarget-container {
   display: flex;
+  position:relative;
+  .slide-btn-icon{
+        &.slide-left{
+            left:235px;
+        }
+        &.slide-right{
+            left: 0;
+        }
+    }
   * {
     box-sizing: border-box;
   }
@@ -540,6 +557,7 @@ export default {
   }
   .left-cont {
     min-width: 250px;
+    width:250px;
     margin-right: 20px;
     padding: 30px 0;
     // overflow: hidden;
@@ -566,11 +584,12 @@ export default {
     }
   }
   .right-cont {
-    width: 80%;
+    flex:1;
+    overflow-x: auto;
     padding: 30px;
     .right-box {
       max-width: 100%;
-      max-height: calc(100vh - 230px);
+      max-height: calc(100vh - 240px);
       border-left: 1px solid #dcdfe6;
       border-right: 1px solid #dcdfe6;
       overflow: auto;
@@ -594,9 +613,12 @@ export default {
       margin-top: 20px;
       display: flex;
       flex-wrap: wrap;
+      gap:20px;
+      .el-button{
+            margin-left: 0 !important;
+        }
       .frequency-btn {
         width: 112px;
-        margin: 0 30px 10px 0;
       }
     }
   }

+ 8 - 2
src/views/dataEntry_manage/components/LegendEditDia.vue

@@ -48,8 +48,14 @@ data () {
   };
 },
 watch: {
-  isEditLegend(val) {
-    if(val) {
+  // isEditLegend(val) {
+  //   if(val) {
+  //     // 数据没加载出来时 打开弹窗 legendListCopy 会为空
+  //     this.legendListCopy = _.cloneDeep(this.legendList)
+  //   }
+  // },
+  legendList(val){
+    if(val){
       this.legendListCopy = _.cloneDeep(this.legendList)
     }
   }

+ 8 - 2
src/views/dataEntry_manage/components/SaveChartOther.vue

@@ -25,7 +25,7 @@
           clearable
         />
       </el-form-item>
-      <el-form-item label="图表分类" prop="classify">
+      <el-form-item label="图表分类" prop="classify" v-if="![10,'cross_variety'].includes(this.source)">
         <el-cascader
           v-model="form.classify"
           :options="classifyOptions"
@@ -53,7 +53,7 @@
 import { dataBaseInterface } from '@/api/api.js';
 import futuresInterface from '@/api/modules/futuresBaseApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi.js';
-import { fittingEquationInterface,statisticFeatureInterface } from '@/api/modules/chartRelevanceApi';
+import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
 export default {
   props: {
     show: Boolean,
@@ -114,6 +114,8 @@ export default {
         res=await fittingEquationInterface.classifyList()
       }else if([7,8,9,'statistic_feature'].includes(this.source)) { //标准差 百分位 频率图
         res=await statisticFeatureInterface.classifyList()
+      }else if([10,'cross_variety'].includes(this.source)) { //跨品种分析
+        res = await crossVarietyInterface.classifyList();
       }else{
         res=await dataBaseInterface.chartClassify();
       }
@@ -128,6 +130,8 @@ export default {
         this.filterNodes(res.Data.AllNodes,1)
       }else if([7,8,9,'statistic_feature'].includes(this.source)) { //标准差 百分位 频率图
         this.filterNodes(res.Data.AllNodes,1)
+      }else if([10,'cross_variety'].includes(this.source)) { //
+        this.filterNodes(res.Data.AllNodes,1)
       }else{
         this.filterNodes(res.Data.AllNodes,3)
       }
@@ -163,6 +167,8 @@ export default {
         res=await fittingEquationInterface.saveOtherChart(params)
       }else if([7,8,9,'statistic_feature'].includes(this.source)) { //标准差 百分位 频率图
         res=await statisticFeatureInterface.saveOtherChart(params)
+      }else if([10,'cross_variety'].includes(this.source)) { //跨品种分析
+        res = await crossVarietyInterface.saveOtherChart(params);
       }else{
         res=await dataBaseInterface.saveChartOther(params)
       }

+ 7 - 1
src/views/dataEntry_manage/components/insertData.vue

@@ -138,7 +138,13 @@ export default {
     },
     // 上传成功之后
     handleSuccess(result) {
-      let res = this.$parseData(result);
+      //兼容下结构
+      let res = this.$parseData({
+        headers: {
+          dk: sessionStorage.getItem('dk')||""
+        },
+        data: result
+      });
       if (res.Ret === 200) {
         // 0成功 1部分失败 -1全部失败
         let str = `

+ 46 - 12
src/views/dataEntry_manage/components/setEnNameDia.vue

@@ -1,6 +1,14 @@
 <template>
-  <el-dialog title="英文名称" :visible.sync="isOpenDialog" :close-on-click-modal="false" :modal-append-to-body='false'
-       @close="cancel" custom-class="dialog" width="800px" v-dialogDrag>
+  <el-dialog 
+    title="英文名称" 
+    :visible.sync="isOpenDialog" 
+    :close-on-click-modal="false" 
+    :modal-append-to-body='false'
+    @close="cancel" 
+    custom-class="set-en-dialog" 
+    width="800px" 
+    v-dialogDrag
+  >
       <el-form v-if="cType=='chart'" style="padding:0 40px" label-width="140px">
         <!-- 截面散点图 -->
         <div class="set-en-name-box" v-if="chartType===10">
@@ -74,21 +82,17 @@
             </el-collapse-item>
           </el-collapse>
         </div>
-				<el-form-item style="text-align: center;margin-top: 30px;">
-					<el-button type="primary" @click="saveEnName">保存</el-button>
-					<el-button @click="cancel">取消</el-button>
-				</el-form-item>
 			</el-form>
 			<el-form v-else label-width="110px" >
 				<el-form-item :label="item.label+':'" :prop="item.key" v-for="item in copyFormData" :key="item.key">
 					<span v-show="item.notEdit">{{item.value}}</span>
           <el-input v-show="!item.notEdit" v-model="item.value" :placeholder="item.placeholder" style="width: 100%;"></el-input>
 				</el-form-item>
-				<el-form-item style="text-align: center;margin-left:-110px">
-					<el-button @click="cancel">取消</el-button>
-					<el-button type="primary" @click="saveEnName">确定</el-button>
-				</el-form-item>
 			</el-form>
+      <div class="btn-bottom">
+        <el-button type="primary" @click="saveEnName" style="margin-right:20px">确定</el-button>
+        <el-button @click="cancel">取消</el-button>
+      </div>
 		</el-dialog>
 </template>
 <script>
@@ -185,8 +189,29 @@ export default {
       this.$emit('updateEnName',params)
     },
 
+    /* 跨品种分析参数设置 */
+    setCrossVarietyEn() {
+      console.log(this.copyFormData)
+      const { chartInfo,chartsList }  = this.copyFormData;
+      let params = {
+        ChartInfoId: chartInfo[1].id,
+        ChartNameEn: chartInfo[1].value.trim(),
+        TagList: [
+          { ChartTagId: chartInfo[3].id,TagNameEn: chartInfo[3].value },
+          { ChartTagId: chartInfo[5].id,TagNameEn: chartInfo[5].value }
+        ],
+        VarietyList: chartsList.map(_ => ({
+          ChartVarietyId: _[1].id,
+          VarietyNameEn: _[1].value
+        }))
+      }
+      this.$emit('updateEnName',params)
+    },
+
     saveEnName(){
       if(this.cType === 'chart'&&this.chartType === 10) return this.setSectionScatterEn();
+      else if(this.cType === 'chart'&&this.copyFormData.chartInfo[0].source === 10) return this.setCrossVarietyEn();
+
       if(JSON.stringify(this.copyFormData) === JSON.stringify(this.formData)){
         // 没有修改过
         this.$emit('cancel')
@@ -230,9 +255,13 @@ export default {
 }
 </script>
 <style lang="scss">
+.set-en-dialog {
+  .el-dialog__body {
+    max-height:600px;
+    overflow-y:auto;
+  }
+}
 .set-en-name-box{
-  max-height:600px;
-  overflow-y:auto;
   .el-collapse-item__header{
     background-color:#DCDFE6;
     padding-left:8px;
@@ -275,4 +304,9 @@ export default {
       .el-input {  min-width: 240px;}
     }
   }
+  .btn-bottom {
+    display: flex;
+    margin: 40px 0;
+    justify-content: center;
+  }
 </style>

+ 22 - 0
src/views/dataEntry_manage/css/baseTargetPage.scss

@@ -0,0 +1,22 @@
+//可调整宽度目录的统一样式
+.target-container{
+    position:relative;
+    .slide-btn-icon{
+        &.slide-left{
+            right:0;
+        }
+        &.slide-right{
+            left: 0;
+        }
+    }
+    .right-cont{
+        flex:1;
+        overflow-x: auto;
+    }
+    .frequency-list{
+        gap:20px;
+        .el-button{
+            margin-left: 0 !important;
+        }
+    }
+}

+ 11 - 1
src/views/dataEntry_manage/css/exchangedata.scss

@@ -4,6 +4,15 @@ div{
 .exchangedata-wrap{
     display: flex;
     height: 86vh;
+    position: relative;
+    .slide-btn-icon{
+        &.slide-left{
+            left:185px;
+        }
+        &.slide-right{
+            left: 0;
+        }
+      }
     .box{
         background: #FFFFFF;
         border: 1px solid #ECECEC;
@@ -73,6 +82,8 @@ div{
         }
         .num-warp{
             display: flex;
+            flex-wrap: wrap;
+            gap:20px;
             margin-top: 20px;
             .num-box{
                 line-height: 40px;
@@ -84,7 +95,6 @@ div{
                 min-width: 100px;
                 padding: 0 10px;
                 cursor: pointer;
-                margin-right: 20px;
                 color: #409EFF;
             }
             .num-active{

+ 26 - 6
src/views/dataEntry_manage/dataEntry.vue

@@ -1,7 +1,14 @@
 <template>
   <div>
     <div class="data-entry-wrap" @click="rightMouseMenu.show = false">
-      <div class="left-wrap wrap-box">
+        <span
+            class="slide-btn-icon"
+            :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
+      <div class="left-wrap wrap-box" v-show="isLeftWrapShow">
         <div
           style="display: flex; justify-content: space-between; flex-wrap: wrap"
           v-if="role != 'special_researcher'"
@@ -205,8 +212,7 @@
             v-for="item in frequencyList"
             :key="item"
             @click="handleFrequencyChange(item)"
-            >{{ item }}</span
-          >
+            >{{ item }}</span>
         </div>
       </div>
     </div>
@@ -247,6 +253,7 @@ export default {
   components: { insertData },
   data() {
     return {
+      isLeftWrapShow:true,
       timeArr: [],
       TradeCode: "",
       exportDataurl: process.env.VUE_APP_API_ROOT + "/entry/export/dataList", //导出数据
@@ -1146,13 +1153,23 @@ export default {
 <style lang="scss" scoped>
 .data-entry-wrap {
   display: flex;
+  position: relative;
+    .slide-btn-icon{
+        &.slide-left{
+            left:285px;
+        }
+        &.slide-right{
+            left: 0;
+        }
+    }
   .wrap-box {
     background: #ffffff;
     border: 1px solid #ececec;
     box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
     border-radius: 4px;
     padding: 15px;
-    height: calc(100vh - 160px);
+    height: calc(100vh - 120px);
+    box-sizing: border-box;
   }
   .left-wrap {
     min-width: 300px;
@@ -1180,7 +1197,8 @@ export default {
     }
   }
   .right-wrap {
-    width: 80%;
+    flex:1;
+    overflow-x: auto;
     .sticky {
       position: sticky;
       border-right: 1px solid #dcdfe6;
@@ -1225,6 +1243,9 @@ export default {
 
     .frequency-wrap {
       margin-top: 20px;
+      display: flex;
+      flex-wrap: wrap;
+      gap:20px;
       .item {
         cursor: pointer;
         width: 105px;
@@ -1236,7 +1257,6 @@ export default {
         display: inline-block;
         line-height: 40px;
         text-align: center;
-        margin-right: 30px;
       }
       .active {
         color: #fff;

+ 555 - 56
src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue

@@ -1,75 +1,195 @@
 <template>
 	<div class="addTargtDia-box" v-if="isAddTarget">
-		<el-dialog :visible.sync="isAddTarget" :close-on-click-modal="false" :modal-append-to-body='false'
+		<el-dialog :visible.sync="isAddTarget" :close-on-click-modal="false" :modal-append-to-body='false' 
 			@close="cancelHandle" custom-class="custom-dialog fit-screen-dialog" top="5vh" center width="85vw" v-dialogDrag>
 			<div slot="title" style="display:flex;alignItems:center;">
 				<img :src="$icons.add" style="color:#fff;width:16px;height:16px;marginRight:5px;">
 				<span style="fontSize:16px;">添加指标</span>
 			</div>
-			<div class="dialog-top">
-				<div>
-					<span>数据来源</span>
-					<el-select v-model="fromType" placeholder="请选择来源" style="width:240px;margin-left:10px" @change="changeTrade"
-						:disabled="haveResult">
-						<el-option v-for="item in fromArr" :key="item" :label="item" :value="item">
-						</el-option>
-					</el-select>
+			<div v-if="wsdAddStep==1" v-loading="isLoadingData" element-loading-text="加载中······">
+				<div class="dialog-top" >
+					<div>
+						<span>数据来源</span>
+						<el-select v-model="fromType" placeholder="请选择来源" style="width:240px;margin-left:10px" @change="changeTrade"
+							:disabled="haveResult">
+							<el-option v-for="item in fromArr" :key="item" :label="item" :value="item">
+							</el-option>
+						</el-select>
+						<el-select v-model="fromDatabase" placeholder="请选择数据库" style="width:240px;margin-left:10px"
+							:disabled="haveResult" v-if="hasDateSequence">
+							<el-option v-for="item in databaseType" :key="item.value" :label="item.label" :value="item.value">
+							</el-option>
+						</el-select>
+					</div>
+					<el-input v-show="isCompanyCode" placeholder="公司ID" v-model="search_company_txt" style="maxWidth:340px;"
+						@keyup.enter.native="searchHandle" :disabled="haveResult" clearable>
+						<i slot="prefix" class="el-input__icon el-icon-search"></i>
+					</el-input>
+
+					<el-input placeholder="指标ID" v-model="search_txt" style="maxWidth:300px" v-if="!(hasDateSequence && fromDatabase=='1')"
+						@keyup.enter.native="searchHandle" :disabled="haveResult" clearable>
+						<i slot="prefix" class="el-input__icon el-icon-search"></i>
+					</el-input>
+				</div>
+				<div v-if="hasDateSequence && fromDatabase=='1'">
+					<div class="wsd-index-box">
+						<el-input placeholder="请输入证券代码,每次只查询一个证券代码" v-model.trim="securityCodeText" class="wsd-index-input" 
+						@blur="codeInputBlur('security')" style="margin-bottom: 20px;"></el-input>
+						<div class="wsd-index-code">
+							<el-input placeholder="请输入指标代码,多个指标代码用英文逗号分隔" v-model.trim="indexCodeText" 
+							class="wsd-index-input" @blur="codeInputBlur('index')"></el-input>
+							<div class="index-code-hint">
+								{{ indexCodeHintText }}
+							</div>
+						</div>
+						<el-select v-model="THSIndexCodeType" placeholder="请选择常用指标类型" v-if="fromType=='同花顺'"
+						@change="THSIndexCodeTypeChange" style="margin-bottom: 15px;" class="wsd-index-input">
+							<el-option :label="item.label" :value="item.value" 
+							v-for="item in THSIndexCodeTypeArr" :key="item.value"></el-option>
+						</el-select>
+						<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>
+						<div class="wsd-code-row" style="margin-top: -10px;">
+							<div class="wsd-code-item" v-for="item in indexCode" :key="item">
+								<div class="wsd-code-item-text">{{ item }}</div>
+								<img src="~@/assets/img/icons/close_icon_black.png" @click="deleteCode(item)" />
+							</div>
+						</div>
+					</div>
+					<div class="dia-bot">
+						<el-button type="primary" @click="wsdNextHandle" :disabled="!isCodeComplete" 
+						style="width: 120px;" :loading="isLoadingData" >下一步
+						</el-button>
+					</div>
 				</div>
-				<el-input v-show="isCompanyCode" placeholder="公司ID" v-model="search_company_txt" style="maxWidth:340px;"
-					@keyup.enter.native="searchHandle" :disabled="haveResult" clearable>
-					<i slot="prefix" class="el-input__icon el-icon-search"></i>
-				</el-input>
+				<template v-else>
+					<div class="warn_txt" v-if="status === 1">
+						该数据已存在数据库,名称为:{{have_edbobj.edb_name}},目录为:{{ have_edbobj.warnTip }},如需重新添加,请删除原指标
+					</div>
+					<div class="warn_txt" v-else-if="status === 3">
+						该数据已存在数据库,名称为:{{have_edbobj.edb_name}},目录为:{{ have_edbobj.warnTip }}
+					</div>
 
-				<el-input placeholder="指标ID" v-model="search_txt" style="maxWidth:340px"
-					@keyup.enter.native="searchHandle" :disabled="haveResult" clearable>
-					<i slot="prefix" class="el-input__icon el-icon-search"></i>
-				</el-input>
-			</div>
-			<div class="warn_txt" v-if="status === 1">
-				该数据已存在数据库,名称为:{{have_edbobj.edb_name}},目录为:{{ have_edbobj.warnTip }},如需重新添加,请删除原指标
-			</div>
-			<div class="warn_txt" v-else-if="status === 3">
-				该数据已存在数据库,名称为:{{have_edbobj.edb_name}},目录为:{{ have_edbobj.warnTip }}
+					<div class="no-auth" v-if="status === 3">
+						您当前暂无权限查看该指标,如需查看,请联系管理员
+					</div>
+					<div class="dialog-main" v-else>
+						<el-table ref="Table" :data="tableData" highlight-current-row border
+							:style="(status === 1 || !tableData.length) ? 'height:350px' : ''">
+							<el-table-column v-for="item in tableColums" :key="item.label" :label="item.label" align="center">
+								<template slot-scope="scope">
+									<span v-if="item.key == 'StartDate' || item.key == 'EndDate'">{{ scope.row[item.key] |
+											formatTime
+									}}</span>
+									<span v-else>{{ scope.row[item.key] }}</span>
+								</template>
+							</el-table-column>
+							<div slot="empty" style="padding:40px 0 120px;">
+								<tableNoData text="未搜索到该指标" size="mini"/>
+							</div>
+						</el-table>
+						<ul class="value-ul" v-show="dataList.length && status === 2">
+							<li class="value-item" v-for="(item, index) in dataList" :key="index">
+								<span>{{ item.DataTime }}</span>
+								<span style="min-width:200px;text-align:center;">{{ item.Value }}</span>
+							</li>
+						</ul>
+					</div>
+					<div class="dia-bot">
+						<el-button type="primary" v-if="status === 2" @click="addTargtHandler" 
+						:disabled="!tableData.length">下一步
+						</el-button>
+						<el-button type="primary" v-else-if="[1,3].includes(status)" @click="cancelHandle">知道了</el-button>
+					</div>
+				</template>
 			</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="left: 0;text-align: center;">
+                  {{ edbTableHeadData.get(item) }}
+                </td>
+                <td v-for="(data, sub_index) in edbIndexDatas" :key="sub_index" :colspan="2" 
+								:class="highLightIndex.includes(data.EdbName) && item=='EdbName' ?'exist-highlight':''">
+									<template v-if="item === 'ClassifyId'">
+										<el-cascader :options="options" v-model="data[item]" placeholder="请选择所属目录"
+										size="mini" :disabled="!data.Source"
+										:props="{label: 'ClassifyName',
+											value: 'ClassifyId',
+											children: 'Children',
+											checkStrictly: true,
+											emitPath:false}">
+										</el-cascader>
+									</template>
+									<template v-else-if="item === 'Unit'">
+										<el-autocomplete
+										:disabled="!data.Source"
+											v-model.trim="data[item]"
+											:fetch-suggestions="querySearchUnit"
+											placeholder="请输入单位"
+											suffix-icon="el-icon-arrow-down"
+											size="mini"
+										></el-autocomplete>
+									</template>
+									<template v-else-if="item === 'Frequency'">
+										<el-select v-model="data[item]" placeholder="请选择频度" size="mini" :disabled="!data.Source">
+											<el-option :label="item" :value="item"
+											v-for="item in frequencyArr" :key="item"></el-option>
+										</el-select>
+									</template>
+									<template v-else-if="item === 'EdbName'">
+										<el-input v-model.trim="data[item]" placeholder="请输入指标名称" size="mini" :disabled="!data.Source"></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 v-for="(item,index) in edbIndexDatas[0].DataList.length" :key="index">
+								<td :rowspan="edbIndexDatas[0].DataList.length" v-if="index==0"
+								class="sticky" style="left: 0;text-align: center;">
+									数据详情
+								</td>
+								<template v-for="(item1,index1) in edbIndexDatas.length">
+									<td>{{ edbIndexDatas[index1].DataList[index].DataTime }}</td>
+									<td>{{ edbIndexDatas[index1].DataList[index].Value }}</td>
+								</template>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+				<div class="dia-bot">
+					<el-button @click="wsdPrevHandle" style="width: 120px;">上一步</el-button>
+					<el-button type="primary" @click="wsdSaveHandle" style="width: 120px;margin-left: 50px;">保存</el-button>
+				</div>
+			</template>
+		</el-dialog>
 
-			<div class="no-auth" v-if="status === 3">
-				您当前暂无权限查看该指标,如需查看,请联系管理员
-			</div>
-			<div class="dialog-main" v-else>
-				<el-table ref="Table" :data="tableData" highlight-current-row border
-					:style="(status === 1 || !tableData.length) ? 'height:350px' : ''">
-					<el-table-column v-for="item in tableColums" :key="item.label" :label="item.label" align="center">
-						<template slot-scope="scope">
-							<span v-if="item.key == 'StartDate' || item.key == 'EndDate'">{{ scope.row[item.key] |
-									formatTime
-							}}</span>
-							<span v-else>{{ scope.row[item.key] }}</span>
-						</template>
-					</el-table-column>
-					<div slot="empty" style="padding:40px 0 120px;">
-						<tableNoData text="未搜索到该指标" size="mini"/>
+		<el-dialog :visible.sync="checkFailShow" :close-on-click-modal="false" :modal-append-to-body='false' 
+			width="600px" title="操作提示">
+			<div class="check-fail-box">
+				<div>
+					<div style="margin-bottom: 20px;">指标库中已存在以下指标,请勿重新输入!</div>
+					<div v-for="(item,index) in existIndexList" class="exist-index-item" @click="existIndexClick(item)">
+						{{ index+1+'、'+item.text }}
 					</div>
-				</el-table>
-				<ul class="value-ul" v-show="dataList.length && status === 2">
-					<li class="value-item" v-for="(item, index) in dataList" :key="index">
-						<span>{{ item.DataTime }}</span>
-						<span style="min-width:200px;text-align:center;">{{ item.Value }}</span>
-					</li>
-				</ul>
-			</div>
-			
-			<div class="dia-bot">
-				<el-button type="primary" v-if="status === 2" @click="addTargtHandler" :disabled="!tableData.length">下一步
-				</el-button>
-				<el-button type="primary" v-else-if="[1,3].includes(status)" @click="cancelHandle">知道了</el-button>
+				</div>
+				<div class="check-fail-button">
+					<el-button type="primary" @click="checkFailShow=false" style="width: 120px;">知道了</el-button>
+				</div>
 			</div>
 		</el-dialog>
 	</div>
 </template>
 
 <script>
-import { dataBaseInterface } from '@/api/api.js'
-import { fromArr, fromCode ,frequencyArr} from './util';
+import { dataBaseInterface,dataInterence } from '@/api/api.js'
+import { fromArr, fromCode ,frequencyArr,windCommonIndexCodeArr,THSCommonIndexStockCodeArr,THSCommonIndexFuturesCodeArr} from './util';
 export default {
 	name: '',
 	props: {
@@ -77,11 +197,51 @@ export default {
 			type: Boolean
 		}
 	},
+	computed:{
+		isCodeComplete(){
+			return this.securityCodeText && (this.indexCode.length>0 || this.indexCodeSelected.length>0)
+		},
+		hasDateSequence(){
+			return ["wind","同花顺"].includes(this.fromType)
+		},
+		// 常用的指标代码
+		indexCodeArr(){
+			if(this.fromType=='wind'){
+				return windCommonIndexCodeArr
+			}else if(this.fromType=='同花顺'){
+				if(this.THSIndexCodeType==1){
+					//期货常用
+					return THSCommonIndexFuturesCodeArr
+				}else{
+					//股票常用
+					return THSCommonIndexStockCodeArr
+				}
+			}
+		},
+		indexCodeHintText(){
+			if(this.fromType=='wind'){
+				return 'Wind金融终端输入“CG”会弹出代码生成器,可在代码生成器上获取其他指标的代码'
+			}else if(this.fromType=='同花顺'){
+				return '可用Excel同花顺插件/日期序列功能,根据所选指标获取指标代码,期货和股票常用代码可在下方勾选'
+			}
+		}
+	},
 	data() {
+		this.prefixMap=new Map([
+			["wind","wsd"],
+			["同花顺","thsds"]
+		])
 		return {
 			search_txt: '',//搜素关键词 M001625518 M0001427
 			fromType: 'wind',
+			fromDatabase:'0',
 			fromArr,
+			indexCodeSelected:[],
+			databaseType:[
+				{value:'0',label:'经济数据库'},
+				{value:'1',label:'日期序列'}
+			],
+			wsdAddStep:1,
 			fromCode,
 			tableColums: [
 				{
@@ -107,19 +267,56 @@ export default {
 				edb_name: '',
 			},
 			isCompanyCode: false,
-			search_company_txt: ''
+			search_company_txt: '',
+			securityCodeText:"",
+			indexCodeText:'',
+			indexCode:[],
+			edbIndexDatas:[],
+			edbTableHeadKey: [
+        "ClassifyId",
+        "Unit",
+        "Frequency",
+        "EdbName",
+        "StockCode",
+        "EdbCode",
+      ],
+			edbTableHeadData:new Map([
+				["ClassifyId", "所属目录"],
+				["Unit", "单位"],
+				["Frequency", "频度"],
+				["EdbName", "指标名称"],
+				["StockCode", "证券代码"],
+				["EdbCode", "指标代码"],
+			]),
+			BatchList:[],
+			options:[],
+			unitList:[],
+			frequencyArr,
+			checkFailShow:false,
+			existIndexList:[],
+			isLoadingData:false,
+			highLightIndex:[],
+			// 同花顺常用指标类型
+			THSIndexCodeType:1,
+			THSIndexCodeTypeArr:[
+				{value:1,label:"期货常用指标"},
+				{value:2,label:"股票常用指标"}
+			]
 		};
 	},
 	watch:{
 		isAddTarget(newVal){
 			if(newVal){
 				this.getTargetSource()
+				this.getMenu()
+				this.getTargetUnitList()
 			}
 		}
 	},
 	methods: {
 		init() {
 			this.fromType = 'wind'
+			this.fromDatabase='0'
 			this.status = ''
 			this.tableData = []
 			this.dataList = []
@@ -127,6 +324,12 @@ export default {
 			this.search_txt = '';
 			this.haveResult = false;
 			this.search_company_txt = '';
+			this.wsdAddStep=1
+			this.securityCodeText=""
+			this.indexCodeText=''
+			this.indexCode=[]
+			this.indexCodeSelected=[]
+			this.THSIndexCodeType=1
 			this.isCompanyCode = false;
 		},
 		cancelHandle() {
@@ -230,10 +433,21 @@ export default {
 			} else {
 				this.isCompanyCode = false;
 			}
+			if(this.fromDatabase=='1'){
+				this.fromDatabase='0'
+				this.securityCodeText=""
+				this.indexCodeText=''
+				this.indexCode=[]
+				this.indexCodeSelected=[]
+				this.THSIndexCodeType=1
+			}
 			this.search_txt = '';
 			this.search_company_txt = '';
 			this.loading && this.loading.close();
 		},
+		THSIndexCodeTypeChange(){
+			this.indexCodeSelected=[]
+		},
 		getTargetSource(){
 			this.fromArr = []
 			this.fromCode = []
@@ -248,6 +462,167 @@ export default {
 					}))
 				}
 			})
+		},
+		codeInputBlur(type){
+			if(type == 'security'){
+				this.securityCodeText=this.securityCodeText.replaceAll(' ','')
+			}else if(type == 'index'){
+				if(!this.indexCodeText) return  
+				this.indexCodeText=this.indexCodeText.replaceAll(' ','')
+				this.indexCode=Array.from(new Set([...this.indexCode,...this.indexCodeText.split(',')]))
+
+				this.indexCodeText=''
+			}
+
+		},
+		deleteCode(code){
+			this.indexCode = this.indexCode.filter(it => it!=code)
+		},
+		/* 获取目录结构 */
+		getMenu() {
+			dataBaseInterface.menuListV3().then(res => {
+				if(res.Ret === 200) {
+					this.filterNodes(res.Data.AllNodes||[]);
+					this.options = res.Data.AllNodes || [];
+				}
+			})
+		},
+		// 递归改变目录结构
+		filterNodes(arr) {
+			arr.length && arr.forEach(item => {
+				item.Children.length && this.filterNodes(item.Children)
+				if(!item.Children.length) {
+					item.Children=null
+				}
+			})
+		},
+		// 获取指标单位
+		async getTargetUnitList(){
+			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);
+		},
+		wsdNextHandle(){
+			this.getMenu()
+			setTimeout(()=>{
+				if(this.isCodeComplete){
+					let params={
+						Source:Number(this.fromCode.get(this.fromType)),
+						SubSource:this.fromDatabase,
+						EdbCode:Array.from(new Set([...this.indexCode,...this.indexCodeSelected])).join(','),
+						StockCode:this.securityCodeText
+					}
+					dataBaseInterface.edbExistCheck(params).then(res=>{
+						if(res.Ret == 200){
+							// console.log(res,'res');
+							// return 
+							if(res.Data.IndexExist){
+								// 有重复
+								this.existIndexList=[]
+								let existEdbInfo=res.Data.ExistEdbInfo || []
+								let text=''
+								existEdbInfo.map(item =>{
+									text=`${item.EdbName}(${item.EdbCode})`
+									this.existIndexList.push({text,code:item.UniqueCode,id:item.EdbInfoId,classifyId:item.ClassifyId})
+								})
+								this.checkFailShow=true
+							}else{
+								// 没有重复
+								this.isLoadingData=true
+								dataBaseInterface.getTarget(params).then(res => {
+									if(res.Ret == 200){
+										let stockList = res.Data.SearchItem.StockList || []
+										this.edbIndexDatas=[]
+										this.BatchList=[]
+										let Source = Number(this.fromCode.get(this.fromType))
+										stockList.map((item,index) =>{
+											let isCommon = this.indexCodeArr.find(it => it.value == item.EdbCode)
+											let params={
+												Source,
+												ClassifyId:0,
+												Unit:'',
+												Frequency:'日度',
+												EdbName:isCommon?`${item.StockCode}${isCommon.label}`:`${item.StockCode}${item.EdbCode}`,
+												EdbCode:item.EdbCode,
+												StockCode:item.StockCode
+											}
+											this.BatchList.push(params)
+											let datas = item.DataList || []
+											let datasLength = datas.length
+											if( datasLength<10){
+												for (let i = datasLength; i < 10; i++) {
+													datas.push({DataTime:'',Value:''})													
+												}
+											}
+											this.edbIndexDatas.push({...params,DataList:datas})
+										})
+
+										let edbIndexDataLength = this.edbIndexDatas.length
+										//填充空的列
+										for (let i = edbIndexDataLength; i < 6; i++) {
+											this.edbIndexDatas.push({
+												Source:0,
+												ClassifyId:0,
+												Unit:'',
+												Frequency:'',
+												EdbName:'',
+												EdbCode:'',
+												StockCode:'',
+												DataList:new Array(10).fill({DataTime:'',Value:''})
+											})
+										}
+										this.wsdAddStep=2
+									}
+								}).finally(()=>{
+									this.isLoadingData=false
+								})
+							}
+						}
+					})
+				}
+			},50)
+		},
+		existIndexClick({code,id,classifyId}){
+			const { href } = this.$router.resolve({ path: '/database',query:{code,id,classifyId}});
+			window.open(href, '_blank');
+		},
+		wsdPrevHandle(){
+			this.wsdAddStep=1
+		},
+		wsdSaveHandle(){
+			 let flag = this.edbIndexDatas.some(it => {
+				return (it.StockCode && it.EdbCode) && ((!it.ClassifyId) || (!it.Unit) || (!it.Frequency) || (!it.EdbName))
+			})
+			if(flag){
+				this.$message.warning("指标信息未填写完整")
+				return 
+			}
+			this.BatchList.map((it,ind) => {
+				it.ClassifyId = this.edbIndexDatas[ind].ClassifyId
+				it.EdbCode = this.edbIndexDatas[ind].EdbCode
+				it.EdbName = this.edbIndexDatas[ind].EdbName
+				it.Frequency = this.edbIndexDatas[ind].Frequency
+				it.StockCode = this.edbIndexDatas[ind].StockCode
+				it.Unit = this.edbIndexDatas[ind].Unit
+			})
+			dataBaseInterface.edbAddBatch({BatchList:this.BatchList}).then(res=>{
+				if(res.Ret == 200){
+					this.$message.success("添加指标成功")
+					this.$emit('addSuccessHandle',{ code:res.Data.UniqueCode,id:res.Data.EdbInfoId,classifyId:res.Data.ClassifyId })	
+					this.cancelHandle()	
+				}else if(res.Ret == 403){
+					this.highLightIndex=res.Data?res.Data.ExistEdbName || []:[]
+				}
+			})
 		}
 	},
 	created() { },
@@ -260,6 +635,32 @@ export default {
 .addTargtDia-box {
     .custom-dialog{
         max-width: 1200px !important;
+				min-width: 1100px;
+				.el-checkbox{
+					margin-right: 20px;
+					margin-bottom: 16px;
+				}
+				.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>
@@ -272,7 +673,49 @@ export default {
 		border: 1px solid #ECECEC;
 		box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
 	}
-
+	.wsd-index-box{
+		padding-top: 20px;
+		.wsd-index-code{
+			display: flex;
+			align-items: center;
+			margin-bottom: 20px;
+			.index-code-hint{
+				color: #C0C4CC;
+				font-size: 15px;
+			}
+		}
+		.wsd-code-row{
+			margin-top: 10px;
+			min-height: 60px;
+			display: flex;
+			align-items: center;
+			flex-wrap: wrap;
+			.wsd-code-item{
+				height: 40px;
+				background-color: #EBEFF6;
+				display: flex;
+				align-items: center;
+				margin-right: 10px;
+				padding: 10px;
+				box-sizing: border-box;
+				margin-bottom: 10px;
+				.wsd-code-item-text{
+					color: #333333;
+					margin-right: 10px;
+				}
+				img{
+					height: 16px;
+					width: 16px;
+					cursor: pointer;
+				}
+			}
+		}
+		.wsd-index-input{
+			min-width: 400px;
+			width:400px;
+			margin-right: 10px;
+		}
+	}
 	.warn_txt {
 		font-size: 16px;
 		color: #FF4E00;
@@ -312,5 +755,61 @@ export default {
 		color: #FF4E00;
 		border: 1px dashed #FF4E00;
 	}
+	// 预览表格
+	.sticky {
+		position: sticky;
+		border-right: 1px solid #dcdfe6;
+		z-index: 10;
+	}
+	.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;
+    }
+    thead {
+      position: sticky;
+      z-index: 2;
+      top: 0;
+    }
+    td {
+      min-width: 100px;
+      max-width: 100px;
+      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;
+    }
+		.exist-highlight{
+			border: red solid 1px;
+		}
+	}
+	.check-fail-box{
+		padding: 0 0 15px 40px;	
+		color: #333333;
+		.exist-index-item{
+			cursor: pointer;
+			&:hover{
+				text-decoration: underline;
+			}
+		}
+		.check-fail-button{
+			margin-top: 80px;
+			display: flex;
+			justify-content: flex-end;
+		}
+	}
 }
+
+
 </style>

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

@@ -170,7 +170,7 @@ export default {
                 }
             });
             
-            if(this.isOpenDetail) this.$refs.chartDetailRef.getChartDetail();
+            if(this.isOpenDetail) this.$refs.chartDetailRef.getChartInfo();
         },
 
         //显示详情

+ 47 - 1
src/views/dataEntry_manage/databaseComponents/util.js

@@ -192,7 +192,7 @@ export const allFromArr = [
 	{ name: 'wind',key: 2 },
 	{ name: '同花顺',key: 1 },
 	{ name: '彭博',key: 3 },
-	{name:'彭博财务',key:28},
+	{ name:'彭博财务',key:28},
 	{ name: '路透', key: 25 },
 	{ name: '手工指标', key: 9 },
 	{ name: '隆众指标', key: 10 },
@@ -437,3 +437,49 @@ export const formulaTip = new Map([
 	5、旬度值转日均值=旬度值/对应旬度天数 <br>
 	6、周度值转日均值=周度值/7`]
 ])
+
+// wind 日期序列常见指标代码
+export const windCommonIndexCodeArr=[
+	{value:'pre_close',label:"前收盘价"},
+	{value:'open',label:"开盘价"},
+	{value:'high',label:"最高价"},
+	{value:'low',label:"最低价"},
+	{value:'close',label:"收盘价"},
+	{value:'settle',label:"结算价"},
+	{value:'volume',label:"成交量"},
+	{value:'amt',label:"成交额"},
+	{value:'pct_chg',label:"涨跌幅"},
+	{value:'swing',label:"振幅"},
+	{value:'turn',label:"换手率"},
+	{value:'oi',label:"持仓量"},
+	{value:'oiamount',label:"持仓额"}
+]
+
+// 同花顺 日期序列常见 股票指标代码
+export const THSCommonIndexStockCodeArr=[
+	{value:'ths_pre_close_stock',label:"前收盘价"},
+	{value:'ths_open_price_stock',label:"开盘价"},
+	{value:'ths_high_price_stock',label:"最高价"},
+	{value:'ths_low_stock',label:"最低价"},
+	{value:'ths_close_price_stock',label:"收盘价"},
+	{value:'ths_vol_stock',label:"成交量"},
+	{value:'ths_amt_stock',label:"成交额"},
+	{value:'ths_chg_ratio_stock',label:"涨跌幅"},
+	{value:'ths_swing_stock',label:"振幅"},
+	{value:'ths_turnover_ratio_stock',label:"换手率"},
+]
+
+// 同花顺 日期序列常见 指标代码
+export const THSCommonIndexFuturesCodeArr=[
+	{value:'ths_pre_close_future',label:"前收盘价"},
+	{value:'ths_open_price_future',label:"开盘价"},
+	{value:'ths_high_price_future',label:"最高价"},
+	{value:'ths_low_future',label:"最低价"},
+	{value:'ths_close_price_future',label:"收盘价"},
+	{value:'ths_settle_future',label:"结算价"},
+	{value:'ths_vol_future',label:"成交量"},
+	{value:'ths_amt_future',label:"成交额"},
+	{value:'ths_chg_ratio_future',label:"涨跌幅"},
+	{value:'ths_swing_d_future',label:"日振幅"},
+	{value:'ths_open_interest_future',label:"持仓量"},
+]

+ 22 - 16
src/views/dataEntry_manage/databaseList.vue

@@ -65,9 +65,9 @@
 			<!-- <target-tree /> -->
 			<div class="main-left left" id="left" v-show="isMainLeftShow">
 				<div class="tree-cont">
+					<div class="target_tree">
 					<el-tree
 						ref="menuTree"
-						class="target_tree"
 						:data="treeData"
 						node-key="UniqueCode"
 						:props="defaultProp"
@@ -170,6 +170,7 @@
 							</span>
 						</span>
 					</el-tree>
+					</div>
 					<div class="noDepart" @click="addLevelOneHandle" v-if="CanOpClassify&&isEdbBtnShow('editCatalog')">
 						<img
 							src="~@/assets/img/set_m/add_ico.png"
@@ -242,7 +243,7 @@
 								type="text" @click.stop="saveEdbLimit">保存</el-button>
 							<el-button v-if="EdbData.EdbType===2&&isEdbBtnShow('toSource')"
 								type="text" @click="isLookHistory=true;lookEdbId=selected_edbid">指标溯源</el-button>
-							<el-popover 
+							<el-popover v-if="showPopver"
 								placement="bottom-end" 
 								trigger="hover"
 								popper-class="edb-tool-popover"
@@ -338,6 +339,7 @@
 			ref="addTargetDiaBase"
 			:isAddTarget="isAddTarget"
 			@cancelHandle="isAddTarget = false"
+			@addSuccessHandle="addTargetSuccess"
 		/>
 		<!-- 完善指标信息 -->
 		<completeTargetDia
@@ -472,7 +474,7 @@
 			:isShow.sync="isUpdateNewestData"
 			:edbinfo="tableData[0]"
 			:dataList="dataList"
-			@success="initGetData"
+			@success="updateNewest"
 		/>
 
 		 <!-- 指标历史记录 -->
@@ -802,6 +804,15 @@ export default {
 		//是否显示指标详情
 		isShowDetail(){
 			return !this.showAssociateChart&&!this.showAssociateComputeData&&this.selected_edbid
+		},
+		//是否显示更多操作
+		showPopver(){
+			return this.isEdbBtnShow('setEn')||
+			this.EdbData.Button.InsertNewDataButton&&this.isEdbBtnShow('newValue')||
+			this.EdbData.EdbType===2&&this.isEdbBtnShow('calculateAgain')||
+			this.EdbData.EdbType===1&&this.isEdbBtnShow('refreshAll')||
+			this.isEdbBtnShow('copyData')||
+			this.EdbData.Button.DeleteButton&&this.isEdbBtnShow('deleteEdb')
 		}
 	},
 	methods: {
@@ -1505,14 +1516,6 @@ export default {
 				? e.target.childNodes[0].style.backgroundColor = '#409eff' 
 				: e.target.style.backgroundColor = '#409eff';
 			}
-			const dropLine=$('.el-tree__drop-indicator')[0]
-			if(dropLine){
-				// console.log(dropLine);
-				setTimeout(() => {
-					dropLine.style.top=e.layerY+'px'
-					// console.log(e.layerY,dropLine);
-				}, 100);
-			}
 			
 		},
 		/* 拖拽离开/拖拽完成重置背景色 */
@@ -1836,7 +1839,10 @@ export default {
 		updateNewestDataHandle() {
 			this.isUpdateNewestData = true;
 		},
-
+		updateNewest(){
+				this.initGetData()
+				this.rePainChart()
+		},
 		/* 获取标签列表 */
 		getlabelList(){
 			const List = JSON.parse(sessionStorage.getItem('database'))||[]
@@ -1947,6 +1953,10 @@ export default {
 			this.selectCurrentNode(params);
 			this.select_classifyId = 0;
 		},
+		// 添加wind wsd指标成功
+		addTargetSuccess(params){
+			this.getTreeData(params);
+		}
 	},
 	//离开页面时保存标签
 	beforeRouteLeave(to,from,next){
@@ -1954,10 +1964,6 @@ export default {
 		next()
 	},
 	mounted() {
-		if (document.body.clientWidth <= 1400) {
-			//小屏适配
-			this.isMainLeftShow = false;
-		}
 		this.getlabelList()
 		this.getEdbChartList()
 		this.$route.query.code 

+ 2 - 1
src/views/dataEntry_manage/editChart.vue

@@ -161,6 +161,7 @@
 					></el-date-picker>
 					<el-checkbox label="跨年" v-model="isSpanYear" :disabled="isSpanYearDisable"
 					style="margin-top: 12px;" @change="changeIsSpanYear"></el-checkbox>
+					<br />
 					<div class="legend-set-text" @click="openLegendEditDia">
 						<span>图例名称设置</span>
 						<img src="~@/assets/img/icons/edit-blue.png" />
@@ -918,7 +919,7 @@ export default {
 				.legend-set-text{
 					font-size: 15px;
 					color: #1B7BDE;
-					display: flex;
+					display: inline-flex;
 					align-items: center;
 					justify-content: flex-start;
 					margin-top: 20px;

+ 240 - 24
src/views/dataEntry_manage/mixins/chartPublic.js

@@ -8,7 +8,7 @@ import { dataBaseInterface } from '@/api/api';
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
 import futuresInterface from '@/api/modules/futuresBaseApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
-import { fittingEquationInterface,statisticFeatureInterface } from '@/api/modules/chartRelevanceApi';
+import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
 
 /* 散点x轴 */
 const scatterXAxis = {
@@ -36,7 +36,19 @@ const basicYAxis = {
   showLastLabel: true,
   tickPixelInterval: 50,
 }
-
+/**备注一下 越多越乱
+ * @params
+ * Source 1 ; chartType 1曲线 2季节 3面积 4堆积柱 5散点 6组合 7柱形 8截面散点
+ * 2 商品价格
+ * 3 相关性
+ * 4 滚动相关性
+ * 5 商品利润
+ * 6 拟合方程
+ * 7 统计特征/标准差
+ * 8 统计特征/百分位
+ * 9 统计特征/频率
+ * 10 跨品种分析
+ */
 export const chartSetMixin = {
 	data() {
 		return {
@@ -174,6 +186,9 @@ export const chartSetMixin = {
 				XEndDate:"12-31", // 横坐标显示范围-结束
 				JumpYear:0, //是否跨年
 			},
+
+      /* 跨品种分析图 */
+      crossVarietyChartData: {}
 		}
 	},
   watch: {
@@ -212,16 +227,17 @@ export const chartSetMixin = {
       //不同图表来源 1eta图 2商品价格图 3相关性图表
       const sourceMap = {
         1: this.changeOptions,
-        2: this.changeCommodityOptions,
-        3: this.changeRelevanceOptions,
-        4: this.changeRelevanceOptions,
-        5: this.changeCommodityOptions,
+        2: this.changeCommodityLang,
+        3: this.changeRelevanceLang,
+        4: this.changeRelevanceLang,
+        5: this.changeCommodityLang,
+        // 10: wydgw 
       }
 
       sourceMap[this.chartInfo.Source]()
 		},
     // 打开设置英文信息弹窗
-    openEnNameDia(){
+    async openEnNameDia(){
       this.formItemArray={}
       this.formItemArray.chartInfo=[]
       this.formItemArray.chartsList=[]
@@ -230,6 +246,7 @@ export const chartSetMixin = {
         value:this.chartInfo.ChartName,
         key:'ChartName',
         id:this.chartInfo.ChartInfoId,
+        source: this.chartInfo.Source,
         notEdit:true
       },
       {
@@ -239,7 +256,8 @@ export const chartSetMixin = {
         id:this.chartInfo.ChartInfoId,
         placeholder:'请输入英文图表名称'
       })
-      if(![3,6,7,8,9].includes(this.chartInfo.Source)){//相关性图表
+
+      if([1,2,5].includes(this.chartInfo.Source)){ //需要设置指标的
         this.tableData.map(item =>{
           if(item.Unit){
             this.formItemArray.chartsList.push([
@@ -312,7 +330,7 @@ export const chartSetMixin = {
       }
 
       //利润曲线
-      if(this.chartInfo.Source===5) {
+      else if(this.chartInfo.Source===5) {
         this.formItemArray.chartInfo.push({
           label:'盘面利润名称',
           value:this.chartInfo.ProfitName,
@@ -328,6 +346,62 @@ export const chartSetMixin = {
           placeholder:'请输入英文盘面利润名称'
         })
       }
+
+      //跨品种分析
+      else if(this.chartInfo.Source===10) {
+        let { Data } = await crossVarietyInterface.chartLangOption({ChartInfoId: this.chartInfo.ChartInfoId})
+
+        const { TagList,VarietyList } = Data;
+
+        this.formItemArray.chartInfo.push({
+          label:'X轴名称',
+          value:this.crossVarietyChartData.XName,
+          key:'XName',
+          id:TagList[0].ChartTagId,
+          notEdit:true
+        },
+        {
+          label:'英文X轴名称',
+          value:this.crossVarietyChartData.XNameEn,
+          key:'XNameEn',
+          id:TagList[0].ChartTagId,
+          placeholder:'请输入英文X轴名称'
+        },{
+          label:'Y轴名称',
+          value:this.crossVarietyChartData.YName,
+          key:'YName',
+          id:TagList[1].ChartTagId,
+          notEdit:true
+        },
+        {
+          label:'英文Y轴名称',
+          value:this.crossVarietyChartData.YNameEn,
+          key:'YNameEn',
+          id:TagList[1].ChartTagId,
+          placeholder:'请输入英文Y轴名称'
+        })
+
+        VarietyList.forEach(item => {
+          this.formItemArray.chartsList.push([
+            {
+              label:'品种名称',
+              value:item.ChartVarietyName,
+              key:'ChartVarietyName',
+              id:item.ChartVarietyId,
+              notEdit:true
+            },
+            {
+              label:'英文品种名称',
+              value:item.ChartVarietyNameEn,
+              key:'ChartVarietyNameEn',
+              id:item.ChartVarietyId,
+              placeholder:'请输入英文品种名称'
+            }
+          ])
+        })
+      }
+
+
       this.setEnName = true
     },
     // 更新英文信息
@@ -358,6 +432,8 @@ export const chartSetMixin = {
           ChartInfoId: enNameData.ChartInfoId,
           ChartNameEn: enNameData.ChartNameEn
         })
+      }else if(this.chartInfo.Source === 10) {//跨品种分析
+        res=await crossVarietyInterface.editChartEn(enNameData)
       }else{
         res = await dataBaseInterface.chartInfoEditEn(enNameData)
       }
@@ -431,7 +507,7 @@ export const chartSetMixin = {
     },
 
     /* 切换商品价格图中英文 */
-    changeCommodityOptions() {
+    changeCommodityLang() {
       console.log(this.options)
         this.options.yAxis.forEach(item => {
           item.title.text = this.currentLang == 'ch' ? item.title.textCh : item.title.textEn
@@ -447,8 +523,7 @@ export const chartSetMixin = {
     },
 
     /* 切换相关性图中英文 */
-    changeRelevanceOptions(){
-      console.log(this.options)
+    changeRelevanceLang(){
         this.options.yAxis.forEach(item => {
           item.title.text = this.currentLang == 'ch' ? item.title.textCh : item.title.textEn
         });
@@ -580,14 +655,28 @@ export const chartSetMixin = {
         data.push(obj);
         ydata.push(yItem);
       });
-
-      this.xLabelDealHandle();
+      
+      /* x轴处理 */
+      let isLessThanOneYear = this.xLabelDealHandle();
+      let xAxis = {
+        ...defaultOpts.xAxis,
+        labels: {
+          formatter: function (ctx) {
+            return isLessThanOneYear
+              ? Highcharts.dateFormat('%m/%d', ctx.value)
+              : Highcharts.dateFormat('%y/%m', ctx.value);
+          },
+        }
+      }
 
       this.options = {
         series: data,
         yAxis: ydata,
+        xAxis
       };
 
+      console.log(this.options)
+
       //滚动相关性独立tooltip
       if(this.chartInfo.Source === 4) {
         const { LeadValue,LeadUnit } = this.relevanceChartData.CorrelationChartInfo;
@@ -738,12 +827,23 @@ export const chartSetMixin = {
         data.push(obj);
         ydata.push(yItem);
       });
-
-      this.xLabelDealHandle();
+      
+      let isLessThanOneYear = this.xLabelDealHandle();
+      let xAxis = {
+        ...defaultOpts.xAxis,
+        labels: {
+          formatter: function (ctx) {
+            return isLessThanOneYear
+              ? Highcharts.dateFormat('%m/%d', ctx.value)
+              : Highcharts.dateFormat('%y/%m', ctx.value);
+          },
+        }
+      }
       
       this.options = {
         series: data,
         yAxis: ydata,
+        xAxis,
       };
       if(this.currentLang=='en') this.changeOptions()
     },
@@ -1324,7 +1424,7 @@ export const chartSetMixin = {
         tooltip
       }
 
-      this.currentLang==='en' && this.changeCommodityOptions();
+      this.currentLang==='en' && this.changeCommodityLang();
     },
 
     /* 处理无效数据为null */
@@ -1502,7 +1602,7 @@ export const chartSetMixin = {
       this.rightIndex = -1;
       this.rightTwoIndex = -1;
       
-      const { DataList,XName,XNameEn,XUnitName,XUnitNameEn,YName,YNameEn,YUnitName,YUnitNameEn } = this.sectionScatterData;
+      const { DataList,XName,XNameEn,YName,YNameEn } = this.sectionScatterData;
       const { min,max,x_min,x_max }  = this.chartLimit;
 
       //y轴
@@ -1751,6 +1851,123 @@ export const chartSetMixin = {
       this.currentLang=='en' && this.changeOptions()
     },
 
+    /* 跨品种分析 */
+    setCrossVarietyChart() {
+      this.leftIndex = -1;
+      this.rightIndex = -1;
+      this.rightTwoIndex = -1;
+      
+      const { min,max,x_min,x_max }  = this.chartLimit;
+
+      const { DataList,XName,YName,XNameEn,YNameEn } = this.crossVarietyChartData;
+
+      //y轴
+      let yAxis = {
+        ...basicYAxis,
+        title: {
+          text: YName,
+          textCh:YName,// 中文
+          textEn:YNameEn||YName,
+          align: 'middle',
+        },
+        opposite: false,
+        reversed: false,
+        min: Number(min),
+        max: Number(max),
+        tickWidth: 1,
+      }
+
+      // x轴
+      let xAxis = {
+        ...scatterXAxis,
+        title: {
+          text: XName,
+          textCh:XName,// 中文
+          textEn:XNameEn || XName,
+          align: 'middle',
+        },
+        min: Number(x_min),
+        max: Number(x_max),
+      }
+
+       //数据列
+      let series = [];
+      DataList.forEach(item => {
+        //数据列
+        let series_item = {
+          data: [],
+          type: 'scatter',
+          name: item.Name,
+          nameCh: item.Name,
+          nameEn: item.NameEn||item.Name,
+          color: item.Color,
+          lineWidth: 0,
+          chartType: 'linear',
+          zIndex:1
+        }
+        item.CoordinatePointData.forEach(_ => {
+          series_item.data.push({x: _.X,y: _.Y,})
+        })
+        series.push(series_item);
+      })
+
+      let edbInfoList = this.tableData;
+      let tooltip = {
+        formatter: function() {
+          let series_obj = DataList.find(_ => _.Name === this.series.name);
+          let ponit_obj = series_obj.CoordinatePointData.find(_ => _.X ===this.x && _.Y===this.y);
+          
+          let xEdbInfo = edbInfoList.find(_ => _.EdbInfoId===ponit_obj.XEdbInfoId);
+          let yEdbInfo = edbInfoList.find(_ => _.EdbInfoId===ponit_obj.YEdbInfoId);
+
+          let str=`<b>${ this.series.name }</b>`;
+          str += `<br><span style="color:${this.color}">\u25CF</span>${xEdbInfo.EdbName}: ${this.x} ${ponit_obj.XDate}<br>`;
+          str += `<span style="color:${this.color}">\u25CF</span>${yEdbInfo.EdbName}: ${this.y} ${ponit_obj.YDate}`;
+
+          return str
+        },
+        formatterCh: function() {
+          let series_obj = DataList.find(_ => _.Name === this.series.name);
+          let ponit_obj = series_obj.CoordinatePointData.find(_ => _.X ===this.x && _.Y===this.y);
+          
+          let xEdbInfo = edbInfoList.find(_ => _.EdbInfoId===ponit_obj.XEdbInfoId);
+          let yEdbInfo = edbInfoList.find(_ => _.EdbInfoId===ponit_obj.YEdbInfoId);
+
+          let str=`<b>${ this.series.name }</b>`;
+          str += `<br><span style="color:${this.color}">\u25CF</span>${xEdbInfo.EdbName}: ${this.x} ${ponit_obj.XDate}<br>`;
+          str += `<span style="color:${this.color}">\u25CF</span>${yEdbInfo.EdbName}: ${this.y} ${ponit_obj.YDate}`;
+
+          return str
+          
+        },
+        formatterEn: function() {
+          let series_obj = DataList.find(_ => _.NameEn === this.series.name);
+          let ponit_obj = series_obj.CoordinatePointData.find(_ => _.X ===this.x && _.Y===this.y);
+          
+          let xEdbInfo = edbInfoList.find(_ => _.EdbInfoId===ponit_obj.XEdbInfoId);
+          let yEdbInfo = edbInfoList.find(_ => _.EdbInfoId===ponit_obj.YEdbInfoId);
+
+          let str=`<b>${ this.series.name }</b>`;
+          str += `<br><span style="color:${this.color}">\u25CF</span>${xEdbInfo.EdbNameEn}: ${this.x} ${ponit_obj.XDate}<br>`;
+          str += `<span style="color:${this.color}">\u25CF</span>${yEdbInfo.EdbNameEn}: ${this.y} ${ponit_obj.YDate}`;
+
+          return str
+        }
+      }
+
+      this.options = {
+        title: {
+          text:''
+        },
+        series,
+        yAxis: [yAxis],
+        xAxis,
+        tooltip
+      }
+      this.currentLang=='en' && this.changeRelevanceLang()
+
+    },
+
 		/* 查询范围为1年内 x轴显示为月/日 否则默认年/月 */
 		xLabelDealHandle() {
 			const end =
@@ -1766,13 +1983,9 @@ export const chartSetMixin = {
 			);
 			// console.log(year_differ)
 			if ([5, 6].includes(this.year_select) && year_differ <= 1) {
-				defaultOpts.xAxis.labels = {
-					formatter: function () {
-						return Highcharts.dateFormat('%m/%d', this.value);
-					},
-				};
+        return true
 			} else {
-				defaultOpts.xAxis.labels = {};
+        return false;
 			}
 		},
 
@@ -2048,12 +2261,15 @@ export const chartSetMixin = {
 
     /* 改变上下限时重绘图 依赖于chartLimit的柱 商品价格 散点截面 */
     changeLimit() {
+      //source1 eta图库的类型对应
       const typeMap = {
         7: this.setBarChart,
         10: this.setSectionScatterChart
       }
+      //其他source
       const sourceMap = {
         2: this.setCommodityChart,
+        10: this.setCrossVarietyChart
         // 3:
       }
       if(this.chartInfo.Source === 1) {

+ 1 - 1
src/views/dataEntry_manage/targetList.vue

@@ -12,7 +12,7 @@
 				placeholder="关键字搜索"
 				v-model="search_txt"
 				@input="searchHandle"
-				style="maxWidth:520px;float:right">
+				style="maxWidth:260px;float:right">
 				<i slot="prefix" class="el-input__icon el-icon-search"></i>
 			</el-input>
 		</div>

+ 19 - 5
src/views/dataEntry_manage/thirdBase/BAIINFOTargetbase.vue

@@ -1,6 +1,20 @@
 <template>
-  <div class="smmTarget-container" id="box">
-    <div class="left-cont minHeight" id="left">
+  <div class="smmTarget-container target-container" id="box">
+    <span
+        v-show="!isLeftWrapShow"
+        class="slide-btn-icon slide-right"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" id="left" v-show="isLeftWrapShow">
+        <span
+            v-show="isLeftWrapShow"
+            class="slide-btn-icon slide-left"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
       <div class="left-top">
         <el-button
           v-permission="permissionBtn.dataSourcePermission.bcyfData_export"
@@ -295,6 +309,7 @@ export default {
   watch: {},
   data() {
     return {
+      isLeftWrapShow:true,
       exportBase:
         process.env.VUE_APP_API_ROOT + "/datamanage/export/baiinfoList", //ssm数据导出接口
       dataloading: false,
@@ -1190,6 +1205,7 @@ export default {
 </script>
 <style lang="scss">
 @import "../css/customtree.scss";
+@import "../css/baseTargetPage.scss";
 .smmTarget-dialog-cont {
   .el-cascader {
     .el-input {
@@ -1289,11 +1305,10 @@ export default {
     }
   }
   .right-cont {
-    width: 82%;
     padding: 30px;
     .right-box {
       max-width: 100%;
-      max-height: calc(100vh - 230px);
+      max-height: calc(100vh - 240px);
       border-left: 1px solid #dcdfe6;
       border-right: 1px solid #dcdfe6;
       overflow: auto;
@@ -1319,7 +1334,6 @@ export default {
       flex-wrap: wrap;
       .frequency-btn {
         width: 112px;
-        margin: 0 30px 10px 0;
       }
     }
     .nodata-cont {

+ 19 - 2
src/views/dataEntry_manage/thirdBase/NationalDataBase.vue

@@ -38,7 +38,14 @@
       >
     </div>
     <div class="data-show-cotainer" v-loading="searchLoading">
-      <div class="data-list-wrap wrap">
+        <span
+            class="slide-btn-icon"
+            :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
+      <div class="data-list-wrap wrap" v-show="isLeftWrapShow">
         <p class="sub-menu-title" v-if="currentMenu">{{ currentMenu.label }}</p>
         <div class="search-box">
           <el-select
@@ -122,6 +129,7 @@ export default {
   components: { lzTable },
   data() {
     return {
+      isLeftWrapShow:true,
       /* menu */
       menuList: [], //菜单列表
       currentMenu: null, //当前选择的菜单
@@ -545,8 +553,17 @@ export default {
   }
   .data-show-cotainer {
     display: flex;
+    position: relative;
+    .slide-btn-icon{
+        &.slide-left{
+            left:385px;
+        }
+        &.slide-right{
+            left: 0;
+        }
+    }
     .wrap {
-      height: calc(100vh - 192px);
+      height: calc(100vh - 194px);
       background-color: white;
       border: 1px solid #dcdfe6;
       border-radius: 4px;

+ 18 - 2
src/views/dataEntry_manage/thirdBase/SCITargetbase.vue

@@ -1,6 +1,20 @@
 <template>
-  <div class="smmTarget-container" id="box">
-    <div class="left-cont minHeight" id="left">
+  <div class="smmTarget-container target-container" id="box">
+    <span
+        v-show="!isLeftWrapShow"
+        class="slide-btn-icon slide-right"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" id="left" v-show="isLeftWrapShow">
+        <span
+            v-show="isLeftWrapShow"
+            class="slide-btn-icon slide-left"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
       <div class="left-top">
         <el-button
           v-permission="permissionBtn.dataSourcePermission.hongtao3Data_export"
@@ -247,6 +261,7 @@ export default {
   watch: {},
   data() {
     return {
+      isLeftWrapShow:true,
       exportBase: process.env.VUE_APP_API_ROOT + "/datamanage/export/sciList", //sci数据导出接口
       dataloading: false,
       rightShow: false,
@@ -1078,6 +1093,7 @@ export default {
 </script>
 <style lang="scss">
 @import "../css/customtree.scss";
+@import "../css/baseTargetPage.scss";
 .smmTarget-dialog-cont {
   .el-cascader {
     .el-input {

+ 9 - 1
src/views/dataEntry_manage/thirdBase/chinaFinancialFutures.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="exchangedata-wrap">
-        <div class="left-wrap box">
+    <span
+        class="slide-btn-icon"
+        :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+        <div class="left-wrap box" v-show="isLeftWrapShow">
             <el-date-picker 
                 style="width:100%" 
                 v-model="time" 
@@ -75,6 +82,7 @@ export default {
     name:"chinaFinancialFutures",
     data() {
         return {
+            isLeftWrapShow:true,
             labelArr: {
                 Rank: "名次",
                 DealShortName: "会员简称",

+ 288 - 0
src/views/dataEntry_manage/thirdBase/components/batchAddEdbDia.vue

@@ -0,0 +1,288 @@
+<template>
+  <el-dialog
+    :visible.sync="isOpenDialog"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    top="5vh"
+    title="添加指标"
+    @close="cancelHandle"
+    custom-class="dialog"
+    center
+    width="780px"
+    v-dialogDrag
+  >
+    <div
+    v-loading="isAddLoading"
+    element-loading-text="加载时间大概五分钟,关闭弹窗不影响加载"
+    element-loading-spinner="el-icon-loading">
+      <div class="dialog-main">
+        <el-row :gutter="10" class="row" style="margin-bottom: 15px;">
+          <el-col style="width: 250px;" class="col title-col">指标ID</el-col>
+          <el-col style="width: 382px;" class="col title-col">所属分类</el-col>
+        </el-row>
+        <el-form :model="edbForm" ref="edbFormDataListRef" >
+          <div class="form-box" ref="formBoxRef">
+            <el-row v-for="(item,index) in edbForm.edbDataList" :key="item.edbIndex" :gutter="10" class="row">
+            <el-col class="col edb-col">
+              <el-form-item :prop="`edbDataList.${index}.IndexCode`" 
+              :rules="[{required:true,message:'指标ID不能为空',trigger:'blur'},
+                        {validator:checkAge,trigger:'blur'}]">
+                <el-input v-model.trim="item.IndexCode" placeholder="请输入指标ID"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col class="col classify-col">
+              <el-form-item :prop="`edbDataList.${index}.BaseFromMysteelChemicalClassifyId`" 
+              :rules="{required:true,message:'所属分类不能为空',trigger:'change'}">
+                <el-cascader
+                  class="classify-cascader"
+                  :ref="'classifyCascader'+item.edbIndex"
+                  v-model="item.BaseFromMysteelChemicalClassifyId"
+                  :options="classifyOptions"
+                  :key="item.edbIndex"
+                  :props="{
+                    label: 'ClassifyName',
+                    value: 'BaseFromMysteelChemicalClassifyId',
+                    children: 'Children',
+                    emitPath: false,
+                  }"
+                  placeholder="请选择分类"
+                />
+              </el-form-item>
+            </el-col>
+            <img src="~@/assets/img/delete-minus-red.png" @click="delEdbItem(index)" v-if="edbForm.edbDataList.length>1" />
+          </el-row>
+          </div>
+          <div class="add-box" @click="addEdbItem">
+            <img src="~@/assets/img/add-quadrate-blue.png"/>
+            <span>添加</span>
+          </div>
+        </el-form>
+      </div>
+      <div class="dia-bot">
+        <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+          >保存</el-button
+        >
+        <el-button type="primary" plain @click="cancelHandle">取消</el-button>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { steelInterface } from "@/api/modules/thirdBaseApi";
+
+  export default {
+    props: {
+      isOpenDialog: {
+        type: Boolean,
+      },
+      classifyList: {
+        type: Array,
+      },
+    },
+    watch: {
+      isOpenDialog(newval) {
+        if (newval) {
+          let classifyArr = _.cloneDeep(this.classifyList);
+          this.filterNodes(classifyArr);
+          this.classifyOptions = classifyArr;
+        }
+      },
+    },
+    data(){
+      this.checkAge=(rule, value, callback) => {
+        // 不能输入中文和空格
+        let reg = /[\u4e00-\u9fa5]+|\s+/
+        if(reg.test(value)){
+          callback(new Error('不能输入中文和空格'))
+        }else{
+          callback()
+        }
+      }
+      return{
+        isAddLoading: false,
+        classifyOptions:[],
+        // edbIndex 仅前端使用的唯一标识
+        edbForm:{edbDataList:[{edbIndex:1,IndexCode:'',BaseFromMysteelChemicalClassifyId:''}]},
+        timer:null,
+        emitParams:{},
+        getAddBack:false
+      }
+    },
+    methods:{
+      saveHandle(){
+        this.$refs.edbFormDataListRef.validate((valid)=>{
+          if(valid){
+            // console.log(this.edbForm.edbDataList);
+            steelInterface.edbAdd({List:this.edbForm.edbDataList}).then(res=>{
+                if (res.Ret !== 200) return;
+                this.isAddLoading = true;
+                // console.log(this.edbForm.edbDataList);
+                let edbItem = this.edbForm.edbDataList.find(it => it.IndexCode.toUpperCase() == res.Data.IndexCode.toUpperCase())
+                if(!edbItem){
+                  edbItem=this.edbForm.edbDataList[0]
+                }
+                let edbIndexCurrent = edbItem?edbItem.edbIndex:0
+                let selectClassifyNodes=this.$refs['classifyCascader'+edbIndexCurrent][0].getCheckedNodes()[0].path.map(it => it+'')
+                this.emitParams={
+                  code: res.Data.UniqueCode,
+                  id: res.Data.BaseFromMysteelChemicalIndexId,
+                  indexCode:res.Data.IndexCode,
+                  selectClassifyNodes
+                }
+                this.getAddBack=true
+                setTimeout(() => {
+                  this.cancelHandle();
+                  
+                }, 5*60000);
+              })
+          
+          }else{
+            this.$message.error("指标信息请填写完整!")
+            let errorElDom = this.$refs.edbFormDataListRef.fields.filter((item) => {
+              return item.validateState === 'error';
+            });
+            let errorOffsetTops = errorElDom.map((item) => {
+              return item.$el
+            })
+            // 滚动到指定节点
+            errorOffsetTops[0].scrollIntoView({
+                // 值有start,center,end,nearest
+                block: 'start'
+            })
+          }
+        })
+      },
+      /* 取消 */
+      cancelHandle() {
+        this.isAddLoading = false;
+        this.edbForm={edbDataList:[{edbIndex:1,IndexCode:'',BaseFromMysteelChemicalClassifyId:''}]}
+        this.$refs.edbFormDataListRef && this.$refs.edbFormDataListRef.resetFields();
+        this.$emit("update:isOpenDialog", false);
+        if(this.getAddBack){
+          this.$emit("successCallback", this.emitParams);
+          clearTimeout(this.timer)
+          this.getAddBack=false
+        }
+      },
+      // 递归改变第三级目录结构
+      filterNodes(arr) {
+        arr.length &&
+          arr.forEach((item) => {
+            item.Children &&
+              item.Children.length &&
+              this.filterNodes(item.Children);
+            if (item.Level === 2) {
+              delete item.Children;
+            }
+          });
+      },
+      addEdbItem(){
+        this.$refs.edbFormDataListRef.validate(valid=>{
+          if(valid){
+            if(this.edbForm.edbDataList.length>=100){
+              this.$message.warning('添加数量已达上限(上限100)!')
+              return 
+            }
+            let lastItem = this.edbForm.edbDataList[this.edbForm.edbDataList.length-1]
+            this.edbForm.edbDataList.push({
+              edbIndex:lastItem?1+lastItem.edbIndex:1,
+              IndexCode:'',
+              BaseFromMysteelChemicalClassifyId:lastItem?lastItem.BaseFromMysteelChemicalClassifyId:''
+            })
+            this.$nextTick(()=>{
+              // console.log(this.$refs.formBoxRef.scrollTop,this.$refs.formBoxRef.scrollHeight,'');
+              this.$refs.formBoxRef.scrollTop = this.$refs.formBoxRef.scrollHeight
+            })
+
+          }else{
+            // console.log(this.$refs.edbFormDataListRef.fields,'this.$refs.edbFormDataListRef.fields');
+            let errorElDom = this.$refs.edbFormDataListRef.fields.filter((item) => {
+              return item.validateState === 'error';
+            });
+            let errorOffsetTops = errorElDom.map((item) => {
+              return item.$el
+            })
+            // 滚动到指定节点
+            errorOffsetTops[0].scrollIntoView({
+                // 值有start,center,end,nearest
+                block: 'start'
+            })
+          }
+        })
+      },
+      delEdbItem(index){
+        this.edbForm.edbDataList.splice(index,1)
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+.dialog-main {
+  padding: 0 35px;
+  .form-box{
+    max-height: 450px;
+    overflow-y: auto;
+    overflow-x: hidden;
+    scroll-behavior: smooth;
+  }
+  .add-box{
+    display: inline-flex;
+    align-items: center;
+    cursor: pointer;
+    margin-top: 10px;
+    img{
+      height: 18px;
+      width: 18px;
+      margin-right: 7px;
+    }
+    span{
+      font-size: 14px;
+      color: #0052D9;
+    }
+  }
+  .row{
+    .title-col{
+      color: #333333;
+    }
+    .edb-col{
+      width: 250px;
+    }
+    .classify-col{
+      width: 382px;
+    }
+    img{
+      height: 18px;
+      width: 18px;
+      margin: 10px 0 0 8px;
+      cursor: pointer;
+    }
+  }
+}
+
+.dia-bot {
+  margin: 52px 0 30px;
+  display: flex;
+  justify-content: center;
+}
+</style>
+<style lang="scss">
+.form-box{
+  .el-form-item{
+    margin-bottom: 18px;
+  }
+}
+.col{
+  .el-input{
+    width: 100%;
+    height: 38px;
+    .el-input__inner{
+      height: 38px;
+    }
+  }
+  .classify-cascader{
+    min-width: 100%;
+  }
+}
+</style>

+ 23 - 17
src/views/dataEntry_manage/thirdBase/components/targetDialog.vue

@@ -37,6 +37,7 @@
               }"
               style="width: 90%"
               placeholder="请选择分类"
+              ref='classifyIns'
             />
           </el-form-item>
           <el-form-item label="指标ID" prop="from_edb_code">
@@ -48,7 +49,7 @@
               :disabled="edbForm.edb_id"
             />
           </el-form-item>
-          <el-form-item>
+          <!-- <el-form-item>
             <template slot="label">
               <span>
                 更新频度
@@ -96,7 +97,7 @@
                 </el-option>
               </el-select>
             </div>
-          </el-form-item>
+          </el-form-item> -->
         </el-form>
       </div>
       <div class="dia-bot">
@@ -144,19 +145,19 @@ export default {
     },
   },
   computed: {
-    timeArr() {
-      //30间隔的时间数组
-      const timeArrays = new Array(48).fill("").map((item, index) => {
-        let time_val = index * 30;
-        let hour = Math.floor(time_val / 60);
-        let min = time_val % 60;
-        let time =
-          (hour < 10 ? "0" + hour : hour) + ":" + (min === 0 ? "00" : min);
+    // timeArr() {
+    //   //30间隔的时间数组
+    //   const timeArrays = new Array(48).fill("").map((item, index) => {
+    //     let time_val = index * 30;
+    //     let hour = Math.floor(time_val / 60);
+    //     let min = time_val % 60;
+    //     let time =
+    //       (hour < 10 ? "0" + hour : hour) + ":" + (min === 0 ? "00" : min);
 
-        return time;
-      });
-      return timeArrays;
-    },
+    //     return time;
+    //   });
+    //   return timeArrays;
+    // },
   },
   data() {
     return {
@@ -177,7 +178,7 @@ export default {
           { required: true, message: "指标ID不能为空" },
         ],
       },
-      frequencyArr: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
+      // frequencyArr: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
     };
   },
   methods: {
@@ -196,12 +197,15 @@ export default {
             ...params,
             BaseFromMysteelChemicalIndexId: edb_id,
           })
-        : await steelInterface.edbAdd({
+        : await steelInterface.edbAdd([{
             ...params,
             IndexCode: from_edb_code,
-          });
+          }]);
       if (Ret !== 200) return;
 
+      //获取所选的父级分类数据id
+      const selectClassifyNodes=this.$refs.classifyIns.getCheckedNodes()[0].path
+      console.log(selectClassifyNodes);
       if (!edb_id) {
         //新增
         this.isAddLoading = true;
@@ -209,6 +213,7 @@ export default {
           this.cancelHandle();
           this.$emit("successCallback", {
             code: Data.UniqueCode,
+            selectClassifyNodes:selectClassifyNodes,
             id: Data.BaseFromMysteelChemicalIndexId,
           });
         }, 20000);
@@ -217,6 +222,7 @@ export default {
         this.cancelHandle();
         this.$emit("successCallback", {
           code: Data.UniqueCode,
+          selectClassifyNodes:selectClassifyNodes,
           id: Data.BaseFromMysteelChemicalIndexId,
         });
       }

+ 9 - 1
src/views/dataEntry_manage/thirdBase/dlExchangeData.vue

@@ -1,6 +1,13 @@
 <template>
     <div class="exchangedata-wrap">
-        <div class="left-wrap box">
+        <span
+            class="slide-btn-icon"
+            :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
+        <div class="left-wrap box" v-show="isLeftWrapShow">
             <el-date-picker 
                 style="width:100%" 
                 v-model="time" 
@@ -73,6 +80,7 @@ export default {
     name: "大连交易所数据",
     data() {
         return {
+            isLeftWrapShow:true,
             labelArr: {
                 Rank: "名次",
                 DealShortName: "会员简称",

+ 22 - 3
src/views/dataEntry_manage/thirdBase/elaSteoBase.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="eteo-container">
-    <div class="left-cont minHeight">
+    <span
+        class="slide-btn-icon"
+        :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" v-show="isLeftWrapShow">
       <div class="left-top">
         <el-button
           v-permission="permissionBtn.dataSourcePermission.eiaData_export"
@@ -83,6 +90,7 @@ export default {
   components: { lzTable },
   data() {
     return {
+      isLeftWrapShow:true,
       exportBase: process.env.VUE_APP_API_ROOT + "/datamanage/eia_steo/data", //数据导出接口
       dataloading: false,
       rightShow: false,
@@ -296,6 +304,15 @@ export default {
 <style lang="scss" scoped>
 .eteo-container {
   display: flex;
+  position:relative;
+  .slide-btn-icon{
+    &.slide-left{
+        left:225px;
+    }
+    &.slide-right{
+        left: 0;
+    }
+  }
   * {
     box-sizing: border-box;
   }
@@ -309,7 +326,8 @@ export default {
     width: 5px !important;
   }
   .left-cont {
-    min-width: 160px;
+    min-width: 240px;
+    width:240px;
     margin-right: 20px;
     padding: 30px 0;
     overflow: hidden;
@@ -336,8 +354,9 @@ export default {
     }
   }
   .right-cont {
-    width: 86%;
+    flex:1;
     padding: 30px;
+    overflow-x: auto;
     .right-box {
       max-width: 100%;
       max-height: calc(100vh - 230px);

+ 27 - 5
src/views/dataEntry_manage/thirdBase/glTargetbase.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="lzTarget-container">
-    <div class="left-cont minHeight">
+    <span
+        class="slide-btn-icon"
+        :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" v-show="isLeftWrapShow">
       <div class="left-top">
         <!-- <el-button type="primary" plain size="medium" @click="exportClick" :loading="btnload">导出Excel</el-button> -->
         <el-button
@@ -114,6 +121,7 @@ export default {
   },
   data() {
     return {
+      isLeftWrapShow:true,
       dataloading: false,
       rightShow: false,
       exportBase: process.env.VUE_APP_API_ROOT + "/datamanage/export/glList", //钢联数据导出接口
@@ -439,6 +447,15 @@ export default {
 <style lang="scss" scoped>
 .lzTarget-container {
   display: flex;
+  position:relative;
+  .slide-btn-icon{
+        &.slide-left{
+            left:225px;
+        }
+        &.slide-right{
+            left: 0;
+        }
+    }
   * {
     box-sizing: border-box;
   }
@@ -452,7 +469,8 @@ export default {
     width: 5px !important;
   }
   .left-cont {
-    min-width: 140px;
+    min-width: 240px;
+    width:240px;
     margin-right: 20px;
     padding: 30px 0;
     overflow: hidden;
@@ -479,11 +497,12 @@ export default {
     }
   }
   .right-cont {
-    width: 86%;
+    flex:1;
     padding: 30px;
+    overflow-x: auto;
     .right-box {
       max-width: 100%;
-      max-height: calc(100vh - 230px);
+      max-height: calc(100vh - 240px);
       border-left: 1px solid #dcdfe6;
       border-right: 1px solid #dcdfe6;
       overflow: auto;
@@ -507,9 +526,12 @@ export default {
       margin-top: 20px;
       display: flex;
       flex-wrap: wrap;
+      gap:20px;
+      .el-button{
+            margin-left: 0 !important;
+        }
       .frequency-btn {
         width: 112px;
-        margin: 0 30px 10px 0;
       }
     }
   }

+ 28 - 7
src/views/dataEntry_manage/thirdBase/lzTargetbase.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="lzTarget-container">
-    <div class="left-cont minHeight">
+    <span
+        class="slide-btn-icon"
+        :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" v-show="isLeftWrapShow">
       <div class="left-top">
         <el-button
           v-permission="permissionBtn.dataSourcePermission.longzhongData_export"
@@ -103,6 +110,7 @@ export default {
   },
   data() {
     return {
+      isLeftWrapShow:true,
       dataloading: false,
       rightShow: false,
       exportBase: process.env.VUE_APP_API_ROOT + "/datamanage/export/lzList", //隆众数据导出接口
@@ -372,6 +380,15 @@ export default {
 <style lang="scss" scoped>
 .lzTarget-container {
   display: flex;
+  position: relative;
+  .slide-btn-icon{
+        &.slide-left{
+            left:225px;
+        }
+        &.slide-right{
+            left: 0;
+        }
+    }
   * {
     box-sizing: border-box;
   }
@@ -385,7 +402,8 @@ export default {
     width: 5px !important;
   }
   .left-cont {
-    min-width: 140px;
+    min-width: 240px;
+    width:240px;
     margin-right: 20px;
     padding: 30px 0;
     overflow: hidden;
@@ -412,13 +430,13 @@ export default {
     }
   }
   .right-cont {
-    width: 86%;
+    flex:1;
     padding: 30px;
-
+    overflow-x: auto;
     .right-box {
       max-width: 100%;
-      max-height: calc(100vh - 230px);
-      border-left: 1px solid #dcdfe6;
+      max-height: calc(100vh - 240px);
+      /* border-left: 1px solid #dcdfe6; */
       border-right: 1px solid #dcdfe6;
       overflow: auto;
       .data-header {
@@ -441,9 +459,12 @@ export default {
       margin-top: 20px;
       display: flex;
       flex-wrap: wrap;
+      gap:20px;
+      .el-button{
+            margin-left: 0 !important;
+        }
       .frequency-btn {
         width: 112px;
-        margin: 0 30px 10px 0;
       }
     }
   }

+ 14 - 4
src/views/dataEntry_manage/thirdBase/mixins/leftMixin.js

@@ -38,13 +38,22 @@ export default {
 
   methods: {
     /* 根据unicode展开树结构并选中 */
-    selectCurrentNode({ code, id, type }) {
+    selectCurrentNode({ code, id, type ,selectClassifyNodes}) {
       let deep_arr = _.cloneDeep(this.classifyList);
       // 查找图表的分类父级id
-      let arr = this.findParentNodeHandle(deep_arr, code).slice(1).reverse(); // 父的父的父-父的父-父
-      this.defaultShowNodes = arr;
+      if(selectClassifyNodes && selectClassifyNodes.length>0){
+        this.defaultShowNodes = selectClassifyNodes.map(_e=>`${_e}`);
+      }else{
+        let arr = this.findParentNodeHandle(deep_arr, code).slice(1).reverse(); // 父的父的父-父的父-父
+        this.defaultShowNodes = arr;
+      }
       this.select_node = code;
-      this.$refs.treeRef.setCurrentKey(this.select_node);
+      this.$nextTick(()=>{
+        setTimeout(() => {
+          this.$refs.treeRef.setCurrentKey(this.select_node);
+        }, 300);
+      })
+      
       // // 重置筛选状态
       this.edb_id = id;
       this.getFrequency();
@@ -68,6 +77,7 @@ export default {
 
     /* 拖动时node宽度跟随变化 */
     resetNodeStyle: _.debounce(function(node) {
+      console.log(node);
 			const tree = $('.target_tree')[0];
 			let width = tree.offsetWidth;
 			let label_wid =

+ 9 - 1
src/views/dataEntry_manage/thirdBase/shEnergy.vue

@@ -1,6 +1,13 @@
 <template>
   <div class="exchangedata-wrap">
-        <div class="left-wrap box">
+        <span
+            class="slide-btn-icon"
+            :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
+        <div class="left-wrap box" v-show="isLeftWrapShow">
             <el-date-picker 
                 style="width:100%" 
                 v-model="time" 
@@ -70,6 +77,7 @@ export default {
     name: "上海国际能源交易中心",
     data() {
         return {
+            isLeftWrapShow:true,
             labelArr: {
                 Rank: "名次",
                 DealShortName: "会员简称",

+ 9 - 1
src/views/dataEntry_manage/thirdBase/shFutures.vue

@@ -1,6 +1,13 @@
 <template>
     <div class="exchangedata-wrap">
-        <div class="left-wrap box">
+        <span
+            class="slide-btn-icon"
+            :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
+        <div class="left-wrap box" v-show="isLeftWrapShow">
             <el-date-picker
                 style="width: 100%"
                 v-model="time"
@@ -88,6 +95,7 @@ export default {
     name: "上海期货交易所",
     data() {
         return {
+            isLeftWrapShow:true,
             labelArr: {
                 Rank: "名次",
                 DealShortName: "会员简称",

+ 65 - 14
src/views/dataEntry_manage/thirdBase/smmTargetbase.vue

@@ -1,6 +1,20 @@
 <template>
-  <div class="smmTarget-container" id="box">
-    <div class="left-cont minHeight" id="left">
+  <div class="smmTarget-container target-container" id="box">
+    <span
+        v-show="!isLeftWrapShow"
+        class="slide-btn-icon slide-right"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" id="left" v-show="isLeftWrapShow">
+        <span
+            v-show="isLeftWrapShow"
+            class="slide-btn-icon slide-left"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
       <div class="left-top">
         <el-button
           v-permission="permissionBtn.dataSourcePermission.smmData_export"
@@ -55,12 +69,15 @@
           :props="{
             label: 'ClassifyName',
             children: 'Children',
+            isLeaf:'isLeaf'
           }"
           draggable
           :current-node-key="select_node"
           :expand-on-click-node="false"
           check-strictly
           empty-text="暂无分类"
+          lazy
+					:load="getLazyTreeData"
           @current-change="nodeChangeHandle"
           :default-expanded-keys="defaultShowNodes"
           @node-expand="handleNodeExpand"
@@ -260,6 +277,7 @@ export default {
   watch: {},
   data() {
     return {
+      isLeftWrapShow:true,
       exportBase: process.env.VUE_APP_API_ROOT + "/datamanage/export/smmList", //ssm数据导出接口
       dataloading: false,
       rightShow: false,
@@ -377,6 +395,37 @@ export default {
       });
       return arr;
     },
+    // 懒加载指标
+    async getLazyTreeData(node,resolve){
+      // console.log(node);
+      let arr=[]
+      // 点击二级分类或者一级分类但是分类id为0的
+      if((node.level===2&&node.data.ClassifyId!=0)||(node.level===1&&node.data.ClassifyId==0)){
+        const res=await smmDataInterface.edbListForClassify({ClassifyId:node.data.ClassifyId})
+        if(res.Ret===200){
+          const temarr = res.Data.List || [];
+					arr=temarr.map(item=>{
+						return {
+							...item,
+              UniqueCode:`${item.ClassifyId}_${item.BaseFromSmmIndexId}_${item.BaseFromSmmIndexCode}`,
+              Button:{
+                AddButton: false,
+                OpButton: true,
+                DeleteButton: false,
+                MoveButton: true,
+                cleanButton: true,
+                targetDelButton: true,
+              },
+							isLeaf:true
+						}
+					})
+        }
+      }
+      if(node.level===1&&node.data.ClassifyId!==0){
+        arr=node.data.Children||[]
+      }
+      resolve(arr)
+    },
     /* 获取频度 */
     async getFrequency(defaultSelect) {
       const res = await smmDataInterface.frequencyList({
@@ -621,7 +670,7 @@ export default {
 
       this.$nextTick(() => {
         //找到父节点并展开
-        const targetData = this.getTargetData(e.IndexCode, this.classifyList);
+        const targetData = this.getTargetData(e.ClassifyId, this.classifyList);
         if (targetData) {
           //一级节点
           const { topParentNodeId, UniqueCode } = targetData;
@@ -636,11 +685,14 @@ export default {
           let width = tree.offsetWidth;
           let label_width =
             width > 500 ? "auto" : width <= 500 ? 90 : 0.7 * width;
-          targetData.NodeWidth = label_width;
-          this.select_node = UniqueCode;
-          this.$refs.treeRef.setCurrentNode(targetData);
-          const node = this.$refs.treeRef.getCurrentNode();
-          this.resetNodeStyle(node);
+          // targetData.NodeWidth = label_width;
+          this.select_node = `${e.ClassifyId}_${e.BaseFromSmmIndexId}_${e.IndexCode}`;
+
+          setTimeout(() => {
+            this.$refs.treeRef.setCurrentKey(this.select_node);
+            const node = this.$refs.treeRef.getNode(this.select_node);
+            this.resetNodeStyle(node);
+          }, 1000);
         }
         //this.handleScrollLeftWrap()
       });
@@ -652,11 +704,11 @@ export default {
         scrollTop: top - 200,
       });
     },
-    getTargetData(code, arr) {
+    getTargetData(ClassifyId, arr) {
       for (const item of arr) {
-        if (item.BaseFromSmmIndexCode === code) return item;
+        if (item.ClassifyId === ClassifyId) return item;
         if (item.Children && item.Children.length) {
-          const _item = this.getTargetData(code, item.Children);
+          const _item = this.getTargetData(ClassifyId, item.Children);
           if (_item) return _item;
         }
       }
@@ -1109,6 +1161,7 @@ export default {
 </script>
 <style lang="scss">
 @import "../css/customtree.scss";
+@import "../css/baseTargetPage.scss";
 .smmTarget-dialog-cont {
   .el-cascader {
     .el-input {
@@ -1208,11 +1261,10 @@ export default {
     }
   }
   .right-cont {
-    width: 82%;
     padding: 30px;
     .right-box {
       max-width: 100%;
-      max-height: calc(100vh - 230px);
+      max-height: calc(100vh - 240px);
       border-left: 1px solid #dcdfe6;
       border-right: 1px solid #dcdfe6;
       overflow: auto;
@@ -1238,7 +1290,6 @@ export default {
       flex-wrap: wrap;
       .frequency-btn {
         width: 112px;
-        margin: 0 30px 10px 0;
       }
     }
     .nodata-cont {

+ 108 - 15
src/views/dataEntry_manage/thirdBase/steelChemicalbase.vue

@@ -1,10 +1,24 @@
 <template>
   <div class="steelChemical-container" id="box">
-    <div class="left-cont minHeight" id="left">
+    <span
+        v-show="!isLeftWrapShow"
+        class="slide-btn-icon slide-right"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" id="left" v-show="isLeftWrapShow">
+        <span
+            v-show="isLeftWrapShow"
+            class="slide-btn-icon slide-left"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
       <div class="left-top">
         <div>
           <el-button v-permission="permissionBtn.dataSourcePermission.mysteelData_add"
-          type="primary" size="medium" @click="addTargetHandle"
+          type="primary" size="medium" @click="addTargetBatch"
             >新增指标</el-button
           >
           <el-button
@@ -48,6 +62,7 @@
           :props="{
             label: 'ClassifyName',
             children: 'Children',
+            isLeaf:'isLeaf'
           }"
           :allow-drag="canDragHandle"
           :allow-drop="canDropHandle"
@@ -57,6 +72,8 @@
           :expand-on-click-node="false"
           check-strictly
           empty-text="暂无分类"
+          lazy
+					:load="getLazyTreeData"
           @node-expand="handleNodeExpand"
           @node-collapse="handleNodeCollapse"
           @current-change="nodeChangeHandle"
@@ -231,6 +248,10 @@
       :edbForm="edbForm"
       @successCallback="addSuccessCallback"
     />
+    <!-- 批量添加指标弹窗 -->
+    <batch-add-edb-dia :isOpenDialog.sync="batchAddDiaShow" 
+    :classifyList="classifyList" 
+    @successCallback="addSuccessCallback"/>
   </div>
 </template>
 
@@ -239,13 +260,15 @@ import lzTable from "@/components/lzTable.vue";
 import { steelInterface } from "@/api/modules/thirdBaseApi";
 import mDialog from "@/components/mDialog.vue";
 import targetDialog from "./components/targetDialog.vue";
+import batchAddEdbDia from "./components/batchAddEdbDia.vue";
 import leftMixin from "./mixins/leftMixin.js";
 export default {
   name: "",
   mixins: [leftMixin],
-  components: { lzTable, mDialog, targetDialog },
+  components: { lzTable, mDialog, targetDialog,batchAddEdbDia },
   data() {
     return {
+      isLeftWrapShow:true,
       dataloading: false,
       rightShow: false,
       exportBase:
@@ -265,6 +288,7 @@ export default {
       isRefresh: false,
 
       edb_id: "", //搜索指标id
+      index_code: "", //添加指标后的code,无论是否加载出来,无论是否加载成功
       select_node: "",
       dynamicNode: null,
       defaultShowNodes: [], //展开节点
@@ -284,6 +308,8 @@ export default {
 
       addTargetDialog: false, //添加指标弹窗
       edbForm: {},
+      //批量添加指标弹窗
+      batchAddDiaShow:false
     };
   },
   methods: {
@@ -302,6 +328,28 @@ export default {
         });
       });
     },
+    //指标懒加载
+    async getLazyTreeData(node,resolve){
+      let arr=[]
+      if(node.level===2){
+        const res=await steelInterface.edbListForClassify({
+          BaseFromMysteelChemicalClassifyId:node.data.BaseFromMysteelChemicalClassifyId
+        })
+        if(res.Ret===200){
+          const temarr=res.Data.List||[]
+          arr=temarr.map(item=>{
+            return {
+              ...item,
+              isLeaf:true
+            }
+          })
+        }
+      }else{
+        arr=node.data.Children||[]
+      }
+
+      resolve(arr)
+    },
 
     /* 获取频度 */
     getFrequency(defaultSelect) {
@@ -324,7 +372,33 @@ export default {
               : "";
 
           this.page_no = 1;
-          this.select_frequency && this.getDataList();
+          if(!this.select_frequency){
+            if(this.index_code){
+              this.tableOption=[{
+                IndexName:'',
+                IndexCode:this.index_code,
+                FrequencyName:'',
+                UnitName:'',
+                UpdateTime:''
+              }]
+              //为了美观
+              for (let i = 0; i < 6; i++) {
+                this.tableOption.push({
+                  IndexName:'',
+                  IndexCode:'',
+                  FrequencyName:'',
+                  UnitName:'',
+                  UpdateTime:''
+                })
+              }
+              //为了美观
+              this.dateArr=new Array(12).fill('')
+              this.haveMore=false
+              this.rightShow=true
+            }
+          }else{
+            this.getDataList();
+          }
         });
     },
 
@@ -395,7 +469,6 @@ export default {
             }
 
           this.dataloading = false;
-          
           this.rightShow = true;
           this.page_no === 1 &&
             this.$nextTick(() => {
@@ -417,6 +490,7 @@ export default {
       this.select_node = data.UniqueCode;
       this.select_classify = data.BaseFromMysteelChemicalClassifyId;
       this.edb_id = data.BaseFromMysteelChemicalIndexId;
+      this.index_code = data.IndexCode
 
       this.select_frequency = "";
       this.rightShow = false;
@@ -473,7 +547,9 @@ export default {
 
       this.leftSearchVal = e.IndexName;
 
-      this.getClassify({ code: e.UniqueCode, id: e.Id });
+      // 父级
+      let selectClassifyNodes=[`${e.ParentClassifyId}`,`${e.BaseFromMysteelChemicalClassifyId}`]
+      this.getClassify({ code: e.UniqueCode, id: e.Id ,selectClassifyNodes});
     },
 
     /* 编辑分类 */
@@ -600,12 +676,15 @@ export default {
       this.openClassifyDia = false;
     },
 
+    // /* 添加指标 */
+    // addTargetHandle() {
+    //   this.edbForm = {};
+    //   this.addTargetDialog = true;
+    // },
     /* 添加指标 */
-    addTargetHandle() {
-      this.edbForm = {};
-      this.addTargetDialog = true;
+    addTargetBatch() {
+      this.batchAddDiaShow = true;
     },
-
     /* 指标刷新 */
     edbRefreshHandle() {
       this.isRefresh = true;
@@ -623,8 +702,9 @@ export default {
     },
 
     /* 添加后回调 */
-    addSuccessCallback({ code, id }) {
-      this.getClassify({ code, id });
+    addSuccessCallback({ code, id,selectClassifyNodes,indexCode }) {
+      indexCode && (this.index_code = indexCode)
+      this.getClassify({ code, id,selectClassifyNodes });
     },
 
     // 对[# ;]转义
@@ -651,6 +731,15 @@ export default {
 <style lang="scss" scoped>
 .steelChemical-container {
   display: flex;
+  position: relative;
+  .slide-btn-icon{
+        &.slide-left{
+            right:0;
+        }
+        &.slide-right{
+            left: 0;
+        }
+    }
   * {
     box-sizing: border-box;
   }
@@ -722,12 +811,13 @@ export default {
     }
   }
   .right-cont {
-    width: 82%;
+    flex:1;
+    overflow-x: auto;
     padding: 30px;
     position: relative;
     .right-box {
       max-width: 100%;
-      max-height: calc(100vh - 230px);
+      max-height: calc(100vh - 240px);
       border-left: 1px solid #dcdfe6;
       border-right: 1px solid #dcdfe6;
       overflow: auto;
@@ -751,9 +841,12 @@ export default {
       margin-top: 20px;
       display: flex;
       flex-wrap: wrap;
+      gap:20px;
+      .el-button{
+            margin-left: 0 !important;
+        }
       .frequency-btn {
         width: 112px;
-        margin: 0 30px 10px 0;
       }
     }
   }

+ 9 - 1
src/views/dataEntry_manage/thirdBase/zzExchangeData.vue

@@ -1,6 +1,13 @@
 <template>
     <div class="exchangedata-wrap">
-        <div class="left-wrap box">
+        <span
+            class="slide-btn-icon"
+            :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
+        <div class="left-wrap box" v-show="isLeftWrapShow">
             <el-date-picker 
                 style="width:100%" 
                 v-model="time" 
@@ -65,6 +72,7 @@ export default {
     name: "郑州交易所数据",
     data() {
         return {
+            isLeftWrapShow:true,
             labelArr: {
                 Rank: "名次",
                 DealShortName: "会员简称",

+ 162 - 0
src/views/dataSource_manage/accountList.vue

@@ -0,0 +1,162 @@
+<template>
+    <div class="account-list-page">
+
+        <el-button 
+            type="primary" 
+            @click="showEditAccount=true;activeTermId=0;initData={}"
+            v-permission="permissionBtn.dataSourcePermission.dataSource_account_add"
+        >新增终端账号</el-button>
+        <el-table
+            style="margin-top:30px"
+            :data="tableData"
+            border
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.key"
+                :label="col.name"
+                :prop="col.key"
+                :sortable="col.sortable"
+                align="center"
+            >
+                <template slot-scope="scope">
+                    <span 
+                        v-if="col.key==='Status'"
+                        :style="{color:scope.row.Status===1?'':'#FF0000'}"
+                    >{{scope.row.Status===1?'启用':'禁用'}}</span>
+                    <span v-else>{{scope.row[col.key]}}</span>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" width="100">
+                <template slot-scope="scope">
+                    <span 
+                        style="color:#409EFF;cursor: pointer;" 
+                        @click="handleEditAccount(scope.row)"
+                        v-permission="permissionBtn.dataSourcePermission.dataSource_account_edit"
+                    >编辑</span>
+                    <span 
+                        style="color:#409EFF;cursor: pointer;" 
+                        @click="handleSetAccountStatus(scope.row,2)" 
+                        v-if="scope.row.Status===1"
+                        v-permission="permissionBtn.dataSourcePermission.dataSource_account_enable"
+                    >禁用</span>
+                    <span 
+                        style="color:#409EFF;cursor: pointer;" 
+                        @click="handleSetAccountStatus(scope.row,1)" 
+                        v-if="scope.row.Status===2"
+                        v-permission="permissionBtn.dataSourcePermission.dataSource_account_enable"
+                    >启用</span>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+
+        <!-- 新增/编辑终端账号 -->
+        <EditAccount 
+            v-model="showEditAccount" 
+            :TerminalId="activeTermId" 
+            :initData="initData"
+            @change="getAccountList"
+        />
+    </div>
+</template>
+
+<script>
+import EditAccount from './components/EditAccount.vue'
+import {apiDataSource} from '@/api/modules/dataSource.js'
+export default {
+    components:{EditAccount},
+    data() {
+        return {
+            tableData:[],
+            tableColOpts:[
+                {
+                    name:'终端编码',
+                    key:'TerminalCode',
+                },
+                {
+                    name:'终端名称',
+                    key:'Name',
+                },
+                {
+                    name:'文件夹路径',
+                    key:'DirPath',
+                },
+                {
+                    name:'终端地址',
+                    key:'ServerUrl',
+                },
+                {
+                    name:'终端token',
+                    key:'Value',
+                },
+                {
+                    name:'数据源类型',
+                    key:'Source',
+                },
+                {
+                    name:'状态',
+                    key:'Status',
+                },
+                {
+                    name:'指标数据量',
+                    key:'Num',
+                },
+                {
+                    name:'更新时间',
+                    key:'ModifyTime',
+                    sortable:true
+                },
+            ],
+
+            showEditAccount:false,
+            activeTermId:0,
+            initData:{},
+        }
+    },
+    created() {
+        this.getAccountList()
+    },
+    methods: {
+        async getAccountList(){
+            const res=await apiDataSource.accountList({})
+            if(res.Ret===200){
+                const arr=res.Data.List||[]
+                this.tableData=arr
+            }
+        },
+
+        // 点击编辑账号
+        handleEditAccount(e){
+            this.activeTermId=e.TerminalId
+            this.initData=e
+            this.showEditAccount=true
+        },
+
+        // 启用/禁用账号
+        handleSetAccountStatus(e,status){
+            apiDataSource.accountSet({
+                TerminalId:e.TerminalId,
+                Status:status
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.$message.success('操作成功')
+                    this.getAccountList()
+                }
+            })
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.account-list-page{
+    padding: 30px;
+    border-radius: 4px;
+    border: 1px solid #DCDFE6; 
+    background-color: #fff;
+    min-height: calc(100vh - 260px);
+}
+</style>

+ 177 - 0
src/views/dataSource_manage/components/DelEDBTable.vue

@@ -0,0 +1,177 @@
+<template>
+    <div class="del-table-wrap">
+        <div>
+            <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;float:right" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+            @sort-change="handleTableSortChange"
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                :sortable="col.IsSort===1?'custom':false"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="3" @change="handleTableColChange"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import SetTableCols from './SetTableCols.vue'
+export default {
+    components:{SetTableCols},
+    data() {
+        return {
+            tipsKeysArr:['EdbNameSource','ErDataUpdateDate'], 
+            tableLoading:false,
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            filterState:{
+                sortKey:'',
+                sortType:'',
+            },
+
+            showSetTableCols:false,
+        }
+    },
+    created() {
+        this.getTableColOpts()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLDelTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                SortParam:this.filterState.sortKey,
+                SortType:this.filterState.sortType,
+                CreateTime:''
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableColOpts=[]
+            this.tableLoading=true
+            apiDataSource.GLTableColOpts({ColumnType:3}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableColOpts=arr.filter(item=>item.IsShow===1)
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                }
+            })
+        },
+
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 排序
+        handleTableSortChange({column, prop, order}){
+            console.log(column, prop, order);
+            this.filterState.sortKey=prop
+            this.filterState.sortType=order==='descending'?'desc':order==='ascending'?'asc':''
+            this.handleRefreshList()
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                EdbNameSource:'指标在数据源的全称',
+                ErDataUpdateDate:'指标数据发生变化的最早日期',
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                DataUpdateTime:'150px',
+                ErDataUpdateDate:'200px',
+                StartDate:'150px',
+                LatestDate:'150px',
+                CreateTime:'150px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.del-table-wrap{
+    .top-wrap{
+        display: flex;
+        justify-content: flex-end;
+        margin-bottom: 30px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+</style>

+ 313 - 0
src/views/dataSource_manage/components/DetailTable.vue

@@ -0,0 +1,313 @@
+<template>
+    <div class="detail-table-wrap">
+        <div class="top-wrap">
+        <div class="filter-box">
+            <el-select
+                v-model="filterState.terminalCode"
+                placeholder="终端编码"
+                multiple
+                clearable
+                collapse-tags
+                style="width:250px"
+                @change="handleRefreshList"
+            >
+                <el-option
+                    v-for="item in terminalCodeOpts"
+                    :key="item.TerminalCode"
+                    :label="item.Name"
+                    :value="item.TerminalCode"
+                />
+            </el-select> 
+            <el-cascader
+                v-model="filterState.user"
+                placeholder="创建人"
+                :options="sysUserOpts"
+                :props="props"
+                collapse-tags
+                :show-all-levels="false"
+                clearable
+                @change="handleRefreshList"
+                filterable
+                style="width:250px"
+            />
+            <el-select
+                v-model="filterState.frequency"
+                placeholder="频度"
+                multiple
+                clearable
+                collapse-tags
+                style="width:250px"
+                @change="handleRefreshList"
+            >
+                <el-option
+                    v-for="item in frequencyOpt"
+                    :key="item"
+                    :label="item"
+                    :value="item"
+                />
+            </el-select>
+            <el-input
+                placeholder="指标ID/指标名称"
+                prefix-icon="el-icon-search"
+                v-model="filterState.keyword"
+                clearable
+                style="width:250px"
+                @input="handleRefreshList"
+            />
+        </div>
+        <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+            @sort-change="handleTableSortChange"
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                :sortable="col.IsSort===1?'custom':false"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+                <template slot-scope="scope">
+                    <span v-if="col.ColumnKey==='IsAdd'">{{scope.row.IsAdd===1?'是':'否'}}</span>
+                    <span v-else-if="col.ColumnKey==='NeedRefresh'">{{scope.row.NeedRefresh===1?'是':'否'}}</span>
+                    <span v-else-if="col.ColumnKey==='HasRefresh'">{{scope.row.HasRefresh===1?'是':'否'}}</span>
+                    <span v-else-if="col.ColumnKey==='DataUpdateResult'">{{scope.row.DataUpdateResult===1?'是':'否'}}</span>
+                    
+                    <span v-else>{{scope.row[col.ColumnKey]}}</span>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          @size-change="handleSizeChange"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="1" @change="handleTableColChange"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import {frequencyOpt} from '../utils/config'
+import SetTableCols from './SetTableCols.vue'
+import { departInterence } from "@/api/api.js";
+export default {
+    components:{SetTableCols},
+    data() {
+        return {
+            tipsKeysArr:['EdbNameSource','DataUpdateTime','ErDataUpdateDate','NeedRefresh','HasRefresh','UpdateTime'],
+            frequencyOpt,
+            terminalCodeOpts:[],
+            sysUserOpts:[],
+            props: {
+                value: "AdminId",
+                label: "RealName",
+                children: "ChildrenList",
+                multiple: true,
+                emitPath:false
+            },
+            filterState:{
+                frequency:'',
+                keyword:'',
+                sortKey:'',
+                sortType:'',
+                terminalCode:'',
+                user:[],
+                dateVal:this.$moment().format('YYYY-MM-DD')||''
+            },
+            checkAll:false,
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            tableLoading:false,
+
+            showSetTableCols:false,
+
+        }
+    },
+    created() {
+        this.getTableColOpts()
+        this.getTerminalCodeOpts()
+        this.getSysUserList()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLDetailTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                SortParam:this.filterState.sortKey,
+                SortType:this.filterState.sortType,
+                CreateTime:this.filterState.dateVal,
+                TerminalCode:this.filterState.terminalCode?this.filterState.terminalCode.join(','):'',
+                SysUserId:this.filterState.user?this.filterState.user.join(','):'',
+                Frequency:this.filterState.frequency?this.filterState.frequency.join(','):'',
+                KeyWord:this.filterState.keyword
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableLoading=true
+            this.tableColOpts=[]
+            apiDataSource.GLTableColOpts({ColumnType:1}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableColOpts=arr.filter(item=>item.IsShow===1)
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                    
+                }
+            })
+        },
+
+        // 表格配置项变更
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        // 排序
+        handleTableSortChange({column, prop, order}){
+            console.log(column, prop, order);
+            this.filterState.sortKey=prop
+            this.filterState.sortType=order==='descending'?'desc':order==='ascending'?'asc':''
+            this.handleRefreshList()
+        },
+
+        // 获取终端编码数据
+        getTerminalCodeOpts(){
+            apiDataSource.terminalCodeArr().then(res=>{
+                if(res.Ret===200){
+                    this.terminalCodeOpts=res.Data.List||[]
+                }
+            })
+        },
+
+        // 获取所有系统用户
+        async getSysUserList() {
+            const res = await departInterence.getQuestionAdminList();
+            if (res.Ret === 200) {
+                this.sysUserOpts = res.Data.List||[];
+            }
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                EdbNameSource:'指标在数据源的全称',
+                DataUpdateTime:'指标最近一次数据发生变化的时间',
+                ErDataUpdateDate:'指标数据发生变化的最早日期',
+                NeedRefresh:'该指标今日是否设置了定时刷新任务',
+                HasRefresh:'该指标是否发起了刷新任务',
+                UpdateTime:'指标最近一次执行刷新任务的时间'
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                EdbNameSource:'120px',
+                DataUpdateTime:'120px',
+                ErDataUpdateDate:'200px',
+                NeedRefresh:'200px',
+                HasRefresh:'200px',
+                SourceUpdateTime:'120px',
+                DataUpdateResult:'120px',
+                SourceUpdateFailedReason:'120px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss">
+.detail-table-wrap{
+    .top-wrap{
+        .el-cascader__search-input{
+            min-width: 30px;
+        }
+    }
+}
+
+</style>
+<style lang="scss" scoped>
+.top-wrap{
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    margin-bottom: 30px;
+    .filter-box{
+        margin-right: 100px;
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        gap: 10px 20px;
+    }
+    .right-opt-box{
+        display: flex;
+        align-items: center;
+        gap: 20px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+
+</style>

+ 183 - 0
src/views/dataSource_manage/components/EDBInfoChangeTable.vue

@@ -0,0 +1,183 @@
+<template>
+    <div class="edbinfo-table-wrap">
+        <div>
+            <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;float:right" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+            @sort-change="handleTableSortChange"
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                :sortable="col.IsSort===1?'custom':false"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          @size-change="handleSizeChange"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="4" @change="handleTableColChange"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import SetTableCols from './SetTableCols.vue'
+export default {
+    components:{SetTableCols},
+    data() {
+        return {
+            tipsKeysArr:['EdbNameSource','EdbName','ErDataUpdateDate'],
+            tableLoading:false,
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            tableLoading:false,
+            filterState:{
+                dateVal:this.$moment().format('YYYY-MM-DD')||'',
+                sortKey:'',
+                sortType:'',
+            },
+
+            showSetTableCols:false,
+        }
+    },
+    created() {
+        this.getTableColOpts()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLEdbInfoTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                SortParam:this.filterState.sortKey,
+                SortType:this.filterState.sortType,
+                CreateTime:this.filterState.dateVal,
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableColOpts=[]
+            this.tableLoading=true
+            apiDataSource.GLTableColOpts({ColumnType:4}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableColOpts=arr.filter(item=>item.IsShow===1)
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                }
+            })
+        },
+
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        // 排序
+        handleTableSortChange({column, prop, order}){
+            console.log(column, prop, order);
+            this.filterState.sortKey=prop
+            this.filterState.sortType=order==='descending'?'desc':order==='ascending'?'asc':''
+            this.handleRefreshList()
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                EdbNameSource:'指标在数据源的全称',
+                EdbName:'指标在ETA指标库保存的指标名称',
+                ErDataUpdateDate:'指标数据发生变化的最早日期',
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                EdbName:'150px',
+                DataUpdateTime:'150px',
+                ErDataUpdateDate:'200px',
+                StartDate:'150px',
+                LatestDate:'150px',
+                CreateTime:'150px',
+                EdbNameSource:'150px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.edbinfo-table-wrap{
+    .top-wrap{
+        display: flex;
+        justify-content: flex-end;
+        margin-bottom: 30px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+</style>

+ 158 - 0
src/views/dataSource_manage/components/EditAccount.vue

@@ -0,0 +1,158 @@
+<template>
+    <el-dialog
+      :title="TerminalId?'编辑终端账号':'新增终端账号'"
+      :visible.sync="show"
+      :modal-append-to-body="false"
+      :close-on-click-modal="false"
+      :center="true"
+      v-dialogDrag
+      custom-class="dialogclass"
+      width="540px"
+      @close="handleClose"
+    >
+        <el-form 
+            :model="formState" 
+            :rules="rules" 
+            ref="formIns" 
+            label-width="120px" 
+            class="demo-ruleForm"
+        >
+            <el-form-item label="终端名称" prop="name">
+                <el-input placeholder="请输入终端名称" v-model="formState.name" style="width:300px"></el-input>
+            </el-form-item>
+            <el-form-item label="文件夹路径" prop="dirUrl">
+                <el-input placeholder="请输入文件夹路径" v-model="formState.dirUrl"  style="width:300px" :disabled="TerminalId"></el-input>
+            </el-form-item>
+            <el-form-item label="终端地址" prop="url">
+                <el-input placeholder="请输入终端地址" v-model="formState.url"  style="width:300px"></el-input>
+            </el-form-item>
+            <el-form-item label="终端token" prop="token">
+                <el-input placeholder="请输入终端token" v-model="formState.token"  style="width:300px"></el-input>
+            </el-form-item>
+            <el-form-item label="数据源类型" prop="type">
+                <el-select 
+                    v-model="formState.type" 
+                    placeholder="请选择数据源类型"
+                    style="width:300px"
+                    :disabled="TerminalId"
+                >
+                    <el-option 
+                        v-for="item in dataSourceOpt"
+                        :key="item.EdbSourceId"
+                        :label="item.SourceName"
+                        :value="item.EdbSourceId"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="指标数据量" prop="num">
+                <el-input placeholder="请输入指标数据量" type="number" min="0" v-model.number="formState.num"  style="width:300px"></el-input>
+            </el-form-item>
+        </el-form>
+        <div style="text-align:center;margin:30px 0">
+            <el-button type="primary" plain @click="handleClose">取消</el-button>
+            <el-button type="primary" @click="handleSave">确定</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource.js'
+import {dataBaseInterface} from '@/api/api.js'
+export default {
+    model:{
+        prop:"show",
+        event:'close'
+    },
+    props:{
+        show:{
+            type:Boolean,
+            default:false
+        },
+        TerminalId:{
+            type:Number,
+            default:0
+        },
+        initData:{
+            type:Object,
+            default:{}
+        }
+    },
+    watch: {
+        show(n,o){
+            if(n&&this.TerminalId){
+                console.log('aa');
+                console.log(this.initData);
+                this.formState.name=this.initData.Name
+                this.formState.url=this.initData.ServerUrl
+                this.formState.dirUrl=this.initData.DirPath
+                this.formState.type=this.initData.Source
+                this.formState.num=this.initData.Num
+                this.formState.token=this.initData.Value
+            }
+            if(!n){
+                this.formState.name=''
+                this.formState.url=''
+                this.formState.dirUrl=''
+                this.formState.type=''
+                this.formState.num=''
+                this.formState.token=''
+            }
+        }
+    },
+    data() {
+        return {
+            dataSourceOpt:[],
+            formState:{
+                name:'',
+                url:'',
+                token:'',
+                dirUrl:'',
+                type:'',
+                num:''
+            }
+        }
+    },
+    created() {
+        this.getTargetSource()
+    },
+    methods: {
+        handleClose(){
+            this.$emit('close', false)
+        },
+
+        async handleSave(){
+            const params={
+                TerminalId:this.TerminalId||0,
+                Source:Number(this.formState.type),//终端类型
+                Name:this.formState.name,
+                ServerUrl:this.formState.url,
+                DirPath:this.formState.dirUrl,
+                Num:Number(this.formState.num),
+                Value:this.formState.token
+            }
+            console.log(params);
+            const res=await apiDataSource.accountSave(params)
+            if(res.Ret===200){
+                this.$message.success('保存成功')
+                this.$emit('change')
+                this.handleClose()
+            }
+        },
+
+        // 获取数据源类型
+        getTargetSource(){
+			this.dataSourceOpt = []
+			dataBaseInterface.getDataSource({IsBase:1}).then(res=>{
+				if(res.Ret!==200) return
+				if(res.Data){
+					this.dataSourceOpt = res.Data||[]
+				}
+			})
+		}
+    },
+}
+</script>
+
+<style>
+
+</style>

+ 137 - 0
src/views/dataSource_manage/components/GLRefreshFailDetail.vue

@@ -0,0 +1,137 @@
+<template>
+    <el-dialog
+        title="更新失败指标详情"
+        :visible.sync="show"
+        :close-on-click-modal="false"
+        :append-to-body="true"
+        :center="true"
+        v-dialogDrag
+        width="645px"
+        @close="handleClose"
+    >
+        <div class="gl-refresh-fail-detail-wrap">
+            <div style="margin-bottom:20px">
+                <span>终端名称:{{info.Name}}</span>
+                <span style="display:inline-block;margin-left:20px">文件夹路径:{{info.DirPath}}</span>
+            </div>
+            <div style="display:flex;justify-content: space-between;">
+                <div>
+                    <span>已成功刷新指标数:{{info.UpdateSuccessNum}}</span>
+                    <span>更新失败指标数:{{info.UpdateFailedNum}}</span>
+                </div>
+                <div style="display:flex;align-items:center;color:#409EFF;cursor: pointer;" @click="showBZ=true">
+                    <img src="~@/assets/img/data_m/icon01.png" alt="">
+                    <span>排查步骤</span>
+                </div>
+            </div>
+            <el-table
+                :data="info.List"
+                border
+                height="500"
+            >
+                <el-table-column
+                    label="频度"
+                    prop="Frequency"
+                    align="center"
+                >
+                </el-table-column>
+                <el-table-column
+                    label="数量"
+                    prop="Num"
+                    align="center"
+                >
+                </el-table-column>
+                <el-table-column
+                    label="原因"
+                    prop="SourceUpdateFailedReason"
+                    align="center"
+                >
+                </el-table-column>
+                <div slot="empty">
+                    <tableNoData text="暂无数据"/>
+                </div>
+            </el-table>
+        </div>
+
+        <!-- 排查步骤说明 -->
+        <el-dialog
+            title="排查步骤"
+            :visible.sync="showBZ"
+            :close-on-click-modal="false"
+            :center="true"
+            v-dialogDrag
+            :append-to-body="true"
+            width="500px"
+        > 
+            <div style="padding-bottom:30px;line-height:2;color:#333">
+                <div>1、在钢联终端上,用指标编码查询下是否存在该指标,避免因为指标编码变更的原因导致刷新失败。</div>
+                <div>2、核实钢联终端账号处于登录状态。</div>
+                <div>3、打开Excel,如果“钢联数据2.0”插件不存在,则需要先退出所有Excel和WPS,在钢联终端:最上面的导航栏选择工具->Excel插件修复->点击一键修复,完成钢联数据2.0插件安装。</div>
+                <div>4、打开Excel,选中“钢联数据2.0”插件,查看登录状态是否正常。</div>
+                <div>5、打开文件目录下的一个Excel,选中“钢联数据2.0”插件,点击“更新所有页”按钮后,等待十几秒,查看Excel左下角是否提示额度超限。</div>
+            </div>
+        </el-dialog>
+    </el-dialog>
+    
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource.js'
+export default {
+    model:{
+        prop:"show",
+        event:'close'
+    },
+    props:{
+        show:{
+            type:Boolean,
+            default:false
+        },
+        TerminalCode:{
+            type:String,
+            default:''
+        },
+        date:{
+            type:String,
+            default:''
+        }
+    },
+    watch: {
+      show(n){
+          if(n){
+              this.getDetail()
+          }
+      }  
+    },
+    data() {
+        return {
+            info:{},
+            showBZ:false
+        }
+    },
+    methods: {
+        handleClose(){
+            this.$emit('close', false)
+        },
+
+        getDetail(){
+            apiDataSource.GLRefreshFailDetail({
+                TerminalCode:this.TerminalCode,
+                CreateTime:this.date
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.info=res.Data
+                }
+            })
+        }
+    },
+}
+</script>
+
+<style lang='scss'>
+.gl-refresh-fail-detail-wrap{
+    color: #333;
+    padding-bottom: 30px;
+}
+
+</style>

+ 123 - 0
src/views/dataSource_manage/components/SetTableCols.vue

@@ -0,0 +1,123 @@
+<template>
+    <el-dialog
+      title="自定义列"
+      :visible.sync="show"
+      :modal-append-to-body="false"
+      :close-on-click-modal="false"
+      :center="true"
+      v-dialogDrag
+      custom-class="dialogclass"
+      width="550px"
+      @close="handleClose"
+    >
+        <draggable
+            v-model="list"
+            class="list-wrap"
+            animation="300"
+            tag="div"
+            handle=".drag"
+        >
+            <div class="list-item" v-for="item in list" :key="item.ColumnKey">
+                <el-checkbox v-model="item.checked" :disabled="item.IsMust===1">
+                    <span class="name" :style="{color:item.IsMust===1?'#C0C4CC':''}">{{item.ColumnName}}</span>
+                </el-checkbox>
+                <img class="drag" src="~@/assets/img/data_m/move_ico2.png" alt="">
+            </div>
+        </draggable>
+        <div style="text-align:center;margin:30px 0">
+            <el-button type="primary" plain @click="handleClose">取消</el-button>
+            <el-button type="primary" @click="handleSave">确定</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import draggable from 'vuedraggable';
+import {apiDataSource} from '@/api/modules/dataSource'
+export default {
+    components:{draggable},
+    model:{
+        prop:"show",
+        event:'close'
+    },
+    props:{
+        show:{
+            type:Boolean,
+            default:false
+        },
+        ColumnType:{//1数据源明细表,2数据源统计表,3删除指标列表,4指标信息变更表"
+            type:Number,
+            default:0
+        }
+    },
+    watch: {
+        show(n){
+            if(n){
+                this.getTableColOpts()
+            }
+        }  
+    },
+    data() {
+        return {
+            list:[]
+        }
+    },
+    methods: {
+        // 获取表格列配置项
+        getTableColOpts(){
+            apiDataSource.GLTableColOpts({ColumnType:this.ColumnType}).then(res=>{
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.list=arr.map(item=>{
+                        return {
+                            ...item,
+                            checked:item.IsShow===1?true:false
+                        }
+                    })
+                }
+            })
+        },
+
+        handleSave(){
+            const list=this.list.map(item=>{
+                return {
+                    Id:item.Id,
+                    IsShow:item.checked?1:0
+                }
+            })
+            apiDataSource.GLTableColEdit({
+                list:list
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.$message.success('保存成功')
+                    this.$emit('change')
+
+                    this.handleClose()
+                }
+            })
+        },
+
+        handleClose(){
+            this.$emit('close', false)
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.list-wrap{
+    .list-item{
+        padding: 10px 0;
+        border-bottom: 1px solid #000;
+        display: flex;
+        justify-content: space-between;
+        .name{
+            font-size: 16px;
+            color: #000;
+        }
+        .drag{
+            cursor: move;
+        }
+    }
+}
+</style>

+ 186 - 0
src/views/dataSource_manage/components/StatisticTable.vue

@@ -0,0 +1,186 @@
+<template>
+    <div class="statistic-table-wrap">
+        <div>
+            <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;float:right" @click="showSetTableCols=true">
+        </div>
+        <el-table
+            v-loading="tableLoading"
+            ref="tableIns"
+            :data="tableData"
+            border
+        >
+            <el-table-column
+                v-for="col in tableColOpts"
+                :key="col.ColumnKey"
+                :column-key="col.ColumnKey"
+                :label="col.ColumnName"
+                :prop="col.ColumnKey"
+                align="center"
+                :width="getColWidth(col.ColumnKey)"
+            >
+                <template slot="header" slot-scope="scope">
+                    <span>{{col.ColumnName}}</span>
+                    <el-tooltip 
+                        effect="dark" 
+                        :content="getTableHeadTips(col.ColumnKey)" 
+                        placement="top-start"
+                    >
+                        <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                    </el-tooltip>
+                </template>
+                <template slot-scope="scope">
+                    <span 
+                        v-if="col.ColumnKey==='UpdateFailedNum'" 
+                        style="color:#409EFF;cursor: pointer;"
+                        @click="handleShowFail(scope.row)"
+                    >{{scope.row.UpdateFailedNum}}</span>
+                    <span v-else>{{scope.row[col.ColumnKey]}}</span>
+                </template>
+            </el-table-column>
+            <div slot="empty">
+                <tableNoData text="暂无数据"/>
+            </div>
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          @size-change="handleSizeChange"
+          :total="total"
+          style="float: right;margin-top:20px"
+        />
+        <!-- 自定义列表 -->
+        <SetTableCols v-model="showSetTableCols" :ColumnType="2" @change="handleTableColChange"/>
+
+        <!-- 刷新失败详情 -->
+        <GLRefreshFailDetail v-model="showFail" :TerminalCode="TerminalCode" :date="filterState.dateVal"/>
+    </div>
+</template>
+
+<script>
+import {apiDataSource} from '@/api/modules/dataSource'
+import SetTableCols from './SetTableCols.vue'
+import GLRefreshFailDetail from './GLRefreshFailDetail.vue'
+export default {
+    components:{SetTableCols,GLRefreshFailDetail},
+    data() {
+        return {
+            tipsKeysArr:['NeedRefreshNum','HasRefreshNum','RefreshSuccessNum','RefreshFailedNum','UpdateFailedNum','UpdateSuccessNum'],
+            tableColOpts:[],
+            tableData:[],
+            pageSize:15,
+            page:1,
+            total:0,
+            filterState:{
+                dateVal:this.$moment().format('YYYY-MM-DD')||''
+            },
+
+            showSetTableCols:false,
+            tableLoading:false,
+
+            showFail:false,
+            TerminalCode:''
+        }
+    },
+    created() {
+        this.getTableColOpts()
+    },
+    methods: {
+        //获取表格数据
+        getTableList(){
+            this.tableLoading=true
+            apiDataSource.GLStatisticTableList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                CreateTime:this.filterState.dateVal,
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret===200){
+                    const arr=res.Data.List||[]
+                    this.tableData=arr
+                    this.total=res.Data.Paging.Totals
+                }
+            })
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getTableList()
+        },
+
+        // 筛选项刷新列表
+        handleRefreshList(){
+            this.page=1
+            this.getTableList()
+        },
+
+        // 获取表格列配置项
+        getTableColOpts(){
+            this.tableLoading=true
+            this.tableColOpts=[]
+            apiDataSource.GLTableColOpts({ColumnType:2}).then(res=>{
+                if(res.Ret===200){
+                    this.tableColOpts=res.Data.List||[]
+                    this.$nextTick(()=>{
+                        // this.$refs.tableIns.doLayout()
+                        this.tableLoading=false
+                    })
+                    this.getTableList()
+                }
+            })
+        },
+
+        handleTableColChange(){
+            this.getTableColOpts()
+        },
+
+        handleShowSetTableCol(){
+            this.showSetTableCols=true
+        },
+
+        handleShowFail(e){
+            this.TerminalCode=e.TerminalCode
+            this.showFail=true
+        },
+
+        // table说明文案
+        getTableHeadTips(key){
+            const tipsMap={
+                NeedRefreshNum:'今日该终端需定时刷新的指标数量',
+                HasRefreshNum:'今日该终端发起刷新任务的指标数量',
+                RefreshSuccessNum:'今日该终端刷新成功的指标数量',
+                RefreshFailedNum:'今日该终端刷新失败的指标数量',
+                UpdateFailedNum:'今日该终端成功发起刷新任务,但指标数据未变化的指标数量',
+                UpdateSuccessNum:' 今日该终端数据发生变化的指标数量'
+            }
+            return tipsMap[key]
+        },
+
+        // 设置列的宽度
+        getColWidth(key){
+            const widthMap={
+                NeedUpdateNum:'200px',
+                HasUpdateNum:'200px',
+                UpdateSuccessNum:'200px'
+            }
+
+            return widthMap[key]
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.statistic-table-wrap{
+    .top-wrap{
+        display: flex;
+        justify-content: flex-end;
+        margin-bottom: 30px;
+        .set-icon{
+            width: 40px;
+            cursor: pointer;
+        }
+    }
+}
+</style>

+ 108 - 0
src/views/dataSource_manage/dataSourceListGL.vue

@@ -0,0 +1,108 @@
+<template>
+    <div class="data-source-list-page">
+        <div class="top-wrap">
+            <ul class="nav-box">
+                <li 
+                    :class="['nav-item',item.key===activeNav?'active':'']" 
+                    v-for="item in navOpt" 
+                    :key="item.key"
+                    @click="activeNav=item.key"
+                >{{item.name}}</li>
+            </ul>
+            <div>
+                <el-date-picker
+                    v-model="time"
+                    type="date"
+                    placeholder="选择日期"
+                    value-format="yyyy-MM-dd"
+                    :clearable="false"
+                    @change="handleDateChange"
+                    style="width:200px"
+                    v-if="activeNav!='DelEDBTable'"
+                />
+            </div>
+        </div>
+        <div class="main-box">
+            <component :is='activeNav' ref="comIns"></component>
+        </div>
+    </div>
+</template>
+
+<script>
+import DelEDBTable from './components/DelEDBTable.vue'
+import DetailTable from './components/DetailTable.vue'
+import EDBInfoChangeTable from './components/EDBInfoChangeTable.vue'
+import StatisticTable from './components/StatisticTable.vue'
+export default {
+    components:{DelEDBTable,DetailTable,EDBInfoChangeTable,StatisticTable},
+    watch: {
+        activeNav(n){
+            this.time=this.$moment().format('YYYY-MM-DD')
+        }  
+    },
+    data() {
+        return {
+            navOpt:[
+                {name:'数据源明细表',key:'DetailTable'},
+                {name:'数据源统计表',key:'StatisticTable'},
+                {name:'删除指标表',key:'DelEDBTable'},
+                {name:'指标信息变更表',key:'EDBInfoChangeTable'}
+            ],
+            activeNav:'DetailTable',
+            time:this.$moment().format('YYYY-MM-DD')||''
+        }
+    },
+    methods: {
+        handleShowSetTableCol(){
+            this.$refs.comIns.handleShowSetTableCol()
+        },
+
+        handleDateChange(){
+            this.$refs.comIns.filterState.dateVal=this.time
+            this.$refs.comIns.handleRefreshList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.data-source-list-page{
+    .top-wrap{
+        padding: 20px 30px;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6; 
+        background-color: #fff;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .nav-box{
+            display: flex;
+            border: 1px solid #DCDFE6;
+            border-radius: 4px;
+            overflow: hidden;
+            &:last-child{
+                border-right: none;
+            }
+            .nav-item{
+                padding: 10px;
+                color: #666;
+                border-right: 1px solid #DCDFE6;
+                cursor: pointer;
+                &.active{
+                    background-color: #0052D9;
+                    color: #fff;
+                }
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        padding: 30px;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6; 
+        background-color: #fff;
+        min-height: calc(100vh - 380px);
+        padding-bottom: 80px;
+    }
+}
+</style>

+ 4 - 0
src/views/dataSource_manage/utils/config.js

@@ -0,0 +1,4 @@
+export const frequencyOpt=['日度','周度','旬度','月度','季度','年度']
+
+export const refreshFrequencyOpt=['每工作日','周一','周二','周三','周四','周五','周六','周日','每月',]
+

+ 1 - 1
src/views/datasheet_manage/addSheet.vue

@@ -10,7 +10,7 @@
             style="width:240px">
           </el-input>
         </li>
-        <li>          
+        <li>
           <el-select 
             v-model="sheetForm.classify" 
             placeholder="请选择表格分类"

+ 43 - 8
src/views/datasheet_manage/common/customTable.js

@@ -41,8 +41,7 @@ export function findCellByFactor (str) {
 
   let table = document.querySelector('.table');
   let el = table.querySelector("td span[data-rindex='" + newStr[1] + "'][data-cindex='" + newStr[0] + "']") || table.querySelector("td input[data-rindex='" + newStr[1] + "'][data-cindex='" + newStr[0] + "']");
-
-  return el ? (el.innerText||'') : null;
+  return el ? (el.innerText||el.value||'') : null;
 }
 
 //转大写
@@ -136,7 +135,35 @@ export function setCellBg(e) {
 }
 
 //右键菜单
-export function getRightClickMenu(pos) {
+export function getRightClickMenu(pos,canEdit=false) {
+
+  let cellMenu = [
+    { label: "根据表格中日期选择指标值", key: "choose-target" },
+    // { label: "插入指标值", key: "insert-value" },
+    { label: "导入系统日期", key: "insert-sys-date" },
+    { label: "导入指标日期", key: "insert-edb-date" },
+    { label: "指标计算",
+      key: "insert-edb-calculate",
+      children: [
+        { label: '累计值转月/季值',source: 1,fromEdbKey:5 },
+        { label: '同比值',source: 3,fromEdbKey:6 },
+        { label: '同差值',source: 4,fromEdbKey:7 },
+        { label: 'N数值移动平均计算',source: 5,fromEdbKey:8 },
+        { label: 'N数值环比值',source: 6,fromEdbKey:12 },
+        { label: 'N数值环差值',source: 7,fromEdbKey:13 },
+        { label: '升频',source: 8,fromEdbKey:14 },
+        { label: '时间移位',source: 10,fromEdbKey:22 },
+        { label: '超季节性',source: 11,fromEdbKey:35 },
+        { label: '年化',source: 12,fromEdbKey:52 },
+        { label: '降频',source: 9,fromEdbKey:51 },
+        { label: '累计值',source: 13,fromEdbKey:62 },
+        { label: '指数修匀',source: 15,fromEdbKey:'alpha' },
+        { label: '日均值',source: 16,fromEdbKey:75 },
+      ]
+    },
+    { label: "清空", key: "reset" },
+  ]
+
   const menuMap = {
     'col': [
       { label: "向左插入列", key: "insert-col-left" },
@@ -148,11 +175,9 @@ export function getRightClickMenu(pos) {
       { label: "向下插入行", key: "insert-row-down" },
       { label: "删除", key: "del" },
     ],
-    'cell': [
-      { label: "选择指标", key: "choose-target" },
-      { label: "插入指标值", key: "insert-value" },
-      { label: "清空", key: "reset" },
-    ]
+    'cell': canEdit 
+      ? [{ label: '编辑',key: 'cell-edit' },...cellMenu]
+      : cellMenu
   }
 
   return menuMap[pos];
@@ -226,3 +251,13 @@ export function resetDialogCellStyle() {
   })
 }
 
+
+// 根据行头列头位置找key
+export function findCellKeyByFactor(str) {
+  let newStr = splitString(toUpperCase(str));
+
+  let table = document.querySelector('.table');
+  let el = table.querySelector("td [data-rindex='" + newStr[1] + "'][data-cindex='" + newStr[0] + "']");
+
+  return el ? (el.dataset.key||'') : null;
+}

+ 38 - 3
src/views/datasheet_manage/components/CustomTable.vue

@@ -77,6 +77,8 @@
                 :class="([2,3,5].includes(edb.Data.find(_ =>_.DataTime === date).DataType)&&edb.Data.find(_ =>_.DataTime === date).ShowValue)?'insert': ''"
                 @click="clickCell($event,edb.Data.find(_ =>_.DataTime === date))"
                 @dblclick="dblClickCell($event,edb.Data.find(_ =>_.DataTime === date))"
+                @copy="copyCellHandle($event,edb.Data.find(_ =>_.DataTime === date))"
+                @paste="pasteCellHandle($event,edb.Data.find(_ =>_.DataTime === date))"
               >
                 <!-- 实际值/插值 -->
                 <span 
@@ -118,6 +120,8 @@
                 :class="([2,3,5].includes(cell.DataType)&&cell.ShowValue)?'insert': ''"
                 @click="clickCell($event,cell)"
                 @dblclick="dblClickCell($event,cell)"
+                @copy="copyCellHandle($event,cell)"
+                @paste="pasteCellHandle($event,cell)"
               >
               
                   <span 
@@ -193,7 +197,9 @@
                 :data-rindex="rowHeader[index+dateArr.length]"
                 :class="([2,3,5].includes(column[0].DataType)&&column[0].ShowValue)?'insert': ''"
                 @click="clickCell($event,column[0])"
-                 @dblclick="dblClickCell($event,column[0])"
+                @dblclick="dblClickCell($event,column[0])"
+                @copy="copyCellHandle($event,column[0])"
+                @paste="pasteCellHandle($event,column[0])"
               >
                 <span 
                   :data-cindex="-1"
@@ -250,6 +256,8 @@
                 :class="([2,3,5].includes(data.DataType)&&data.ShowValue)?'insert': ''"
                 @click="clickCell($event,data)"
                 @dblclick="dblClickCell($event,data)"
+                @copy="copyCellHandle($event,data)"
+                @paste="pasteCellHandle($event,data)"
               >
                 <!-- 实际值/插值 -->
                 <span
@@ -281,6 +289,8 @@
                 :class="([2,3,5].includes(column[edb_index+1].DataType)&&column[edb_index+1].ShowValue)?'insert': ''"
                 @click="clickCell($event,column[edb_index+1])"
                 @dblclick="dblClickCell($event,column[edb_index+1])"
+                @copy="copyCellHandle($event,column[edb_index+1])"
+                @paste="pasteCellHandle($event,column[edb_index+1])"
               >
                 <span 
                   :data-rindex="rowHeader[column_index+dateArr.length]"
@@ -494,6 +504,7 @@ export default {
       isEditEdbAliasDialog: false,
       editEdb: {},
 
+      copyCellItem: {},
       hasInit:false
     };
   },
@@ -629,7 +640,7 @@ export default {
         return
       }
 
-      if(value.includes('=')) {
+      if(value.startsWith('=')) {
         cell.DataType = 4;
         let calculateVal = await this.getValueByFormula(value);
         cell.ShowValue = calculateVal;
@@ -830,7 +841,31 @@ export default {
     dragEnd(e) {
       let dom = document.querySelector('.add-fixed');
       dom.style.top = e.clientY-10 + 'px';
-    }
+    },
+
+    /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
+    copyCellHandle(e,cell) {
+      this.copyCellItem = cell;
+      // 阻止默认的复制操作
+      e.preventDefault();
+    },
+
+    /* 要支持复制粘贴把公式也带过去 公式单元格类型为4 其余就正常复制文本 */
+    pasteCellHandle(e,cell) {
+      if(this.copyCellItem.DataType === 4) {
+        cell.DataType = this.copyCellItem.DataType;
+        cell.ShowValue = this.copyCellItem.ShowValue;
+        cell.Value = this.copyCellItem.Value;
+      }else {
+        cell.DataType = 3;
+        cell.ShowValue = this.copyCellItem.ShowValue;
+        cell.Value = this.copyCellItem.ShowValue;
+      }
+      
+      // 阻止默认的粘贴操作
+      e.preventDefault();
+    }  
+    
   },
 };
 </script>

+ 458 - 64
src/views/datasheet_manage/components/MixedTable.vue

@@ -1,6 +1,17 @@
 <template>
-  <div class="table-wrapper">
+  <div class="table-wrapper" @keydown="handlekeyDownKeys">
     <template v-if="config.data.length">
+      
+      <!-- 公式显示区 -->
+      <div class="formula-wrapper" v-if="!disabled">
+        <span style="flex-shrink: 0;color:#C0C4CC">公式</span>
+        <el-input
+          v-if="selectCell&&selectCell.DataType===6"
+          v-model="selectCell.Value"
+          @change="updateValueByFormula"
+        />
+      </div>
+
       <table
         width="auto"
         border="0"
@@ -45,15 +56,23 @@
               :data-cindex="columnHeader[cell_index]"
               :data-key="cell.Uid"
               @click="clickCell($event, cell)"
+              @dblclick="dblClickCellHandle($event,cell)"
               @contextmenu.prevent="rightClickHandle($event,cell)"
               @mouseenter="getRelationEdbInfo(cell)"
+              @copy="copyCellHandle($event,cell)"
+              @paste="pasteCellHandle($event,cell)"
             >
 
             <!-- 插入单元格禁止编辑 -->
-            <template v-if="[4,5].includes(cell.DataType) || disabled">
-              <!-- 单元格类型5显示指标浮窗 -->
+            <template 
+              v-if="([4,5,6,7].includes(cell.DataType)&&!cell.CanEdit)
+              ||disabled
+              ||(cell.DataType===1&&[1,2].includes(cell.DataTimeType))"
+            >
+              
+              <!-- 单元格类型5 7显示指标浮窗 -->
               <el-popover
-                v-if="cell.DataType===5&&!disabled"
+                v-if="[5,7].includes(cell.DataType)&&!disabled"
                 placement="top-start"
                 width="350"
                 trigger="hover"
@@ -63,6 +82,10 @@
                     <label style="min-width:80px;">指标名称</label> 
                     {{cellrelationEdbInfo.EdbName}}
                   </li>
+                  <li style="display:flex;margin:10px;">
+                    <label style="min-width:80px;">最新日期</label> 
+                    {{cellrelationEdbInfo.LatestDate}}
+                  </li>
                   <li style="display:flex;margin:10px;">
                     <label style="min-width:80px;">指标ID</label> 
                     {{cellrelationEdbInfo.EdbCode}}
@@ -86,7 +109,8 @@
 
               <el-autocomplete
                 v-else
-                v-model="cell.ShowValue"
+                v-model="cell.Value"
+                :ref="`inputRef${cell.Uid}`"
                 :fetch-suggestions="searchTarget"
                 popper-class="edb-select-popover"
                 :data-key="cell.Uid"
@@ -96,6 +120,7 @@
                 @select="selectTarget($event,cell)"
                 @click="clickCell($event, cell)"
                 @change.native="changeVal($event, cell)"
+                @keydown.native="keyEnterHandle($event,cell)"
               >
                 <template slot-scope="scope">
                     <edbDetailPopover :info="scope.item">
@@ -115,7 +140,25 @@
 
       <!-- 右键菜单 -->
       <div class="contextMenu-wrapper" id="contextMenu-wrapper" @mouseleave="hideContextMenu">
-        <div :class="['item',{'deletesty': menu.key==='reset'}]" v-for="menu in config.contextMenuOption" :key="menu.key" @click="handleContext(menu.key)">{{menu.label}}</div>
+        <div :class="['item',{'deletesty': menu.key==='reset'}]" v-for="menu in config.contextMenuOption" :key="menu.key" @click="handleContext(menu.key)">
+          {{menu.label}}
+          
+          <i class="el-icon-arrow-right" v-if="menu.children"></i>
+
+          <!-- 二级菜单 -->
+          <div class="subMenu-wrapper" v-if="menu.children">
+            <div slot="reference" class="item" v-for="submenu in menu.children" :key="submenu.key" @click="edbCalculateInsertOpen(submenu)">
+                <el-popover
+                  width="300"
+                  trigger="hover"
+                  placement="right"
+                >
+                  <div v-html="formulaTip.get(submenu.fromEdbKey)"></div>
+                  <div slot="reference" style="width:100%">{{submenu.label}}</div>   
+                </el-popover>
+            </div>
+          </div>
+        </div>
       </div>
     </template>
 
@@ -129,6 +172,21 @@
       @insert="insertSelectData"
       ref="selectTargetValueRef"
     />
+
+    <!-- 插入系统/指标日期弹窗 -->
+    <insertDateDia
+      :isShow.sync="isInsertDateDialog"
+      :info="insertDateInfo"
+      @insert="insertDatehandle"
+    />
+
+    <!-- 指标计算弹窗 -->
+    <calculateEdbDia
+      ref="calculateEdbDiaRef"
+      :isShow.sync="isInsertCalculate"
+      :info="insertCalculateInfo"
+      @insert="insertCalculateData"
+    />
   </div>
 </template>
 <script>
@@ -143,12 +201,20 @@ import {
   setFocus,
   findCellByKey,
   resetRelationStyle,
-  resetDialogCellStyle
+  resetDialogCellStyle,
+  extractFactorsFromFormula,
+  findCellByFactor,
+  splitString,
+  toUpperCase,
+  findCellKeyByFactor
 } from "../common/customTable";
 import * as sheetInterface from "@/api/modules/sheetApi.js";
 import { dataBaseInterface } from '@/api/api.js';
 import md5 from '@/utils/md5.js';
 import selectTargetValueDia from './selectTargetValueDia.vue';
+import insertDateDia from './insertDateDia.vue';
+import calculateEdbDia from './calculateEdbDia.vue';
+import { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
 export default {
   props: {
     disabled: { //是否只预览
@@ -156,7 +222,7 @@ export default {
       default: false,
     }
   },
-  components: { selectTargetValueDia },
+  components: { selectTargetValueDia,insertDateDia,calculateEdbDia },
   computed: {
     //列头
     columnHeader() {
@@ -192,7 +258,18 @@ export default {
   data() {
     return {
       config: {
-        data: [], //单元格类型 1日期格 2指标格 3自定义输入 4插入值 有关联的日期和指标格 5弹窗里的插入值 有关联日期格
+        /* 单元格类型 
+          1手动日期格 DataTimeType 0
+          2指标格 
+          3自定义输入 
+          4插入值 表格里有关联的日期和指标格  //隐藏 又不要这个功能了
+          5弹窗里的插入值 有关联日期格 
+          6公式计算单元格 
+          1系统日期导入格 DataTimeType 1
+          1指标日期导入格 DataTimeType 2
+          7指标计算的插入值单元格
+        */
+        data: [], 
         contextMenuOption: [],
       },
 
@@ -200,14 +277,32 @@ export default {
 
       rightClickCell: {},//右键单元格 key c r
 
-      insertTargetCell: {},//选择右键插入指标的单元格 可和右键单元格不一样 key c r
+      insertTargetCell: {},//选择右键插入的单元格 可和右键单元格不一样 key c r
 
-      insertRelationArr: [],
+      insertRelationArr: [], //表格单元格依赖关系数组
 
       isSelectTargetValueDialog: false,
 
-      cellrelationEdbInfo: {},
+      cellrelationEdbInfo: {}, //指标浮窗信息
+
+      copyCellItem: {},//复制时的单元格信息 用于粘贴赋值
+
+      calculateClickCell: null,//双击公式单元格时的单元格信息 用于之后选其他单元格拼接公式
+
+      isInsertDateDialog: false,//导入日期弹窗
+      insertDateInfo: {
+        key: '',
+      },
+
+      calculateChainList: [],//公式链 key数组 后端需要
+
+      isInsertCalculate: false,//插入指标计算值
+      insertCalculateInfo: {},//指标计算单元格info
+
+      formulaTip,
+      
       hasInit:false,
+
     };
   },
   mounted() {
@@ -215,8 +310,15 @@ export default {
   },
   methods: {
 
+    /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索 */
     async searchTarget(query,cb) {
-      if(!query||checkDateFormat(query)) return cb([])
+      //又要过滤掉2020-05-这样的奇葩其他格式 不让检索
+      let dateOtherRegex = /^(?:(?:19|20)\d\d)([-])(0[1-9]|1[0-2])(-?)$/
+      if(!query
+        ||checkDateFormat(query)
+        ||dateOtherRegex.test(query)
+        ||query.startsWith('=')
+      ) return cb([])
       
       const { DataType,EdbInfoId } = this.selectCell;
 
@@ -242,8 +344,15 @@ export default {
       
       setFocus(e);
 
-      //插入值时寻找关联依赖的单元格 设置选框
-      if([4,5].includes(cell.DataType)) {
+      /* 如果当前有公式单元格在编辑就拼接当前单元格进公式 */
+      // if(this.calculateClickCell && this.calculateClickCell.Uid!==cell.Uid) {
+      //   console.log(this.calculateClickCell)
+      //   const { cindex,rindex } = e.target.dataset;
+      //   this.calculateClickCell.Value += `${cindex}${rindex}`
+      // }
+
+      //是插值单元格时寻找关联依赖的单元格 设置选框
+      if([4,5,7].includes(cell.DataType)) {
         const { key } = e.target.dataset;
         if(!this.insertRelationArr.find(_ => _.key===key)) return
         let { relation_date,relation_edb } = this.insertRelationArr.find(_ => _.key===key)
@@ -252,7 +361,11 @@ export default {
         relation_edb.key && setRelationStyle(relation_edb)
       }
 
+      //选择指标弹窗打开时选择日期更新弹窗数据
       this.isSelectTargetValueDialog&&this.$refs.selectTargetValueRef.chooseEdb(this.$refs.selectTargetValueRef.edbInfo)
+
+      //计算指标弹窗打开时选择日期更新弹窗数据
+      this.isInsertCalculate&&this.$refs.calculateEdbDiaRef.showResult&&this.$refs.calculateEdbDiaRef.calculateHandle()
     },
 
     /* 插入值 往左往上寻找同行同列是否有符合条件的一指标一日期 */
@@ -262,6 +375,7 @@ export default {
       console.log(params)
       if(!params) {
         this.selectCell.DataType = 3;
+        this.selectCell.DataTimeType = 0;
         this.selectCell.ShowValue = '';
         this.selectCell.Value = '';
         this.selectCell.DataTime = '';
@@ -270,22 +384,24 @@ export default {
         return
       }
 
-      const { EdbInfoId,Date } = params
+      const { EdbInfoId,Date,DataTimeType } = params
 
       const res = await sheetInterface.insertData({EdbInfoId,Date})
       if(res.Ret !==200) return
 
-      if(!res.Data){
-        this.selectCell.DataType = 3;
-        this.selectCell.ShowValue = '';
-        this.selectCell.Value = '';
-        this.selectCell.DataTime = '';
-        this.selectCell.EdbInfoId = 0;
-        this.$message.warning('所选指标的所选日期无值')
-        return
-      }
+      //日期无值也要建立关联关系
+      // if(!res.Data&&!DataTimeType){
+      //   this.selectCell.DataType = 3;
+      //   this.selectCell.DataTimeType = 0;
+      //   this.selectCell.ShowValue = '';
+      //   this.selectCell.Value = '';
+      //   this.selectCell.DataTime = '';
+      //   this.selectCell.EdbInfoId = 0;
+      //   this.$message.warning('所选指标的所选日期无值')
+      //   return
+      // }
 
-      this.$message.success('插入成功')
+      res.Data ? this.$message.success('插入成功') : this.$message.warning('当前日期暂无值') 
 
       this.selectCell.DataType = 4;
       this.selectCell.ShowValue = res.Data;
@@ -299,6 +415,7 @@ export default {
     // 建立插入单元格和依赖单元格关联关系
     setRelation(data,cellType=4) {
       const { insert_cell } = data;
+
       let relation_obj = {
         type: cellType,
         key: insert_cell.key,
@@ -348,6 +465,7 @@ export default {
             if((row_cell_arr[i].DataType===1&&col_cell_arr[j].DataType===2)
             ||(row_cell_arr[i].DataType===2&&col_cell_arr[j].DataType===1)) {
               params = {
+                DataTimeType: row_cell_arr[i].DataType===1 ? row_cell_arr[i].DataTimeType : col_cell_arr[j].DataTimeType,
                 Date: row_cell_arr[i].DataType===1 ? row_cell_arr[i].ShowValue : col_cell_arr[j].ShowValue,
                 EdbInfoId: row_cell_arr[i].DataType===2 ? row_cell_arr[i].EdbInfoId : col_cell_arr[j].EdbInfoId,
                 insert_cell: {
@@ -383,10 +501,12 @@ export default {
       this.checkCellRelation(cell)
     },
 
-    /* 输入框失焦  */
+    /* 输入框失焦 设置单元格类型 处理关联关系 */
     async changeVal(e, cell) {
+
       // 是日期格式 DataType为1
-      // 否则是3
+      // 自定义内容 DataType 3
+      //有=号为输入公式 DataType 6
 
       const {value} = e.target;
       if(!value){ //无值重置单元格
@@ -395,24 +515,34 @@ export default {
         cell.Value = value;
         cell.EdbInfoId = 0;
         cell.DataTime = '';
+        cell.Extra=''
       }else {
         //指标类型不做格式处理
         if(cell.DataType===2) return
         
         console.log(checkDateFormat(value))
-        if(checkDateFormat(value)) { //是日期格式
+        let dateFormat = checkDateFormat(value);
+        if(dateFormat) { //是日期格式
           cell.DataType = 1;
+          cell.Extra='';
+          cell.ShowValue = dateFormat;
+          cell.Value = dateFormat;
+        }else if(value.startsWith('=')) { //公式单元格
+          cell.DataType = 6;
+          let calculateVal = await this.getValueByFormula(value);
+          if(!calculateVal) return
+          cell.ShowValue = calculateVal;
+          //处理公式关系
+          this.$set(cell,'Extra',this.dealFormulaConstruction(value))
           
-          cell.ShowValue = checkDateFormat(value);
-          cell.Value = checkDateFormat(value);
-        }else if(cell.EdbInfoId&&!cell.DataTime&&cell.Value===value) {//指标
-  
+
         }else {//自定义值
           cell.DataType = 3;
           cell.ShowValue = value;
           cell.Value = value;
           cell.EdbInfoId = 0;
           cell.DataTime = '';
+          cell.Extra=''
         }
       }
 
@@ -457,9 +587,10 @@ export default {
           const res = await sheetInterface.insertData(params)
           if(res.Ret !==200) return
 
-          !res.Data && this.updateInsertCell(relation.key);
-  
-          res.Data && this.config.data.forEach(row => {
+          //现在日期无值也不清除关系了
+          // !res.Data && this.updateInsertCell(relation.key);
+          
+          this.config.data.forEach(row => {
             row.forEach(cell => {
               if(cell.Uid === relation.key) {
                   cell.DataType = relation.type;
@@ -497,6 +628,40 @@ export default {
       this.insertRelationArr.splice(relationIndex,1)
     },
 
+    /* 输入公式的计算值 */
+    async getValueByFormula(val) {
+
+      // 提取因数数组
+      let factors = extractFactorsFromFormula(val)
+      console.log(factors)
+      
+      //根据因数找单元格
+      let isAllCell = factors.some(_ => findCellByFactor(_)===null||isNaN(findCellByFactor(_)))
+      if(isAllCell) {
+        this.$message.warning('公式参数有误')
+        return '';
+      } 
+
+      let TagMap = {};
+      factors.forEach(_ => {
+        if(!TagMap[_]) {
+          TagMap[_] = Number(findCellByFactor(_))
+        }
+      });
+
+      const res = await sheetInterface.calculateCustomCellData({
+        CalculateFormula: val,
+        TagMap
+      })
+      if(res.Ret !== 200) return 
+      return res.Data
+    },
+
+    /* 顶部公式改变 */
+    async updateValueByFormula(value) {
+      this.changeVal({target: {value}},this.selectCell)
+    },
+
     /* 右键 */
     rightClickHandle(e,cell) {
       if(this.disabled) return
@@ -518,15 +683,26 @@ export default {
       }else {//单元格
         pos = 'cell'
       }
-      this.config.contextMenuOption = getRightClickMenu(pos)
+      this.config.contextMenuOption = pos === 'cell' 
+        ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||cell.DataType===7)
+        : getRightClickMenu(pos)
 
+      this.$nextTick(() => {
+        let dom = $('#contextMenu-wrapper')[0];
 
-      const dom = $('#contextMenu-wrapper')[0];
-			dom.style.left = e.clientX-3 + 'px';
-			dom.style.top = e.clientY-3 + 'px';
+        if(e.clientY > window.innerHeight/2) {
+          dom.style.left = e.clientX-3 + 'px';
+          dom.style.top = e.clientY-dom.offsetHeight-3 + 'px';
+        }else {
+          dom.style.left = e.clientX-3 + 'px';
+          dom.style.top = e.clientY-3 + 'px';
+        }
+
+        ['col','row'].includes(pos) && selectMoreCellStyle(e);
+        pos==='cell' && this.clickCell(e,cell);
+
+      })
       
-      ['col','row'].includes(pos) && selectMoreCellStyle(e);
-      pos==='cell' && this.clickCell(e,cell);
     },
 
     /*  */
@@ -538,52 +714,66 @@ export default {
 
     /* 右键事件 */
     async handleContext(key) {
+
+      let editHandlesMap = {
+        1: this.insertDateOpen,
+        7: this.edbCalculateInsertOpen
+      }
+
       const keyMap = {
-        'del': this.delColOrRow,
-        'insert-col-left': this.insertCol,
-        'insert-col-right': this.insertCol,
-        'insert-row-up': this.insertRow,
-        'insert-row-down': this.insertRow,
-        'insert-value': this.insertValue,
-        'choose-target': this.selectTargetOpen,
-        'reset': this.clearCell
+        'del': this.delColOrRow,//删除
+        'insert-col-left': this.insertCol,//向左插入列
+        'insert-col-right': this.insertCol,//向右插入列
+        'insert-row-up': this.insertRow,//向上插入行
+        'insert-row-down': this.insertRow,//向下插入行
+        'insert-value': this.insertValue,//插入值
+        'choose-target': this.selectTargetOpen,//选择指标插入值
+        'insert-sys-date': this.insertDateOpen,//导入系统日期
+        'insert-edb-date': this.insertDateOpen,//导入指标日期
+        'reset': this.clearCell, //清空
+        'cell-edit': this.selectCell ? editHandlesMap[this.selectCell.DataType] : null
       }
       keyMap[key] && keyMap[key](key)
       
-      this.hideContextMenu()
+      key!=='insert-edb-calculate' && this.hideContextMenu()
     },
 
     /* 打开选择指标弹窗  
-    打开弹窗后仍可以在页面上点击 多存一个选择指标时的信息 */
+    打开弹窗后仍可以在页面上点击 多存一个选择指标时的当前单元格信息 */
     selectTargetOpen() {
       this.insertTargetCell = this.selectCell;
       resetDialogCellStyle();
       setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target')
       this.isSelectTargetValueDialog = true;
+
+      this.isInsertCalculate = false;
+      this.$refs.calculateEdbDiaRef.initData();
     },
 
     /* 插入选择指标的值 */
-    insertSelectData({ edbId,value }) {
+    insertSelectData({ edbId,value,date }) {
 
       this.insertTargetCell.DataType = 5;
       this.insertTargetCell.ShowValue = value;
       this.insertTargetCell.Value = value;
       this.insertTargetCell.EdbInfoId = edbId;
-      this.insertTargetCell.DataTime = this.selectCell.ShowValue;
+      this.insertTargetCell.DataTime = date;
 
       this.$message.success('插入成功')
 
-      //建立新的关联关系
-      let relation = {
-        insert_cell: {
-          key: this.insertTargetCell.Uid,
-          relation_date: this.selectCell.Uid,
-          relation_edb: '',
+      //如果有关联表格日期就建立新的关联关系
+      if(date) {
+        let relation = {
+          insert_cell: {
+            key: this.insertTargetCell.Uid,
+            relation_date: this.selectCell.Uid,
+            relation_edb: '',
+          }
         }
+  
+        this.setRelation(relation,5);
       }
 
-      this.setRelation(relation,5);
-
     },
 
     /* 清除单元格内容 格式 关联关系 */
@@ -594,6 +784,7 @@ export default {
       this.selectCell.ShowValue = '';
       this.selectCell.Value = '';
       this.selectCell.DataTime = '';
+      this.selectCell.DataTimeType = 0;
       this.selectCell.EdbInfoId = 0;
 
       this.checkCellRelation(this.selectCell)
@@ -637,7 +828,6 @@ export default {
         this.config.data.splice(index,1)
 
       }
-      // console.log(this.insertRelationArr)
     },
 
     /* 删除时清除关联关系 和删除单元格有关联的插入值单元格和 */
@@ -693,7 +883,7 @@ export default {
 
     /* 单元格类型5 浮到上面展示指标信息浮窗 */
     async getRelationEdbInfo({EdbInfoId,DataType}) {
-      if(DataType!==5||this.disabled) return
+      if(![5,7].includes(DataType)||this.disabled) return
 
       const res = await dataBaseInterface.targetDetail({EdbInfoId})
 
@@ -702,6 +892,95 @@ export default {
       this.cellrelationEdbInfo =  res.Data;
     },
 
+    /* 导入系统/指标日期弹窗 */
+    insertDateOpen(type) {
+      this.insertTargetCell = this.selectCell;
+      resetDialogCellStyle();
+
+      if(type === 'cell-edit') { //编辑日期
+        const { DataTimeType } = this.insertTargetCell;
+        this.insertDateInfo = {
+          key: DataTimeType===1? 'insert-sys-date' : 'insert-edb-date',
+          ...this.insertTargetCell
+        }
+      }else {
+        this.insertDateInfo = {
+          key:type
+        }
+      }
+      this.isInsertDateDialog = true;
+
+      this.isSelectTargetValueDialog = false;
+      this.$refs.selectTargetValueRef.initData();
+      this.isInsertCalculate = false;
+      this.$refs.calculateEdbDiaRef.initData();
+    },
+
+    /* 插入系统/指标日期 */
+    insertDatehandle({insertValue,dataTimeType,str}) {
+
+      this.insertTargetCell.DataType = 1;
+      this.insertTargetCell.DataTimeType = dataTimeType;
+      this.insertTargetCell.ShowValue = insertValue;
+      this.insertTargetCell.Value = str;
+      this.insertTargetCell.EdbInfoId = 0;
+      this.insertTargetCell.DataTime = insertValue;
+    },
+
+    /* 指标计算弹窗 */
+    edbCalculateInsertOpen(item) {
+      this.insertTargetCell = this.selectCell;
+      resetDialogCellStyle();
+      setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target');
+
+      if(item === 'cell-edit') { //编辑
+        const { Value } = this.insertTargetCell;
+
+        let menuInfo = this.config.contextMenuOption
+          .find(_ => _.key==='insert-edb-calculate').children
+          .find(menu => menu.source === JSON.parse(Value).Source);
+
+        this.insertCalculateInfo = {
+          ...menuInfo,
+          formStr: Value,
+        }
+      }else {
+        this.insertCalculateInfo = {
+          ...item
+        }
+      }
+      this.isInsertCalculate = true;
+
+      this.isSelectTargetValueDialog = false;
+      this.$refs.selectTargetValueRef.initData();
+    },
+
+    /* 导入指标计算值 */
+    insertCalculateData(item) {
+      console.log(item)
+      const { InsertValue,EdbInfoId,Str,Date } = item;
+      this.insertTargetCell.DataType = 7;
+      this.insertTargetCell.ShowValue = InsertValue;
+      this.insertTargetCell.Value = Str;
+      this.insertTargetCell.EdbInfoId = EdbInfoId;
+      this.insertTargetCell.DataTime = Date;
+
+      this.$message.success('插入成功')
+
+      //如果有关联表格日期就建立新的关联关系
+      if(Date) {
+        let relation = {
+          insert_cell: {
+            key: this.insertTargetCell.Uid,
+            relation_date: this.selectCell.Uid,
+            relation_edb: '',
+          }
+        }
+  
+        this.setRelation(relation,7);
+      }
+    },
+
     /* 初始化8行5列 */
     initData(initData=null) {
       console.log('initData');
@@ -717,6 +996,7 @@ export default {
             ShowValue: "",
             Value: "",
             DataType: 3,
+            DataTimeType: 0,
             DataTime: "",
             EdbInfoId:0,
             Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`)
@@ -727,6 +1007,91 @@ export default {
         this.hasInit=true
       })
     },
+
+     /* 处理因数结构 =a1+b1 => [{ Tag: a,Row:1,Key:'' }] */
+    dealFormulaConstruction(val) {
+      // 提取因数数组
+      let factors = extractFactorsFromFormula(val)
+      let arr = factors.map(str => ({
+          Tag: splitString(toUpperCase(str))[0],
+          Row: splitString(toUpperCase(str))[1],
+          Key: findCellKeyByFactor(str)
+      }))
+      return JSON.stringify(arr)
+    },
+
+
+    /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
+    copyCellHandle(e,cell) {
+      this.copyCellItem = cell;
+      // 阻止默认的复制操作
+      e.preventDefault();
+    },
+
+    /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
+    pasteCellHandle(e,cell) {
+      if(this.copyCellItem.DataType === 6) {
+        cell.DataType = this.copyCellItem.DataType;
+        cell.ShowValue = this.copyCellItem.ShowValue;
+        cell.Value = this.copyCellItem.Value;
+        cell.DataTime = this.copyCellItem.DataTime;
+        cell.EdbInfoId = this.copyCellItem.EdbInfoId;
+      }else {
+        cell.DataType = 3;
+        cell.ShowValue = this.copyCellItem.ShowValue;
+        cell.Value = this.copyCellItem.ShowValue;
+        cell.DataTime = '';
+        cell.EdbInfoId = 0;
+      }
+
+      // 阻止默认的粘贴操作
+      e.preventDefault();
+    },
+
+    /* 单元格enter时切换编辑状态 */
+    keyEnterHandle(e,cell) {
+      if(e.keyCode===13) {
+        //非得搞个要回车失焦
+        e.target.nodeName && e.target.blur();
+        this.$refs[`inputRef${e.target.dataset.key}`]&&this.$refs[`inputRef${e.target.dataset.key}`][0].close()
+
+        cell.DataType===6 && this.$set(cell,'CanEdit',false)
+        // this.calculateClickCell = null
+      }
+    },
+
+    /* 支持公式单元格双击切换状态 */
+    dblClickCellHandle(e,cell) {
+      if(this.disabled || cell.DataType!==6) return
+
+      this.$set(cell,'CanEdit',true)
+
+      // this.calculateClickCell = cell;
+      // setRelationStyle({ key:cell.Uid },'td-choose-insert-target')
+
+      this.$nextTick(() => {
+        if(e.target.childNodes[0].childNodes[0].childNodes[1].nodeName==='INPUT') e.target.childNodes[0].childNodes[0].childNodes[1].focus();
+      })
+    },
+
+    /* 处理保存的参数 */
+    getSaveParams() {
+      const { data } = this.config;
+
+      let params = {
+        CellRelation: JSON.stringify(this.insertRelationArr),
+        Data: data
+      }
+
+      return params
+    },
+
+    /* tab禁掉 */
+    handlekeyDownKeys(e) {
+      if(e.keyCode === 9) {
+        e.preventDefault();
+      }
+    }
   },
 };
 </script>
@@ -740,10 +1105,23 @@ export default {
 .table-wrapper {
   width: 100%;
   overflow: auto;
+
+  .formula-wrapper {
+    height: 42px;
+    display: flex;
+    align-items: center;
+    background: #fff;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    border: 1px solid #DCDFE6;
+    margin-bottom: 15px;
+    padding: 0 15px;
+  }
   .table td,th {
     width: 104px;
     min-width: 104px;
     height: 35px;
+    max-height: 35px;
     background: #fff;
     text-align: center;
     word-break: break-all;
@@ -862,6 +1240,21 @@ export default {
       &:hover {
         background-color: #f5f7fa;
       }
+      &:hover .subMenu-wrapper {
+        display: block;
+      }
+    }
+
+    .subMenu-wrapper {
+      display: none;
+      padding: 10px 0;
+      box-shadow: 0 1px 4px #999;
+      background: #fff;
+      position: absolute;
+      right: -172px;
+      top:-205px;
+      max-height: 400px;
+      overflow-y: auto;
     }
   }
 }
@@ -881,6 +1274,7 @@ export default {
     background-color: #fff;
   }
 }
+.formula-wrapper .el-input__inner { border: none; outline: none; }
 .edb-select-popover {
   width: 300px !important;
   .edb-item {

+ 24 - 0
src/views/datasheet_manage/components/SheetExcel.vue

@@ -4,6 +4,7 @@
 </template>
 
 <script>
+import { copyFit } from '@/utils/svgToblob.js';
 import { initSheet } from '../common/option';
 export default {
   props: {
@@ -32,10 +33,18 @@ export default {
       let optionData = this.option ? this.option : {};
       let callbackItems={updated:this.updateEmit}
       initSheet('sheet-container',optionData,this.sheetInfo,this.limit,callbackItems)
+      setTimeout(() => {
+        //获取sheet-container的宽度,设置更多操作的宽度
+        //#luckysheet-icon-morebtn-div
+        const sheetDom = document.querySelector('#sheet-container')
+        const morebtn = document.querySelector('#luckysheet-icon-morebtn-div')
+        morebtn.style.maxWidth = sheetDom.clientWidth - 70 +'px';
+      }, 300);
     },
     copyDisable(e){
       // 变向的禁止复制
       // console.log(e.target.value && e.target.value.indexOf('lucksheet'));
+      this.copyData()
       if(!this.limit.disabled) return
       if(e.target.value && e.target.value.indexOf('lucksheet')){
         luckysheet.enterEditMode();
@@ -43,6 +52,21 @@ export default {
         return false
       }
     },
+
+    copyData() {
+      let rangeArr = luckysheet.getRangeArray('twoDimensional');
+      let str = ''
+      rangeArr.forEach(item => {
+        let row = ''
+        item.forEach((cell,index) => {
+          row+= `${index!==0?'\t':''}${cell||''}`
+        })
+        str+=`${row}\n`
+      });
+      
+      copyFit(str)
+    },
+
     updateEmit(){
       this.$emit("updated")
     }

+ 521 - 0
src/views/datasheet_manage/components/calculateEdbDia.vue

@@ -0,0 +1,521 @@
+<template>
+  <div v-dialogDrag v-if="isShow" >
+    <div class="calculate-edb-value-dialog el-dialog" >
+      <div class="header el-dialog__header">
+        <span>{{info.label}}</span>
+        <i class="el-icon-close" @click="cancelHandle"/>
+      </div>
+
+      <div class="main">
+
+        <section class="main-top">
+
+          <template v-if="info.fromEdbKey===5">
+            <el-radio-group 
+              v-model="formData.source"
+              @change="changeSource"
+            >
+              <el-radio :label="1">累计值转月</el-radio>
+              <el-radio :label="2">累计值转季值</el-radio>
+            </el-radio-group>
+          </template>
+
+          <template v-else-if="info.fromEdbKey===62"> 
+            <el-radio-group 
+              v-model="formData.source"
+              @change="changeSource"
+            >
+              <el-radio :label="13">累计值</el-radio>
+              <el-radio :label="14">年初至今累计值</el-radio>
+            </el-radio-group>
+          </template>
+
+          <selectTarget
+            :defaultId="search_edb"
+            :defaultOpt="searchOptions"
+            ref="selectRef"
+            @select="selectTargetHandle"
+            :filter="false"
+            style="margin: 20px 0"
+          />
+
+          <!-- 表格已存在的指标列表 -->
+          <div class="edb-list">
+              <el-tag 
+                :effect="selectEdbInfo&&selectEdbInfo.EdbInfoId===item.EdbInfoId?'dark':'plain'" 
+                v-for="(item,index) in edbArrFromTable" 
+                :key="index"
+                @click="selectTableEdbHandle(item)"
+              >{{ item.ShowValue }}</el-tag>
+          </div>
+        </section>
+        
+        <!-- 指标详情 -->
+        <edbDetailSection
+          :tableData="selectEdbInfo?[selectEdbInfo]:[]"
+        />
+
+        <section class="form-section">
+          <el-form
+						ref="form"
+						label-position="left"
+						inline
+						label-width="80px"
+						:model="formData"
+						:rules="formRules"
+					>
+						<el-form-item label="移动方式" style="display: block;" v-if="info.fromEdbKey === 22" prop="moveVal">
+							<el-select
+								v-model="formData.moveType"
+								style="width: 100px"
+								placeholder=""
+								size="mini"
+								@change="changeParams"
+							>
+								<el-option
+									v-for="item in moveTypeOpions"
+									:key="item.key"
+									:label="item.label"
+									:value="item.key"
+								>
+								</el-option>
+							</el-select>
+							<el-input
+								style="width: 80px"
+								type="number"
+								min="0"
+								size="mini"
+								v-model="formData.moveVal"
+								@keyup.native="filterCode(formData)"
+                @change="changeParams"
+							></el-input>
+							<el-select
+								v-model="formData.moveUnit"
+								size="mini"
+								placeholder=""
+								style="width: 100px"
+                @change="changeParams"
+							>
+								<el-option
+									v-for="item in fre_options"
+									:key="item"
+									:label="item"
+									:value="item"
+								>
+								</el-option>
+							</el-select>
+						</el-form-item>
+
+						<el-form-item label="N等于" prop="nNum" v-if="[8,12,13,35].includes(info.fromEdbKey)">
+							<el-input
+								v-model="formData.nNum"
+								style="width: 200px"
+								placeholder="请输入N数值"
+								type="number"
+								@change="changeParams"
+							/>
+						</el-form-item>
+
+						<el-form-item label="日历" prop="calendarType" v-if="info.fromEdbKey===35">
+							<el-select
+								v-model="formData.calendarType"
+								placeholder="请选择日历"
+								style="width: 200px"
+								@change="changeParams"
+							>
+								<el-option
+									v-for="item in calendarOptions"
+									:key="item.key"
+									:label="item.label"
+									:value="item.label"
+								>
+								</el-option>
+							</el-select>
+						</el-form-item>
+
+            <el-form-item label="频度" prop="frequency" v-if="[9,13].includes(formData.source)">
+							<el-select
+								v-model="formData.frequency"
+								placeholder="请选择频度"
+								style="width: 200px"
+								clearable
+                @change="changeParams"
+							>
+								<el-option
+									v-for="item in frequencyArr"
+									:key="item"
+									:label="item"
+									:value="item"
+								>
+								</el-option>
+							</el-select>
+						</el-form-item>
+
+						<el-form-item label="数据取值" prop="valueType" v-if="info.fromEdbKey===51">
+							<el-select
+								v-model="formData.valueType"
+								placeholder="请选择数据取值类型"
+								style="width: 200px"
+                @change="changeParams"
+							>
+								<el-option key="期末值" label="期末值" value="期末值"/>
+								<el-option key="平均值" label="平均值" value="平均值"/>
+							</el-select>
+						</el-form-item>
+
+						<el-form-item label="alpha值" prop="alphaValue" v-if="info.fromEdbKey==='alpha'">
+              <el-input 
+                v-model="formData.alphaValue" 
+                placeholder="请选择alpha值"
+                style="width: 200px"
+                @change="changeParams"
+              />
+						</el-form-item>
+					</el-form>
+        </section>
+
+        <!-- 计算结果 -->
+        <section class="result-section" v-if="showResult">
+          <label>计算结果:</label>
+          <ul class="data-cont" v-if="calculateShowData.length">
+              <li 
+                v-for="(item,index) in calculateShowData" 
+                :key="index" 
+                :class="[{'choose': item.DataTime===chooseItem.Date || (!chooseItem.Date&&index===0)},'data-li']"
+              >
+                <span>{{item.DataTime}}</span>
+                <span style="min-width:150px">{{item.Value}}</span>
+              </li>
+          </ul>
+
+          <tableNoData text="无对应的数据" size="mini" v-else/>
+        </section>
+
+        <section class="bot">
+          <el-button type="primary" @click="insertData" v-if="showResult">插入值</el-button>
+          <el-button type="primary" @click="calculateHandle" v-else>计算</el-button>
+          <el-button type="primary" plain @click="cancelHandle">取消</el-button>
+
+        </section>
+
+      </div>
+
+    </div>
+  </div>    
+</template>
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
+import { resetDialogCellStyle } from "../common/customTable";
+import selectTarget from '@/views/chartRelevance_manage/components/selectTarget.vue';
+import edbDetailSection from './edbDetailSection.vue';
+import { formRules } from '@/views/dataEntry_manage/databaseComponents/util';
+export default {
+  props: {
+    isShow: {
+      type: Boolean
+    },
+    info: {
+      type: Object
+    }
+  },
+  components: { selectTarget,edbDetailSection },
+  computed: {
+    edbArrFromTable() {
+      let arr = this.$parent.config.data.flat().filter(_ =>_.DataType === 2);
+      let filterArr =  []
+      
+      arr.forEach(item => {
+        if(filterArr.findIndex(_ => _.EdbInfoId===item.EdbInfoId)===-1) {
+          filterArr.push(item)
+        }
+      })
+      
+       return filterArr
+    }
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+      console.log(this.info)
+      const { source,formStr } = this.info;
+
+      this.formData.source = source;
+      //回显
+      if(formStr) {
+        const {
+          Source,
+          Frequency,
+          Formula,
+          EdbInfoId,
+          MoveFrequency,
+          MoveType, 
+          Calendar 
+        } = JSON.parse(formStr);
+
+        this.formData = {
+          source: Source,
+          frequency: Frequency,
+          nNum: Formula,
+          moveType: MoveType,
+          moveUnit: MoveFrequency,
+          moveVal: Formula,
+          calendarType: Calendar,
+          valueType: Formula,
+          alphaValue: Formula,
+        }
+        this.selectTableEdbHandle({EdbInfoId})
+      }
+    }
+  },
+  data() {
+    return {
+      isCalculateDia: true,
+      formData: {
+        source: this.info.fromEdbKey,
+        frequency: '',
+        nNum: 1,
+				moveType: 1,
+				moveUnit: '天',
+				moveVal: '',
+				calendarType: '公历',
+				valueType: '期末值',
+        alphaValue: 0,
+      },
+      formRules,
+      frequencyArr: ['日度', '周度','旬度', '月度', '季度', '年度'],
+
+      showResult: false,
+      calculateShowData: [], //计算全部数据
+      chooseItem: {
+        Date: ''
+      },//要插入表格的项
+
+      search_edb: '',
+      searchOptions: [],
+      selectEdbInfo: null,
+
+      moveTypeOpions: [
+				{
+					label: '领先',
+					key: 1
+				},
+				{
+					label: '滞后',
+					key: 2
+				},
+			],
+      fre_options: ['天','周','月','季','年'],
+      calendarOptions: [
+				{label: '公历',key: 1},
+				{label: '农历',key: 2},
+			],
+    }
+  },
+  mounted(){
+
+  },
+  methods:{
+    /* 计算结果 */
+    async calculateHandle() {
+      await this.$refs.form.validate();
+      
+      const {  
+        source,
+        nNum,
+				moveType,
+				moveUnit,
+				calendarType,
+        frequency
+      } = this.formData;
+
+      const valueMap = {
+        22: 'moveVal',
+        51: 'valueType',
+        'alpha': 'alphaValue'
+      }
+
+      let DataTime = this.$parent.selectCell.DataType === 1 ? this.$parent.selectCell.ShowValue : ''
+
+      let params = {
+        DataTime,
+        Source: source,
+        Frequency: frequency,
+        Formula: valueMap[this.info.fromEdbKey] ? String(this.formData[valueMap[this.info.fromEdbKey]]) : String(nNum),
+        EdbInfoId: this.selectEdbInfo.EdbInfoId,
+        MoveFrequency: moveUnit,
+        MoveType: moveType, 
+        Calendar: calendarType
+      }
+
+      const res = await sheetInterface.getMixedCalculateData(params)
+      if(res.Ret!==200) return 
+
+      this.showResult = true;
+      this.calculateShowData = res.Data.List || [];
+
+      // if(!this.calculateShowData.length && DataTime) return this.$message.warning('所选指标所选日期无值')
+
+      let InsertValue = this.calculateShowData.length 
+        ? (this.calculateShowData.find(_ => _.DataTime===DataTime) ? this.calculateShowData.find(_ => _.DataTime===DataTime).Value.toString() : this.calculateShowData[0].Value.toString()) 
+        : ''
+      this.chooseItem = {
+          Date:DataTime,
+          EdbInfoId: this.selectEdbInfo.EdbInfoId,
+          InsertValue,
+          Str: JSON.stringify(params)
+        }
+      
+    },
+
+    /* 已计算过改参数重新计算 */
+    changeParams() {
+      this.showResult && this.calculateHandle()
+    },
+
+    /* 插入值 */
+    insertData() {
+
+      // if(this.$parent.selectCell.DataType !== 1) return this.$message.warning('请在表格中选择日期')
+        
+      if(!this.calculateShowData.length) return this.$message.warning('该日期无数据')
+      
+      this.$emit('insert',this.chooseItem)
+      this.cancelHandle();
+    },
+
+    /* 选择指标 */
+    async selectTargetHandle(e) {
+      this.changeSource();
+      if(!e) {
+        this.selectEdbInfo = null
+        return
+      }
+
+      const res = e.EdbInfoType === 1 
+        ? await preDictEdbInterface.edbDataInfo({EdbInfoId:e.EdbInfoId,CurrentIndex: 1})
+        : await dataBaseInterface.targetList({EdbInfoId:e.EdbInfoId,CurrentIndex: 1})
+
+      if(res.Ret !== 200) return
+
+      const { EdbInfoId,EdbCode,EdbName,Frequency,Unit,StartDate,ModifyTime,SourceName,PredictDataList,DataList } = res.Data.Item;
+      this.selectEdbInfo = {
+        EdbCode,EdbName,Frequency,Unit,StartDate,ModifyTime,SourceName,EdbInfoId,
+        DataList: PredictDataList ? [...PredictDataList,...DataList].slice(0,5) : DataList.slice(0,5)
+      };
+    },
+
+    /* 选择表格指标 */
+    async selectTableEdbHandle(item) {
+      const res = await dataBaseInterface.targetDetail({EdbInfoId:item.EdbInfoId})
+      if(res.Ret !== 200) return
+
+      const { EdbInfoId,EdbInfoType,EdbName,Frequency } = res.Data;
+
+      if(this.formData.source===1&&Frequency!=='月度') return this.$message.warning('只能选择月度指标')
+      else if(this.formData.source===2&&Frequency!=='季度') return this.$message.warning('不能选择季度指标')
+      else if(this.formData.source===8&&Frequency==='日度') return this.$message.warning('不能选择日度指标')
+      else if(this.formData.source===14&&Frequency==='年度') return this.$message.warning('不能选择年度指标')
+
+
+      this.search_edb = EdbName;
+      this.selectTargetHandle({EdbInfoId,EdbInfoType,EdbName})
+    },
+
+    /*  */
+    changeSource() {
+      this.showResult = false;
+      this.calculateShowData = [];
+      this.chooseItem = { Date: '' };
+    },
+
+    initData() {
+      this.search_edb='';
+      this.selectEdbInfo = null;
+      this.showResult = false;
+      this.calculateShowData = [];
+      this.chooseItem = { Date: '' };
+      this.formData = {
+        source: this.formData.source, 
+        frequency: '',
+        nNum: 1,
+				moveType: 1,
+				moveUnit: '天',
+				moveVal: '',
+				calendarType: '公历',
+				valueType: '期末值'
+      }
+    },
+
+    cancelHandle() {
+      this.initData();
+      this.$emit('update:isShow',false);
+      resetDialogCellStyle();
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+@import "~@/styles/theme-vars.scss";
+.calculate-edb-value-dialog {
+  background: #fff;
+  position: fixed;
+  top: 20%;
+  left: 50%;
+  width: 750px;
+  border-radius: 2px;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+  z-index: 9999;
+  .header { 
+    font-size: 16px;
+    background: $theme-color;
+    color: #fff;
+    padding: 15px;
+    display: flex;
+    align-content: center;
+    justify-content: space-between;
+    .el-icon-close {
+      font-size: 20px;
+      cursor: pointer;
+    }
+  }
+
+  .main {
+    padding: 20px;
+    max-height: calc(100vh - 350px);
+    min-height: 300px;
+    overflow-y: auto;
+    .main-top {
+      margin-bottom: 20px;
+    }
+    .edb-list {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 10px;
+      .el-tag {
+        cursor: pointer;
+      }
+    }
+    .form-section { margin: 20px 0; }
+    .bot {
+      display: flex;
+      justify-content: center;
+      margin: 30px 0;
+    }
+    .data-cont {
+      margin: 15px 0;
+      border: 1px solid #DCDFE6;
+      .data-li {
+        display: flex;
+        padding: 15px;
+        text-align: center;
+        justify-content: space-around;
+        &.choose {
+          background: #ECF5FF;
+        }
+      }
+    }
+  }
+}  
+</style>

部分文件因为文件数量过多而无法显示