瀏覽代碼

Merge branch 'master' into eta1.4.1

Karsa 1 年之前
父節點
當前提交
e8e06efc8a
共有 66 個文件被更改,包括 4825 次插入1419 次删除
  1. 338 1
      src/api/modules/chartRelevanceApi.js
  2. 10 0
      src/api/modules/pptApi.js
  3. 10 0
      src/api/modules/pptEnApi.js
  4. 二進制
      src/assets/img/icons/ai_Company.png
  5. 二進制
      src/assets/img/icons/ai_avatar.png
  6. 二進制
      src/assets/img/icons/gpt-4-turbo.png
  7. 二進制
      src/assets/img/icons/gpt-4.png
  8. 22 10
      src/components/chart/chartDetailHandlesWrap.vue
  9. 7 3
      src/components/chart/chartListWrap.vue
  10. 21 7
      src/routes/modules/chartRoutes.js
  11. 18 0
      src/utils/buttonConfig.js
  12. 11 1
      src/views/Home.vue
  13. 24 0
      src/views/chartRelevance_manage/components/explainText.js
  14. 670 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue
  15. 208 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/chartFormSection.vue
  16. 140 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/edbTableSection.vue
  17. 182 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/tagRelationDialog.vue
  18. 203 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/tagSetDialog.vue
  19. 570 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/list.vue
  20. 1 1
      src/views/chartRelevance_manage/css/index.scss
  21. 4 4
      src/views/chartRelevance_manage/fittingEquation/fittingEquationChartEditor.vue
  22. 3 3
      src/views/chartRelevance_manage/fittingEquation/fittingEquationList.vue
  23. 35 21
      src/views/chartRelevance_manage/mixins/classifyMixin.js
  24. 4 4
      src/views/chartRelevance_manage/relevance/list.vue
  25. 5 5
      src/views/chartRelevance_manage/relevance/relevanceChartEditor.vue
  26. 5 5
      src/views/chartRelevance_manage/statistic/statisticFeatureChartEditor.vue
  27. 3 3
      src/views/chartRelevance_manage/statistic/statisticFeatureList.vue
  28. 2 1
      src/views/dataEntry_manage/addChart.vue
  29. 8 2
      src/views/dataEntry_manage/components/LegendEditDia.vue
  30. 8 2
      src/views/dataEntry_manage/components/SaveChartOther.vue
  31. 46 12
      src/views/dataEntry_manage/components/setEnNameDia.vue
  32. 97 104
      src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue
  33. 46 0
      src/views/dataEntry_manage/databaseComponents/util.js
  34. 2 1
      src/views/dataEntry_manage/editChart.vue
  35. 209 14
      src/views/dataEntry_manage/mixins/chartPublic.js
  36. 15 2
      src/views/datasheet_manage/components/sheetClassifyDia.vue
  37. 1 0
      src/views/datasheet_manage/components/sheetListWrap.vue
  38. 15 1
      src/views/mychart_manage/components/chartDetailDia.vue
  39. 21 20
      src/views/mychart_manage/components/chooseChart.vue
  40. 54 21
      src/views/operation_manage/AIQA/AIQA.vue
  41. 6 4
      src/views/operation_manage/AIQA/components/messageItem.vue
  42. 2 3
      src/views/operation_manage/AIQA/components/newWindowHint.vue
  43. 1 1
      src/views/operation_manage/AIQA/components/windowListItem.vue
  44. 116 1
      src/views/ppt_manage/mixins/mixins.js
  45. 107 18
      src/views/ppt_manage/mixins/pptMixins.js
  46. 1 0
      src/views/ppt_manage/newVersion/components/catalog/pptContent.vue
  47. 1 0
      src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue
  48. 22 2
      src/views/ppt_manage/newVersion/pptCatalog.vue
  49. 10 12
      src/views/ppt_manage/newVersion/pptEditor.vue
  50. 22 2
      src/views/ppt_manage/newVersion/pptEnCatalog.vue
  51. 23 12
      src/views/ppt_manage/newVersion/pptEnEditor.vue
  52. 1 0
      src/views/report_manage/addreportNew.vue
  53. 3 0
      src/views/report_manage/editChapterReport.vue
  54. 1 0
      src/views/report_manage/editreportNew.vue
  55. 71 13
      src/views/report_manage/mixins/reportMixin.js
  56. 1 0
      src/views/report_manage/reportEn/reportEditor.vue
  57. 1 6
      src/views/sandbox_manage/common/edge.js
  58. 36 78
      src/views/sandbox_manage/common/events.js
  59. 3 5
      src/views/sandbox_manage/common/gragh.js
  60. 223 108
      src/views/sandbox_manage/common/mindmap.js
  61. 1 12
      src/views/sandbox_manage/common/node.js
  62. 158 274
      src/views/sandbox_manage/index_new_version.vue
  63. 649 0
      src/views/sandbox_manage/sandFlowNew/components/addLInkDia.vue
  64. 339 617
      src/views/sandbox_manage/sandFlowNew/index.vue
  65. 7 0
      src/views/smartReport/components/StatisticAnalysis.vue
  66. 2 3
      src/vuex/modules/sand.js

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

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

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


二進制
src/assets/img/icons/ai_avatar.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]

+ 7 - 3
src/components/chart/chartListWrap.vue

@@ -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)

+ 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: "跨品种分析",
+				}
+			},
 		]
 	},
 

+ 18 - 0
src/utils/buttonConfig.js

@@ -513,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',
 }
 /*
  * --------------------------------------------------------------------------供应分析------------------------------------------------

+ 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=>{

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

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

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

@@ -136,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 {

+ 4 - 4
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: {

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

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

@@ -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>

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

@@ -373,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: {

+ 5 - 5
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: {

+ 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

@@ -172,6 +172,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" />
@@ -881,7 +882,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;

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

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

+ 97 - 104
src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue

@@ -15,8 +15,8 @@
 							<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" @change="changeDatabase"
-							:disabled="haveResult" v-if="fromType=='wind'">
+						<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>
@@ -26,32 +26,34 @@
 						<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="!(this.fromType=='wind' && this.fromDatabase=='1')"
+					<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="this.fromType=='wind' && this.fromDatabase=='1'">
+				<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-code-row">
-							<div class="wsd-code-item" v-for="item in securityCode" :key="item">
-								<div class="wsd-code-item-text">{{ item }}</div>
-								<img src="~@/assets/img/icons/close_icon_black.png" @click="deleteCode('security',item)" />
-							</div>
-						</div> -->
 						<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">Wind金融终端输入“CG”会弹出代码生成器,可在代码生成器上获取其他指标的代码</div>
+							<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('index',item)" />
+								<img src="~@/assets/img/icons/close_icon_black.png" @click="deleteCode(item)" />
 							</div>
 						</div>
 					</div>
@@ -110,7 +112,8 @@
                 <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">
+                <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"
@@ -172,8 +175,8 @@
 			<div class="check-fail-box">
 				<div>
 					<div style="margin-bottom: 20px;">指标库中已存在以下指标,请勿重新输入!</div>
-					<div v-for="(item,index) in existIndexList">
-						{{ index+1+'、'+item }}
+					<div v-for="(item,index) in existIndexList" class="exist-index-item" @click="existIndexClick(item)">
+						{{ index+1+'、'+item.text }}
 					</div>
 				</div>
 				<div class="check-fail-button">
@@ -186,7 +189,7 @@
 
 <script>
 import { dataBaseInterface,dataInterence } from '@/api/api.js'
-import { fromArr, fromCode ,frequencyArr} from './util';
+import { fromArr, fromCode ,frequencyArr,windCommonIndexCodeArr,THSCommonIndexStockCodeArr,THSCommonIndexFuturesCodeArr} from './util';
 export default {
 	name: '',
 	props: {
@@ -196,33 +199,44 @@ export default {
 	},
 	computed:{
 		isCodeComplete(){
-			// return this.securityCode.length>0 && (this.indexCode.length>0 || this.indexCodeSelected.length>0)
 			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:[],
-			indexCodeArr:[
-				{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:"持仓额"},
-			], // 常用的指标代码
 			databaseType:[
 				{value:'0',label:'经济数据库'},
 				{value:'1',label:'日期序列'}
@@ -255,35 +269,9 @@ export default {
 			isCompanyCode: false,
 			search_company_txt: '',
 			securityCodeText:"",
-			// securityCode:[],
 			indexCodeText:'',
 			indexCode:[],
-			edbIndexDatas:[
-				// {Source:1,Catalogue:'',Unit:"",Frequency:'日度',SecName:'CU2403收盘价',SecurityCode:'CU2403.SHF',IndexCode:'close',
-				// DataList:[{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"}]},
-				// {Catalogue:'',Unit:"",Frequency:'日度',SecName:'CU2403收盘价',SecurityCode:'CU2403.SHF',IndexCode:'close',
-				// DataList:[{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"}]},
-				// {Catalogue:'',Unit:"",Frequency:'日度',SecName:'CU2403收盘价',SecurityCode:'CU2403.SHF',IndexCode:'close',
-				// DataList:[{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"}]},
-				// {Catalogue:'',Unit:"",Frequency:'日度',SecName:'CU2403收盘价',SecurityCode:'CU2403.SHF',IndexCode:'close',
-				// DataList:[{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"}]},
-				// {Catalogue:'',Unit:"",Frequency:'日度',SecName:'CU2403收盘价',SecurityCode:'CU2403.SHF',IndexCode:'close',
-				// DataList:[{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"}]},
-				// {Catalogue:'',Unit:"",Frequency:'日度',SecName:'CU2403收盘价',SecurityCode:'CU2403.SHF',IndexCode:'close',
-				// DataList:[{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},
-				// {Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"},{Close: "632107.0000",Dt: "2023-09-07"}]}
-			],
+			edbIndexDatas:[],
 			edbTableHeadKey: [
         "ClassifyId",
         "Unit",
@@ -306,7 +294,14 @@ export default {
 			frequencyArr,
 			checkFailShow:false,
 			existIndexList:[],
-			isLoadingData:false
+			isLoadingData:false,
+			highLightIndex:[],
+			// 同花顺常用指标类型
+			THSIndexCodeType:1,
+			THSIndexCodeTypeArr:[
+				{value:1,label:"期货常用指标"},
+				{value:2,label:"股票常用指标"}
+			]
 		};
 	},
 	watch:{
@@ -322,7 +317,6 @@ export default {
 		init() {
 			this.fromType = 'wind'
 			this.fromDatabase='0'
-			this.wsdAddStep=1
 			this.status = ''
 			this.tableData = []
 			this.dataList = []
@@ -330,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() {
@@ -434,18 +434,18 @@ export default {
 				this.isCompanyCode = false;
 			}
 			if(this.fromDatabase=='1'){
-				this.changeDatabase('0')
+				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();
 		},
-		changeDatabase(e){
-			this.fromDatabase=e
-			this.securityCodeText=""
-			// this.securityCode=[]
-			this.indexCodeText=''
-			this.indexCode=[]
+		THSIndexCodeTypeChange(){
 			this.indexCodeSelected=[]
 		},
 		getTargetSource(){
@@ -466,18 +466,6 @@ export default {
 		codeInputBlur(type){
 			if(type == 'security'){
 				this.securityCodeText=this.securityCodeText.replaceAll(' ','')
-				// if(!this.securityCodeText) return  
-				// if(!(this.securityCode.length<5)){
-				// 	this.$message.warning('证券代码一次最多输入5个')
-				// 	this.securityCodeText=''
-				// 	return
-				// }
-				// this.securityCode=Array.from(new Set([...this.securityCode,...this.securityCodeText.split(',')])).filter(Boolean)
-				// if(this.securityCode.length>5){
-				// 	this.securityCode = this.securityCode.slice(0,5)
-				// 	this.$message.warning('证券代码一次最多输入5个')
-				// }
-				// this.securityCodeText=''
 			}else if(type == 'index'){
 				if(!this.indexCodeText) return  
 				this.indexCodeText=this.indexCodeText.replaceAll(' ','')
@@ -487,12 +475,8 @@ export default {
 			}
 
 		},
-		deleteCode(type,code){
-			if(type == 'security'){
-				// this.securityCode = this.securityCode.filter(it => it!=code)
-			}else if(type == 'index'){
-				this.indexCode = this.indexCode.filter(it => it!=code)
-			}
+		deleteCode(code){
+			this.indexCode = this.indexCode.filter(it => it!=code)
 		},
 		/* 获取目录结构 */
 		getMenu() {
@@ -535,28 +519,21 @@ export default {
 						Source:Number(this.fromCode.get(this.fromType)),
 						SubSource:this.fromDatabase,
 						EdbCode:Array.from(new Set([...this.indexCode,...this.indexCodeSelected])).join(','),
-						// StockCode:this.securityCode.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 ExistEdbCodeArr=res.Data.ExistEdbCodeArr
-								// let ExistStockCodeArr=res.Data.ExistStockCodeArr
+								let existEdbInfo=res.Data.ExistEdbInfo || []
 								let text=''
-								// ExistStockCodeArr.map(item =>{
-									Array.from(new Set(ExistEdbCodeArr)).map(item1 =>{
-										let isCommon = this.indexCodeArr.find(it => it.value == item1)
-										if(isCommon){
-											text=`${this.securityCodeText}${isCommon.label}(wsd${this.securityCodeText}${isCommon.value})`
-										}else{
-											text=`${this.securityCodeText}${item1}(wsd${this.securityCodeText}${item1})`
-										}
-										this.existIndexList.push(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{
 								// 没有重复
@@ -614,6 +591,10 @@ export default {
 				}
 			},50)
 		},
+		existIndexClick({code,id,classifyId}){
+			const { href } = this.$router.resolve({ path: '/database',query:{code,id,classifyId}});
+			window.open(href, '_blank');
+		},
 		wsdPrevHandle(){
 			this.wsdAddStep=1
 		},
@@ -638,6 +619,8 @@ export default {
 					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 || []:[]
 				}
 			})
 		}
@@ -695,7 +678,7 @@ export default {
 		.wsd-index-code{
 			display: flex;
 			align-items: center;
-			margin-bottom: 15px;
+			margin-bottom: 20px;
 			.index-code-hint{
 				color: #C0C4CC;
 				font-size: 15px;
@@ -728,7 +711,8 @@ export default {
 			}
 		}
 		.wsd-index-input{
-			width: 400px;
+			min-width: 400px;
+			width:400px;
 			margin-right: 10px;
 		}
 	}
@@ -806,10 +790,19 @@ export default {
       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;

+ 46 - 0
src/views/dataEntry_manage/databaseComponents/util.js

@@ -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:"持仓量"},
+]

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

@@ -173,6 +173,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" />
@@ -951,7 +952,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;

+ 209 - 14
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
         });
@@ -1259,7 +1334,7 @@ export const chartSetMixin = {
         tooltip
       }
 
-      this.currentLang==='en' && this.changeCommodityOptions();
+      this.currentLang==='en' && this.changeCommodityLang();
     },
 
     /* 处理无效数据为null */
@@ -1437,7 +1512,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轴
@@ -1686,6 +1761,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 =
@@ -1979,12 +2171,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) {

+ 15 - 2
src/views/datasheet_manage/components/sheetClassifyDia.vue

@@ -40,7 +40,7 @@
 import * as sheetInterface from '@/api/modules/sheetApi.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: {
 		isOpenDialog: {
@@ -88,7 +88,8 @@ export default {
 				'/commordityChartBase': this.commodityClassifyApi,
 				'/chartrelevance':this.relevanceClassifyApi,
 				'/fittingEquationList': this.fittingEquationClassifyApi,
-				'/statisticFeatureList': this.statisticFeatureClassifyApi
+				'/statisticFeatureList': this.statisticFeatureClassifyApi,
+				'/crossVarietyChartList': this.crossVarietyClassifyApi
 			}
 			handleMap[this.$route.path] && handleMap[this.$route.path](classify_name,classify_id)
 		},
@@ -153,6 +154,18 @@ export default {
 			this.$emit('successCallback')
 		},
 
+		/* 跨品种分析 */
+		async crossVarietyClassifyApi(classify_name,classify_id){
+			const { Ret,Msg } = !classify_id
+				? await crossVarietyInterface.classifyAdd({ ChartClassifyName:classify_name })
+				: await crossVarietyInterface.classifyEdit({ ChartClassifyName:classify_name, ChartClassifyId:classify_id  })
+				
+			if( Ret !== 200) return
+			this.$message.success(Msg);
+			this.cancelHandle();
+			this.$emit('successCallback')
+		},
+
 		/* 取消 */
 		cancelHandle() {
       this.formData = {}

+ 1 - 0
src/views/datasheet_manage/components/sheetListWrap.vue

@@ -59,6 +59,7 @@ export default {
 </script>
 <style scoped lang='scss'>
   .sheet-list-cont {
+    width: 100%;
     color: #333;
     .el-card .el-card__header,
     .el-card__body {

+ 15 - 1
src/views/mychart_manage/components/chartDetailDia.vue

@@ -122,7 +122,7 @@
               class="span-item"
               style="margin-left: 7px"
               @click="saveChartMapHandle"
-              v-if="![3,4,6,7,8,9].includes(chartInfo.Source)"
+              v-if="[1,2,5].includes(chartInfo.Source)"
             >
               <span> <i class="el-icon-collection" />&nbsp;保存 </span>
             </span>
@@ -750,6 +750,16 @@ export default {
             this.tableData = res.Data.EdbInfoList;
             this.statisticFrequencyData = res.Data.DataResp;
             this.setStatisticFrequency();
+          }else if(this.chartInfo.Source===10) { //跨品种分析
+            this.tableData = res.Data.EdbInfoList;
+            this.crossVarietyChartData = res.Data.DataResp;
+            this.chartLimit = {
+              min: Number(res.Data.DataResp.YMinValue),
+              max: Number(res.Data.DataResp.YMaxValue),
+              x_min: Number(res.Data.DataResp.XMinValue),
+              x_max: Number(res.Data.DataResp.XMaxValue)
+            }
+            this.setCrossVarietyChart();
           }
         });
     },
@@ -900,6 +910,8 @@ export default {
         res=await fittingEquationInterface.refreshChart({ ChartInfoId })
       }else if([7,8,9].includes(Source)) {
         res=await statisticFeatureInterface.refreshChart({ ChartInfoId })
+      }else if(Source===10) {
+        res=await crossVarietyInterface.refreshChart({ ChartInfoId })
       }
      
         this.refreshLoading = false;
@@ -1309,6 +1321,8 @@ export default {
         path='/fittingEquationChartEditor'
       }else if([7,8,9].includes(this.chartInfo.Source)) {
         path='/statisticFeatureChartEditor'
+      }else if(this.chartInfo.Source===10) {
+        path='/crossVarietyChartEditor'
       }
 
 

+ 21 - 20
src/views/mychart_manage/components/chooseChart.vue

@@ -36,6 +36,7 @@
 						<el-radio :label="3">相关性图表</el-radio>
 						<el-radio :label="6">拟合方程曲线</el-radio>
 						<el-radio :label="7">统计特征</el-radio>
+						<el-radio :label="10">跨品种分析</el-radio>
 					</el-radio-group>
           <el-checkbox v-model="isShowMe"  @change="searchHandle">只看我的</el-checkbox>
         </div>
@@ -96,7 +97,7 @@
 import { mychartInterface } from '@/api/api.js';
 import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyDia';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
-import { fittingEquationInterface,statisticFeatureInterface } from '@/api/modules/chartRelevanceApi';
+import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
 import futuresInterface from '@/api/modules/futuresBaseApi';
 export default {
   components: {
@@ -140,26 +141,26 @@ export default {
         KeyWord: this.search_txt,
         IsShowMe: this.isShowMe
       };
-      let res=null 
-      if(this.chart_source===1){
-        res=await mychartInterface.publicList(params)
-      }else if(this.chart_source===2){
-				res=await futuresInterface.searchChart(params)
-			}else if(this.chart_source===3){
-        res=await chartRelevanceApi.getChartList(params)
-      }else if(this.chart_source===6) {
-        res=await fittingEquationInterface.getChartList(params)
-      }else if(this.chart_source===7) {
-        res=await statisticFeatureInterface.getChartList(params)
+
+      const apiMap = {
+        1: mychartInterface.publicList,
+        2: futuresInterface.searchChart,
+        3: chartRelevanceApi.getChartList,
+        6: fittingEquationInterface.getChartList,
+        7: statisticFeatureInterface.getChartList,
+        10: crossVarietyInterface.searchChart,
       }
-        if (res.Ret !== 200) return;
-        this.haveMove = res.Data ? this.page_no < res.Data.Paging.Pages : false;
-        this.chartPublicList = res.Data
-          ? this.page_no === 1
-            ? res.Data.List
-            : [...this.chartPublicList, ...res.Data.List]
-          : [];
-        this.haveData = this.chartPublicList.length ? true : false;
+      let res = await apiMap[this.chart_source](params)
+
+
+      if (res.Ret !== 200) return;
+      this.haveMove = res.Data ? this.page_no < res.Data.Paging.Pages : false;
+      this.chartPublicList = res.Data
+        ? this.page_no === 1
+          ? res.Data.List
+          : [...this.chartPublicList, ...res.Data.List]
+        : [];
+      this.haveData = this.chartPublicList.length ? true : false;
       
     },
 

+ 54 - 21
src/views/operation_manage/AIQA/AIQA.vue

@@ -3,10 +3,10 @@
         <div class="window-list-wrap">
             <div class="window-title">
                 <div class="title-wrap">
-                    <p style="color: #333333;font-size: 20px;font-weight: 600;">HORIZON INSIGHTS</p>
-                    <span style="color: #666666;font-size: 16px;">弘则研究AI问答小助手</span>
+                    <p class="text-ellipsis" style="color: #333333;font-size: 20px;font-weight: 600;">{{companyName}}</p>
+                    <span style="color: #666666;font-size: 16px;">研究AI问答小助手</span>
                 </div>
-                <div class="icon"><img src="~@/assets/img/icons/horizon.png" /></div>
+                <div class="icon"><img src="~@/assets/img/icons/ai_company.png"/></div>
             </div>
             <div class="add-btn" @click="handleAddNewWindow"><i class="el-icon-circle-plus-outline"></i>新建对话窗口</div>
             <div class="list-wrap hidden-scrollbar">
@@ -28,10 +28,10 @@
             <div class="content-header">
                 <div class="title-wrap">
                     <p>{{activeWindowId<=0?'新对话窗口':activeWindow.TopicName||''}}</p>
-                    <span>{{activeWindowId<=0?'弘则AI助手使用说明':`${historyList.length||0} messages`}}</span>
+                    <span>{{activeWindowId<=0?'AI助手使用说明':`${historyList.length||0} messages`}}</span>
                 </div>
                 <div class="select-box">
-                    <el-select v-model="model" :class="{'hint':showHint}" :disabled="isTyping||(windowContentLoading&&windowContentLoading.visible)" ref="modelSelect" 
+                    <!-- <el-select v-model="model" :class="{'hint':showHint}" :disabled="isTyping||(windowContentLoading&&windowContentLoading.visible)" ref="modelSelect" 
                         @click.native="selectClick"
                         @change="changeModel">
                         <el-option v-for="item in modelList" :key="item.label"
@@ -40,7 +40,7 @@
                             <span style="float:left">{{item.label}}</span>
                             <span style="float:right"><img :src="item.icon" style="margin-top:5px;width:24px;height:24px;"/></span>
                         </el-option>
-                    </el-select>
+                    </el-select> -->
                 </div>
             </div>
             <!-- 仅这一部分滚动 -->
@@ -74,6 +74,7 @@ import NewWindowHint from './components/newWindowHint.vue';
 import WindowListItem from './components/windowListItem';
 /* api */
 import {aiQAInterence} from '@/api/modules/aiApi.js'; 
+import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
 export default {
     components: { WindowListItem,NewWindowHint, MessageItem },
     data() {
@@ -86,17 +87,25 @@ export default {
             /* window-content*/
             historyList:[],//当前窗口历史记录
             inputText:'',
-            model:'',//当前选择的模型
+            model:'GPT-4 Turbo',//当前选择的模型
             modelOldValue:'',
             modelList:[
                 {
-                    label:'gpt-3.5-turbo',
-                    icon:require('@/assets/img/icons/chat-gpt.png'),
+                    label:'GPT-4 Turbo',
+                    icon:require('@/assets/img/icons/gpt-4-turbo.png'),
+                },
+                {
+                    label:'GPT4',
+                    icon:require('@/assets/img/icons/gpt-4.png'),
                 },
                 {
                     label:'gpt-3.5-turbo-16k',
                     icon:require('@/assets/img/icons/chat-gpt-16k.png'),
                 },
+                {
+                    label:'gpt-3.5-turbo',
+                    icon:require('@/assets/img/icons/chat-gpt.png'),
+                },
                 {
                     label:'eta',
                     icon:require('@/assets/img/icons/horizon.png'),
@@ -105,6 +114,8 @@ export default {
             showHint:false,//选择模型提示
             isTyping:false,//是否处于打字动画中
             windowContentLoading:null,
+            answerLoading:false,//回答中
+            companyName:'',
         };
     },
     watch:{
@@ -153,7 +164,7 @@ export default {
                 this.historyList = List||[]
                 this.windowContentLoading&&this.windowContentLoading.close()
                 //使用模型
-                this.model = this.historyList.length?this.historyList[this.historyList.length-1].Model:''
+                this.model = this.historyList.length?this.historyList[this.historyList.length-1].Model:'GPT-4 Turbo'
                 //如果有历史记录,则滚动到底部
                 this.$nextTick(()=>{
                     const windowContentWrap = document.querySelector('.window-content-wrap')
@@ -199,7 +210,7 @@ export default {
             this.activeWindowId=0
             this.activeWindow=null
             this.historyList=[]
-            this.model=''
+            this.model='GPT-4 Turbo'
             //this.inputText=''
             this.isTyping = false
         },
@@ -285,23 +296,24 @@ export default {
                 this.inputText+='\n'
                 return
             }
-            if(this.isTyping){
+            if(this.isTyping||this.answerLoading){
                 this.$message.warning('请等待回答完成')
                 return
             }
             //新建窗口,未选择模型
-            if(this.activeWindowId===0&&this.model===''){
-                this.showHint = true
-                this.$message.error('请选择模型')
-                this.$nextTick(()=>{
-                    this.$refs.modelSelect.focus()
-                })
-                return
-            }
+            // if(this.activeWindowId===0&&this.model===''){
+            //     this.showHint = true
+            //     this.$message.error('请选择模型')
+            //     this.$nextTick(()=>{
+            //         this.$refs.modelSelect.focus()
+            //     })
+            //     return
+            // }
             if(this.inputText.length===0){
                 this.$message.warning('请输入提问')
                 return
             }
+            this.answerLoading=true
             this.activeWindowId===0&&(this.activeWindowId = -1)
             //this.activeWindowId!==0&&this.getWindowDetail()
             //mock 加入到historyList中
@@ -329,8 +341,9 @@ export default {
             aiQAInterence.sendChatMsg({
                 AiChatTopicId:this.activeWindowId<=0?0:this.activeWindowId,
                 Ask:inputText,
-                Model:this.model
+                // Model:this.model
             }).then(res=>{
+                this.answerLoading=false
                 //在回答未获取前切换了新窗口
                 if(this.historyList.length===0){
                     this.getWindowList()
@@ -365,6 +378,8 @@ export default {
                 msg.Model = Model
                 msg.isPlay = true
                 this.historyList.splice(this.historyList.length-1,1,msg)
+            }).catch(()=>{
+                this.answerLoading=false
             })
         },
         //获取窗口列表
@@ -378,10 +393,19 @@ export default {
                 this.windowList = res.Data.List||[]
                 this.listWrapLoading&&this.listWrapLoading.close()
             })
+        },
+
+        getBaseConfig(){
+            etaBaseConfigInterence.getBaseConfig().then(res=>{
+                if(res.Ret===200){
+                    this.companyName=res.Data.CompanyName||''
+                }
+            })
         }
     },
     mounted(){
         this.getWindowList()
+        this.getBaseConfig()
     }
 };
 </script>
@@ -422,10 +446,19 @@ $border-color:#3D52A1;
             display: flex;
             justify-content: space-between;
             align-items: center;
+            // overflow: hidden;
             .icon img{
                 width:58px;
                 height:58px;
             }
+            .title-wrap{
+                overflow: hidden;
+            }
+            .text-ellipsis{
+                overflow: hidden;
+                white-space: nowrap;
+                text-overflow: ellipsis;
+            }
         }
         .add-btn{
             border:2px dashed $border-color;

+ 6 - 4
src/views/operation_manage/AIQA/components/messageItem.vue

@@ -28,10 +28,12 @@ export default {
     data() {
         return {
             iconMap:{
-                'user':require('@/assets/img/set_m/user_img.png'),
+                'user':require('@/assets/img/icons/ai_avatar.png'),
                 'gpt-3.5-turbo':require('@/assets/img/icons/chat-gpt.png'),
                 'gpt-3.5-turbo-16k':require('@/assets/img/icons/chat-gpt-16k.png'),
-                'eta':require('@/assets/img/icons/horizon.png')
+                'eta':require('@/assets/img/icons/horizon.png'),
+                'GPT4':require('@/assets/img/icons/gpt-4.png'),
+                'GPT-4 Turbo':require('@/assets/img/icons/gpt-4-turbo.png'),
             },
             isPlay:false,//是否播放动画
             typingText:'',
@@ -51,13 +53,13 @@ export default {
     computed:{
         IconSrc(){
             const {messageType,modelName} = this.messageInfo
-            const iconType = messageType==='question'?'user':modelName
+            const iconType = messageType==='question'?'user':'GPT-4 Turbo'
             return this.iconMap[iconType]||''
         }
     },
     methods: {
         async playTyping(){
-            const writeText = (text,delay=150)=>{
+            const writeText = (text,delay=20)=>{
                 return new Promise((res,rej)=>{
                     setTimeout(()=>{
                         this.typingText+=text

+ 2 - 3
src/views/operation_manage/AIQA/components/newWindowHint.vue

@@ -1,9 +1,8 @@
 <template>
     <div class="new-window-hint-wrap">
         <p class="title">使用说明:</p>
-        <p>1、每账号每天最高50次问答。</p>
-        <p>2、在同一个对话窗口内提问,选择同一模型可联系上下文回答,切换模型后不支持。</p>
-        <p>3、历史问答默认用该对话窗口内第一个提问命名,可修改。</p>
+        <p>1、每账号每天最高500次问答。</p>
+        <p>2、历史问答默认用该对话窗口内第一个提问命名,可修改。</p>
     </div>
 </template>
 

+ 1 - 1
src/views/operation_manage/AIQA/components/windowListItem.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="list-item" :class="{'active':activeWindowId===item.AiChatTopicId}">
+    <div class="list-item" :class="[activeWindowId===item.AiChatTopicId?'active':'']">
         <template v-if="!isEdit">
             <p>{{item.TopicName}}</p>
             <!-- <span>6 messages </span> -->

+ 116 - 1
src/views/ppt_manage/mixins/mixins.js

@@ -72,7 +72,10 @@ export default {
       },
 
       /* 统计频率图 */
-      statisticFrequencyData: {}
+      statisticFrequencyData: {},
+
+      /* 跨品种分析图 */
+      crossVarietyChartData: {}
     }
   },
   methods: {
@@ -1231,6 +1234,118 @@ export default {
       }
     },
 
+     /* 跨品种分析 */
+     setCrossVarietyChart() {
+      
+      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.dataList;
+      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
+      }
+    },
+
     /* 查询范围为1年内 x轴显示为月/日 否则默认年/月 */
     xTimeDiffer() {
       const end_date =

+ 107 - 18
src/views/ppt_manage/mixins/pptMixins.js

@@ -7,7 +7,7 @@ import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
 import {pptEnInterface} from '@/api/modules/pptEnApi.js';
 import * as sheetInterface from '@/api/modules/sheetApi.js';
 import futuresInterface from '@/api/modules/futuresBaseApi';
-import { fittingEquationInterface,statisticFeatureInterface } from '@/api/modules/chartRelevanceApi';
+import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi.js';
 import { defaultOpts } from '@/utils/defaultOptions';
 import {formatPPTDate,checkPPTpageElemant,getStrSize,isShowPPTTitle} from '../newVersion/utils/untils.js';
@@ -98,7 +98,8 @@ export default {
 			TemplateType,
       ReportId,
       ModifyTime,
-      PublishTime
+      PublishTime,
+      Editor
 		} = res.Data
       const pptDate = formatPPTDate(this.currentLang,PptDate)
       let legalContent = JSON.parse(Content)
@@ -118,13 +119,24 @@ export default {
 			},
       ReportId,
       ModifyTime,
-      PublishTime
+      PublishTime,Editor
 		}
       }else{
         this.result = {status:'',content:'获取ppt数据失败!'}
       }
     },
-    //ppt设置相关,引用mixins.js里的setOptions
+    //ppt设置相关,引用mixins.js里的setOptions chartType只有source是1才有用
+    /* Source 1 ; chartType 1曲线 2季节 3面积 4堆积柱 5散点 6组合 7柱形 8截面散点
+    * 2 商品价格
+    * 3 相关性
+    * 4 滚动相关性
+    * 5 商品利润
+    * 6 拟合方程
+    * 7 统计特征/标准差
+    * 8 统计特征/百分位
+    * 9 统计特征/频率
+    * 10 跨品种分析
+    */
     //获取图表数据
     async getchartData(id,lang='ch') {
       const currentLang = this.currentLang || lang
@@ -187,6 +199,17 @@ export default {
         this.dataList = res.Data.EdbInfoList;
         this.statisticFrequencyData = res.Data.DataResp;
         this.setStatisticFrequency();
+      }else if(this.chartInfo.Source===10) {
+        this.dataList = res.Data.EdbInfoList;
+        this.crossVarietyChartData = res.Data.DataResp;
+        this.chartLimit = {
+          min: Number(res.Data.DataResp.YMinValue),
+          max: Number(res.Data.DataResp.YMaxValue),
+          x_min: Number(res.Data.DataResp.XMinValue),
+          x_max: Number(res.Data.DataResp.XMaxValue)
+        }
+        this.setCrossVarietyChart();
+        this.changeRelevanceOptions();//更改英文一样
       }
 
       //根据图表数据获取配置项
@@ -299,16 +322,25 @@ export default {
       if(!this.chartInfo.ChartNameEn){
         result = false
       }
-      //指标名称:this.dataList[].EdbNameEn
-      //指标单位:this.dataList[].UnitEn
-      this.dataList.forEach(item=>{
-        if(!item.EdbNameEn){
-          result = false
-        }
-        if(this.chartInfo.ChartType!==10&&item.Unit&&!item.UnitEn){
-          result = false
-        }
-      })
+
+      if(this.chartInfo.Source === 10) {
+        const { XNameEn,YNameEn,DataList } = this.crossVarietyChartData;
+
+        let haveOneNoEn = DataList.some(_ =>!_.NameEn);
+
+        if(haveOneNoEn || !XNameEn || !YNameEn) result = false
+      }else {
+        //指标名称:this.dataList[].EdbNameEn
+        //指标单位:this.dataList[].UnitEn
+        this.dataList.forEach(item=>{
+          if(!item.EdbNameEn){
+            result = false
+          }
+          if(this.chartInfo.ChartType!==10&&item.Unit&&!item.UnitEn){
+            result = false
+          }
+        })
+      }
       return result
     },
     //刷新图表数据
@@ -608,6 +640,7 @@ export default {
         value:chartInfo.ChartName,
         key:'ChartName',
         id:chartInfo.ChartInfoId,
+        source: chartInfo.Source,
         notEdit:true
       },
       {
@@ -617,7 +650,7 @@ export default {
         id:chartInfo.ChartInfoId,
         placeholder:'请输入英文图表名称'
       })
-      if(![3,6,7,8,9].includes(chartInfo.Source)){
+      if([1,2,5].includes(chartInfo.Source)){
         this.formItemArray.chartsList = tableData.map(item => {
           return item.Unit 
             ? [
@@ -688,7 +721,7 @@ export default {
       }
 
       //利润曲线
-      if(chartInfo.Source===5) {
+      else if(chartInfo.Source===5) {
         this.formItemArray.chartInfo.push({
           label:'盘面利润名称',
           value:Data.DataResp.ProfitName,
@@ -704,6 +737,60 @@ export default {
           placeholder:'请输入英文盘面利润名称'
         })
       }
+
+      //跨品种分析
+      else if(chartInfo.Source===10) {
+        let res = await crossVarietyInterface.chartLangOption({ChartInfoId: chartInfo.ChartInfoId})
+
+        const { TagList,VarietyList } = res.Data;
+
+        this.formItemArray.chartInfo.push({
+          label:'X轴名称',
+          value:Data.DataResp.XName,
+          key:'XName',
+          id:TagList[0].ChartTagId,
+          notEdit:true
+        },
+        {
+          label:'英文X轴名称',
+          value:Data.DataResp.XNameEn,
+          key:'XNameEn',
+          id:TagList[0].ChartTagId,
+          placeholder:'请输入英文X轴名称'
+        },{
+          label:'Y轴名称',
+          value:Data.DataResp.YName,
+          key:'YName',
+          id:TagList[1].ChartTagId,
+          notEdit:true
+        },
+        {
+          label:'英文Y轴名称',
+          value:Data.DataResp.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
 		},
@@ -727,16 +814,18 @@ export default {
           ChartInfoId: enNameData.ChartInfoId,
           ChartNameEn: enNameData.ChartNameEn
         })
-      }else if(this.chartInfo.Source===6){//拟合方程
+      }else if(this.chart_source===6){//拟合方程
         res=await fittingEquationInterface.editChartEn({
           ChartInfoId: enNameData.ChartInfoId,
           ChartNameEn: enNameData.ChartNameEn
         })
-      }else if(this.chartInfo.Source===7){//统计特征
+      }else if(this.chart_source===7){//统计特征
         res=await statisticFeatureInterface.editChartEn({
           ChartInfoId: enNameData.ChartInfoId,
           ChartNameEn: enNameData.ChartNameEn
         })
+      }else if(this.chart_source===10) {//跨品种分析
+        res=await crossVarietyInterface.editChartEn(enNameData)
       }
       
 			if(res.Ret !==200) return

+ 1 - 0
src/views/ppt_manage/newVersion/components/catalog/pptContent.vue

@@ -173,6 +173,7 @@ export default {
           this.firstPage.BackIndex = FirstPage.TemplateType-1
           this.firstPage.imgLocalUrl = this.bgList[FirstPage.TemplateType-1]
           this.pptTime = this.pptItem.PptxUrl?PublishTime:ModifyTime
+          this.$emit('resetToolList',this.result)
         }else{
           this.$message.error('获取ppt数据失败!')
           this.dataLoading.close();

+ 1 - 0
src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue

@@ -168,6 +168,7 @@ export default {
           this.firstPage.BackIndex = FirstPage.TemplateType-1
           this.firstPage.imgLocalUrl = pptCoverEn[FirstPage.TemplateType-1]
           this.pptTime = this.pptItem.PptxUrl?PublishTime:ModifyTime
+          this.$emit('resetToolList',this.result)
         }else{
           this.$message.error('获取ppt数据失败!')
           this.dataLoading.close();

+ 22 - 2
src/views/ppt_manage/newVersion/pptCatalog.vue

@@ -240,6 +240,7 @@
             :pptItem="pptItem"
             :key="pptItem.PptId"
             @isLegal="handleIsLegal"
+            @resetToolList="setToolList"
           ></ppt-content>
           <ppt-content-old 
             v-else
@@ -545,7 +546,7 @@ export default {
       }
     },
     //设置操作按钮
-    setToolList(){
+    setToolList(pptDetail={}){
       //公共目录:显示除 删除, 编辑 外的全部按钮
       if(this.treeName==='public'){
         this.pptToolList = toolList.filter((i)=>{
@@ -592,6 +593,16 @@ export default {
       this.pptToolList = this.pptToolList.filter((i)=>{
           return authArr.includes(i.key)
         })
+      //若有人在编辑,则显示编辑中
+      if(this.pptToolList.find(i=>i.key==='edit')){
+        const {Editor={}} = pptDetail
+        const labelName = Editor.IsEditing?`${Editor.Editor}编辑中...`:'编辑'
+        this.pptToolList.map(i=>{
+            if(i.key==='edit'){
+                i.label = labelName
+            }
+        })
+      }
     },
     //判断公共目录按钮是否显示
     checkNode(data){
@@ -722,7 +733,7 @@ export default {
       })
     },
     //点击操作栏事件处理
-    handleToolClick(item){
+    async handleToolClick(item){
       const urlMap = {
         edit:`/ppteditor?id=${this.pptItem.PptId}`,
         publish:`/pptpublish?id=${this.pptItem.PptId}`,
@@ -732,6 +743,15 @@ export default {
       if(urlMap[item.key]){
         if(this.pptItem.PptVersion===2){
           if(!this.pptItem.overLimit||item.key!=='publish'){
+            if(item.key==='edit'){
+                if(item.label.length>2){
+                    this.$message.warning("他人正在编辑中,不可重复编辑")
+                    return
+                }
+                //调接口加锁然后跳转
+                const res = await pptInterface.pptEditLock({PptId:Number(this.pptItem.PptId),Status:1})
+                if(res.Ret!==200) return
+            }
             window.open(urlMap[item.key],'_blank');
           }else if(item.key==='publish'){
             //this.$message.warning('该PPT页数超过60页或图表数量超过100张,无法发布,请修改后重试')

+ 10 - 12
src/views/ppt_manage/newVersion/pptEditor.vue

@@ -129,6 +129,7 @@
                   <el-radio :label="3" style="margin-bottom:5px">相关性图表</el-radio>
                   <el-radio :label="6" style="margin-bottom:5px">拟合方程曲线</el-radio>
                   <el-radio :label="7" style="margin-bottom:5px">统计特征</el-radio>
+                  <el-radio :label="10">跨品种分析</el-radio>
                 </el-radio-group>
                 <div style="margin: 10px 0">
                   <el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}">只看我的</el-checkbox>
@@ -270,7 +271,7 @@ import {modelInfo,defaultPosition} from './utils/config'
 import { dataBaseInterface ,sandInterface } from "@/api/api.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';
 import pptmixin from '../mixins/pptMixins';
 import {uploadFileDirect} from "@/utils/common.js"
 import mixins from '../mixins/mixins';
@@ -735,18 +736,15 @@ export default {
         PageSize: this.search_page_sizes,
         IsShowMe: this.isShowMe
       }
-      let res=null
-      if(this.chart_source === 1){
-        res=await dataBaseInterface.chartSearchByEs(params)
-      }else if(this.chart_source === 2){
-        res=await futuresInterface.searchChart(params)
-      }else if(this.chart_source === 3){
-        res=await chartRelevanceApi.searchChart(params)
-      }else if(this.chart_source === 6){
-        res=await fittingEquationInterface.searchChart(params)
-      }else if(this.chart_source === 7){
-        res=await statisticFeatureInterface.searchChart(params)
+      const apiMap = {
+        1: dataBaseInterface.chartSearchByEs,
+        2: futuresInterface.searchChart,
+        3: chartRelevanceApi.searchChart,
+        6: fittingEquationInterface.searchChart,
+        7: statisticFeatureInterface.searchChart,
+        10: crossVarietyInterface.searchChart,
       }
+      let res = await apiMap[this.chart_source](params)
 
       if (res.Ret !== 200) return;
       res.Data.List = res.Data.List || [];

+ 22 - 2
src/views/ppt_manage/newVersion/pptEnCatalog.vue

@@ -234,6 +234,7 @@
             :pptItem="pptItem"
             :key="pptItem.PptId"
             @isLegal="handleIsLegal"
+            @resetToolList="setToolList"
           ></ppt-content>
         </div>
         <div class="tool-side ppt-page-wrap">
@@ -518,7 +519,7 @@ export default {
       }
     },
     //设置操作按钮
-    setToolList(){
+    setToolList(pptDetail={}){
       //公共目录:显示除 删除, 编辑 外的全部按钮
       if(this.treeName==='public'){
         this.pptToolList = toolList.filter((i)=>{
@@ -560,6 +561,16 @@ export default {
       this.pptToolList = this.pptToolList.filter((i)=>{
           return authArr.includes(i.key)
         })
+      //若有人在编辑,则显示编辑中
+      if(this.pptToolList.find(i=>i.key==='edit')){
+        const {Editor={}} = pptDetail
+        const labelName = Editor.IsEditing?`${Editor.Editor}编辑中...`:'编辑'
+        this.pptToolList.map(i=>{
+            if(i.key==='edit'){
+                i.label = labelName
+            }
+        })
+      }  
 
     },
     //判断公共目录按钮是否显示
@@ -688,7 +699,7 @@ export default {
       })
     },
     //点击操作栏事件处理
-    handleToolClick(item){
+    async handleToolClick(item){
       const urlMap = {
         edit:`/ppteneditor?id=${this.pptItem.PptId}`,
         publish:`/pptenpublish?id=${this.pptItem.PptId}`,
@@ -697,6 +708,15 @@ export default {
       //要跳转页面的:预览发布,编辑,演示
       if(urlMap[item.key]){
         if(!this.pptItem.overLimit||item.key!=='publish'){
+            if(item.key==='edit'){
+                if(item.label.length>2){
+                    this.$message.warning("他人正在编辑中,不可重复编辑")
+                    return
+                }
+                //调接口加锁然后跳转
+                const res = await pptEnInterface.pptEditLock({PptId:Number(this.pptItem.PptId),Status:1})
+                if(res.Ret!==200) return
+            }
           window.open(urlMap[item.key],'_blank');
         }else if(item.key==='publish'){
           if(!this.pptItem.overLimitHint.chartNum){

+ 23 - 12
src/views/ppt_manage/newVersion/pptEnEditor.vue

@@ -126,6 +126,7 @@
                   <el-radio :label="3" style="margin-bottom:5px">相关性图表</el-radio> 
                   <el-radio :label="6" style="margin-bottom:5px">拟合方程曲线</el-radio>
                   <el-radio :label="7" style="margin-bottom:5px">统计特征</el-radio>
+                  <el-radio :label="10">跨品种分析</el-radio>
                 </el-radio-group>
                 <div style="margin: 10px 0">
                   <el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}">只看我的</el-checkbox>
@@ -281,7 +282,7 @@ import {modelInfo,defaultPosition} from './utils/config'
 import { dataBaseInterface ,sandInterface } from "@/api/api.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';
 import pptmixin from '../mixins/pptMixins';
 import mixins from '../mixins/mixins';
 import layerMixins from '../mixins/layerMixins';
@@ -729,18 +730,28 @@ export default {
           PageSize: this.search_page_sizes,
           IsShowMe: this.isShowMe
         }
-        let res=null
-        if(this.chart_source === 1){
-          res=await dataBaseInterface.chartSearchByEs(params)
-        }else if(this.chart_source === 2){
-          res=await futuresInterface.searchChart(params)
-        }else if(this.chart_source === 3){
-          res=await chartRelevanceApi.searchChart(params)
-        }else if(this.chart_source === 6){
-          res=await fittingEquationInterface.searchChart(params)
-        }else if(this.chart_source === 7){
-          res=await statisticFeatureInterface.searchChart(params)
+        // let res=null
+        // if(this.chart_source === 1){
+        //   res=await dataBaseInterface.chartSearchByEs(params)
+        // }else if(this.chart_source === 2){
+        //   res=await futuresInterface.searchChart(params)
+        // }else if(this.chart_source === 3){
+        //   res=await chartRelevanceApi.searchChart(params)
+        // }else if(this.chart_source === 6){
+        //   res=await fittingEquationInterface.searchChart(params)
+        // }else if(this.chart_source === 7){
+        //   res=await statisticFeatureInterface.searchChart(params)
+        // }
+
+        const apiMap = {
+          1: dataBaseInterface.chartSearchByEs,
+          2: futuresInterface.searchChart,
+          3: chartRelevanceApi.searchChart,
+          6: fittingEquationInterface.searchChart,
+          7: statisticFeatureInterface.searchChart,
+          10: crossVarietyInterface.searchChart,
         }
+        let res = await apiMap[this.chart_source](params)
 
         if (res.Ret !== 200) return;
         res.Data.List = res.Data.List || [];

+ 1 - 0
src/views/report_manage/addreportNew.vue

@@ -197,6 +197,7 @@
 						<el-radio :label="3">相关性图表</el-radio>
 						<el-radio :label="6">拟合方程曲线</el-radio>
 						<el-radio :label="7">统计特征</el-radio>
+						<el-radio :label="10">跨品种分析</el-radio>
 					</el-radio-group>
 					<div style="margin: 10px 0">
 						<el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}">只看我的</el-checkbox>

+ 3 - 0
src/views/report_manage/editChapterReport.vue

@@ -178,6 +178,7 @@
             <el-radio :label="3">相关性图表</el-radio>
             <el-radio :label="6">拟合方程曲线</el-radio>
             <el-radio :label="7">统计特征</el-radio>
+            <el-radio :label="10">跨品种分析</el-radio>
           </el-radio-group>
           <div style="margin: 10px 0">
             <el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}">只看我的</el-checkbox>
@@ -357,6 +358,8 @@ export default {
       tabsactive: "基础信息",
       ticketList: [], //指标列表
       key_word: "",
+      newreportlist: [],
+
       // 沙盘插入 ----------start
       sandTabelQuery: {
         PageSize: 13,

+ 1 - 0
src/views/report_manage/editreportNew.vue

@@ -197,6 +197,7 @@
 						<el-radio :label="3">相关性图表</el-radio>
 						<el-radio :label="6">拟合方程曲线</el-radio>
 						<el-radio :label="7">统计特征</el-radio>
+						<el-radio :label="10">跨品种分析</el-radio>
 					</el-radio-group>
 					<div style="margin: 10px 0">
 						<el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}">只看我的</el-checkbox>

+ 71 - 13
src/views/report_manage/mixins/reportMixin.js

@@ -5,6 +5,7 @@ import chartRelevanceApi from "@/api/modules/chartRelevanceApi";
 import {
   fittingEquationInterface,
   statisticFeatureInterface,
+  crossVarietyInterface
 } from "@/api/modules/chartRelevanceApi";
 export default {
   watch:{
@@ -317,6 +318,7 @@ export default {
           value: chartInfo.ChartName,
           key: "ChartName",
           id: chartInfo.ChartInfoId,
+          source: chartInfo.Source,
           notEdit: true,
         },
         {
@@ -327,7 +329,7 @@ export default {
           placeholder: "请输入英文图表名称",
         }
       );
-      if (![3, 6, 7, 8, 9].includes(chartInfo.Source)) {
+      if ([1,2,5].includes(chartInfo.Source)) {
         this.formItemArray.chartsList = tableData.map((item) => {
           return item.Unit
             ? [
@@ -400,7 +402,7 @@ export default {
       }
 
       //利润曲线
-      if (chartInfo.Source === 5) {
+      else if (chartInfo.Source === 5) {
         this.formItemArray.chartInfo.push(
           {
             label: "盘面利润名称",
@@ -418,6 +420,60 @@ export default {
           }
         );
       }
+
+       //跨品种分析
+      else if(chartInfo.Source===10) {
+        let res = await crossVarietyInterface.chartLangOption({ChartInfoId: chartInfo.ChartInfoId})
+
+        const { TagList,VarietyList } = res.Data;
+
+        this.formItemArray.chartInfo.push({
+          label:'X轴名称',
+          value:Data.DataResp.XName,
+          key:'XName',
+          id:TagList[0].ChartTagId,
+          notEdit:true
+        },
+        {
+          label:'英文X轴名称',
+          value:Data.DataResp.XNameEn,
+          key:'XNameEn',
+          id:TagList[0].ChartTagId,
+          placeholder:'请输入英文X轴名称'
+        },{
+          label:'Y轴名称',
+          value:Data.DataResp.YName,
+          key:'YName',
+          id:TagList[1].ChartTagId,
+          notEdit:true
+        },
+        {
+          label:'英文Y轴名称',
+          value:Data.DataResp.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;
     },
 
@@ -452,6 +508,8 @@ export default {
           ChartInfoId: enNameData.ChartInfoId,
           ChartNameEn: enNameData.ChartNameEn,
         });
+      }else if (this.chart_source === 10) {
+        res=await crossVarietyInterface.editChartEn(enNameData)
       }
 
       if (res.Ret !== 200) return;
@@ -471,18 +529,16 @@ export default {
         PageSize: this.search_page_sizes,
         IsShowMe: this.isShowMe,
       };
-      let res = null;
-      if (this.chart_source === 1) {
-        res = await dataBaseInterface.chartSearchByEs(params);
-      } else if (this.chart_source === 2) {
-        res = await futuresInterface.searchChart(params);
-      } else if (this.chart_source === 3) {
-        res = await chartRelevanceApi.searchChart(params);
-      } else if (this.chart_source === 6) {
-        res = await fittingEquationInterface.searchChart(params);
-      } else if (this.chart_source === 7) {
-        res = await statisticFeatureInterface.searchChart(params);
+
+      const apiMap = {
+        1: dataBaseInterface.chartSearchByEs,
+        2: futuresInterface.searchChart,
+        3: chartRelevanceApi.searchChart,
+        6: fittingEquationInterface.searchChart,
+        7: statisticFeatureInterface.searchChart,
+        10: crossVarietyInterface.searchChart,
       }
+      let res = await apiMap[this.chart_source](params)
 
       if (res.Ret !== 200) return;
       res.Data.List = res.Data.List || [];
@@ -491,6 +547,8 @@ export default {
           ? res.Data.List
           : [...this.newreportlist, ...res.Data.List];
       this.search_have_more = this.search_page < res.Data.Paging.Pages;
+
+      console.log(this.chart_source,this.newreportlist)
     },
 
     loadReportHandle() {

+ 1 - 0
src/views/report_manage/reportEn/reportEditor.vue

@@ -203,6 +203,7 @@
 						<el-radio :label="3">相关性图表</el-radio> 
 						<el-radio :label="6">拟合方程曲线</el-radio>
 						<el-radio :label="7">统计特征</el-radio>
+						<el-radio :label="10">跨品种分析</el-radio>
 					</el-radio-group>
 					<div style="margin: 10px 0">
 						<el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}">只看我的</el-checkbox>

+ 1 - 6
src/views/sandbox_manage/common/edge.js

@@ -4,12 +4,7 @@ const { line} = configOpt;
 import store from "@/vuex/index"
 
 const styleConfig=store.state.sand.styleConfig
-// export const myEdges = [
-// 	{
-// 		type: 'noArrowStraight',
-//     ImgUrl:'~@/assets/icons/arrow.svg'
-// 	}
-// ]
+
 /**type--类型  xP--定位点的横坐标 yP--定位点的纵坐标
  * 创建的线条
  * 斜直线无箭头、斜直线单项箭头、斜直线双线箭头

+ 36 - 78
src/views/sandbox_manage/common/events.js

@@ -5,13 +5,11 @@ const { line} = configOpt;
 
 /* 节点操作监听事件 */
 export const myEvents = (graph,mindmapDataUseFun) => {
-		
 		/* 节点双击编辑 */
 		graph.on('node:dblclick', ({ node, e }) => {
 			// 节点当前设置的样式同步到编辑区
 
 			const { text, rect} = node.attrs;
-			// console.log(node,'nodenode');
 			const edit_area = document.createElement('div');
 			edit_area.contentEditable = "true";
 			edit_area.id = "editable-wrapper";
@@ -23,25 +21,14 @@ export const myEvents = (graph,mindmapDataUseFun) => {
 
 			const position = node.position();
       const size = node.size();
-			// console.log(position,size);
-      // const pos = graph.localToClient(position);
       const pos = graph.localToGraph(position);
       const zoom = graph.zoom();
       let width = size.width,height = size.height;
 
-			// const edit_area =  $('#editable-wrapper')[0];
-			// if(node.shape.indexOf('mindmap')!==-1){
-
-			// 	edit_area.innerText = text.text
-			// 	node.attr('text/text', '');
-			// }else{
-				edit_area.innerText = text.text || text.textWrap.text || ' ';
-				// 开启editText的事务 
-				graph.startBatch('editText')
-				node.attr('text/textWrap/text', '');
-				
-			// }
-
+			edit_area.innerText = text.text || text.textWrap.text || ' ';
+			// 开启editText的事务 
+			graph.startBatch('editText')
+			node.attr('text/textWrap/text', '');
 
 			edit_area.style.left = `${pos.x}px`;
 			edit_area.style.top = `${pos.y}px`;
@@ -68,15 +55,12 @@ export const myEvents = (graph,mindmapDataUseFun) => {
 			edit_area.oninput = () => {
 				const domH = (edit_area.getBoundingClientRect().height) /zoom;
 				node.size(width,domH > 50 ? domH : 50);
-				// node.size(width,domH > height ? domH : height);
-
 			}
 
 			//失焦后设置内容
 			edit_area.onblur = () => {
 				let newval = edit_area.innerText.replace(/(\n[\s\t]*\r*\n)/g,'\n');
 
-				// console.log(node.shape,'edit_area');
 
 				node.attr('text/textWrap/text', newval);
 				node.attr('text/text', newval);
@@ -84,7 +68,8 @@ export const myEvents = (graph,mindmapDataUseFun) => {
 				graph.stopBatch('editText')
 
 				if(node.shape.indexOf('mindmap')!==-1){
-					const mindmapDataUse=mindmapDataUseFun()
+					if(!mindmapDataUseFun) return 
+					const mindmapDataUse=mindmapDataUseFun().mindmapDataUse
 					let ids = node.id.split('-')
 					let mindmapDataIndex = mindmapDataUse.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
 					let mindMapDataCurrent = mindmapDataUse[mindmapDataIndex]?mindmapDataUse[mindmapDataIndex].mindmapData:{}
@@ -97,23 +82,15 @@ export const myEvents = (graph,mindmapDataUseFun) => {
 					}
 					mindMapDataCurrent.label = newval
 				}
-				if(node.shape.indexOf('mindmap')==-1){
-					const domH = (edit_area.getBoundingClientRect().height) /zoom;
-					node.size(width,domH > 50 ? domH : 50);
-					// node.size(width,domH);
-				}else{
-					const domH = (edit_area.getBoundingClientRect().height) /zoom;
-					// node.size(width,domH);
-					node.size(width,domH > 50 ? domH : 50);
-					// node.fit({ deep: true })
-				}
+
+				const domH = (edit_area.getBoundingClientRect().height) /zoom;
+				node.size(width,domH > 50 ? domH : 50);
 
 				$('#sand-chart-container')[0].removeChild(edit_area);
 			}
 		})
 		/* 鼠标移入移出控制连接桩 */
 		graph.on('node:mouseenter', ({ node, e }) => {
-			// console.log(node)
 			for(let i of document.querySelectorAll(`g[data-cell-id="${node.id}"] .x6-port-body`)) {
 				i.style.display = 'block'
 			}
@@ -135,7 +112,6 @@ export const myEvents = (graph,mindmapDataUseFun) => {
 
 		/* 选中事件 */
 		// graph.on('cell:selected',({cell,options}) => {
-		// 	// console.log(cell)
 		// 	//节点
 		// 	if(cell.shape === 'rect') {
 		// 		const { key } = cell.data;
@@ -174,21 +150,16 @@ export const myEvents = (graph,mindmapDataUseFun) => {
 		// })
 
 		const changeSelection=_.debounce((selected)=> {
-			// console.log(selected,'selected');
 			store.commit('sand/SET_SELECT_CELLS',selected)
 		},50)
 
 		/* 监听选中事件 */
 		graph.on('selection:changed',({selected}) => {
-			// console.log(selected,'选中修改');
-			// selected.length ? store.commit('sand/SET_SELECT_CELL',selected[0]) : store.commit('sand/SET_SELECT_CELL',null);
 			changeSelection(selected)
 		})
 
 		/* 监听选中事件 */
 		graph.on('edge:mouseenter', ({ cell }) => {
-			// console.log(cell,'myEdgeOption');
-			// console.log(cell.store.data);
 			if(cell.store.data.shape=="mindmap-edge"){
 				// 思维导图的边
 			}else{
@@ -236,11 +207,10 @@ export const myEvents = (graph,mindmapDataUseFun) => {
 }
 
 /* 绑定键盘事件 */
-export const bindKey = (graph,mindmapDataUseFun,mindmapAssistData) => {
+export const bindKey = (graph,mindmapDataUseFun) => {
 	 // 删除
 	graph.bindKey(['delete', 'backspace'], () => {
-		const mindmapDataUse=mindmapDataUseFun()
-		deleteNodes(graph,mindmapDataUse,mindmapAssistData)
+		deleteNodes(graph,mindmapDataUseFun)
 		return false
 	}, 'keydown');
 
@@ -278,27 +248,20 @@ export const bindKey = (graph,mindmapDataUseFun,mindmapAssistData) => {
 }
 
 /* 右键事件 */
-export const contextEvent = (graph,key,mindmapDataUse,mindmapAssistData) => {
-	// console.log(key)
+export const contextEvent = (graph,key,mindmapDataUseFun) => {
 	switch (key) {
 		case 'copy':
 			nodeCopyAndPaste(graph);
 			break;
 		case 'del': 
-			nodeDelete(graph,mindmapDataUse,mindmapAssistData);
+			deleteNodes(graph,mindmapDataUseFun);
 			break;
 	}
 }
 
-/* 删除节点 清空选区*/
-const nodeDelete = (graph,mindmapDataUse,mindmapAssistData) => {
-	deleteNodes(graph,mindmapDataUse,mindmapAssistData)
-}
 /* 复制粘贴节点 */
 const nodeCopyAndPaste = (graph) => {
 	const select_cell = graph.getSelectedCells();
-	// console.log(select_cell)
-	// return
 	if (select_cell.length) {
 		graph.copy(select_cell);
 		const copy_cell = graph.paste({ offset: 30 });
@@ -309,7 +272,6 @@ const nodeCopyAndPaste = (graph) => {
 
 /* 关联三种基础图形选中样式 */
 // const setSelectedOptions = ({ rect, text }, key) => {
-// 	console.log({ rect, text },'{ rect, text }',key);
 // 	return ['rect','date'].includes(key) ? {
 // 		text: { //文本设置
 // 			size: text.fontSize,
@@ -332,13 +294,19 @@ const nodeCopyAndPaste = (graph) => {
 // 	}: {}
 // }
 
-const deleteNodes=(graph,mindmapDataUse,mindmapAssistData)=>{
-	console.log(mindmapDataUse,mindmapAssistData,'最源数据');
+const deleteNodes=(graph,mindmapDataUseFun)=>{
 	const select_cell = graph.getSelectedCells();
 	let delete_cells=[]
+	if(!mindmapDataUseFun){
+		delete_cells = select_cell
+		if (delete_cells.length) {
+			// 移除工具
+			delete_cells.forEach(item => item.removeTools());
+			graph.removeCells(delete_cells)
+		}
+		return 
+	}
 	let mindmapCell=[]
-	// return 
-	// console.log(select_cell.length,'select_cell.length');
 	for (let i = 0; i < select_cell.length; i++) {
 		const cell = select_cell[i];
 		if(cell.shape == "mindmap-edge"){
@@ -347,63 +315,53 @@ const deleteNodes=(graph,mindmapDataUse,mindmapAssistData)=>{
 			mindmapCell.push(cell)
 			// 拿到该节点的所有子节点
 			let Successors = graph.getSuccessors(cell) 
-			// console.log(Successors,'Successors');
 			mindmapCell = [...mindmapCell,...Successors]
 		}
 		delete_cells.push(cell)
 	}
 	// 去重
 	const uniqueArr = mindmapCell.filter((item, index) => mindmapCell.findIndex(i => i.id === item.id) === index);
-	// console.log(uniqueArr,'uniqueArr');
 
 	delete_cells = [...delete_cells,...uniqueArr]
-	// return 
 	if (delete_cells.length) {
 		// 移除工具
 		delete_cells.forEach(item => item.removeTools());
 		graph.removeCells(delete_cells)
 	}
+	const mindmapAssistData = mindmapDataUseFun()
+
 	let shouldOperations=[]
-	mindmapDataUse.map((item,index)=>{
+	mindmapAssistData.mindmapDataUse.map((item,index)=>{
 		let levelIds = uniqueArr.filter(mindMap => mindMap.id.startsWith(item.mindmapData.id)).map(mindMap => mindMap.id)
-		// console.log(levelIds,'levelIds');
 		if(!(levelIds && levelIds.length>0)) return 
-		// console.log(levelIds,'levelIds');
 		let mindMapIds=[...levelIds]
 		for (let i = 0; i < levelIds.length; i++) {
 			const element = levelIds[i]
 			mindMapIds=mindMapIds.filter( id => id.indexOf(element) !=0 || id==element)
 		}
-		// console.log(mindMapIds,'mindMapIds');
 		shouldOperations.push(mindMapIds)
 	})
-	// 删除前备份
-	console.log(mindmapDataUse,'元数据');
-	mindmapAssistData.mindmapDataRecoverUse=[JSON.stringify(mindmapDataUse)]
 
-	console.log('删除备份',JSON.parse(mindmapAssistData.mindmapDataRecoverUse[0]),mindmapAssistData.mindmapDataRecoverUse.length,mindmapAssistData.mindmapDataRecoverUse);
-	
-	// console.log(shouldOperations,'shouldOperations');
+	mindmapAssistData.deletedMindmapData.push([])
 	shouldOperations.map(it =>{
 		it.map(it1 =>{
-			deleteMindmapData(it1,mindmapDataUse)
+			deleteMindmapData(it1,mindmapAssistData)
 		})
 	})
-	// console.log(mindmapDataUse,'mindmapDataUse',mindmapAssistData,'mindmapAssistData');
-
 }
 
 const deleteMindmapData=(id,data)=>{
-	// console.log(id,data,'id,data');
-	// return 
+
 	let ids = id.split('-')
-	let mindmapDataIndex = data.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
+	let mindmapDataIndex = data.mindmapDataUse.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
 	if(ids.length==1){
-		data.splice(mindmapDataIndex,1)
+		let spliceData=data.mindmapDataUse.splice(mindmapDataIndex,1)
+		// 备份删除掉的数据
+		data.deletedMindmapData[data.deletedMindmapData.length-1].push(spliceData)
 		return 
 	}
 
-	let mindmapData = data[mindmapDataIndex].mindmapData
+	let mindmapData = data.mindmapDataUse[mindmapDataIndex].mindmapData
 	let findId = ids[0]
 	for (let i = 1; i < ids.length-1; i++) {
 		const element = ids[i];
@@ -418,6 +376,6 @@ const deleteMindmapData=(id,data)=>{
 		return 
 	}
 	let endIndex = mindmapData.children.findIndex(it => it.id == findId+'-'+endId)
-	mindmapData.children.splice(endIndex,1)
-	// console.log(data);
+	let spliceData=mindmapData.children.splice(endIndex,1)
+	data.deletedMindmapData[data.deletedMindmapData.length-1].push(spliceData)
 }

+ 3 - 5
src/views/sandbox_manage/common/gragh.js

@@ -2,12 +2,11 @@ import { Graph,Shape } from '@antv/x6';
 import { bindKey,myEvents } from './events';
 import { configOpt } from './toolConfig';
 import store from '@/vuex/index'
-console.log(store,'store');
 const styleConfig=store.state.sand.styleConfig
 
 const { line } = configOpt;
 // wrapper DOM的Id mindmapDataUseFun 返回思维导图数组函数,传递给事件 type 模式,编辑和查看
-export function myGraph (wrapper,mindmapDataUseFun,mindmapAssistData,type='edit') {
+export function myGraph (wrapper,mindmapDataUseFun,type='edit') {
 	const graph = new Graph({
 		container: document.getElementById(wrapper),
 		// width: $(window).width(),
@@ -15,7 +14,6 @@ export function myGraph (wrapper,mindmapDataUseFun,mindmapAssistData,type='edit'
 		history:{
 			enabled:true,
 			beforeAddCommand(event, args){
-				console.log(event, args,'event, args');
 				if(args.key=='tools'){
 					// 工具的改变不加入撤销和重做的队列
 					return false
@@ -61,7 +59,7 @@ export function myGraph (wrapper,mindmapDataUseFun,mindmapAssistData,type='edit'
 			visible: false,
 		},
 		highlighting: {
-			// 当链接桩可以被链接时,在链接桩外围渲染一个 2px 宽的色矩形框
+			// 当链接桩可以被链接时,在链接桩外围渲染一个 2px 宽的天蓝色矩形框
 			magnetAvailable: {
 					name: "stroke",
 					args: {
@@ -150,7 +148,7 @@ export function myGraph (wrapper,mindmapDataUseFun,mindmapAssistData,type='edit'
 	
 
 	/* 键盘事件 */
-	if(type!='view') bindKey(graph,mindmapDataUseFun,mindmapAssistData);
+	if(type!='view') bindKey(graph,mindmapDataUseFun);
 
 	return graph;
 }

+ 223 - 108
src/views/sandbox_manage/common/mindmap.js

@@ -7,7 +7,12 @@ export default {
       mindMapDataCurrent:{},
       positionCurrent:{},
       addTypeCurrent:'',
-      styleConfig:{}
+      styleConfig:{},
+      mindmapAssistData:{
+        mindmapDataUse:[],
+        deletedMindmapData:[],// 用于撤销删除,恢复删除掉的数据
+        mindmapDataRecoverUse:[],//用于 重做时 恢复思维导图数据
+      },
     }
   },
   mounted() {
@@ -15,7 +20,6 @@ export default {
   },
   created() {
     this.styleConfig=this.$store.state.sand.styleConfig
-    // console.log(this.styleConfig,'this.styleConfig');
     // 中心主题
     Graph.registerNode(
       'mindmap-topic',          
@@ -43,8 +47,6 @@ export default {
           body: {
             rx: 6,
             ry: 6,
-            // stroke: this.$store.state.sand.styleConfig.borderColor,
-            // fill: this.$store.state.sand.styleConfig.backgroundColor,
             strokeWidth: 1,
             width:100,
             height:50
@@ -111,8 +113,6 @@ export default {
           body: {
             rx: 6,
             ry: 6,
-            // stroke: this.$store.state.sand.styleConfig.borderColor,
-            // fill: this.$store.state.sand.styleConfig.backgroundColor,
             strokeWidth: 1,
             width:100,
             height:50
@@ -167,8 +167,6 @@ export default {
           body: {
             rx: 6,
             ry: 6,
-            // stroke: this.$store.state.sand.styleConfig.borderColor,
-            // fill: this.$store.state.sand.styleConfig.backgroundColor,
             strokeWidth: 1,
             width:100,
             height:50
@@ -196,53 +194,12 @@ export default {
       },
       true,
     )
-    // 分支主题
-    // Graph.registerNode(
-    //   'mindmap-topic-child',
-    //   {
-    //     inherit: 'rect',
-    //     markup: [
-    //       {
-    //         tagName: 'rect',
-    //         selector: 'body',
-    //       },
-    //       {
-    //         tagName: 'text',
-    //         selector: 'text',
-    //       },
-    //       {
-    //         tagName: 'path',
-    //         selector: 'line',
-    //       },
-    //     ],
-    //     attrs: {
-    //       body: {
-    //         fill: '#ffffff',
-    //         strokeWidth: 0,
-    //         stroke: '#5F95FF',
-    //       },
-    //       text: {
-    //         fontSize: 14,
-    //         fill: '#262626',
-    //         textVerticalAnchor: 'bottom',
-    //       },
-    //       line: {
-    //         stroke: '#5F95FF',
-    //         strokeWidth: 2,
-    //         d: 'M 0 15 L 60 15',
-    //       },
-    //     },
-    //   },
-    //   true,
-    // )
-
     // 连接器
     Graph.registerConnector(
       'mindmap',
       (sourcePoint, targetPoint, routerPoints, options) => {
-        // console.log(sourcePoint, targetPoint, routerPoints, options,'sourcePoint, targetPoint, routerPoints, options');
         const midX = sourcePoint.x + 10
-        const midY = sourcePoint.y
+        // const midY = sourcePoint.y
         const ctrX = (targetPoint.x - midX) / 5 + midX
         const ctrY = targetPoint.y
         const pathData = `
@@ -265,7 +222,6 @@ export default {
         attrs: {
           line: {
             targetMarker: false,
-            // stroke: this.$store.state.sand.styleConfig.lineColor,
             strokeWidth: 2,
           },
         },
@@ -276,6 +232,7 @@ export default {
   },
   methods: {
     setGraph(){
+      // 添加左边节点
       this.graph.on('add:topic:left', ({ node }) => {
         if(this.operationType=='view') return 
         const { id } = node
@@ -285,7 +242,7 @@ export default {
           this.mindMapRender()      
         }
       })
-
+      // 添加右边节点
       this.graph.on('add:topic:right', ({ node }) => {
         if(this.operationType=='view') return 
         const { id } = node
@@ -295,12 +252,13 @@ export default {
           this.mindMapRender()      
         }
       })
+      // 改变大小 - 更新数据源
       this.graph.on('node:change:size', (args) => { 
         if(this.operationType=='view') return 
         if(args.node.shape.indexOf('mindmap')!==-1){
           let ids = args.node.id.split('-')
-					let mindmapDataIndex = this.mindmapDataUse.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
-					let mindMapDataCurrent = this.mindmapDataUse[mindmapDataIndex]?this.mindmapDataUse[mindmapDataIndex].mindmapData:{}
+					let mindmapDataIndex = this.mindmapAssistData.mindmapDataUse.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
+					let mindMapDataCurrent = this.mindmapAssistData.mindmapDataUse[mindmapDataIndex]?this.mindmapAssistData.mindmapDataUse[mindmapDataIndex].mindmapData:{}
 
 					let findId = ids[0]
 
@@ -314,39 +272,19 @@ export default {
 					mindMapDataCurrent.height = args.node.size().height
         }
       })
+      // 改变位置 - 更新数据源
       this.graph.on('node:change:position', (args) => { 
         if(this.operationType=='view') return 
         if(args.node.shape.indexOf('mindmap')!==-1 && Number(args.node.id)){
 
-          let index = this.mindmapDataUse.findIndex(it =>it.mindmapData.id == args.node.id)
-          // let index = Number(args.node.id)
+          let index = this.mindmapAssistData.mindmapDataUse.findIndex(it =>it.mindmapData.id == args.node.id)
           if(index!=-1){
-            this.mindmapDataUse[index].position = args.current
-          // this.setCurrent(args.node.id)
+            this.mindmapAssistData.mindmapDataUse[index].position = args.current
           }
         }
       })
-      // this.graph.on('node:added', ({node}) => { 
-      //   if(node.shape.indexOf('mindmap')!=-1){
-      //     // 思维导图需要处理相对应的数据
-      //     console.log('mindmap',node.id);
-      //   }
-      //   console.log(node,'node:added');
-      // })
-      // this.graph.on('node:removed', (args) => { 
-      //   console.log(args,'node:removed');
-      // })
-      // this.graph.bindKey(['backspace', 'delete'], () => {
-      //   const selectedNodes = this.graph.getSelectedCells().filter((item) => item.isNode())
-      //   if (selectedNodes.length) {
-      //     const { id } = selectedNodes[0]
-      //     if (this.removeNode(id)) {
-      //       this.mindMapRender()
-      //     }
-      //   }
-      // })
-      
-      this.graph.bindKey('tab', (e) => {  
+      // tab 键添加节点-右边的 - 更新数据源
+      this.graph.bindKey('tab', (e) => {
         if(this.operationType=='view') return 
         e.preventDefault()
         const selectedNodes = this.graph.getSelectedCells().filter((item) => {
@@ -362,20 +300,88 @@ export default {
           }
         }
       })
+      // 撤销 - 入栈
+      this.graph.history.on('undo', (args) => { 
+        let mindmapNodes=args.cmds.filter(it => it.data.props && it.data.props.shape.indexOf('mindmap')!=-1 && it.data.node)
+        if(!(mindmapNodes && mindmapNodes.length>0)) return 
+        let mindmapUndoType=mindmapNodes[0].event
+        
+        if(mindmapUndoType=="cell:added"){
+          this.mindmapDeleteRecordPush(mindmapNodes)
+        }else if(mindmapUndoType=="cell:removed"){
+          this.mindmapAddRecordPush()
+        }
+      })
+      // 重做,出栈
+      this.graph.history.on('redo', (args) => { 
+        let mindmapNodes=args.cmds.filter(it => it.data.props && it.data.props.shape.indexOf('mindmap')!=-1 && it.data.node)
+        if(!(mindmapNodes && mindmapNodes.length>0)) return
+        this.mindmapRecover()
+      })
+    },
+    // 生成思维导图初始化数据
+    generateMindmapData(position,addType){
+      let beId=this.mindmapAssistData.mindmapDataUse.length>0?
+      parseInt(this.mindmapAssistData.mindmapDataUse[this.mindmapAssistData.mindmapDataUse.length-1].mindmapData.id)+1+'':'1'
+      let mindmapData={
+        id: beId,
+        type: 'topic',
+        label: '中心主题',
+        width: 160,
+        height: 50,
+        direction:'double',
+        children: [
+          {
+            id: beId+'-1',
+            type: 'topic-branch',
+            label: '分支主题1',
+            width: 100,
+            height: 40,
+            direction:'left',
+            children: [
+              {
+                id: beId+'-1-1',
+                type: 'topic-child',
+                label: '子主题1',
+                width: 60,
+                height: 30,
+                direction:'left',
+              },
+              {
+                id: beId+'-1-2',
+                type: 'topic-child',
+                label: '子主题2',
+                width: 60,
+                height: 30,
+                direction:'left',
+              },
+            ],
+          },
+          {
+            id: beId+'-2',
+            type: 'topic-branch',
+            label: '分支主题2',
+            width: 100,
+            height: 40,
+            direction:'right',
+          },
+        ],
+      }
+      this.mindmapAssistData.mindmapDataUse.push({mindmapData,position,addType})
     },
     // 通过id设置当前操作的思维导图
     setCurrent(id){
       let rootId = id.split('-')[0]
-      let index = this.mindmapDataUse.findIndex(it =>it.mindmapData.id == rootId)
-      this.mindMapDataCurrent = this.mindmapDataUse[index]?this.mindmapDataUse[index].mindmapData:{}
-      this.positionCurrent = this.mindmapDataUse[index]?this.mindmapDataUse[index].position:{x:0,y:0}
-      this.addTypeCurrent = this.mindmapDataUse[index]?this.mindmapDataUse[index].addType:'singleMindmap'
+      let index = this.mindmapAssistData.mindmapDataUse.findIndex(it =>it.mindmapData.id == rootId)
+      this.mindMapDataCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].mindmapData:{}
+      this.positionCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].position:{x:0,y:0}
+      this.addTypeCurrent = this.mindmapAssistData.mindmapDataUse[index]?this.mindmapAssistData.mindmapDataUse[index].addType:'singleMindmap'
     },
     mindMapRender(i){
       this.graph.startBatch('renderMindmap')
-      let mindMapType = i || i==0?this.mindmapDataUse[i].addType:this.addTypeCurrent
-      this.mindMapDataCurrent = i || i==0?this.mindmapDataUse[i].mindmapData:this.mindMapDataCurrent
-      this.positionCurrent = i || i==0?this.mindmapDataUse[i].position:this.positionCurrent
+      let mindMapType = i || i==0?this.mindmapAssistData.mindmapDataUse[i].addType:this.addTypeCurrent
+      this.mindMapDataCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].mindmapData:this.mindMapDataCurrent
+      this.positionCurrent = i || i==0?this.mindmapAssistData.mindmapDataUse[i].position:this.positionCurrent
       const result = Hierarchy.mindmap(this.mindMapDataCurrent, {
         direction: 'H',
         getHeight(d) {
@@ -397,14 +403,11 @@ export default {
       const cells = []
       let xGap = this.positionCurrent?this.positionCurrent.x-result.x:0
       let yGap = this.positionCurrent?this.positionCurrent.y-result.y:0
-      // console.log(result,'result');
-      // return 
+
       const traverse = (hierarchyItem) => {
         if (hierarchyItem) {
           const { data, children } = hierarchyItem
-          // console.log(hierarchyItem,'hierarchyItemhierarchyItemhierarchyItem');
           let mindmapDirection = mindMapType.indexOf('double') != -1?data.direction:'right'
-          // console.log(mindmapDirection,data.label,data.direction);
           let currentCell=this.graph.getCellById(data.id)
 
           if(!currentCell){
@@ -434,7 +437,6 @@ export default {
             // 有,更新下位置信息
             currentCell.position(xGap+hierarchyItem.x,yGap+hierarchyItem.y)
           }
-          // return 
    
           if (children) {
             children.forEach((item) => {
@@ -477,13 +479,10 @@ export default {
       traverse(result)
       // 排下序,把边放最后面 不然 边 会找不到 节点
       let sortCells = cells.sort(cell => cell.shape.indexOf('edge'))
-      // console.log(sortCells,'result');
-      // return 
-      // this.graph.removeCells(sortCells)
+
       this.graph.addCell(sortCells)
       this.graph.stopBatch('renderMindmap')
-      // this.graph.resetCells(cells)
-      // this.graph.centerContent()
+
     },
     findItem(obj,id){
       if (obj.id === id) {
@@ -507,16 +506,13 @@ export default {
       return null
     },
     addChildNode (id, type,direction='left'){
-      console.log('添加');
       // 重做不了 清空重做栈
       this.mindmapAssistData.mindmapDataRecoverUse = []
-      // console.log(this.mindmapAssistData);
 
       const res = this.findItem(this.mindMapDataCurrent, id)
       const dataItem = res && res.node
       if (dataItem) {
         let item = null
-        // console.log(dataItem.children);
         let addId ='1'
         if(dataItem.children && dataItem.children.length>0){
           let ids = dataItem.children[dataItem.children.length-1].id.split('-')
@@ -552,15 +548,134 @@ export default {
       }
       return null
     },
-    removeNode (id) {
-      const res = this.findItem(this.mindMapDataCurrent, id)
-      const dataItem = res && res.parent
-      if (dataItem && dataItem.children) {
-        const { children } = dataItem
-        const index = children.findIndex((item) => item.id === id)
-        return children.splice(index, 1)
+    getMindmapDataUse(){
+      return this.mindmapAssistData
+    },
+    mindmapDeleteRecordPush(mindmapNodes){
+      let shouldOperations=[]
+      this.mindmapAssistData.mindmapDataUse.map((item,index)=>{
+        let levelIds = mindmapNodes.filter(mindMap => mindMap.data.id.startsWith(item.mindmapData.id)).map(mindMap => mindMap.data.id)
+        if(!(levelIds && levelIds.length>0)) return 
+        let mindMapIds=[...levelIds]
+        for (let i = 0; i < levelIds.length; i++) {
+          const element = levelIds[i]
+          mindMapIds=mindMapIds.filter( id => id.indexOf(element) !=0 || id==element)
+        }
+        shouldOperations.push(mindMapIds)
+      })
+      // 入栈
+      if(!this.canRedo){
+        this.mindmapAssistData.mindmapDataRecoverUse=[JSON.stringify(this.mindmapAssistData.mindmapDataUse)]
+      }else{
+        this.mindmapAssistData.mindmapDataRecoverUse.push(JSON.stringify(this.mindmapAssistData.mindmapDataUse))
       }
-      return null
-    }
+      shouldOperations.map(it =>{
+        it.map(it1 =>{
+          this.deleteMindmapData(it1,this.mindmapAssistData.mindmapDataUse)
+        })
+      })
+    },
+    mindmapAddRecordPush(){
+      // 入栈
+      if(!this.canRedo){
+        this.mindmapAssistData.mindmapDataRecoverUse=[JSON.stringify(this.mindmapAssistData.mindmapDataUse)]
+      }else{
+        this.mindmapAssistData.mindmapDataRecoverUse.push(JSON.stringify(this.mindmapAssistData.mindmapDataUse))
+      }
+      let recoverDeletedData=this.mindmapAssistData.deletedMindmapData.pop()
+      if(recoverDeletedData && recoverDeletedData.length>0){
+        // 添加
+        recoverDeletedData.map(it =>{
+          it.map(it1 =>{
+            this.addMindmapData(it1,this.mindmapAssistData.mindmapDataUse)
+          })
+        })
+      }
+    },
+    deleteMindmapData(id,data){
+      let ids = id.split('-')
+      let mindmapDataIndex = data.findIndex(mindmap => mindmap.mindmapData.id == ids[0])
+      if(ids.length==1){
+        data.splice(mindmapDataIndex,1)
+        return 
+      }
+
+      let mindmapData = data[mindmapDataIndex].mindmapData
+      let findId = ids[0]
+      for (let i = 1; i < ids.length-1; i++) {
+        const element = ids[i];
+        findId = findId+'-'+element
+        mindmapData=mindmapData.children.find(it => it.id==findId)
+      }
+      let endId = ids[ids.length-1]
+      let endIndex = mindmapData.children.findIndex(it => it.id == findId+'-'+endId)
+      mindmapData.children.splice(endIndex,1)
+    },
+    addMindmapData(item,data){
+      let isRoot = item.mindmapData?true:false
+      let id = isRoot?item.mindmapData.id:item.id
+      
+      if(isRoot){
+        // 恢复根节点
+        let mindmapDataIndexRoot=data.length
+        for (let i = 0; i < data.length-1; i++) {
+          const element = data[i];
+          if((+id) < (+element.mindmapData.id)){
+            mindmapDataIndexRoot=0
+            break
+          }else if((+id) > (+element.mindmapData.id) && (+id) < (+data[i+1].mindmapData.id)){
+            mindmapDataIndexRoot=i+1
+            break
+          }
+        }
+        data.splice(mindmapDataIndexRoot,0,item)
+        return
+      }
+
+      let ids = id.split('-')
+      let mindmapDataIndex = data.findIndex(mindmap => {
+        return mindmap.mindmapData.id == ids[0]
+      })
+      let mindmapData = data[mindmapDataIndex].mindmapData
+      let findId = ids[0]
+      for (let i = 1; i < ids.length-1; i++) {
+        const element = ids[i];
+        findId = findId+'-'+element
+        mindmapData=mindmapData.children.find(it => it.id==findId)
+      }
+      let endId = ids[ids.length-1]
+      let endIndex = mindmapData.children.length
+      if(mindmapData.children.length==1){
+        // 只有一个
+        let prevIdx = mindmapData.children[0].id.substring(mindmapData.children[0].id.lastIndexOf('-')+1)
+        if((+endId) < (+prevIdx)){
+          endIndex=0
+        }else{
+          endIndex=1
+        }
+      }else{
+        for (let i = 0; i < mindmapData.children.length-1; i++) {
+          // 两个及以上
+          const element = mindmapData.children[i];
+
+          let prevIdx = element.id.substring(element.id.lastIndexOf('-')+1)
+          let nextIdx = mindmapData.children[i+1].id.substring(mindmapData.children[i+1].id.lastIndexOf('-')+1)
+          // 找到对应位置,前提 id是按顺序的
+          if((+endId) < (+prevIdx)){
+            endIndex=0
+            break
+          }else if((+endId) > (+prevIdx) && (+endId) < (+nextIdx)){
+            endIndex=i+1
+            break
+          }
+        }
+      }
+      mindmapData.children.splice(endIndex,0,item)
+    },
+    mindmapRecover(){
+      // 重做添加时 恢复数据指针前进
+      let recoverData = this.mindmapAssistData.mindmapDataRecoverUse.pop()
+      if(recoverData) this.mindmapAssistData.mindmapDataUse=JSON.parse(recoverData) 
+    },
   },
 }

+ 1 - 12
src/views/sandbox_manage/common/node.js

@@ -3,7 +3,6 @@ import store from "@/vuex/index"
 
 const { line,border,text } = configOpt;
 
-console.log(store,'storestorestore');
 const styleConfig=store.state.sand.styleConfig
 
 //定义图形
@@ -273,17 +272,7 @@ export const myNodeOption = (key) => {
 							// 		position: 'bottom',
 							// 		zIndex: 20,
 							// 		...portStyle
-							// },
-							// "port-left": {
-							// 		position: 'left',
-							// 		zIndex: 20,
-							// 		...portStyle
-							// },
-							// "port-right": {
-							// 		position: 'right',
-							// 		zIndex: 20,
-							// 		...portStyle
-							// },
+							// }
 					}
 				},
 			}

+ 158 - 274
src/views/sandbox_manage/index_new_version.vue

@@ -110,6 +110,7 @@
     </div>
     <!-- 目录自定义按钮区域 -->
     <div id="custom-button-zone" class="custom-button-zone">
+      <img src="~@/assets/img/data_m/move_ico.png" style="pointer-events: none;" v-permission="permissionBtn.sandboxPermission.sandbox_classify_move"/>
       <img src="~@/assets/img/sand_new/add_outline.png" class="add-classify-img" v-permission="permissionBtn.sandboxPermission.sandbox_classify_addEdit"/>
       <img src="~@/assets/img/sand_new/edit_outline.png" class="edit-classify-img" v-permission="permissionBtn.sandboxPermission.sandbox_classify_addEdit"/>
       <img src="~@/assets/img/sand_new/delete_outline.png" class="delete-classify-img" v-permission="permissionBtn.sandboxPermission.sandbox_classify_del"/>
@@ -129,15 +130,18 @@
             {{ lastLevelClassifyName }}
           </el-form-item>
           <el-form-item label="目录名称" prop="SandboxClassifyName">
-            <el-input v-model="classifyForm.SandboxClassifyName" style="width: 317px;" placeholder="请输入目录名称"></el-input>
+            <el-input v-model.trim="classifyForm.SandboxClassifyName" style="width: 317px;" placeholder="请输入目录名称"></el-input>
           </el-form-item>
-          <el-form-item label="关联品种" prop="ChartPermissionId" v-if="hasVariety && (classifyAddTitle.indexOf('添加')!==-1)">
+          <el-form-item label="关联品种" prop="ChartPermissionId" v-if="hasVariety">
             <el-cascader 
+              @change="chartPermissionIdChange"
 							:options="classifyArr"
 							:props="classifyProps"
 							v-model="classifyForm.ChartPermissionId" 
 							placeholder="请选择对应品种" 
               id="classifyAddCascader"
+              ref="chartPermissionCascader"
+              :disabled="(classifyForm.SandboxClassifyId && classifyForm.Level!=1) || (!classifyForm.SandboxClassifyId && classifyForm.Level!=0)"
 						/>
           </el-form-item>
         </el-form>
@@ -162,24 +166,15 @@
             <el-input v-model="saveOtherForm.chartName" style="width: 317px;" placeholder="请输入逻辑图名称"></el-input>
           </el-form-item>
           <el-form-item label="分类" prop="classifyId" :rules="{required:true,message:'请选择分类',trigger:'change'}" >
-            <el-popover
-              placement="bottom"
-              width="400"
-              popper-class="classify-popper"
-              trigger="click"
-              v-model="selectClassifyShow">
-                <tree :nodes="onlyClassifyTreeData" :setting="selectSetting" key="saveOther" @onCreated="getSelectZTree" @onClick="selectClassify" />
-                <el-cascader 
-                slot="reference"
-                :options="onlyClassifyTreeData"
-                :props="{children: 'Children',
-                  label: 'SandboxClassifyName',
-                   value: 'SandboxClassifyId',emitPath:false,checkStrictly:true}"
-                v-model="saveOtherForm.classifyId" 
-                popper-class="classify-cascader-popper"
-                placeholder="请选择分类">
-                </el-cascader>
-            </el-popover>
+            <el-cascader 
+            :options="onlyClassifyTreeData"
+            @change="classifyTreeChange"
+            :props="{children: 'Children',
+              label: 'SandboxClassifyName',
+                value: 'SandboxClassifyId',checkStrictly:true}"
+            v-model="saveOtherClassifys" 
+            placeholder="请选择分类">
+            </el-cascader>
           </el-form-item>
         </el-form>
         <div style="text-align: center;padding:40px 0 ;">
@@ -210,7 +205,6 @@ import { myGraph } from './common/gragh';
     mixins:[mindmap],
     watch: {
       initData(newval) {
-        console.log(newval);
         if(!this.graph){
           this.$nextTick(()=>{
             this.init()
@@ -261,9 +255,7 @@ import { myGraph } from './common/gragh';
             showLine:false,
             showIcon:false,
             selectedMulti:false,
-            addDiyDom: this.addDiyDom,
-            // addHoverDom: this.addHoverDom,
-		        // removeHoverDom: this.removeHoverDom
+            addHoverDom: this.addHoverDom,
           },
           edit:{
             enable:true,
@@ -283,25 +275,11 @@ import { myGraph } from './common/gragh';
           }
         },
         zTreeObj:{},
-        selectSetting:{
-          data:{
-            key:{
-              name:"SandboxClassifyName",
-              children:"Children"
-            }
-          },
-          view:{
-            showLine:false,
-            showIcon:false,
-            selectedMulti:false
-          }
-        },
-        selectClassifyShow:false,
-        selectZTreeObj:{},
         lockLoding:null,
         viewSandbox:{},
         activeNode:{},
         addClassifyNodeTid:'',
+        locationNode:'',
         movingRecoveData:{
           targetNode:null,
           treeNode:null,
@@ -309,6 +287,7 @@ import { myGraph } from './common/gragh';
         },
         graph:null,
         initData:{},
+        customButtonDom:'',
         // ------- 添加分类弹窗
         classifyAddTitle:"添加分类",
         classifyAddShow:false,
@@ -316,7 +295,8 @@ import { myGraph } from './common/gragh';
         classifyForm:{
           SandboxClassifyId:0,
           SandboxClassifyName:'',
-          ChartPermissionId:null,
+          ChartPermissionId:0,
+          ChartPermissionName:'',
           ParentId:0,
           Level:0
         },
@@ -337,8 +317,7 @@ import { myGraph } from './common/gragh';
           chartName:"",
           classifyId:""
         },
-        saveOtherClassifys:'',
-        locationActiveNode:'',
+        saveOtherClassifys:[],
         operationType:'view',
         popoverVisible:false,
         popoverFlod:true,
@@ -347,48 +326,27 @@ import { myGraph } from './common/gragh';
         checkedLinkList:[],
         linkNode:null,
         popoverTimeout:null,
-        isSlideLeft:false
+        isSlideLeft:false,
+        locationParentIds:''
       }
     },
     created(){
       this.getClassify()
+      if(sessionStorage.getItem("sandboxEditBack")){
+        this.locationParentIds=sessionStorage.getItem("sandboxEditBack").split(',')
+        this.getSandboxDetailFun(this.locationParentIds[this.locationParentIds.length-1])
+      }else{
+        this.getSandboxList()
+      }
       this.getSandboxClassify()
-      this.getSandboxClassifyOnly()
-      this.getSandboxList()
-      // this.setting.async={
-        // enable:false,
-        // type:'head'
-      //   url:(()=>{
-      //     console.log(process.env);
-      //     // console.log(process.env.VUE_APP_API_ROOT,'process.env.VUE_APP_API_ROOT');
-      //     // if(process.env.NODE_ENV === "development"){
-      //     //   return "http://8.136.199.33:7777/adminapi/sandbox/classify/list"
-      //     // }else{
-      //       return process.env.VUE_APP_API_ROOT+'/sandbox/classify/list'
-      //     // }
-      //   })(),
-      //   type:'get',
-      //   autoParam: ["SandboxClassifyId"],
-      //   otherParam:{ "IsShowMe":this.isOnlyMe},
-      //   dataFilter: (treeId,parentNode,responseData)=>{
-      //     console.log(treeId,parentNode,responseData,'responseData');
-      //     return responseData.Data.AllNodes
-      //   },
-      //   headers:{
-      //     Authorization:localStorage.getItem("auth"),
-      //     Uuid:localStorage.getItem("uuid") || "",
-      //     AccessToken:localStorage.getItem("uuid")+"--zheshiyigename",
-      //   }
-      // }
     },
     mounted(){
-      // this.init()
       this.popoverDom = $('#link-popover')[0];
       this.popoverTriggerDom = $('#link-reference')[0];
       
       this.popoverDom.addEventListener('mouseenter',this.clearPopoverTimeout)
       this.popoverDom.addEventListener('mouseleave',this.closePopover)
-
+      this.customButtonDom = $('#custom-button-zone')[0]
     },
     beforeDestroy(){
       this.popoverDom.removeEventListener('mouseenter',this.clearPopoverTimeout)
@@ -401,20 +359,20 @@ import { myGraph } from './common/gragh';
         customInterence.getvariety({
           CompanyType: 'ficc'
         }).then(res => {
-          console.log(res);
           if(res.Ret !== 200)  return
             this.classifyArr = res.Data.List||[ ]
         })
       },
       // 获取沙盘图分类
       getSandboxClassify(parentNode,locationNode) {
-        console.log(parentNode,locationNode,'parentNode,locationNode');
+        // parentNode--父节点
+        // locationNode--展开父节点后需要定位的子节点,拖拽后
         const sandboxClassifyId = parentNode ? parentNode.SandboxClassifyId:0
         sandInterface.getSandboxClassify({SandboxClassifyId:sandboxClassifyId,IsShowMe:this.searchParams.IsShowMe}).then(res=>{
-          console.log(res);
           if (res.Ret === 200) {
             let nodesData=res.Data.AllNodes || []
             nodesData.map(item =>{
+              // 添加是否是目录的字段
               item.isCatalogue = item.SandboxId?false:true
             })
             if(parentNode){
@@ -422,46 +380,45 @@ import { myGraph } from './common/gragh';
             }else{
               this.treeData = nodesData
             }
-            if(locationNode){
+            let location = locationNode || this.locationNode
+            if(location){
               let searchNode
-              let locationId = locationNode.isCatalogue?locationNode.SandboxClassifyId:locationNode.SandboxId
+              let locationId = location.isCatalogue?location.SandboxClassifyId:location.SandboxId
               if(parentNode){
-                if(locationNode.isCatalogue){
+                if(location.isCatalogue){
                   searchNode=this.zTreeObj.getNodesByParam('SandboxClassifyId',+locationId,parentNode)
                 }else{
                   searchNode=this.zTreeObj.getNodesByParam('SandboxId',+locationId,parentNode)
                 }
-                console.log(searchNode,'searchNode');
                 if(!(searchNode && searchNode.length>0)) return 
                 this.zTreeClick(null,'',searchNode[0],1)
                 this.zTreeObj.selectNode(searchNode[0])
               }else{
                 requestAnimationFrame(()=>{
                   searchNode=this.zTreeObj.getNodesByParam('SandboxClassifyId',+locationId)
-                  console.log(searchNode,'searchNode');
                   if(!(searchNode && searchNode.length>0)) return 
                   this.zTreeClick(null,'',searchNode[0],1)
                   this.zTreeObj.selectNode(searchNode[0])
                 })
               }
+              this.locationNode=''
+            }else if(this.locationParentIds && this.locationParentIds.length>0){
+              // 获取分类列表后需要定位
+              requestAnimationFrame(()=>{
+                this.sandboxLocation(this.locationParentIds)
+                this.locationParentIds=[]
+                sessionStorage.removeItem('sandboxEditBack')
+              })
 
             }
           }
         })
       },
-      getSandboxClassifyOnly(){
-        sandInterface.getSandboxClassifyOnly().then(res=>{
-          if (res.Ret === 200) {
-            this.onlyClassifyTreeData=res.Data.AllNodes || []
-          }
-        })
-      },
       getSandboxList(type){
         if(type == 'setCurrentIndex'){
           this.searchParams.CurrentIndex=1
         }
         sandInterface.getSandboxListV2(this.searchParams).then(res=>{
-          console.log(res,'res');
           if(res.Ret == 200){
             if(!res.Data){
               this.pictureList=[]
@@ -477,45 +434,43 @@ import { myGraph } from './common/gragh';
           }
         })
       },
+      getSandboxDetailFun(SandboxId){
+        sandInterface.getSandboxDetail({SandboxId:SandboxId || this.activeNode.SandboxId}).then(res=>{
+          if(res.Ret == 200){
+            this.viewSandbox=res.Data
+            this.rightType='chart'
+            this.initData = JSON.parse(this.viewSandbox.Content)
+          }
+        })
+      },
       getZTree(zTree){
         this.zTreeObj=zTree
       },
-      getSelectZTree(zTree){
-        this.selectZTreeObj=zTree
-      },
-      selectClassify(event,treeId,treeNode,clickFlag){
-        this.sandSaveParams.SandboxClassifyId = treeNode.SandboxClassifyId
-        this.selectClassifyShow = false
-      },
       zTreeDragBefore(treeId,treeNodes){
         return this.permissionBtn.isShowBtn('sandboxPermission','sandbox_classify_move')
       },
       zTreeDropBefore(treeId,treeNodes,targetNode,moveType,isCopy){
-        console.log(treeId,treeNodes,targetNode,moveType,isCopy,'zTreeDropBefore');
         if((!targetNode) && (!moveType)) return false
         if(((!treeNodes[0].isCatalogue) && targetNode.Level==1 && moveType!='inner')||
         ((!targetNode.isCatalogue) && moveType=='inner')||
         (treeNodes[0].isCatalogue && targetNode.Level==5 && moveType=='inner')){
           return false
         }
-
-        // 接口失败后的还原
-        // this.movingRecoveData.treeNode=treeNodes[0]
-        // if(treeNodes[0].getPreNode()){
-        //   this.movingRecoveData.targetNode = treeNodes[0].getPreNode()
-        //   this.movingRecoveData.moveType = "next"
-        // }else if(treeNodes[0].getNextNode()){
-        //   this.movingRecoveData.targetNode = treeNodes[0].getNextNode()
-        //   this.movingRecoveData.moveType = "prev"
-        // }else if(treeNodes[0].getParentNode()){
-        //   this.movingRecoveData.targetNode = treeNodes[0].getParentNode()
-        //   this.movingRecoveData.moveType = "inner"
-        // }
+        // 用于接口失败后的还原位置
+        this.movingRecoveData.treeNode=treeNodes[0]
+        if(treeNodes[0].getPreNode()){
+          this.movingRecoveData.targetNode = treeNodes[0].getPreNode()
+          this.movingRecoveData.moveType = "next"
+        }else if(treeNodes[0].getNextNode()){
+          this.movingRecoveData.targetNode = treeNodes[0].getNextNode()
+          this.movingRecoveData.moveType = "prev"
+        }else if(treeNodes[0].getParentNode()){
+          this.movingRecoveData.targetNode = treeNodes[0].getParentNode()
+          this.movingRecoveData.moveType = "inner"
+        }
       },
       zTreeDrop(e,treeId,treeNodes,targetNode,moveType,isCopy){
-        console.log(treeId,treeNodes[0],targetNode,moveType,isCopy,'zTreeDrop');
         if((!targetNode) && (!moveType)) return
-        console.log(treeNodes[0].getParentNode(),targetNode.getParentNode());
         let parentNode = treeNodes[0].getParentNode()
         let prevNode = treeNodes[0].getPreNode()
         let nextNode = treeNodes[0].getNextNode()
@@ -536,48 +491,26 @@ import { myGraph } from './common/gragh';
               this.zTreeObj.removeChildNodes(parentNode)
             }
             this.getSandboxClassify(parentNode,treeNodes[0])
+          }else{
+            // 接口失败后的还原位置
+            let result=this.zTreeObj.moveNode(this.movingRecoveData.targetNode,this.movingRecoveData.treeNode,this.movingRecoveData.moveType)
+            if(!result){
+              this.$message.error('目录位置还原失败,刷新目录')
+              setTimeout(()=>{
+                this.getSandboxClassify()
+              },1000)
+            }
           }
         })
-        // if((!targetNode) && (!moveType)) return
-        // let parentNode = treeNodes[0].getParentNode()
-        // let prevNode = treeNodes[0].getPreNode()
-        // let nextNode = treeNodes[0].getNextNode()
-        // //移动分类
-        // let params={
-        //   ClassifyId:treeNodes[0].SandboxClassifyId,
-        //   SandboxId:treeNodes[0].isCatalogue?0:treeNodes[0].SandboxId,
-        //   ParentClassifyId:parentNode?parentNode.SandboxClassifyId:0,
-        //   PrevId:prevNode? (prevNode.isCatalogue?prevNode.SandboxClassifyId:prevNode.SandboxId) :0,
-        //   NextId:nextNode? (nextNode.isCatalogue?nextNode.SandboxClassifyId:nextNode.SandboxId) :0,
-        //   PrevType:prevNode?(prevNode.isCatalogue?1:2):0,
-        //   NextType:nextNode?(nextNode.isCatalogue?1:2):0
-        // }
-        // console.log(params);
-        // sandInterface.sandboxClassifyMove(params).then(res=>{
-        //   if(res.Ret == 200){
-        //     this.$message.success('移动分类成功')
-        //   }else{
-        //     // let result=this.zTreeObj.moveNode(this.movingRecoveData.targetNode,this.movingRecoveData.treeNode,this.movingRecoveData.moveType)
-        //     // if(!result){
-        //     //   window.location.reload()
-        //     // }
-        //   }
-        // })
       },
       zTreeExpandBefore(treeId, treeNode){
-        // console.log( treeId, treeNode);
         if(treeNode.Children && treeNode.Children.length>0){
           return true
         }else{
           this.getSandboxClassify(treeNode)
         }
       },
-      zTreeExpand(event, treeId, treeNode){
-        // console.log(event, treeId, treeNode);
-      },
       zTreeClick(event, treeId, treeNode,clickFlag){
-        console.log(event, treeId, treeNode,clickFlag);
-
         if(clickFlag==1){
           if(this.activeNode.SandboxClassifyId == treeNode.SandboxClassifyId &&
           this.activeNode.SandboxId == treeNode.SandboxId){
@@ -589,26 +522,18 @@ import { myGraph } from './common/gragh';
             this.searchParams.CurrentIndex=1
             this.searchParams.SandboxClassifyId = treeNode.SandboxClassifyId
             this.getSandboxList('setCurrentIndex')
-            // this.rightType='list'
           }else{
             // 沙盘图
-            sandInterface.getSandboxDetail({SandboxId:this.activeNode.SandboxId}).then(res=>{
-              console.log(res);
-              if(res.Ret == 200){
-                this.viewSandbox=res.Data
-                this.rightType='chart'
-                this.initData = JSON.parse(this.viewSandbox.Content)
-              }
-            })
+            this.getSandboxDetailFun()
           }
         }
 
         if(clickFlag==0 && treeNode.isCatalogue){
+          // 取消选中
           this.activeNode={}
           this.searchParams.CurrentIndex=1
           this.searchParams.SandboxClassifyId = ''
           this.getSandboxList('setCurrentIndex')
-          // this.rightType='list'
         }
       },
       onlyMeHandler(){
@@ -618,7 +543,6 @@ import { myGraph } from './common/gragh';
         this.getSandboxList('setCurrentIndex')
       },
       searchHandle(query) {
-        // console.log(query,"搜索");
         this.searchCurrentIndex = 1;
         this.KeyWord = query;
         this.searchSandbox()
@@ -641,7 +565,6 @@ import { myGraph } from './common/gragh';
       },
       searchLoad() {
         // 加载更多
-        console.log("加载更多");
         if(!this.searchHaveMore) return;
         this.searchCurrentIndex++
         this.searchSandbox()
@@ -649,7 +572,6 @@ import { myGraph } from './common/gragh';
       /* 聚焦获取当前检索 */
       inputFocusHandle(e) {
         // 选取
-        console.log('选取',e.target.value);
         this.searchCurrentIndex = 1;
         this.KeyWord = e.target.value;
         if(this.KeyWord) {
@@ -678,12 +600,13 @@ import { myGraph } from './common/gragh';
       },
       addClassify(e,node){
         e.stopPropagation()
-        console.log(node);
         this.addClassifyNodeTid = node.tId
         this.lastLevelClassifyName = this.getParentNodeName(node)
         this.classifyAddTitle="添加分类"
         this.classifyForm.Level = node.Level
         this.classifyForm.ParentId = node.SandboxClassifyId
+        this.classifyForm.ChartPermissionId = node.ChartPermissionId
+        this.classifyForm.ChartPermissionName = node.ChartPermissionName
         this.classifyAddShow=true
       },
       getParentNodeName(node){
@@ -695,13 +618,16 @@ import { myGraph } from './common/gragh';
         }
       },
       editClassify(e,node){
-        console.log(node);
         e.stopPropagation()
+        this.locationNode = node
         let pNode = node.getParentNode()
         this.lastLevelClassifyName = pNode ? pNode.SandboxClassifyName:''
         this.classifyForm.SandboxClassifyId = node.SandboxClassifyId
+        this.classifyForm.Level = node.Level
         this.classifyForm.SandboxClassifyName = node.SandboxClassifyName
-        this.classifyAddTitle="重命名"
+        this.classifyForm.ChartPermissionId = node.ChartPermissionId
+        this.classifyForm.ChartPermissionName = node.ChartPermissionName
+        this.classifyAddTitle="编辑分类"
         this.classifyAddShow=true
       },
       deleteClassify(e,node){
@@ -740,8 +666,7 @@ import { myGraph } from './common/gragh';
                 res.Data.DeleteStatus === 0 && node.SandboxId 
                 ? this.delHandle(node.SandboxClassifyId, node.SandboxId, 1)
                 : this.delHandle(node.SandboxClassifyId, node.SandboxId);
-              }).catch(() => {         
-              });
+              }).catch(() => {});
           }
         })
       },
@@ -754,16 +679,15 @@ import { myGraph } from './common/gragh';
           if (res.Ret === 200) {
             this.zTreeObj.removeNode(currentNode)
             this.$message.success(res.Msg);
-            // if(type && res.Data.SandboxId){
-              
-            // }else{
-
-            // }
           }
         });
       },
+      chartPermissionIdChange(value){
+        this.classifyForm.ChartPermissionName=
+        this.$refs.chartPermissionCascader.getCheckedNodes()[0] ?
+        this.$refs.chartPermissionCascader.getCheckedNodes()[0].label+'' || '':''
+      },
       classifyAddSubmit(){
-        console.log(this.classifyForm);
         //提交
         this.$refs.classifyFormRef.validate(valid=>{
           if(valid){
@@ -771,17 +695,23 @@ import { myGraph } from './common/gragh';
               //编辑
               let params={
                 SandboxClassifyId:this.classifyForm.SandboxClassifyId,
-                SandboxClassifyName:this.classifyForm.SandboxClassifyName
+                SandboxClassifyName:this.classifyForm.SandboxClassifyName,
+                ChartPermissionId:this.classifyForm.ChartPermissionId,
+                ChartPermissionName:this.classifyForm.ChartPermissionName,
               }
               sandInterface.editSandboxClassify(params).then(res=>{
                 if(res.Ret == 200){
                   this.classifyAddShow=false
                   this.$message.success(this.classifyAddTitle+"成功")
-                  let currentNode = this.zTreeObj.getSelectedNodes()[0]
+                  let parentNode = this.locationNode.getParentNode()
 
-                  currentNode.SandboxClassifyName = this.classifyForm.SandboxClassifyName
-                  this.zTreeObj.updateNode(currentNode)
-                  // this.getSandboxClassify()
+                  if(!parentNode){
+                    this.getSandboxClassify(null,this.locationNode)
+                  }else{
+                    this.zTreeObj.removeChildNodes(parentNode)
+                    this.zTreeObj.expandNode(parentNode,true,false,false,true)
+                    this.zTreeClick(null,'',this.locationNode,1)
+                  }
                 }
               })
             }else{
@@ -790,7 +720,8 @@ import { myGraph } from './common/gragh';
                 SandboxClassifyName:this.classifyForm.SandboxClassifyName,
                 ParentId:this.classifyForm.ParentId,
                 Level:this.classifyForm.Level,
-                ChartPermissionId:this.classifyForm.ChartPermissionId
+                ChartPermissionId:this.classifyForm.ChartPermissionId,
+                ChartPermissionName:this.classifyForm.ChartPermissionName,
               }
               sandInterface.addSandboxClassify(params).then(res=>{
                 if(res.Ret == 200){
@@ -800,11 +731,8 @@ import { myGraph } from './common/gragh';
                     this.getSandboxClassify()
                   }else{
                     let curNode = this.zTreeObj.getNodeByTId(this.addClassifyNodeTid)
-                    // console.log(curNode,'');
                     this.zTreeObj.removeChildNodes(curNode)
-                    // this.$nextTick(()=>{
-                      this.zTreeObj.expandNode(curNode,true,false,false,true)
-                    // })
+                    this.zTreeObj.expandNode(curNode,true,false,false,true)
                   }
                 }
               })
@@ -817,7 +745,8 @@ import { myGraph } from './common/gragh';
         this.classifyForm={
           SandboxClassifyId:0,
           SandboxClassifyName:'',
-          ChartPermissionId:null,
+          ChartPermissionId:0,
+          ChartPermissionName:'',
           ParentId:0,
           Level:0
         }
@@ -829,13 +758,9 @@ import { myGraph } from './common/gragh';
         let scrollTop = this.$refs.pictureListRef.scrollTop;
         let clientHeight = this.$refs.pictureListRef.clientHeight;
         let scrollHeight = this.$refs.pictureListRef.scrollHeight;
-        // console.log('scrollTop:',scrollTop)
-        // console.log('clientHeight:',clientHeight)
-        // console.log('scrollHeight:',scrollHeight)
         if(scrollTop + clientHeight >= scrollHeight-10 && this.pictureHaveMore){
           this.searchParams.CurrentIndex++
           this.getSandboxList();
-          console.log("加载更多");
         }
       },300),
       /* 展示详情 */
@@ -849,19 +774,10 @@ import { myGraph } from './common/gragh';
         this.sandboxLocation(ParentClassifys)
       },
       async sandboxLocation(ParentClassifys){
-        console.log(ParentClassifys,'ParentClassifys');
         let beActiveNode=''
         for (let i = 0; i < ParentClassifys.length; i++) {
           const element = ParentClassifys[i];
-          // if(i == (ParentClassifys.length-1)){
-          //   console.log(+element,beActiveNode,'element');
-          //   let searchNode=this.zTreeObj.getNodesByParam('SandboxId',+element,beActiveNode)
-          //   console.log(searchNode[0]);
-          //   this.zTreeObj.selectNode(searchNode[0],false,false)
-          //   return 
-          // }
           let searchNode=this.zTreeObj.getNodesByParam('SandboxClassifyId',+element,beActiveNode)
-          console.log(searchNode,'searchNode',i);
           if(!(searchNode&&searchNode.length>0)){
             if(!beActiveNode){
               break
@@ -883,12 +799,11 @@ import { myGraph } from './common/gragh';
             beActiveNode = searchNode[0]
           }
         }
-        this.locationActiveNode=beActiveNode
         // 选中
-        requestAnimationFrame(()=>{
+        this.activeNode = beActiveNode
+        setTimeout(()=>{
           this.zTreeObj.selectNode(beActiveNode)
-          this.activeNode = beActiveNode
-        })
+        },300)
       },
       expandNodeAsync(parentNode,activeId,isLast=false){
         return new Promise((resolve,reject)=>{
@@ -898,7 +813,6 @@ import { myGraph } from './common/gragh';
           }else{
             resultNode = this.zTreeObj.getNodesByParam('SandboxClassifyId',activeId,parentNode)
           }
-          console.log(resultNode,'resolve(resultNode)');
           if(resultNode.length>0){
             resolve(resultNode)
             return 
@@ -924,7 +838,6 @@ import { myGraph } from './common/gragh';
       },
       copyHandle:_.debounce(function ({ PicUrl }){
         if(!PicUrl) return this.$message('暂无内容可复制')
-        console.log("复制");
         this.lockLoding = this.$loading({
           lock: true,
           text: '复制图片中...',
@@ -965,7 +878,6 @@ import { myGraph } from './common/gragh';
         }
       },500),
       deleteHandle(item,type){
-        console.log(item,type);
         this.$confirm("确定删除该沙盘图吗?", "提示", {
           type: "warning",
         })
@@ -977,7 +889,6 @@ import { myGraph } from './common/gragh';
             if (res.Ret === 200) {
               this.$message.success(res.Msg);
               let result = this.zTreeObj.getNodesByParam('SandboxId',item.SandboxId)[0]
-              console.log(result);
               if(type=='inList'){
                 // 在沙盘图列表中删除
                 if(result){
@@ -985,8 +896,10 @@ import { myGraph } from './common/gragh';
                 }
               }else{
                 // 在沙盘图详情删除
-                this.sandboxLocation([result.SandboxClassifyId])
                 this.zTreeObj.removeNode(result)
+                let parentNode = result.getParentNode()
+                this.zTreeObj.selectNode(parentNode)
+                this.zTreeClick(null,'',parentNode,1)
               }
               this.getSandboxList('setCurrentIndex')
               
@@ -995,16 +908,15 @@ import { myGraph } from './common/gragh';
         })
         .catch(() => {});
       },
-      addDiyDom(treeId, treeNode) {
-        // console.log(treeNode,'treeId, treeNode');
+      addHoverDom(treeId, treeNode){
         var aObj = $("#" + treeNode.tId + "_a");
-        if ($("#diyBtn_"+treeNode.SandboxClassifyId).length>0) return;
+        if (aObj.find('#custom-button-zone').length>0) return;
+        let dom = this.customButtonDom.cloneNode(true)
+        let addClassifyDom = $(dom).find('.add-classify-img')[0]
+        let editClassifyDom = $(dom).find('.edit-classify-img')[0]
+        let delClassifyDom = $(dom).find('.delete-classify-img')[0]
         if(treeNode.isCatalogue){
           //目录添加自定义按钮
-          let dom = $('#custom-button-zone')[0].cloneNode(true)
-          let addClassifyDom = $(dom).find('.add-classify-img')[0]
-          let editClassifyDom = $(dom).find('.edit-classify-img')[0]
-          let delClassifyDom = $(dom).find('.delete-classify-img')[0]
           if(treeNode.Level>4){
             addClassifyDom && (addClassifyDom.style.display='none')
           }else{
@@ -1013,15 +925,13 @@ import { myGraph } from './common/gragh';
           editClassifyDom && editClassifyDom.addEventListener("click",(e)=>this.editClassify(e,treeNode))
           delClassifyDom && delClassifyDom.addEventListener("click",(e)=>this.deleteClassify(e,treeNode))
 
-          aObj.append(dom);
+        }else{
+          addClassifyDom && (addClassifyDom.style.display='none')
+          editClassifyDom && (editClassifyDom.style.display='none')
+          delClassifyDom && (delClassifyDom.style.display='none')
         }
-
+        aObj.append(dom);
       },
-      // removeHoverDom(treeId, treeNode) {
-      //   console.log(treeId, treeNode,'treeId, treeNode');
-      //   $("#diyBtn_"+treeNode.SandboxClassifyId).unbind().remove();
-	    //   $("#diyBtn_space_" +treeNode.SandboxClassifyId).unbind().remove();
-      // }
       addSand(){
         const { href } = this.$router.resolve({ path: '/sandflow' });
         window.open(href, '_blank');
@@ -1031,12 +941,21 @@ import { myGraph } from './common/gragh';
         window.open(href, '_blank');
       },
       saveOther(){
+        sandInterface.getSandboxClassifyOnly().then(res=>{
+          if (res.Ret === 200) {
+            this.onlyClassifyTreeData=res.Data.AllNodes || []
+          }
+        })
         this.saveOtherForm.chartName = this.viewSandbox.Name+"(1)"
         this.saveOtherShow=true
       },
+      classifyTreeChange(value){
+        if(!value){
+          this.saveOtherForm.classifyId=''
+        }
+        this.saveOtherForm.classifyId=value[value.length-1]
+      },
       saveOtherSubmit: _.debounce( function() {
-        // console.log(this.viewSandbox);
-        // return 
         if(!this.graph.toJSON().cells.length) return this.$message.warning('画布无内容');
         this.$refs.saveOtherFormRef.validate(valid=>{
           if(valid){
@@ -1068,12 +987,13 @@ import { myGraph } from './common/gragh';
                 this.lockLoding.close();
                 return;
               }
-              console.log(sandData,'sandData');
               this.lockLoding.close();
               this.$message.success("另存为成功")
-              let saveOtherIds = this.saveOtherClassifys.split(',')
-              saveOtherIds.push(sandData.SandboxId)
-              this.sandboxLocation(saveOtherIds)
+              //沙盘图详情
+              this.getSandboxDetailFun(sandData.SandboxId)
+
+              this.saveOtherClassifys.push(sandData.SandboxId)
+              this.sandboxLocation(this.saveOtherClassifys)
               this.saveOtherShow=false
             },{
               preserveDimensions:true,//让svg为实际图片大小
@@ -1088,19 +1008,6 @@ import { myGraph } from './common/gragh';
                 svg.setAttribute('viewBox',`${x-30} ${y-30} ${width+60} ${height+60}`)
                 // // 在图表右下方 加上"来源:弘则研究"字样
                 // let gNode = svg.getElementsByClassName('x6-graph-svg-viewport')[0]
-                // 去掉不该截图的添加图标
-                let leftImg = svg.getElementsByClassName('left-topic-image')
-                for (let i = 0; i < leftImg.length; i++) {
-                  const element = leftImg[i];
-                  element.parentElement.removeChild(element)
-                  i--
-                }
-                let rightImg = svg.getElementsByClassName('right-topic-image')
-                for (let i = 0; i < rightImg.length; i++) {
-                  const element = rightImg[i];
-                  element.parentElement.removeChild(element)
-                  i--
-                }
                 // let textNode = document.createElement('text')
                 // textNode.setAttribute('x',(x-tx+width)/zoom-85)
                 // textNode.setAttribute('y',(y-ty+height)/zoom+27)
@@ -1117,6 +1024,12 @@ import { myGraph } from './common/gragh';
                 .x6-port {
                     visibility: hidden;
                 }
+                .left-topic-image{
+                  visibility:hidden;
+                }
+                .right-topic-image{
+                  visibility: hidden;
+                }
                 ` 
             })
           }
@@ -1126,10 +1039,11 @@ import { myGraph } from './common/gragh';
       },500),
       saveOtherClosed(){
         this.saveOtherForm={
-          chartName:"逻辑图名称",
+          chartName:"",
           classifyId:""
         }
-        this.selectZTreeObj.cancelSelectedNode()
+        this.saveOtherClassifys=[]
+        // this.selectZTreeObj.cancelSelectedNode()
         this.$refs.saveOtherFormRef.clearValidate()
       },
       copySandHandle: _.debounce(function() {
@@ -1153,8 +1067,6 @@ import { myGraph } from './common/gragh';
         img.onload = ()=>{
           canvas.width = img.width;
           canvas.height = img.height;
-          // console.log('width',img.width)
-          // console.log('height',img.height)
           ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
           ctx.fillStyle="#fff";
           ctx.fillRect(0, 0, img.width, img.height);
@@ -1182,26 +1094,13 @@ import { myGraph } from './common/gragh';
         preserveDimensions:true,//让svg为实际图片大小
         beforeSerialize:(svg)=>{
           const {x,y,width,height} = this.graph.getContentBBox(cells)
-          let {tx,ty} = this.graph.translate()
+          // let {tx,ty} = this.graph.translate()
           //给导出的svg增加一点宽高
           svg.setAttribute('width',width+60)
           svg.setAttribute('height',height+60) 
           //设置viewBox使图像居中
           svg.setAttribute('viewBox',`${x-30} ${y-30} ${width+60} ${height+60}`)
           // let gNode = svg.getElementsByClassName('x6-graph-svg-viewport')[0]
-          // 去掉不该截图的添加图标
-          let leftImg = svg.getElementsByClassName('left-topic-image')
-          for (let i = 0; i < leftImg.length; i++) {
-            const element = leftImg[i];
-            element.parentElement.removeChild(element)
-            i--
-          }
-          let rightImg = svg.getElementsByClassName('right-topic-image')
-          for (let i = 0; i < rightImg.length; i++) {
-            const element = rightImg[i];
-            element.parentElement.removeChild(element)
-            i--
-          }
           // let textNode = document.createElement('text')
           // textNode.setAttribute('x',x-tx+width-90)
           // textNode.setAttribute('y',y-ty+height+22)
@@ -1210,38 +1109,28 @@ import { myGraph } from './common/gragh';
           // textNode.innerText = '来源:弘则研究'
           // gNode.appendChild(textNode)
             },
-        copyStyles:false,
-        stylesheet: `
+          copyStyles:false,
+          stylesheet: `
             svg{
                 background-color:white;
             }
           .x6-port {
               visibility: hidden;
+          }
+          .left-topic-image{
+            visibility:hidden;
+          }
+          .right-topic-image{
+            visibility: hidden;
           }` 
         })
       },500),
-      selectClassify(event,treeId,treeNode,clickFlag){
-        // console.log(treeNode);
-        this.saveOtherForm.classifyId = treeNode.SandboxClassifyId
-        this.saveOtherClassifys=this.getParentClassifyIds(treeNode)
-        this.selectClassifyShow = false
-      },
-      getParentClassifyIds(treeNode){
-        let parentNode = treeNode.getParentNode()
-        if(parentNode){
-          return this.getParentClassifyIds(parentNode)+','+treeNode.SandboxClassifyId
-        }else{
-          return treeNode.SandboxClassifyId+''
-        }
-      },
       //==============================画布
       // 初始化画布
       init() {
-        const graph = new myGraph('sand-chart-body',null,'','view');
-        console.log(graph,'graph');
+        const graph = new myGraph('sand-chart-body',null,'view');
         this.graph = graph;
         graph.on('node:mouseenter', ({ node, e }) => {
-          console.log(node);
           let data = node.data
           this.linkNode = node
           if(data && data.linkData && data.linkData.length>0){
@@ -1266,10 +1155,6 @@ import { myGraph } from './common/gragh';
                 })
                 let clinetPositon=graph.localToClient(node.position())
                 let size=node.size()
-                console.log(clinetPositon,'clinetPositon',node.position());
-                // const dom = $('#link-reference')[0];
-                // console.log(this.popoverTriggerDom,'domdomdom');
-                console.log(clinetPositon.x+size.width/2,clinetPositon.y);
                 this.popoverTriggerDom.style.left = clinetPositon.x+size.width/2 + 'px';
                 this.popoverTriggerDom.style.top = clinetPositon.y + 'px';
                 this.popoverVisible=true
@@ -1300,7 +1185,6 @@ import { myGraph } from './common/gragh';
         })
       },
       navigateTo(item){
-        console.log(item,'item');
         if(item.Type == 1){
           if(item.databaseType==0){
             // 普通指标

+ 649 - 0
src/views/sandbox_manage/sandFlowNew/components/addLInkDia.vue

@@ -0,0 +1,649 @@
+<template>
+    <el-dialog :modal-append-to-body='false' title="添加链接" :visible.sync="show" 
+    :close-on-click-modal="false" width="872px" top="5vh">
+      <div class="add-link-box">
+        <div class="link-box-option">
+          <el-select v-model="addLinkSearchParams.linkType" placeholder="链接类型" style="width: 240px;" @change="changeLinkType">
+            <el-option :label="item.label" :value="item.value" v-for="item in linkTypeList" :key="item.value"></el-option>
+          </el-select>
+          <el-select v-if="addLinkSearchParams.linkType==1"
+            v-model="search_dataBaseId"
+            v-loadMore="dataBaseSearchLoad"
+            ref="searchRef"
+            :filterable="!search_dataBaseId"
+            remote
+            clearable
+            placeholder="指标ID/指标名称"
+            style="width: 240px"
+            :remote-method="dataBaseSearch"
+            @click.native="dataBaseInputFocus"
+          >
+            <i slot="prefix" class="el-input__icon el-icon-search"></i>
+            <el-option
+              v-for="item in dataBaseOptions"
+              :key="item.EdbInfoId"
+              :label="item.EdbName"
+              :value="item.EdbInfoId"
+            >
+            </el-option>
+          </el-select>
+          <el-select v-else-if="addLinkSearchParams.linkType==2"
+            v-model="search_dataBaseId"
+            v-loadMore="dataBaseSearchLoad"
+            ref="searchRef"
+            :filterable="!search_dataBaseId"
+            remote
+            clearable
+            placeholder="图表名称"
+            style="width: 240px"
+            :remote-method="dataBaseSearch"
+            @click.native="dataBaseInputFocus"
+          >
+            <i slot="prefix" class="el-input__icon el-icon-search"></i>
+            <el-option
+              v-for="item in dataBaseOptions"
+              :key="item.ChartInfoId"
+              :label="item.ChartName"
+              :value="item.ChartInfoId"
+            >
+            </el-option>
+          </el-select>
+          <el-input v-else v-model="reportKeyWord" @input="searchReport"
+          placeholder="标题 / 创建人" style="width: 240px;" clearable >
+            <i slot="prefix" class="el-input__icon el-icon-search"></i>
+          </el-input>
+        </div>
+        <div class="link-box-content">
+          <!-- 指标 -->
+          <div class="link-content-dataIndex" v-if="addLinkSearchParams.linkType==1 && databaseTableData && databaseTableData.length>0">
+            <el-table :data="databaseTableData" border style="box-shadow: rgba(155, 170, 219, 0.2) 0px 3px 6px;">
+              <el-table-column label="指标Id" align="center">
+                <template slot-scope="scope">{{ scope.row.EdbCode }}</template>
+              </el-table-column>
+              <el-table-column label="指标名称" align="center" width="200">
+                <template slot-scope="scope">{{ scope.row.EdbName }}</template>
+              </el-table-column>
+              <el-table-column label="频度" align="center" width="50">
+                <template slot-scope="scope">{{ scope.row.Frequency }}</template>
+              </el-table-column>
+              <el-table-column label="单位" align="center">
+                <template slot-scope="scope">{{ scope.row.Unit }}</template>
+              </el-table-column>
+              <el-table-column label="起始时间" align="center" width="100">
+                <template slot-scope="scope">{{ scope.row.StartDate }}</template>
+              </el-table-column>
+              <el-table-column label="更新时间" align="center" width="160">
+                <template slot-scope="scope">{{ scope.row.ModifyTime }}</template>
+              </el-table-column>
+              <el-table-column label="来源" align="center">
+                <template slot-scope="scope">{{ scope.row.SourceName }}</template>
+              </el-table-column>
+              <el-table-column label="操作" align="center" width="50">
+                <template slot-scope="scope">
+                  <span class="delete-button">删除</span>
+                </template>
+              </el-table-column>
+            </el-table>
+            <ul 
+              class="value-ul" 
+              ref="valueUl" 
+              @scroll="databaseScrollHandle" 
+              v-show="databaseList.length">
+              <li
+                class="value-item"
+                v-for="item in databaseList"
+                :key="item.EdbDataId"
+              >
+                <span class="value-label">
+                  <span style="position: relative;">
+                    <i class="new-tag" v-if="databaseTableData[0].LatestDate===item.DataTime"></i>
+                    {{item.DataTime}}
+                  </span>
+                </span>
+                <span :class="['value-label',{'predict-act': databaseTableData[0].DataInsertConfig.Date===item.DataTime}]" style="min-width:200px;text-align:center;">
+                  <span :class="['value-style',{'predict-act': databaseTableData[0].DataInsertConfig.Date===item.DataTime}]">{{item.Value}}</span>
+                </span>
+              </li>
+              <li class="nodata value-item" v-if="!databaseList.length">暂无数据</li>
+            </ul>
+          </div>
+          <div class="link-content-chartIndex" v-else-if="addLinkSearchParams.linkType==2 && this.chartInfo && this.chartInfo.ChartInfoId">
+            <div class="chart-name">{{ this.chartInfo.ChartName }}</div>
+            <Chart :options="options" ref="chartRef" />
+          </div>
+          <div class="link-content-dataIndex" v-else-if="addLinkSearchParams.linkType==3 && this.reportList.length>0">
+            <el-table :data="this.reportList" border style="margin-bottom: 10px;" ref="reportTable"
+            @select="reportSelect" @select-all="reportSelect"> 
+              <el-table-column type="selection" width="40" align="center"></el-table-column>
+              <el-table-column label="报告标题" align="center" show-overflow-tooltip>
+                <template slot-scope="scope">
+                  <span >{{ scope.row.Title }}</span>
+                  <span  v-if="scope.row.MsgSendTime">
+                    ({{ scope.row.MsgSendTime.substring(5, 7)}}{{ scope.row.MsgSendTime.substring(8, 10) }})
+                  </span>
+                  <span v-else-if="scope.row.PublishTime">
+                    ({{ scope.row.PublishTime.substring(5, 7)}}{{ scope.row.PublishTime.substring(8, 10) }})
+                  </span>
+                  <span v-else-if="scope.row.CreateTime">
+                    ({{ scope.row.CreateTime.substring(5, 7)}}{{ scope.row.CreateTime.substring(8, 10) }})
+                  </span>
+                </template>
+              </el-table-column >
+              <el-table-column label="发布时间" align="center">
+                <template slot-scope="scope">
+                  <span>{{scope.row.PrePublishTime?scope.row.PrePublishTime:scope.row.PublishTime}}</span>
+                </template>
+              </el-table-column>
+            </el-table>
+            <m-page :page_no="reportParams.CurrentIndex" :pageSize="5" :total="reportTotal" @handleCurrentChange="pageChange"/>
+          </div>
+          <tableNoData text="暂无数据" v-else/>
+        </div>
+        <div class="link-box-tags">
+          <div class="link-box-tag" v-for="(item,index) in checkedLinkList" :key="item.RId">
+            <span @dblclick.stop="editLinkName(item)" v-if="!item.editing" @click="linkClick(item)">{{ item.Name }}</span>
+            <el-input v-else @blur="editLinkNameFinish(item)" 
+              v-model.trim="editingLabel" class="label-edit-input" ref="labelEditInput"/>
+            <img src="~@/assets/img/sand_new/delete_outline_1.png" @click="linkDelete(item,index)">
+          </div>
+        </div>
+        <div class="link-box-buttons">
+          <el-button type="info" style="width:120px;color:#333333;background-color:#F4F8FE" @click="cancelHandle">取消</el-button>
+          <el-button type="primary" style="width:120px;margin-left: 30px;" @click="saveLink">确定</el-button>
+        </div>
+      </div>
+		</el-dialog>
+</template>
+
+<script>
+import { chartSetMixin } from '../../../dataEntry_manage/mixins/chartPublic'
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+import mPage from "@/components/mPage.vue";
+import Chart from '../../../dataEntry_manage/components/chart.vue'
+import { dataBaseInterface,reportlist} from '@/api/api.js';
+
+  export default {
+    components:{
+      mPage,Chart
+    },
+    props:{
+      show:{
+        reuqired:true,
+        type:Boolean
+      },
+      linkList:{
+        type:Array,
+        default:()=>[]
+      }
+    },
+    mixins:[chartSetMixin],
+    watch:{
+      /* 选中搜索指标 展开目录 选中指标 展示数据 */
+      search_dataBaseId(newval) {
+        if (newval) {
+          if(this.addLinkSearchParams.linkType==1){
+            let search_obj = this.dataBaseOptions.find(
+              (item) => item.EdbInfoId === newval
+            );
+            if(search_obj){
+              this.checkedLinkList.push({
+                RId:this.addLinkSearchParams.linkType+'-'+search_obj.EdbInfoId,
+                Id:search_obj.EdbInfoId,
+                Name:search_obj.EdbName,
+                Type:this.addLinkSearchParams.linkType,
+                editing:false,
+                databaseType:search_obj.EdbInfoType, //0 普通指标 | 1 预测指标
+                detailParams:{
+                  code:search_obj.UniqueCode,
+                  id:search_obj.EdbInfoId,
+                  classifyId:search_obj.ClassifyId
+                }
+              })
+              this.activeItemRId=this.addLinkSearchParams.linkType+'-'+search_obj.EdbInfoId
+              this.initGetData()
+            }
+          }else{
+            let search_obj = this.dataBaseOptions.find(
+              (item) => item.ChartInfoId === newval
+            );
+            if(search_obj){
+              this.checkedLinkList.push({
+                RId:this.addLinkSearchParams.linkType+'-'+search_obj.ChartInfoId,
+                Id:search_obj.ChartInfoId,
+                Name:search_obj.ChartName,
+                Type:this.addLinkSearchParams.linkType,
+                editing:false,
+                detailParams:{
+                  code:search_obj.UniqueCode,
+                  id:search_obj.ChartInfoId
+                }
+              })
+              this.activeItemRId=this.addLinkSearchParams.linkType+'-'+search_obj.ChartInfoId
+              this.getChartDetail(search_obj.ChartInfoId)
+            }
+          }
+        }
+      },
+      edbData: {
+        handler(newval, oldval) {
+          newval.length && !this.chartInfo.WarnMsg && this.setChartOptionHandle(newval);
+        },
+        deep: true,
+      },
+      show(value){
+        if(value){
+          this.addLinkSearchParams.linkType=1
+          this.changeLinkType()
+          this.checkedLinkList = JSON.parse(JSON.stringify(this.linkList))
+        }
+      }
+    },
+    data() {
+      return {
+        linkTypeList:[
+          {value:1,label:"ETA指标/预测指标"},
+          {value:2,label:"ETA图库"},
+          {value:3,label:"ETA研报"}
+        ],
+        addLinkSearchParams:{
+          linkType:1
+        },
+        //添加链接:指标
+        search_dataBaseId:'',
+        dataBaseParams:{
+          pages:1,
+          searchText:'',
+          search_have_more:false
+        },
+        dataBaseOptions:[],
+
+        databaseTableData:[],
+        databaseList:[],
+        databaseHaveMore:false,
+        databasePageNo:1,
+        chartInfo:{},
+        edbData:[],
+        options:{},
+        reportKeyWord:'',
+        reportParams:{
+          CurrentIndex:1,
+          PageSize:5,
+        },
+        reportList:[],
+        selections:[],
+        checkedLinkList:[],
+        reportTotal:0,
+        editingLabel:'',
+        activeItemRId:'',
+      }
+    },
+    methods: {
+      // -------------------------------添加链接
+      changeLinkType(){
+        this.search_dataBaseId=''
+        this.dataBaseOptions=[]
+        this.dataBaseParams={
+          pages:1,
+          searchText:'',
+          search_have_more:false
+        }
+
+        this.databaseTableData=[]
+        this.databaseList=[]
+        this.databaseHaveMore=false
+        this.databasePageNo=1
+        
+        this.chartInfo={}
+        this.edbData=[]
+
+        this.reportKeyWord=''
+        this.reportList=[]
+      },
+      /* 搜索 */
+      dataBaseSearch(query) {
+        this.dataBaseParams.pages = 1;
+        this.dataBaseParams.searchText = query;
+        this.dataBaseSearchApi(this.dataBaseParams.searchText)
+      },
+      // 加载更多
+      dataBaseSearchLoad() {
+        if(!this.dataBaseParams.search_have_more) return;
+        this.dataBaseSearchApi(this.dataBaseParams.searchText,++this.dataBaseParams.pages);
+      },
+      /* 聚焦获取当前检索 */
+      dataBaseInputFocus(e) {
+        this.dataBaseParams.pages = 1;
+        this.dataBaseParams.searchText = e.target.value;
+        if(this.dataBaseParams.searchText) {
+          this.dataBaseSearchApi(this.dataBaseParams.searchText);
+        }else {
+          this.searchOptions = [];
+          this.dataBaseParams.search_have_more=false
+        }
+
+      },
+      dataBaseSearchApi(query,page=1) {
+        if(this.addLinkSearchParams.linkType==1){
+          sheetInterface.searchTarget({
+            KeyWord:query,
+            CurrentIndex: page
+          }).then(res => {
+            if(res.Ret !== 200) return
+            const { List,Paging } = res.Data;
+            this.dataBaseParams.search_have_more = page < Paging.Pages;
+            this.dataBaseOptions = page === 1 ? List : this.dataBaseOptions.concat(List);
+          })
+        }else{
+          dataBaseInterface.chartSearchByEs({
+            Keyword: query,
+            IsShowMe:false,
+            CurrentIndex: page
+          })
+          .then((res) => {
+            if (res.Ret !== 200) return
+            const { List,Paging } = res.Data;
+            this.dataBaseParams.search_have_more = page < Paging.Pages;
+            this.dataBaseOptions = page === 1 ? List : [...this.dataBaseOptions,...List];
+          });
+        }
+
+      },
+      initGetData() {
+        this.databasePageNo = 1;
+        if(this.$refs.edb_detail_data){
+          this.$refs.valueUl.scrollTop=0
+        }
+        this.getDatabaseList();
+      },
+      getDatabaseList(){
+        dataBaseInterface.targetList({
+          PageSize: 20,
+          CurrentIndex: this.databasePageNo,
+          EdbInfoId: this.search_dataBaseId,
+        }).then(res => {
+          if(res.Ret === 200) {
+            if(res.Data) {
+              this.databaseTableData = [res.Data.Item] || [];
+              this.databaseHaveMore =  this.databasePageNo < res.Data.Paging.Pages ? true : false;
+              this.databaseList = this.databasePageNo === 1 ? (res.Data.Item.DataList || []) : this.databaseList.concat(res.Data.Item.DataList);
+            }else {
+              this.databaseTableData = [];
+              this.databaseList = [];  
+            }
+          }
+        })
+      },
+      databaseScrollHandle:_.throttle(function() {
+        let scrollTop = this.$refs.valueUl.scrollTop;
+        let clientHeight = this.$refs.valueUl.clientHeight;
+        let scrollHeight = this.$refs.valueUl.scrollHeight;
+        if(scrollTop===0) return
+        if(scrollTop + clientHeight >= scrollHeight-10 && this.databaseHaveMore){
+          this.databasePageNo++
+          this.getDatabaseList()
+        }
+		  },200),
+      async getChartDetail(ChartInfoId) {
+        const res = await dataBaseInterface.getChartInfoById({ChartInfoId})
+        if (res.Ret !== 200) return;
+        this.chartInfo = res.Data.ChartInfo || {}
+        this.edbData = res.Data.EdbInfoList|| []
+
+        const chartTypeMap = {
+          7: this.initBarData, //柱形图
+          10: this.initSectionScatterData //截面散点
+        }
+
+        chartTypeMap[this.chartInfo.ChartType] && chartTypeMap[this.chartInfo.ChartType](res.Data);
+
+      },
+      editLinkName(item){
+        this.editingLabel = item.Name
+        item.editing=true
+        this.$nextTick(() => {
+          this.$refs.labelEditInput[0].focus();
+        });
+      },
+      linkClick(item){
+        if(this.activeItemRId == item.RId) return
+        this.activeItemRId = item.RId
+        if(item.Type==3){
+          this.$message.info('研报类型的暂无回显')
+        }else if(item.Type==1){
+          this.addLinkSearchParams.linkType=item.Type
+          this.changeLinkType()
+          this.initGetData() 
+        }else if(item.Type==2){
+          this.addLinkSearchParams.linkType=item.Type
+          this.changeLinkType()
+          this.getChartDetail(item.Id)
+        }
+
+      },
+      linkDelete(item,index){
+        if(this.activeItemRId == item.RId){
+          this.activeItemRId=""
+          this.changeLinkType()
+        }
+        if(item.Type==3){
+          let deleteId=this.selections.filter(it=> it.Id==item.Id)
+          if(deleteId[0]){
+            this.$refs.reportTable && this.$refs.reportTable.toggleRowSelection(deleteId[0],false)
+          }
+        }
+        this.checkedLinkList.splice(index,1)
+      },
+      editLinkNameFinish(item){
+        if (this.editingLabel) {
+          item.editing=false
+          item.Name = this.editingLabel
+        } else {
+          this.$message.warning('不能为空');
+        }
+      },
+      searchReport(){
+        this.reportParams.CurrentIndex=1
+        if(!this.reportKeyWord){
+          this.reportList=[]
+          this.reportTotal=0
+        }else{
+          this.getReportList()
+        }
+      },
+      getReportList(){
+        let params={
+          CurrentIndex: this.reportParams.CurrentIndex,
+          PageSize: this.reportParams.PageSize,
+          KeyWord:this.reportKeyWord,
+          State:2
+        }
+        reportlist(params).then((res) => {
+          if (res.Ret === 200) {
+            this.reportList = res.Data.List || [];
+            this.reportTotal = parseInt(res.Data.Paging.Totals);
+          }
+        });    
+      },
+      pageChange(page_no){
+        this.reportParams.CurrentIndex = page_no;
+        this.getReportList();
+      },
+      reportSelect(selection){
+        this.selections=selection
+        let allIds = this.reportList.map(it => {
+          return it.Id
+        })
+        let simpleSelections = selection.map(it => {
+          return {Id:it.Id,Code:it.ReportCode,Name:it.Title}
+        })
+
+        let unselectIds=[]
+
+        if(simpleSelections.length>0){
+          allIds.map(id =>{
+            if(simpleSelections.every(sele => id!=sele.Id )){
+              unselectIds.push(id)
+            }
+          })
+        }else{
+          unselectIds=allIds
+        }
+        //没有就增加
+        simpleSelections.map(item =>{
+          let rId = this.addLinkSearchParams.linkType+'-'+item.Id
+          if(this.checkedLinkList.every(sele => rId!=sele.RId )){
+            this.checkedLinkList.push({
+              RId:rId,
+              Id:item.Id,
+              Name:item.Name,
+              Type:this.addLinkSearchParams.linkType,
+              editing:false,
+              detailParams:{id:item.Id,code:item.Code}
+            })
+          }
+        })
+        //有就去掉
+        unselectIds.map(item =>{
+          let rId = this.addLinkSearchParams.linkType+'-'+item
+          let index = this.checkedLinkList.findIndex(link => rId==link.RId)
+          if(index!=-1){
+            this.checkedLinkList.splice(index,1)
+          }
+        })
+      },
+      saveLink(){
+        this.$emit("saveLink", this.checkedLinkList);
+      },
+      cancelHandle(){
+        this.$emit("update:show", false);
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+    .add-link-box{
+      padding: 15px 40px 35px;
+      .link-box-option{
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: 30px;
+      }
+      .link-box-content{
+        margin-bottom: 30px;
+        .link-content-dataIndex{
+          display: flex;
+          flex-direction: column;
+          .value-ul {
+            flex-grow: 1;
+            overflow-y: auto;
+            margin-top: 10px;
+            height: 200px;
+            border-bottom: 1px solid #EBEFF6;
+            .value-item {
+              /* width: 100%; */
+              padding: 10px 0;
+              border: 1px solid #dcdfe6;
+              border-bottom: none;
+              display: flex;
+              justify-content: space-around;
+              >span{
+                padding:0 16px;
+                box-sizing: border-box;
+              }
+              .value-label {
+                position: relative;
+                color: #666;
+                .value-style{
+                  padding:5px;
+                  border-radius: 4px;
+                  &.predict-act {
+                    color: orange;
+                  }
+                }
+                &.date{
+                  &::after{
+                    content: '';
+                    position:absolute;
+                    right:0;
+                    top:-14px;
+                    height:calc(100% + 28px);
+                    width:1px;
+                    background-color: #dcdfe6;
+                  }
+                }
+              }
+              .predict-act {
+                color: orange;
+              }
+              .new-tag {
+                width: 6px;
+                height: 6px;
+                display: inline-block;
+                position: absolute;
+                left: -12px;
+                top: 50%;
+                transform: translateY(-50%);
+                border-radius: 50%;
+                background: #f00;
+              }
+            }
+            .nodata {
+              text-align: center;
+              padding: 40px 0;
+              color: #999;
+            }
+          }
+          .delete-button{
+            color: #AD352F;
+            font-size: 14px;
+            cursor: pointer;
+          }
+        }
+        .link-content-chartIndex{
+          .chart-name{
+            font-size: 16px;
+            text-align: center;
+            color: #333333;
+          }
+        }
+      }
+      .link-box-tags{
+        display: flex;
+        align-items: center;
+        overflow-x: auto;
+        .link-box-tag{
+          display: flex;
+          align-items: center;
+          padding: 0 8px;
+          height: 30px;
+          max-width: 250px;
+          background-color: #F8F8F8;
+          margin-right: 30px;
+          cursor: pointer;
+          &:last-child{
+            margin-right: 0;
+          }
+          span{
+            color: #666666;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+          }
+          img{
+            height: 16px;
+            width: 16px;
+            margin-left: 8px;
+          }
+        }
+      }
+      .link-box-buttons{
+        margin-top: 60px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+      }
+    }
+</style>

File diff suppressed because it is too large
+ 339 - 617
src/views/sandbox_manage/sandFlowNew/index.vue


+ 7 - 0
src/views/smartReport/components/StatisticAnalysis.vue

@@ -51,6 +51,7 @@ import chartRelevanceApi from "@/api/modules/chartRelevanceApi";
 import {
   fittingEquationInterface,
   statisticFeatureInterface,
+  crossVarietyInterface
 } from "@/api/modules/chartRelevanceApi";
 export default {
     data() {
@@ -67,6 +68,10 @@ export default {
                 {
                     name:'统计特征',
                     key:'统计特征'
+                },
+                {
+                    name:'跨品种分析',
+                    key:'跨品种分析'
                 }
             ],
             keyword:'',
@@ -137,6 +142,8 @@ export default {
                 res = await fittingEquationInterface.searchChart(params);
             } else if (this.activeType === '统计特征') {
                 res = await statisticFeatureInterface.searchChart(params);
+            } else if (this.activeType === '跨品种分析') {
+                res = await crossVarietyInterface.searchChart(params);
             }
 
             if (res.Ret !== 200) return;

+ 2 - 3
src/vuex/modules/sand.js

@@ -2,7 +2,6 @@
 import { configOpt,styleSettings } from '@/views/sandbox_manage/common/toolConfig';
 
 const setSandboxToolStatus=(state,payload)=>{
-	console.log(payload,'payload',state);
 	if(!(payload&&payload.length>0)){
 		state.toolStatus.textDisabled=true
 		state.toolStatus.edgeDisabled=true
@@ -35,7 +34,7 @@ const setSandboxToolStatus=(state,payload)=>{
 		for (let i = 0; i < payload.length; i++) {
 			const element = payload[i];
 			const attrs = element.getAttrs()
-			console.log(element.shape);
+			// console.log(element.shape);
 			if(element.shape.indexOf('edge')==-1){
 				state.toolStatus.textDisabled=false
 				state.toolStatus.edgeDisabled=true
@@ -68,7 +67,7 @@ const setSandboxToolStatus=(state,payload)=>{
 				endArrowSet.add(attrs.line.targetMarker)
 				const router = element.getRouter()
 				const connector = element.getConnector()
-				console.log(router,connector,'router,connector');
+				// console.log(router,connector,'router,connector');
 				if(router && router.name=="normal"){
 					connectStyleSet.add(1)
 				}else{

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