浏览代码

Merge branch 'master' of http://8.136.199.33:3000/eta_front/eta_front into ETA1.5.1

cxmo 1 年之前
父节点
当前提交
65cb41f470
共有 97 个文件被更改,包括 5461 次插入1306 次删除
  1. 0 9
      index.html
  2. 1 0
      package.json
  3. 1 0
      src/App.vue
  4. 73 0
      src/api/modules/chartThemeApi.js
  5. 7 0
      src/api/modules/dataSource.js
  6. 3 0
      src/api/modules/pptApi.js
  7. 3 0
      src/api/modules/pptEnApi.js
  8. 3 3
      src/api/modules/thirdBaseApi.js
  9. 二进制
      src/assets/img/ppt_m/text-icon.png
  10. 1 0
      src/components/edbHistoryDialog.vue
  11. 22 0
      src/main.js
  12. 25 0
      src/routes/modules/oldRoutes.js
  13. 24 3
      src/styles/global.scss
  14. 17 2
      src/utils/buttonConfig.js
  15. 85 0
      src/utils/common.js
  16. 8 4
      src/utils/defaultOptions.js
  17. 2 2
      src/utils/registryComponents.js
  18. 17 1
      src/views/Home.vue
  19. 58 1
      src/views/chartFrame_manage/common/config.js
  20. 2 2
      src/views/chartFrame_manage/common/event.js
  21. 50 15
      src/views/chartFrame_manage/components/frameContainer.vue
  22. 13 5
      src/views/chartFrame_manage/frameEditor.vue
  23. 4 0
      src/views/chartFrame_manage/index.vue
  24. 1 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue
  25. 10 1
      src/views/chartRelevance_manage/crossVarietyAnalysis/components/edbTableSection.vue
  26. 1 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/list.vue
  27. 1 0
      src/views/chartRelevance_manage/fittingEquation/fittingEquationList.vue
  28. 10 0
      src/views/chartRelevance_manage/relevance/list.vue
  29. 1 0
      src/views/chartRelevance_manage/statistic/statisticFeatureList.vue
  30. 157 64
      src/views/dataEntry_manage/addChart.vue
  31. 3 3
      src/views/dataEntry_manage/adjustdata/adjustData.vue
  32. 57 18
      src/views/dataEntry_manage/chartSetting.vue
  33. 400 0
      src/views/dataEntry_manage/components/addMarkerDialog.vue
  34. 6 1
      src/views/dataEntry_manage/components/barOptionSection.vue
  35. 39 43
      src/views/dataEntry_manage/components/chart.vue
  36. 105 0
      src/views/dataEntry_manage/components/chartSourceEditDialog.vue
  37. 300 0
      src/views/dataEntry_manage/components/markersSection.vue
  38. 3 0
      src/views/dataEntry_manage/components/satterSeriesDia.vue
  39. 6 1
      src/views/dataEntry_manage/components/sectionalScatterOption.vue
  40. 3 1
      src/views/dataEntry_manage/css/chartfit.scss
  41. 15 15
      src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue
  42. 1 1
      src/views/dataEntry_manage/databaseComponents/createChart.vue
  43. 1 1
      src/views/dataEntry_manage/databaseComponents/updateNewestDia.vue
  44. 7 7
      src/views/dataEntry_manage/databaseList.vue
  45. 165 71
      src/views/dataEntry_manage/editChart.vue
  46. 202 25
      src/views/dataEntry_manage/mixins/addOreditMixin.js
  47. 317 263
      src/views/dataEntry_manage/mixins/chartPublic.js
  48. 159 103
      src/views/dataEntry_manage/thirdBase/ysTargetBase.vue
  49. 4 3
      src/views/dataSource_manage/components/DelEDBTable.vue
  50. 5 8
      src/views/dataSource_manage/components/DetailTable.vue
  51. 68 10
      src/views/dataSource_manage/components/EDBInfoChangeTable.vue
  52. 138 4
      src/views/dataSource_manage/components/GLRefreshFailDetail.vue
  53. 3 3
      src/views/dataSource_manage/components/StatisticTable.vue
  54. 127 0
      src/views/edbHistoryPage.vue
  55. 9 2
      src/views/futures_manage/chartEditor.vue
  56. 1 0
      src/views/futures_manage/commodityChartBase.vue
  57. 57 19
      src/views/mychart_manage/components/chartDetailDia.vue
  58. 2 1
      src/views/ppt_manage/mixins/layerMixins.js
  59. 372 229
      src/views/ppt_manage/mixins/mixins.js
  60. 9 1
      src/views/ppt_manage/mixins/pptEditorMixins.js
  61. 166 40
      src/views/ppt_manage/mixins/pptMixins.js
  62. 1 0
      src/views/ppt_manage/newVersion/components/Cover.vue
  63. 1 0
      src/views/ppt_manage/newVersion/components/CoverEn.vue
  64. 122 0
      src/views/ppt_manage/newVersion/components/CustomCover.vue
  65. 25 118
      src/views/ppt_manage/newVersion/components/catalog/mergePPTDialog.vue
  66. 4 2
      src/views/ppt_manage/newVersion/components/catalog/pptContent.vue
  67. 4 2
      src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue
  68. 1 1
      src/views/ppt_manage/newVersion/components/catalog/pptContentOld.vue
  69. 1 0
      src/views/ppt_manage/newVersion/components/editor/ChooseCover.vue
  70. 1 0
      src/views/ppt_manage/newVersion/components/editor/ChooseCoverEn.vue
  71. 325 0
      src/views/ppt_manage/newVersion/components/editor/ChooseCoverNew.vue
  72. 192 0
      src/views/ppt_manage/newVersion/components/editor/chooseCover/TextEl.vue
  73. 204 0
      src/views/ppt_manage/newVersion/components/editor/chooseCover/elMixin.js
  74. 44 3
      src/views/ppt_manage/newVersion/components/formatEl/ChartEl.vue
  75. 36 22
      src/views/ppt_manage/newVersion/pptEditor.vue
  76. 28 13
      src/views/ppt_manage/newVersion/pptEnEditor.vue
  77. 6 3
      src/views/ppt_manage/newVersion/pptEnPresent.vue
  78. 25 11
      src/views/ppt_manage/newVersion/pptEnPublish.vue
  79. 6 3
      src/views/ppt_manage/newVersion/pptPresent.vue
  80. 30 84
      src/views/ppt_manage/newVersion/pptPublish.vue
  81. 15 5
      src/views/ppt_manage/newVersion/utils/untils.js
  82. 1 1
      src/views/ppt_manage/pptdtl.vue
  83. 4 4
      src/views/predictEdb_manage/addPredicEdb.vue
  84. 1 0
      src/views/predictEdb_manage/components/chartInfo.vue
  85. 7 27
      src/views/predictEdb_manage/predictEdb.vue
  86. 2 1
      src/views/report_manage/reportdtl.vue
  87. 1 1
      src/views/sandbox_manage/sandFlowNew/components/addLInkDia.vue
  88. 3 3
      src/views/smartReport/editReport.vue
  89. 8 1
      src/views/smartReport/reportDetail.vue
  90. 130 0
      src/views/system_manage/chartTheme/common/config.js
  91. 334 0
      src/views/system_manage/chartTheme/components/optionsSection.vue
  92. 285 0
      src/views/system_manage/chartTheme/index.vue
  93. 212 0
      src/views/system_manage/chartTheme/themeSetting.vue
  94. 1 1
      src/views/system_manage/components/smartReportImgSet.vue
  95. 35 9
      src/views/system_manage/etaBaseConfig.vue
  96. 6 5
      src/views/system_manage/operateAuthManage.vue
  97. 10 1
      src/views/system_manage/outlinkList.vue

+ 0 - 9
index.html

@@ -47,15 +47,6 @@
             src: url(./static/css/fonts/SourceHanSerifCN-Regular.ttf);
         }
     </style>
-	<script>
-		var _hmt = _hmt || [];
-		(function() {
-		  var hm = document.createElement("script");
-		  hm.src = "https://hm.baidu.com/hm.js?2147f2700a1a306aa027116f80ef640d";
-		  var s = document.getElementsByTagName("script")[0]; 
-		  s.parentNode.insertBefore(hm, s);
-		})();
-	</script>	
 	<script>
 		window.addEventListener('error',(e)=>{
 			if(e.message=="Uncaught SyntaxError: Unexpected token '<'"){

+ 1 - 0
package.json

@@ -19,6 +19,7 @@
     "@fullcalendar/timegrid": "^5.10.1",
     "@fullcalendar/vue": "^5.10.1",
     "@tinymce/tinymce-vue": "^2.1.0",
+    "aws-sdk": "^2.1527.0",
     "axios": "^0.15.3",
     "babel-helper-vue-jsx-merge-props": "^2.0.3",
     "babel-plugin-syntax-jsx": "^6.18.0",

+ 1 - 0
src/App.vue

@@ -110,6 +110,7 @@ iframe {
   font-size: 14px;
   color: #C54322;
   cursor: pointer;
+  &:hover{color:#C54322}
 }
 .disty {
   font-size: 14px;

+ 73 - 0
src/api/modules/chartThemeApi.js

@@ -0,0 +1,73 @@
+import http from "@/api/http.js"
+
+/**
+ * 获取图表类型
+ * @param {*} params 
+ * @returns 
+ */
+export const getThemeChartType = params => {
+  return http.get('/datamanage/chart/theme/type/list',params)
+}
+
+/**
+ * 根据类型获取主题
+ * @param {*} params  ChartThemeTypeId
+ * @returns 
+ */
+export const getThemeByType = params => {
+  return http.get('/datamanage/chart/theme/list',params)
+}
+
+/**
+ * 添加主题
+ * @param {*} params ChartThemeName ChartThemeTypeId
+ * @returns 
+ */
+export const addTheme = params => {
+  return http.post('/datamanage/chart/theme/add',params)
+}
+
+/**
+ * 编辑主题
+ * @param {*} params  ChartThemeId ChartThemeName Config
+ * @returns 
+ */
+export const saveTheme = params => {
+  return http.post('/datamanage/chart/theme/edit',params)
+}
+
+/**
+ * 删除主题
+ * @param {*} params ChartThemeId
+ * @returns 
+ */
+export const delTheme = params => {
+  return http.post('/datamanage/chart/theme/delete',params)
+}
+
+/**
+ * 配置默认主题
+ * @param {*} params  ChartThemeId ChartThemeTypeId
+ * @returns 
+ */
+export const setConfigTheme = params => {
+  return http.post('/datamanage/chart/theme/set_default',params)
+}
+
+/**
+ * 预览图数据
+ * @param {*} params 
+ * @returns 
+ */
+export const previewChartData = params => {
+  return http.get('/datamanage/chart/theme/preview_data',params)
+}
+
+/**
+ * 获取主题列表
+ * @param {*} params  ChartType  Source
+ * @returns 
+ */
+export const getThemeBySource = params => {
+  return http.get('/datamanage/chart/theme/list_by_source',params)
+}

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

@@ -56,7 +56,14 @@ const apiDataSource={
     // 获取终端编码数据
     terminalCodeArr:params=>{
         return http.get('/data_stat/terminal/code',{})
+    },
+
+    //数据刷新失败详情列表
+    updateFailDetailList:params=>{
+        return http.get('/data_stat/edb_update_stat/failed/detail',params)
     }
+
+
     
 
 }

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

@@ -23,6 +23,7 @@ export default{
      * FirstPage:{Title,ReportType,PptDate,ImgUrl} 封面信息
      * Content:string ppt具体内容,转字符串
      * GroupId:目录id
+     * CoverContent:string 封面页的具体内容,转字符串
      */
     addppt:params=>{
         return http.post('/pptv2/add',params)
@@ -32,6 +33,7 @@ export default{
      * PptId
      * FirstPage
      * Content
+     * CoverContent
      */
     editppt:params=>{
         return http.post('/pptv2/edit',params)
@@ -71,6 +73,7 @@ export default{
      * PptId
      * FirstPage
      * Content
+     * CoverContent
      */
     saveLog:params=>{
         return http.post('/pptv2/saveLog',params)

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

@@ -16,6 +16,7 @@ export const pptEnInterface = {
      * FirstPage:{Title,ReportType,PptDate,ImgUrl} 封面信息
      * Content:string ppt具体内容,转字符串
      * GroupId:目录id
+     * CoverContent:string 封面页具体内容,转字符串
      */
     addppt:params=>{
         return http.post('/ppt_english/add',params)
@@ -25,6 +26,7 @@ export const pptEnInterface = {
      * PptId
      * FirstPage
      * Content
+     * CoverContent
      */
     editppt:params=>{
         return http.post('/ppt_english/edit',params)
@@ -56,6 +58,7 @@ export const pptEnInterface = {
      * PptId
      * FirstPage
      * Content
+     * CoverContent
      */
     saveLog:params=>{
         return http.post('/ppt_english/saveLog',params)

+ 3 - 3
src/api/modules/thirdBaseApi.js

@@ -192,7 +192,7 @@ const smmDataInterface = {
    * 列表
 	*/
 	getYsDataList:params=>{
-		return http.get('datamanage/smm/api/list',params)
+		return http.post('datamanage/smm/api/list',params)
 	},
 	/**
    * 分类列表
@@ -204,13 +204,13 @@ const smmDataInterface = {
    * 检验有色指标是否存在
 	*/
 	getYsEdbCodeCheck:params=>{
-		return http.get('datamanage/edb_info/smm/exist/check',params)
+		return http.post('datamanage/edb_info/smm/exist/check',params)
 	},
 	/**
    * 查询有色指标
 	*/
 	getYsEdbCodeSearch:params=>{
-		return http.get('datamanage/edb_info/smm/search',params)
+		return http.post('datamanage/edb_info/smm/search',params)
 	},
 	/**
    * 批量添加有色指标

二进制
src/assets/img/ppt_m/text-icon.png


+ 1 - 0
src/components/edbHistoryDialog.vue

@@ -1,4 +1,5 @@
 <template>
+    <!-- ETA1.5.4 将该组件作为一个页面,若上线后无回滚需求可删除 -->
   <el-dialog
 		:visible.sync="isOpenDialog"
 		:close-on-click-modal="false"

+ 22 - 0
src/main.js

@@ -24,6 +24,28 @@ import{endCalc,optionTimeCalc,init}from'@/utils/TimeOnPage.js';
 import setting from '@/mixins/theme.js'
 Vue.prototype.$setting = setting;
 
+Vue.prototype.toHistoryPage = (EdbInfoId,from=[])=>{
+    console.log('from',from)
+    let pathArr = from.map(p=>{
+        return {
+            name:p.name||'',
+            path:p.path||''
+        }
+    })
+    pathArr.push({
+        name:'指标溯源',
+        path:'/edbHistory'
+    })
+    sessionStorage.setItem('edbHistoryPath',JSON.stringify(pathArr))
+    const href = router.resolve({
+        path:'/edbHistory',
+        query:{
+            edbId:EdbInfoId,
+        }
+    }).href
+    window.open(href,"_blank")
+}
+
 //Import Froala Editor
 import "froala-editor/js/plugins.pkgd.min.js";
 import "froala-editor/js/plugins/quick_insert.min.js";

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

@@ -81,6 +81,15 @@ export default [
           keepAlive: false,
         },
       },
+      {
+        path: "edbHistory",
+        component: () => import("@/views/edbHistoryPage.vue"),
+        name: "指标溯源",
+        hidden: true,
+        meta: {
+          keepAlive: false,
+        },
+      },
     ],
   },
 
@@ -335,6 +344,22 @@ export default [
         name: "编辑审批流",
         hidden:true,
       },
+      {
+        path: "chartThemeIndex",
+        component: () => import("@/views/system_manage/chartTheme/index.vue"),
+        name: "图表配置",
+        hidden:false,
+      },
+      {
+        path: "chartThemeSet",
+        component: () => import("@/views/system_manage/chartTheme/themeSetting.vue"),
+        name: "主题配置",
+        hidden:true,
+        meta: {
+          pathFrom: "chartThemeIndex",
+          pathName: "图表配置"
+        },
+      },  
       {
         path: "dataSourceAccountList",
         component: () => import("@/views/dataSource_manage/accountList.vue"),

+ 24 - 3
src/styles/global.scss

@@ -44,9 +44,7 @@ button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusri
 .clear:after{ display:block; height:0; content:""; clear:both; }
 
 .highcharts-range-selector-group{ display:none; }
-.highcharts-legend-item tspan{ font-size:14px; font-weight:400; color:#960000; }
-
-.highcharts-legend-item tspan{ font-size:14px; font-weight:400; color:#960000; }
+.highcharts-legend-item tspan{ font-weight:400;  }
 
 // 英文图表标识
 .chartEn-mark{
@@ -133,4 +131,27 @@ button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusri
     width:85vw;
     margin-top:6vh;
     margin-bottom: 0;
+}
+
+//图表底部来源和图表说明
+.chart-bottom-insruction-info {
+    margin-top: 10px;
+    display: flex;
+    gap: 0 20px;
+    .chart-source {
+        width: 30%;
+        min-width: 150px;
+    }
+
+    .calendar-cont {
+        display: block;
+        margin: 0 auto;
+        text-align: center;
+        flex-shrink: 0;
+    }
+
+    .chart-instruction {
+        flex: 1;
+        text-align: right;
+    }
 }

+ 17 - 2
src/utils/buttonConfig.js

@@ -214,7 +214,9 @@ export const dataSourcePermission = {
     smmData_classifyOpt_add:'smmData:classifyOpt:add',//添加目录和子项
     smmData_classifyOpt_edit:'smmData:classifyOpt:edit',//编辑
     smmData_classifyOpt_delete:'smmData:classifyOpt:delete',//删除
-
+    /*--------有色原始数据库---- */
+    ysTarget_view:'ysTarget:view',
+    ysTarget_addBatch:'ysTarget:addBatch',
     /*--------百川盈孚---- */
     bcyfData_edit:'bcyfData:edit',//编辑指标按钮
     bcyfData_export:'bcyfData:export',
@@ -636,6 +638,10 @@ export const baseConfigPermission = {
     etaBaseConfig_watermark:'etaBaseConfig:watermark',
     etaBaseConfig_watermark_ybChart:'etaBaseConfig:watermark:ybChart',//如果没权限,表单不显示也不校验
     etaBaseConfig_approve:'etaBaseConfig:approve',//研报审批
+    etaBaseConfig_login:'baseSetting:loginSetting',//登录
+    etaBaseConfig_watermark_ybShare:'etaBaseConfig:watermark:ybShare',//如果没权限,表单不显示也不校验
+    etaBaseConfig_source_see:'baseSetting:sourceSetting:see',//资源库查看
+    etaBaseConfig_source_upload:'baseSetting:sourceSetting:upload',//资源库上传
 }
 
 /*-----------外部链接配置-------- */
@@ -665,6 +671,13 @@ export const approvePermission = {
     reportApprove_repeal:'reportApprove:repeal',//撤回(列表中的按钮,审批详情-撤回按钮)
 }
 
+/* 图表主题配置 */
+export const chartThemePermission = {
+    chartTheme_add:'chartTheme:add',//添加
+    chartTheme_edit:'chartTheme:edit',//编辑
+    chartTheme_del:'chartTheme:del',//删除
+}
+
 
 //创建了新的ManageBtn记得添加到这里
 const btnMap  = {
@@ -680,7 +693,9 @@ const btnMap  = {
     productPricePermission,sysDepartPermission,
     operateAuthPermission,baseConfigPermission,
     outlinkConfigPermission,approveFlowPermission,
-    approvePermission
+    approvePermission,
+    outlinkConfigPermission,
+    chartThemePermission
 }
 
 /**

+ 85 - 0
src/utils/common.js

@@ -4,6 +4,8 @@
 
 import {Message} from "element-ui"
 import{getOSSSign} from "@/api/api.js"
+//or <script src="https://sdk.amazonaws.com/js/aws-sdk-2.744.0.min.js"></script>
+import AWS from 'aws-sdk'
 const Minio = require('minio')
 const stream = require('stream')
 
@@ -96,6 +98,12 @@ export function uploadFileDirect(objectStorageClient,file,temName,options={}){
       }
       return handleUploadToMinIO(file,temName,minioOptions)
       // break;
+    case "s3":
+        let s3Options = {}
+        if(options.S3){
+            s3Options = options.S3
+        }
+        return handleUploadToS3(file,temName,s3Options)
     default:
       break;
   }
@@ -229,4 +237,81 @@ const handleUploadToMinIO=(file,fileName,options={})=>{
       reject(error)
     }
   })
+}
+//https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
+const handleUploadToS3=(file,fileName,options={})=>{
+    return new Promise(async(resolve,reject)=>{
+        const res=await getOSSSign({StorageSource:3})
+        if(res.Ret!==200) reject("获取s3签名错误,res.Ret="+res.Ret)
+        const { Endpoint,
+                AccessKeyId,
+                AccessKeySecret,
+                Port,
+                Bucketname,
+                RegionId,
+                S3ForceStyle,
+                S3Protocol
+            } = res.Data
+
+        const s3Client = new AWS.S3({
+            apiVersion: '2006-03-01',
+            endpoint:Endpoint,
+            region:RegionId,
+            s3ForcePathStyle:S3ForceStyle,
+            credentials:{
+                accessKeyId:AccessKeyId,
+                secretAccessKey:AccessKeySecret,
+            }
+        })
+        /* window.s3Client = s3Client
+        console.log('s3:',s3Client) */
+        try {
+            let reader = new FileReader();
+            //console.log(reader);
+            reader.readAsArrayBuffer(file);
+            reader.onloadend = function (e) {
+                const dataurl = e.target.result;
+                let bufferStream = new stream.PassThrough();
+                bufferStream.end(Buffer.from(dataurl))
+                //s3 上传
+                /* s3Client.putObject({
+                    Bucket: Bucketname,
+                    ContentType: file.type || 'application/octet-stream',
+                    Body: file,
+                    ACL: "public-read",
+                    Key: fileName
+                }, function (err, data) {
+                    if (err) {
+                        console.log("Error! err =====> ", err);
+                    } else {
+                        console.log("Successfully uploaded! data =====> ", data);
+                    }
+                }); */
+                //upload会返回完整路径
+                s3Client.upload({
+                    Bucket: Bucketname,
+                    ContentType: file.type || 'application/octet-stream',
+                    Body: file,
+                    ACL: "public-read",
+                    Key: fileName
+                }, function (err, data) {
+                    if (err) {
+                        console.log("Error! err =====> ", err);
+                        throw new Error("上传到s3失败!")
+                    } else {
+                        let url = data['Location'];
+                        console.log("Successfully uploaded! URL =====> ", url);
+                        resolve(url)
+                    }
+                });
+            }
+          } catch (error) {
+            console.error(error);
+            if (error.name !== "cancel") {
+              //不是取消上传的则给错误提示
+              this.$message.warning("上传失败,请刷新重试");
+            }
+            reject(error)
+          }
+    })
 }

+ 8 - 4
src/utils/defaultOptions.js

@@ -2,6 +2,7 @@ export const defaultOpts = {
 	//图表配置
 	chart: {
 
+		spacing: [2,10,2,10]
 	},
 	title: {
 		enabled: false
@@ -80,7 +81,9 @@ export const defaultOpts = {
 	legend: {
 		enabled: true,
 		verticalAlign: 'top',
-		margin:20,
+		margin:12,
+		itemMarginBottom:0,
+		itemMarginTop: 0
 		// layout: 'vertical'
 	},
 	//滚动条
@@ -164,12 +167,13 @@ export const unitArr = [
 /* 季节性图配置 */
 export const seasonOptions = {
 		//默认颜色配置
-	colors:['#4B0082','#7FFFAA','#FF4500','#808000','#EEE8AA','#849EC1','#8A4294','#578B5A','#FDA8C7','#53B3FF','#999999','#000000','#FFDF0C','#FF0000','#0033FF'],
+		/* '#4B0082','#7FFFAA','#FF4500','#808000','#EEE8AA', */
+	colors:['#849EC1','#8A4294','#578B5A','#FDA8C7','#53B3FF','#999999','#000000','#FFDF0C','#FF0000','#0033FF'],
 	yAxis: {
 		lineWidth: 1,
 		lineColor: '#bfbfbf',
 		tickColor: '#bfbfbf',
-		offset: 0,
+		// offset: 0,
 		opposite: false,
 		reversed: false,
 		visible: true,
@@ -198,7 +202,7 @@ export const copyOtherOptions = {
 			color: '#444',
 			textOverflow:undefined
 		},
-		itemMarginBottom:5,
+		itemMarginBottom:0,
 		itemDistance: 0,
 		padding: 0,
 		margin: 10

+ 2 - 2
src/utils/registryComponents.js

@@ -19,8 +19,8 @@ import selectUnit from '@/components/selectUnit.vue'
 Vue.component('selectUnit',selectUnit)
 
 //查看指标历史
-import edbHistoryDialog from '@/components/edbHistoryDialog.vue';
-Vue.component('edbHistoryDialog',edbHistoryDialog);
+/* import edbHistoryDialog from '@/components/edbHistoryDialog.vue';
+Vue.component('edbHistoryDialog',edbHistoryDialog); */
 
 //缺省图统一
 import tableNoData from '@/components/tableNoData.vue'

+ 17 - 1
src/views/Home.vue

@@ -131,7 +131,8 @@
               
               <!-- 面包屑 -->
               <el-breadcrumb separator="/" class="breadcrumb-inner">
-                <el-breadcrumb-item
+                <template v-if="$route.path!=='/edbHistory'">
+                    <el-breadcrumb-item
                   v-for="item in $route.matched"
                   :key="item.path"
                 >
@@ -190,6 +191,18 @@
                   </span>
                   <span v-else>{{ item.name }}</span>
                 </el-breadcrumb-item>
+                </template>
+                <template v-else>
+                    <el-breadcrumb-item v-for="(item,index) in edbHistoryPath" :key="item.path">
+                        <span v-if="index===0">{{item.name}}</span>
+                        <span v-else>
+                            <span @click.stop="$router.push(item.path)" :style="`cursor: pointer; color: ${$setting.theme_color}`">
+                                {{item.name}}
+                            </span>
+                        </span>
+                    </el-breadcrumb-item>
+                </template>
+                
               </el-breadcrumb>
             </div>
 
@@ -346,6 +359,9 @@ export default {
     },
   },
   computed: {
+    edbHistoryPath(){
+        return JSON.parse(sessionStorage.getItem('edbHistoryPath'))||[]
+    },
     breadSelfName() {
       return this.$store.state.breadSelfName;
     },  

+ 58 - 1
src/views/chartFrame_manage/common/config.js

@@ -29,7 +29,7 @@ export const textTool = {
         }]
     }
 }
-//基础节点
+//基础节点 有图分类的节点
 export const baseNode = {
     shape:'rect',
     width: 120,
@@ -86,6 +86,63 @@ export const baseNode = {
         }
     },
 }
+//基础节点2 无图分类的节点
+export const baseNode2 = {
+    shape:'rect',
+    width: 120,
+    height: 50,
+    attrs:{
+        text:{ //文字换行
+            textWrap: {
+                width: -10,
+                ellipsis: true,
+            }
+        },
+        body:{
+            fill:'#FFF1E9',//背景色
+            stroke:'#F7A340',//边框色
+            strokeWidth:1,//边框宽度
+            strokeDasharray:'',//虚线,如果赋值为0保存缩略图时会省略掉边框
+        },
+        label:{ //与svg text属性相同
+            fill:'#E37318',//文字颜色
+            fontSize:14,//文字大小
+            fontWeight:'normal',//文字粗细
+            fontStyle:'normal',//斜体
+            textDecoration:'normal',//下划线
+        }
+    },
+    ports: { //基础连接桩
+        items: [
+            { group: 'port-top', id: 'p_top' },
+            { group: 'port-bottom', id: 'p_bottom' },
+            { group: 'port-left', id: 'p_left' },
+            { group: 'port-right', id: 'p_right' },
+        ],
+        groups: {
+            "port-top": {
+                    position: 'top',
+                    zIndex: 20,
+                    ...portStyle
+            },
+            "port-bottom": {
+                    position: 'bottom',
+                    zIndex: 20,
+                    ...portStyle
+            },
+            "port-left": {
+                    position: 'left',
+                    zIndex: 20,
+                    ...portStyle
+            },
+            "port-right": {
+                    position: 'right',
+                    zIndex: 20,
+                    ...portStyle
+            },
+        }
+    },
+}
 //基础线条
 export const baseEdge = {
     attrs:{

+ 2 - 2
src/views/chartFrame_manage/common/event.js

@@ -12,8 +12,8 @@ export const myEvents = (graph,tempThis=null)=>{
 
     graph.on('node:click',({node,e})=>{
         if(!window.location.pathname.startsWith('/chartframe')) return 
-        console.log('node.data',node.data)
-        if(node.data&&node.data.id){
+        //console.log('node.data',node.data)
+        if(node.data){
             tempThis&&tempThis.$emit('showDialog',node.data)
         }
     })

+ 50 - 15
src/views/chartFrame_manage/components/frameContainer.vue

@@ -32,7 +32,7 @@
 <script>
 import { ElDropdownMenu } from 'element-ui';
 import { myGraph } from '../common/graph';
-import { baseNode , textTool } from '../common/config';
+import { baseNode , baseNode2 , textTool } from '../common/config';
 import FrameToolBar from './frameToolBar.vue';
 export default {
     components:{ElDropdownMenu,FrameToolBar},
@@ -95,7 +95,7 @@ export default {
             //如果有内容,初始化画布内容
             this.FrameworkContent.length&&this.graph.fromJSON(JSON.parse(this.FrameworkContent))
             //如果有内容,将画布内容居中
-            this.FrameworkContent.length&&this.graph.scrollToContent({ animation: { duration: 600 }})
+            this.FrameworkContent.length&&this.graph.scrollToContent(/* { animation: { duration: 600 }} */)
             //如果有内容,遍历每个节点,赋值chartNum
             this.FrameworkContent.length&&this.setNodeInfo()
             //如果是非编辑页,加载完成画布内容后冻结画布
@@ -113,48 +113,83 @@ export default {
                 const currentNode = nodes.find(item=>item.id===node.NodeId)
                 if(currentNode){
                     currentNode.removeTools()
+                    if(!currentNode.data.id) return
                     const toolOption = this.getToolOption({chartNum:node.ChartNum||0,color:currentNode.attrs.label.fill})
                     currentNode.addTools(toolOption)
                 }
             })
         },
         //添加/编辑节点
-        editNode(node){
+        editNode({nodeLink={},nodeName='',nodeId}){
             //获取视口范围
             const position = this.graph.getContentArea()
             const nodes = this.graph.getNodes()
-            const currentNode = nodes.find(item=>item.id===node.nodeId)
+            const currentNode = nodes.find(item=>item.id===nodeId)
+            let tempNode = currentNode
             if(currentNode){
-                currentNode.data.id=node.nodeLink.MyChartClassifyId
-                currentNode.label=node.nodeName
-                currentNode.data.nodeLink = node.nodeLink
+                const oldId = currentNode.data.id
+                const newId = nodeLink.MyChartClassifyId||0
+                const isSetStyle = (oldId===0&&newId!==0)||(oldId!==0&&newId===0)
+                isSetStyle&&this.setNodeStyle(newId,tempNode)
+                
+                tempNode.data.id=nodeLink.MyChartClassifyId||0
+                tempNode.label=nodeName
+                tempNode.data.nodeLink = nodeLink
+                /* currentNode.data.id=nodeLink.MyChartClassifyId||0
+                currentNode.label=nodeName
+                currentNode.data.nodeLink = nodeLink
                 currentNode.removeTools()
-                const toolOption = this.getToolOption({chartNum:node.nodeLink.ChartNum,color:currentNode.attrs.label.fill})
-                currentNode.addTools(toolOption)
+                const newId = currentNode.data.id
+                const isSetStyle = (oldId===0&&newId!==0)||(oldId!==0&&newId===0)
+                isSetStyle&&this.setNodeStyle(newId,currentNode)
+                if(!currentNode.data.id) return 
+                const toolOption = this.getToolOption({chartNum:nodeLink.ChartNum,color:currentNode.attrs.label.fill})
+                currentNode.addTools(toolOption) */
             }else{
                 //在视口范围内添加节点
-                this.graph.addNode({
-                    ...baseNode,
+                const nodeStyle = nodeLink.MyChartClassifyId?baseNode:baseNode2
+                tempNode = this.graph.addNode({
+                    ...nodeStyle,
                     ...{
                     x:position.x+position.width/2+20,
                     y:position.y+position.height/2+20,
                     width:120,
                     height:50,
                     data:{
-                        id:node.nodeLink.MyChartClassifyId,//存储节点对应的myETA分类id
-                        nodeLink:node.nodeLink,
+                        id:nodeLink.MyChartClassifyId||0,//存储节点对应的myETA分类id
+                        nodeLink:nodeLink,
                     },
-                    label:node.nodeName||'',
-                    tools:[this.getToolOption({chartNum:node.nodeLink.ChartNum,color:baseNode.attrs.label.fill})]
+                    label:nodeName,
                 }})
             }
+            tempNode.removeTools()
+            if(!tempNode.data.id) return 
+            const toolOption = this.getToolOption({chartNum:nodeLink.ChartNum,color:tempNode.attrs.label.fill})
+            tempNode.addTools(toolOption)
         },
+        //设置节点图分类的数量
         getToolOption({chartNum,color}){
             const options = _.cloneDeep(textTool)
             options.args.markup[0].textContent = chartNum +''
             options.args.markup[0].attrs.fill = color
             return options
         },
+        //设置有无图分类节点的样式
+        //type: 0 无图分类 非0 有图分类
+        //非0 表示节点从无图分类转换成有图分类,节点样式重置为baseNode
+        //0 表示节点从有图分类转换成无图分类,节点样式重置为baseNode2
+        setNodeStyle(type,node){
+            const {attrs={}} = type?baseNode:baseNode2
+            const {body,label} = attrs
+            const styleMap = {
+                'label/fill':label.fill,
+                'body/fill':body.fill,
+                'body/stroke':body.stroke
+            }
+            for(let k in styleMap){
+                node.attr(k,styleMap[k])
+            }
+        },
         //点击右键菜单事件
         handleContext(key){
             const select_cell = this.graph.getSelectedCells()

+ 13 - 5
src/views/chartFrame_manage/frameEditor.vue

@@ -36,10 +36,10 @@
                     :rules="rules"
                 >
                     <el-form-item label="节点名称" prop="nodeName">
-                        <el-input v-model.trim="modifyNode.nodeName" placeholder="请输入节点名称" style="width:217px;"></el-input>
+                        <el-input v-model="modifyNode.nodeName" placeholder="请输入节点名称" style="width:217px;"></el-input>
                     </el-form-item>
                     <el-form-item label="节点链接" prop="nodeLink">
-                        <el-select v-model="modifyNode.nodeLink" value-key="MyChartClassifyId" placeholder="请选择节点链接" style="width:217px;">
+                        <el-select v-model="modifyNode.nodeLink" value-key="MyChartClassifyId" placeholder="请选择节点链接" clearable style="width:217px;">
                             <el-option v-for="item in myList" 
                                 :key="item.MyChartClassifyId"
                                 :label="item.MyChartClassifyName"
@@ -75,11 +75,14 @@ export default {
                 Nodes:[]
             },
             lockLoding:null,
-            modifyNode: {},//正在编辑的节点
+            modifyNode: {
+                nodeName:'',
+                nodeLink:{}
+            },//正在编辑的节点
             isModifyNodeDialogShow: false,//编辑节点弹窗
             rules: {
                 nodeName: [{ required: true, message: "请输入节点名称", trigger: "blur" }],
-                nodeLink: [{ required: true, message: "请选择节点链接", trigger: "blur" }]
+                /* nodeLink: [{ required: true, message: "请选择节点链接", trigger: "blur" }] */
             },
             myList:[],//我的图库列表
         };
@@ -93,7 +96,12 @@ export default {
         },
         //编辑节点,更改子组件节点信息,隐藏弹窗
         async editNode() {
-            await this.$refs.refForm.validate();
+            this.modifyNode.nodeName&&(this.modifyNode.nodeName = this.modifyNode.nodeName.trim())
+            try{
+                await this.$refs.refForm.validate();
+            }catch(e){
+                return
+            }
             if(!this.$refs.container) return
             this.$refs.container.editNode(this.modifyNode)
             this.$message.success(`${this.modifyNode.nodeId ? '编辑' : '添加'}节点成功`);

+ 4 - 0
src/views/chartFrame_manage/index.vue

@@ -536,6 +536,10 @@ export default {
         },
         //点击框架内节点
         handleShowDialog({id,nodeLink}){
+            if(!id){
+                this.$message.warning("该节点没有选择图分类")
+                return
+            }
             //请求接口看有没有数据
             mychartInterface.myList({
                 PageSize:1200,

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

@@ -92,6 +92,7 @@
               <h2 class="chart-title">{{ chartInfo.ChartName }}</h2>
               <Chart 
                 :options="options"
+                :chartInfo="chartInfo"
                 minHeight="400px" 
                 height="450px"
                 ref="chartRef"

+ 10 - 1
src/views/chartRelevance_manage/crossVarietyAnalysis/components/edbTableSection.vue

@@ -14,7 +14,16 @@
         align="center"
       >
         <template slot-scope="scope">
-          <span>{{ scope.row[item.key] }}</span>
+            <span v-if="item.key==='SourceName'">
+                {{scope.row[item.key]}}
+                <i 
+                    class="el-icon-tickets" 
+                    style="color:#409EFF;font-size:18px" 
+                    @click="toHistoryPage(scope.row.EdbInfoId,$route.matched)"
+                    v-if="scope.row.EdbType===2"
+                />
+            </span>
+          <span v-else>{{ scope.row[item.key] }}</span>
         </template>
       </el-table-column>
       <el-table-column label="操作" key="Copy" align="center" width="140">

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

@@ -138,6 +138,7 @@
                     <h2 class="chart-title">{{ chartInfo.ChartName }}</h2>
                     <Chart 
 											:options="options"
+											:chartInfo="chartInfo"
 											minHeight="440px" 
 											height="500px"
 											ref="chartRef"

+ 1 - 0
src/views/chartRelevance_manage/fittingEquation/fittingEquationList.vue

@@ -162,6 +162,7 @@
                     <h2 class="chart-title">{{ chartInfo.ChartName }}</h2>
                     <Chart 
 											:options="options"
+											:chartInfo="chartInfo"
 											minHeight="440px" 
 											height="500px"
 											ref="chartRef"

+ 10 - 0
src/views/chartRelevance_manage/relevance/list.vue

@@ -168,6 +168,7 @@
                   </h2>
                   <Chart
                     :options="options"
+                    :chartInfo="chartInfo"
                     minHeight="440px"
                     height="500px"
                     ref="chartRef"
@@ -229,6 +230,15 @@
                     clearable
                   />
                 </div>
+                <span v-else-if="item.key==='SourceName'">
+                    {{scope.row[item.key]}}
+                    <i 
+                      class="el-icon-tickets" 
+                      style="color:#409EFF;font-size:18px" 
+                      @click="toHistoryPage(scope.row.EdbInfoId,$route.matched)"
+                      v-if="scope.row.EdbType===2"
+                    />
+                  </span>
                 <span v-else>{{ scope.row[item.key] }}</span>
               </template>
             </el-table-column>

+ 1 - 0
src/views/chartRelevance_manage/statistic/statisticFeatureList.vue

@@ -148,6 +148,7 @@
                     <h2 class="chart-title">{{ chartInfo.ChartName }}</h2>
                     <Chart 
 											:options="options"
+											:chartInfo="chartInfo"
 											minHeight="440px" 
 											height="500px"
 											ref="chartRef"

+ 157 - 64
src/views/dataEntry_manage/addChart.vue

@@ -17,6 +17,7 @@
         <el-button type="primary" plain @click="$router.back()">取消</el-button>
       </div>
 			<div class="left-min">
+
 				<el-form
 					ref="diaForm"
 					label-position="top"
@@ -24,7 +25,7 @@
 					:model="chartInfo"
 					:rules="chartRules"
 				>
-					<el-form-item label="图表生成样式" prop="ChartType">
+					<el-form-item label="生成图表类型" prop="ChartType">
 						<el-select
 							v-model="chartInfo.ChartType"
 							placeholder="请选择生成样式"
@@ -39,6 +40,61 @@
 							</el-option>
 						</el-select>
 					</el-form-item>
+
+					<el-form-item label="图表主题" prop="Theme">
+						<el-select
+							v-model="chartInfo.ChartThemeId"
+							placeholder="请选择图表主题"
+							style="width: 90%"
+							@change="changeThemeHandle"
+						>
+							<el-option
+								v-for="item in chartThemeArr"
+								:key="item.ChartThemeId"
+								:label="item.ChartThemeName"
+								:value="item.ChartThemeId"
+							>
+							</el-option>
+						</el-select>
+					</el-form-item>
+
+					<el-form-item label="">
+						<div class="search-cont" v-if="chartInfo.ChartType!==10">
+							<div>
+								<label>选择指标:</label>
+								<el-radio-group v-model="edbFromType">
+									<el-radio :label="0" style="margin-right: 15px">ETA指标</el-radio>
+									<el-radio :label="1">ETA预测指标</el-radio>
+								</el-radio-group>
+							</div>
+							<el-select
+								v-model="search_txt"
+								v-loadMore="searchLoad"
+								ref="searchRef"
+								:filterable="!search_txt"
+								remote
+								clearable
+								placeholder="指标ID/指标名称"
+								style="width:90%;margin-top: 10px;display: block;"
+								:remote-method="searchHandle"
+								@click.native="inputFocusHandle"
+								@change="selectTarget($event && searchOptions.find(_ => _.EdbInfoId === $event))"
+							>
+								<i slot="prefix" class="el-input__icon el-icon-search"></i>
+								<el-option
+									v-for="item in searchOptions"
+									:key="item.EdbInfoId"
+									:label="chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
+									:value="item.EdbInfoId"
+								>
+									<edbDetailPopover :info="item">
+										<div slot="reference">{{chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName }}</div>
+									</edbDetailPopover>
+								</el-option>
+							</el-select>
+						</div>
+					</el-form-item>
+
 					<el-form-item label="图表名称" prop="ChartName">
 						<el-input
 							v-model="chartInfo.ChartName"
@@ -82,41 +138,6 @@
 					</el-form-item>
 				</el-form>
 
-				<div class="search-cont" v-if="chartInfo.ChartType!==10">
-					<div>
-						<label>选择指标:</label>
-						<el-radio-group v-model="edbFromType">
-							<el-radio :label="0" style="margin-right: 15px">ETA指标</el-radio>
-							<el-radio :label="1">ETA预测指标</el-radio>
-						</el-radio-group>
-					</div>
-					<el-select
-						v-model="search_txt"
-						v-loadMore="searchLoad"
-						ref="searchRef"
-						:filterable="!search_txt"
-						remote
-						clearable
-						placeholder="指标ID/指标名称"
-						style="width:90%;margin-top: 10px;display: block;"
-						:remote-method="searchHandle"
-						@click.native="inputFocusHandle"
-						@change="selectTarget($event && searchOptions.find(_ => _.EdbInfoId === $event))"
-					>
-						<i slot="prefix" class="el-input__icon el-icon-search"></i>
-						<el-option
-							v-for="item in searchOptions"
-							:key="item.EdbInfoId"
-							:label="chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
-							:value="item.EdbInfoId"
-						>
-							<edbDetailPopover :info="item">
-								<div slot="reference">{{chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName }}</div>
-							</edbDetailPopover>
-						</el-option>
-					</el-select>
-				</div>
-
 				<div class="xaxis-range-cont" v-if="chartInfo.ChartType===2 && tableData && tableData.length>0">
 					<!-- 仅用于季节性图配置 -->
 					<div style="margin-bottom: 12px;" class="xaxis-range-tip">
@@ -163,7 +184,7 @@
 					<!-- 仅用于散点图配置 -->
 					<div class="scatter-setting" v-if="chartInfo.ChartType === 5 && tableData.length">
 						<div style="display: flex;margin-right: 15px;">
-							<span style="margin-right: 3px">线条颜色:</span>
+							<span style="margin-right: 3px">散点颜色:</span>
 							<el-color-picker
 								v-model="tableData[0].ChartColor"
 								size="mini"
@@ -309,6 +330,7 @@
 					<bar-option
 						v-if="chartInfo.ChartType===7"
 						ref="BarOptRef"
+						:chartInfo="chartInfo"
 						:edblist="tableData"
 						:datedata="barDateList"
 						@getData="getBarPreviewData"
@@ -318,10 +340,21 @@
 					<sectional-scatter-option
 						v-if="chartInfo.ChartType===10"
 						ref="SectionScatterOptRef"
+						:chartInfo="chartInfo"
 						@getData="getSectionScatterData"
 						@modifySeriesName="IsNameDefault = false"
 					/>
+
+
+					<!-- 标识区 标记线 图表说明 -->
+					<markersSection
+						v-if="tableData.length"
+						ref="markerSectionRef"
+						:chartInfo="chartInfo"
+						@update="setChartMarkerInfo"
+					/>
         </div>
+
 			</div>
       <span
         class="move-btn resize"
@@ -370,8 +403,19 @@
 				<div class="cont-bottom">
 					<div class="chart-show-cont" v-show="options.series">
 						<div class="chartWrapper" id="chartWrapper">
-							<h2 class="chart-title" v-show="chartInfo.ChartName">{{ chartInfo.ChartName }}</h2>
-							<Chart :options="options" ref="chartRef" />
+							<h2 
+								class="chart-title" 
+								v-show="chartInfo.ChartName"
+								:style="`
+									textAlign:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.align};
+									fontSize:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.fontSize}px;
+									color:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.color}
+								`"
+							>
+								{{ chartInfo.ChartName }}
+							</h2>
+
+							<Chart :options="options" :chartInfo="chartInfo" ref="chartRef"/>
 							<div class="range-cont left" v-if="leftIndex != -1">
 								<el-input
 									style="width: 60px; display: block"
@@ -463,20 +507,57 @@
 								</div>
 							</template>
 						</div>
+
+						<div class="chart-bottom-insruction-info">
+
+							<div class="chart-source">
+								<span
+									v-if="chartInfo.SourcesFrom"
+									:style="`
+									color: ${JSON.parse(chartInfo.SourcesFrom).isShow ? JSON.parse(chartInfo.SourcesFrom).color : '#999'};
+									fontSize: ${ JSON.parse(chartInfo.SourcesFrom).fontSize }px;
+								`"
+								>来源:{{ JSON.parse(chartInfo.SourcesFrom).text}}
+								</span>
+
+								<el-switch
+									v-if="chartInfo.SourcesFrom"
+									v-model="chartInfo.SourcesFromVisable"
+									:active-value="true"
+									:inactive-value="false"
+									style="margin:0 15px;"
+									@change="changeSourceVisable"
+								/>
+								<span class="editsty" @click="isShowSourceDialog=true">编辑</span>
+							</div>
+
+							<!-- 公历农历切换 只用于季节性图 -->
+							<el-radio-group
+								v-model="calendar_type"
+								class="calendar-cont"
+								v-if="chartInfo.ChartType === 2"
+								@change="getPreviewSplineInfo"
+							>
+								<el-radio-button label="公历" />
+								<el-radio-button label="农历" />
+							</el-radio-group>
+
+							<!-- 图表说明 -->
+							<div 
+								class="chart-instruction" 
+								v-if="chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow"
+								v-text="JSON.parse(chartInfo.Instructions).text"
+								:style="`
+									color: ${JSON.parse(chartInfo.Instructions).color};
+									fontSize: ${ JSON.parse(chartInfo.Instructions).fontSize }px
+								`"
+							></div>
+						</div>
+
+
 						<span class="chart-author"
 							>作者:{{ chartInfo.SysUserRealName || roleName }}</span
 						>
-
-						<!-- 公历农历切换 只用于季节性图 -->
-						<el-radio-group
-							v-model="calendar_type"
-							class="calendar-cont"
-							v-if="chartInfo.ChartType === 2"
-							@change="getPreviewSplineInfo"
-						>
-							<el-radio-button label="公历" />
-							<el-radio-button label="农历" />
-						</el-radio-group>
 					</div>
 					<el-table
 						:data="tableData"
@@ -493,8 +574,8 @@
 							align="center"
 						>
 							<template slot-scope="scope">
-								<div v-if="item.key === 'EdbName' && chartInfo.ChartType === 7">
-									<!-- 奇怪柱状图用别名 -->
+								<div v-if="item.key === 'EdbName' && [1,4,6,7].includes(chartInfo.ChartType)">
+									<!-- 柱状图用别名 -->
 									<el-input 
 										v-model="scope.row.EdbAliasName"
 										placeholder="指标别名"
@@ -550,6 +631,13 @@
       @cancel="legendEditDiaShow = false"
       @saveLegend="saveLegend"
     />
+
+		<!-- 数据来源编辑弹窗 -->
+		<chartSourceEditDia
+			:isShow.sync="isShowSourceDialog"
+			:chartInfo="chartInfo"
+			@update="value => {chartInfo.SourcesFrom=JSON.stringify({...value,isShow:chartInfo.SourcesFromVisable})}"
+		/>
   </div>
 </template>
 
@@ -563,8 +651,10 @@ import DateChooseDia from './components/DateChooseDia';
 import barOption from './components/barOptionSection.vue';
 import sectionalScatterOption from './components/sectionalScatterOption.vue';
 import LegendEditDia from './components/LegendEditDia.vue';
+import markersSection from './components/markersSection.vue';
+import chartSourceEditDia from './components/chartSourceEditDialog.vue';
 export default {
-  components: { Chart,DateChooseDia,barOption,sectionalScatterOption,LegendEditDia},
+  components: { Chart,DateChooseDia,barOption,sectionalScatterOption,LegendEditDia,markersSection,chartSourceEditDia},
 	directives: {
     drag(el, bindings) {
       el.onmousedown = function (e) {
@@ -658,13 +748,14 @@ export default {
 							return this.$message.warning('横坐标显示范围不能为空');
 						}
 					}
-					
+
 					let db_arr = this.tableData.map(item => ({
 							ChartColor: item.ChartColor,
 							PredictChartColor: item.PredictChartColor,
 							ChartStyle: item.ChartStyle,
 							ChartWidth: Number(item.ChartWidth),
 							EdbInfoId: item.EdbInfoId,
+							EdbAliasName: item.EdbAliasName,
 							EdbInfoType: item.EdbInfoType,
 							IsAxis: item.IsAxis,
 							IsOrder: item.IsOrder,
@@ -675,11 +766,18 @@ export default {
 						})
 					)
 
+					const { ChartType,ChartName,ChartThemeId,SourcesFrom,Instructions,MarkersLines,MarkersAreas,ChartThemeStyle } = this.chartInfo;
 					let public_param = {
 						ChartClassifyId: this.chartInfo.classify.length ? this.chartInfo.classify[this.chartInfo.classify.length - 1] : 0,
-						ChartName: this.chartInfo.ChartName,
-						ChartType: this.chartInfo.ChartType,
 						ChartEdbInfoList: db_arr,
+						ChartName,
+						ChartType,
+						ChartThemeId,
+						SourcesFrom,
+						Instructions,
+						MarkersLines,
+						MarkersAreas,
+						ChartThemeStyle
 					}
 
 					//提交参数
@@ -697,7 +795,6 @@ export default {
 								EndDate: this.year_select === 5 ? this.select_date[1] : '',
 							} 
 						: typePrams
-					// console.log(params);
 					dataBaseInterface.chartAdd(params).then(res => {
 						if(res.Ret !== 200) return;
 							this.setChartImage(res.Data);
@@ -739,6 +836,7 @@ export default {
 	},
   mounted() {
 		this.getMenu();
+		this.getThemeList('init');
 		window.addEventListener('resize', this.reloadRightWid);
 	},
 	destroyed() {
@@ -819,7 +917,6 @@ export default {
 			overflow-y: auto;
 			.search-cont {
 				color: #606266;
-				margin-top: 20px;
 			}
 			.xaxis-range-cont{
 				color: #606266;
@@ -995,11 +1092,6 @@ export default {
 				.highcharts-axis-title {
 					display: block;
 				}
-				.calendar-cont {
-					display: block;
-					margin: 10px auto 0;
-					text-align: center;
-				}
 				/* =================== */
 				.chart-show-cont {
 					min-height: 300px;
@@ -1042,7 +1134,7 @@ export default {
 								justify-content: space-between;
 								top: auto;
 								right: 0;
-								bottom: -3%;
+								bottom: -2%;
 								.left {
 									width: 60px;
 									display: block;
@@ -1068,6 +1160,7 @@ export default {
       color: #666;
 			padding: 100px 0;
     }
+		
 		@media screen and (min-width: 1711px){
 			.min-data-input {
 				margin-top: 310px;

+ 3 - 3
src/views/dataEntry_manage/adjustdata/adjustData.vue

@@ -27,7 +27,7 @@
               >
               </el-option>
             </el-select>
-            <i class="el-icon-tickets" style="color:#409EFF;font-size:18px" @click="isLookHistory=true;lookEdbId=select_target" v-if="select_target"/>
+            <i class="el-icon-tickets" style="color:#409EFF;font-size:18px" @click="toHistoryPage(select_target,$route.matched);lookEdbId=select_target" v-if="select_target"/>
           </li>
           <li v-show="old_edb_info.id">
             <label style="margin-right:5px;"> 查询结果:</label>
@@ -137,10 +137,10 @@
     </div>
 
     <!-- 指标历史记录 -->
-    <edbHistoryDialog
+    <!-- <edbHistoryDialog
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
-    />
+    /> -->
   </div>
 </template>
 

+ 57 - 18
src/views/dataEntry_manage/chartSetting.vue

@@ -369,8 +369,18 @@
                 <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">{{ currentLang==='en'?(chartInfo.ChartNameEn||chartInfo.ChartName):chartInfo.ChartName }}</h2>
-                    <Chart :options="options" ref="chartRef" />
+                    <h2 
+                      class="chart-title"
+                      :style="`
+                        textAlign:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.align};
+                        fontSize:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.fontSize}px;
+                        color:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.color}
+                      `"
+                    >
+                      {{ currentLang==='en'?(chartInfo.ChartNameEn||chartInfo.ChartName):chartInfo.ChartName }}
+                    </h2>
+
+                    <Chart :options="options" :chartInfo="chartInfo" ref="chartRef"/>
 
                     <div class="range-cont left" v-if="leftIndex != -1">
                       <el-input
@@ -481,16 +491,41 @@
                     >作者:{{ chartInfo.SysUserRealName || '' }}</span
                   >
 
-                  <!-- 公历农历切换 只用于季节性图 -->
-                  <el-radio-group
-                    v-model="calendar_type"
-                    class="calendar-cont"
-                    v-if="chartInfo.ChartType === 2"
-                    @change="getPreviewChartInfo"
-                  >
-                    <el-radio-button label="公历" />
-                    <el-radio-button label="农历" />
-                  </el-radio-group>
+                  <div class="chart-bottom-insruction-info">
+
+                    <div class="chart-source" >
+                        <span
+                          v-if="chartInfo.SourcesFrom&&JSON.parse(chartInfo.SourcesFrom).isShow"
+                          :style="`
+                          color: ${JSON.parse(chartInfo.SourcesFrom).color};
+                          fontSize: ${ JSON.parse(chartInfo.SourcesFrom).fontSize }px;
+                        `"
+                        >来源:{{ JSON.parse(chartInfo.SourcesFrom).text}}</span>
+                    </div>
+
+                    <!-- 公历农历切换 只用于季节性图 -->
+                    <el-radio-group
+                      v-model="calendar_type"
+                      class="calendar-cont"
+                      v-if="chartInfo.ChartType === 2"
+                      @change="getPreviewChartInfo"
+                    >
+                      <el-radio-button label="公历" />
+                      <el-radio-button label="农历" />
+                    </el-radio-group>
+
+                    <!-- 图表说明 -->
+                    <div 
+                      class="chart-instruction" 
+                      v-if="chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow"
+                      v-text="JSON.parse(chartInfo.Instructions).text"
+                      :style="`
+                        color: ${JSON.parse(chartInfo.Instructions).color};
+                        fontSize: ${ JSON.parse(chartInfo.Instructions).fontSize }px
+                      `"
+                    ></div>
+                  </div>
+                  
                 </div>
 
                 <!-- 异常显示 -->
@@ -599,7 +634,7 @@
                     <i 
                       class="el-icon-tickets" 
                       style="color:#409EFF;font-size:18px" 
-                      @click="isLookHistory=true;lookEdbId=scope.row.EdbInfoId"
+                      @click="toHistoryPage(scope.row.EdbInfoId,$route.matched)"
                       v-if="scope.row.EdbType===2"
                     />
                   </span>
@@ -749,10 +784,10 @@
     />
 
     <!-- 指标历史记录 -->
-    <edbHistoryDialog
+    <!-- <edbHistoryDialog
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
-    />
+    /> -->
   </div>
 </template>
 
@@ -1556,6 +1591,9 @@ export default {
       }
       if (res.Ret !== 200) return;
       this.chartInfo = res.Data.ChartInfo;
+
+      //处理下历史默认来源
+			this.setDefaultSourceFrom();
   
       this.tableData = res.Data.EdbInfoList;
       // 设置起始日期和最新日期
@@ -2166,7 +2204,7 @@ export default {
         .then((res) => {
           this.refreshLoading.close();
           if (res.Ret === 200) {
-            this.getPreviewChartInfo();
+            [7,10].includes(this.chartInfo.ChartType) ? this.getChartDetail() : this.getPreviewChartInfo();
             this.$message.success(res.Msg);
           }
         });
@@ -2763,6 +2801,7 @@ export default {
       }
       .main-right {
         flex:1;
+        overflow: hidden;
         .mx-datepicker {
           width: 220px !important;
         }
@@ -2873,7 +2912,7 @@ export default {
             }
             /* =================== */
             .chart-show-cont {
-              padding: 0 160px 0 120px;
+              padding: 10px 160px 0 120px;
               position: relative;
               .chart-title {
                 font-size: 16px;
@@ -2913,7 +2952,7 @@ export default {
                     justify-content: space-between;
                     top: auto;
                     right: 0;
-                    bottom: -3%;
+                    bottom: -2%;
                     .left {
                       width: 60px;
                       display: block;

+ 400 - 0
src/views/dataEntry_manage/components/addMarkerDialog.vue

@@ -0,0 +1,400 @@
+<template>
+  <el-dialog
+		:visible.sync="isShow"
+		:close-on-click-modal="false"
+    :append-to-body="true"
+		@close="cancelHandle"
+		custom-class="marker-edit-dialog"
+		center
+		width="650px"
+		v-dialogDrag
+    top="8vh"
+    :title="form.title"
+  >
+    <div class="main">
+      <el-form
+        label-position="left"
+        label-width="120px"
+        ref="formRef"
+        :model="markerForm"
+        hide-required-asterisk
+      >
+          <el-form-item label="选择坐标轴" prop="axis">
+            <el-select 
+              v-model="markerForm.axis"
+              placeholder="请选择日期坐标轴"
+              style="width:200px;"
+              @change="markerForm.axisName=axisLabelMap[markerForm.axis]"
+            >
+              <el-option label="左轴" :value="1" v-if="canSelectLeftYaxis"/>
+              <el-option label="横轴" :value="3" v-if="canSelectXaxis"/>
+              <el-option label="右轴" :value="0" v-if="canSelectRightYaxis"/>
+              <el-option label="右2轴" :value="2" v-if="canSelectRightTwoYaxis"/>
+            </el-select>
+          </el-form-item>
+          <el-form-item :label="form.markerType==='line'?`标记线所在刻度`:`标识区所在范围`" prop="value">
+            <!-- 标识线 -->
+            <template v-if="form.markerType==='line'">
+              <!-- 时间轴1,2,4,6的y轴数字 x轴日期  -->
+              <template v-if="[1,2,4,6].includes(chartInfo.ChartType)">
+                <el-date-picker
+                  v-if="markerForm.axis===3"
+                  v-model="markerForm.value"
+                  :popper-class="{'month-day-picker':chartInfo.ChartType===2}"
+                  type="date"
+                  style="width: 200px;"
+                  placeholder="选择日期"
+                  :clearable="false"
+                  :format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                  :value-format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                ></el-date-picker>
+
+                <el-input
+                  v-else
+                  v-model="markerForm.value"
+                  class="number-input"
+                  style="width: 200px;"
+                  type="number"
+                  placeholder="输入数字"
+                />
+
+              </template>
+
+              <!-- 柱形图,散点,截面散点只可选数字 -->
+              <template v-else-if="[5,7,10].includes(chartInfo.ChartType)">
+                <el-input
+                  v-model="markerForm.value"
+                  style="width: 200px;"
+                  type="number"
+                  class="number-input"
+                  placeholder="输入数字"
+                  clearable
+                />
+              </template>
+            </template>
+
+
+            <!-- 标识区 -->
+            <template v-else>
+              <!-- 时间轴1,2,4,6的y轴数字 x轴日期  -->
+              <template v-if="[1,2,4,6].includes(chartInfo.ChartType)">
+                <div v-if="markerForm.axis===3">
+                  <el-date-picker
+                    v-model="markerForm.fromValue"
+                    :popper-class="{'month-day-picker':chartInfo.ChartType===2}"
+                    type="date"
+                    style="width: 150px;"
+                    placeholder="选择日期"
+                    :clearable="false"
+                    :format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                    :value-format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                  ></el-date-picker>
+                  至
+                  <el-date-picker
+                    v-model="markerForm.toValue"
+                    :popper-class="{'month-day-picker':chartInfo.ChartType===2}"
+                    type="date"
+                    style="width: 150px;"
+                    placeholder="选择日期"
+                    :clearable="false"
+                    :format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                    :value-format="chartInfo.ChartType===2?'MM-dd':'yyyy-MM-dd'"
+                  ></el-date-picker>
+                </div>
+
+                <div v-else>
+                  <el-input
+                    v-model="markerForm.fromValue"
+                    class="number-input"
+                    style="width: 90px;"
+                    type="number"
+                    placeholder="输入数字"
+                  />
+                  至
+                  <el-input
+                    v-model="markerForm.toValue"
+                    class="number-input"
+                    style="width: 90px;"
+                    type="number"
+                    placeholder="输入数字"
+                  />
+
+                </div>
+              </template>
+
+              <!-- 柱形图,散点,截面散点只可选数字 -->
+              <div v-else-if="[5,7,10].includes(chartInfo.ChartType)">
+                <el-input
+                  v-model="markerForm.fromValue"
+                  class="number-input"
+                  style="width: 90px;"
+                  type="number"
+                  placeholder="输入数字"
+                />
+                至
+                <el-input
+                  v-model="markerForm.toValue"
+                  class="number-input"
+                  style="width: 90px;"
+                  type="number"
+                  placeholder="输入数字"
+                />
+
+              </div>
+            </template>
+            
+          </el-form-item>
+          <el-form-item label="线型" prop="dashStyle" v-if="form.markerType==='line'">
+            <el-select 
+              v-model="markerForm.dashStyle"
+              style="width:200px;"
+            >
+              <el-option 
+                v-for="item in dashOptions" 
+                :key="item.value" 
+                :label="item.label" 
+                :value="item.value"
+              >
+                <svg width="60" height="10" viewBox="0 0 60 10" fill="none" xmlns="http://www.w3.org/2000/svg" v-html="item.svg"></svg>
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="颜色" prop="color" style="margin-bottom:8px;">
+            <el-color-picker
+              v-model="markerForm.color"
+              :predefine="predefineColors"
+              show-alpha
+              style="width: 90px"
+            />
+          </el-form-item>
+          <el-form-item label="粗细" prop="lineWidth" v-if="form.markerType==='line'">
+            <el-input
+              v-model="markerForm.lineWidth"
+              style="width: 90px"
+              type="number"
+              :min="1"
+            />
+          </el-form-item>
+          <el-form-item :label="`标记${form.markerType==='line'?'线':'区'}说明`" prop="text">
+            <el-input
+              v-model="markerForm.text"
+              style="width: 200px"
+              placeholder="请输入内容"
+            />
+          </el-form-item>
+          <el-form-item label="文本位置" prop="textPosition">
+            <el-select 
+              v-model="markerForm.textPosition"
+              style="width:200px;"
+            >
+              <el-option 
+                v-for="item in verticalPositions" 
+                :key="item.value" 
+                :label="item.label" 
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="文本颜色" prop="textColor" style="margin-bottom:8px;">
+            <el-color-picker
+              v-model="markerForm.textColor"
+              show-alpha
+              :predefine="predefineColors"
+              style="width: 90px"
+            />
+          </el-form-item>
+          <el-form-item label="文本字号" prop="textFontSize">
+            <el-input
+              v-model="markerForm.textFontSize"
+              class="number-input"
+              style="width: 90px"
+              type="number"
+              :min="1"
+            />
+          </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="bottom">
+      <el-button @click="saveMarker" type="primary" style="margin-right:5%">保存</el-button>
+      <el-button @click="cancelHandle">取消</el-button>
+    </div>
+
+  </el-dialog>
+</template>
+<script>
+import { defaultOpts } from '@/utils/defaultOptions';
+import { verticalPositions } from '@/views/system_manage/chartTheme/common/config';
+export default {
+  props: {
+    isShow: {
+      type: Boolean
+    },
+
+    form: {
+      type: Object  //markerType:’line‘标示线 'area'标识区 
+    },
+
+    axisInfo: {  //轴信息
+      type: Object
+    },
+
+    chartInfo: {
+      type:Object
+    }
+
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+
+      if(this.form.editIndex) { //表单回显
+        this.editIndex = this.form.editIndex;
+        this.markerForm = {
+          ...this.form.data
+        }
+      }else {
+        this.editIndex = 0;
+        
+        let themeOpt = JSON.parse(this.chartInfo.ChartThemeStyle);
+
+        this.markerForm = {
+          axis: this.canSelectLeftYaxis?1:0,
+          axisName:this.axisLabelMap[this.canSelectLeftYaxis?1:0],
+          value: '',
+          from: '',
+          to:'',
+          lineWidth: 2,
+          dashStyle: 'ShortDashDot',
+          color: '#999',
+          text: '',
+          textPosition: 'top',
+          textColor: themeOpt.markerOptions.style.color,
+          textFontSize: themeOpt.markerOptions.style.fontSize,
+          isShow: true,
+        }
+      }
+    }
+  },
+  computed: {
+     /* 是否可选左轴
+      季节图 柱形图 散点图 截面散点固定左轴*/
+    canSelectLeftYaxis() {
+      let isHave = false;
+      if([2,5,7,10].includes(this.chartInfo.ChartType)){
+        isHave=true
+      }else {
+        if(this.axisInfo.leftIndex!=-1) isHave=true
+      }
+      return isHave
+    },
+    /* 是否可选x轴 柱形图不可选*/
+    canSelectXaxis() {
+      return this.chartInfo.ChartType!==7
+    },
+    /* 是否可选右轴 曲线 组合 堆积柱*/
+    canSelectRightYaxis() {
+      return [1,4,6].includes(this.chartInfo.ChartType) && this.axisInfo.rightIndex!=-1
+    },
+    /* 是否可选右2轴 曲线 组合*/
+    canSelectRightTwoYaxis() {
+      return [1,6].includes(this.chartInfo.ChartType) && this.axisInfo.rightTwoIndex!=-1
+    },
+  },
+  data() {
+    return {
+      predefineColors: defaultOpts.colors.slice(0, 2), //定义颜色蓝,红 默认颜色,
+      verticalPositions,
+      editIndex: 0,
+      markerForm: {
+        axis: 1,
+        axisName: '',
+        isShow: true,
+        value: '',//线用
+        fromValue: '',//区用
+        toValue:'',//区用
+        lineWidth: 2,
+        dashStyle: 'ShortDashDot',
+        color: '#999',
+        text: '',
+        textPosition: 'top',
+        textColor: '#999',
+        textFontSize: 12
+      },
+
+      axisLabelMap: { //暂时没有横轴的代表key 规定为3好了
+        1: '左轴',
+        0: '右轴',
+        2: '右二轴',
+        3: '横轴',
+      },
+
+      dashOptions: [
+        { label: '实线',value: 'Solid',svg:`<g clip-path="url(#clip0_2634_4692)"><rect x="-14" y="4" width="116" height="2" fill="#333333"/></g><defs><clipPath id="clip0_2634_4692"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+        { label: '长虚线点',value: 'LongDashDot',svg:`<g clip-path="url(#clip0_2634_4933)"><circle cy="5" r="1" fill="#333333"/><rect x="2" y="4" width="13" height="2" rx="1" fill="#333333"/><circle cx="17" cy="5" r="1" fill="#333333"/><rect x="19" y="4" width="13" height="2" rx="1" fill="#333333"/><circle cx="34" cy="5" r="1" fill="#333333"/><rect x="36" y="4" width="13" height="2" rx="1" fill="#333333"/><circle cx="51" cy="5" r="1" fill="#333333"/><rect x="53" y="4" width="13" height="2" rx="1" fill="#333333"/><circle cx="68" cy="5" r="1" fill="#333333"/><rect x="70" y="4" width="13" height="2" rx="1" fill="#333333"/><circle cx="85" cy="5" r="1" fill="#333333"/><rect x="87" y="4" width="13" height="2" rx="1" fill="#333333"/></g><defs><clipPath id="clip0_2634_4933"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+        { label: '短虚线点',value: 'ShortDashDot',svg:`<g clip-path="url(#clip0_2634_4756)"><rect x="1" y="4" width="2" height="2" fill="#333333"/><rect x="4" y="4" width="5" height="2" fill="#333333"/><rect x="10" y="4" width="2" height="2" fill="#333333"/><rect x="13" y="4" width="5" height="2" fill="#333333"/><rect x="19" y="4" width="2" height="2" fill="#333333"/><rect x="22" y="4" width="5" height="2" fill="#333333"/><rect x="28" y="4" width="2" height="2" fill="#333333"/><rect x="31" y="4" width="5" height="2" fill="#333333"/><rect x="37" y="4" width="2" height="2" fill="#333333"/><rect x="40" y="4" width="5" height="2" fill="#333333"/><rect x="46" y="4" width="2" height="2" fill="#333333"/><rect x="49" y="4" width="5" height="2" fill="#333333"/><rect x="55" y="4" width="2" height="2" fill="#333333"/><rect x="58" y="4" width="5" height="2" fill="#333333"/><rect x="64" y="4" width="2" height="2" fill="#333333"/><rect x="67" y="4" width="5" height="2" fill="#333333"/><rect x="73" y="4" width="2" height="2" fill="#333333"/><rect x="76" y="4" width="5" height="2" fill="#333333"/><rect x="82" y="4" width="2" height="2" fill="#333333"/><rect x="85" y="4" width="5" height="2" fill="#333333"/></g><defs><clipPath id="clip0_2634_4756"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+      ],
+    }
+  },
+  mounted(){
+
+  },
+  methods:{
+
+    async saveMarker() {
+
+      if(this.form.markerType==='line'&&!this.markerForm.value) return this.$message.warning('标识线所在刻度不能为空')
+
+      else if(this.form.markerType==='area'&&(!this.markerForm.fromValue||!this.markerForm.toValue)) return this.$message.warning('标识区所在范围不能为空')
+      
+      else if(this.form.markerType==='area'&&this.markerForm.fromValue===this.markerForm.toValue) return this.$message.warning('标识区所在范围不能相同')
+
+      
+      let item = _.cloneDeep(this.markerForm)
+      
+      this.editIndex 
+        ? this.$emit('edit',{
+            index: this.editIndex,
+            item
+          }) 
+        : this.$emit('add',item)
+
+      this.cancelHandle()
+    },
+   
+    cancelHandle() {
+      this.$emit('update:isShow',false)
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.main {
+  padding-left: 20%;
+}
+.bottom {
+  margin: 30px 0;
+  display: flex;
+  justify-content: center;
+}
+</style>
+<style lang="scss">
+.marker-edit-dialog {
+  .el-color-picker__trigger { width: 100%;padding: 0;border-radius: 4px; }
+  .number-input .el-input__inner { padding: 0 2px 0 10px; }
+
+}
+.month-day-picker {
+  .el-date-picker__header {
+    span:nth-child(3) {
+      display: none;
+    }
+    button:nth-child(1) {
+      display: none;
+    }
+    button:nth-child(5) {
+      display: none;   
+    }
+  }
+}
+</style>

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

@@ -140,6 +140,9 @@ export default {
   props: {
     edblist: Array,
     datedata: Array,
+    chartInfo: {
+      type: Object
+    },
     initData: {
       default: null
     }
@@ -246,8 +249,10 @@ export default {
           Color: ''
         }
         this.dateList.push(date_item)
+        
+        let themeOpt = this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
         this.dateList.forEach((item,index) => {
-          item.Color = item.Color || defaultOpts.colors[index];
+          item.Color = item.Color || (themeOpt&&themeOpt.colorsOptions[index]||defaultOpts.colors[index]);
         })
       }
       this.cancelDialog()

+ 39 - 43
src/views/dataEntry_manage/components/chart.vue

@@ -35,6 +35,10 @@ export default {
 		index: {
 			type: String,
 			default: '1'
+		},
+		chartInfo: {
+			type: Object,
+			default: () => {}
 		}
 	},
 	watch: {
@@ -54,55 +58,26 @@ export default {
 	methods: {
 
 		init() {
-			// if(this.options.isRelevanceChart){//相关性图表设置x轴在y轴0刻度
-			// 	this.$nextTick(()=>{
-			// 		// let h = $('.highcharts-yaxis .highcharts-axis-line')[0].getBoundingClientRect().height;
-			// 		// console.log(h)
-			// 		// this.options.xAxis.offset=-h/2;
-			// 		const h=$(`#container${this.index}`)[0].style.height
-			// 		if(h=='500px'){
-			// 			this.options.xAxis.offset=-200.5
-			// 		}else if(h=='440px'){
-			// 			this.options.xAxis.offset=-170.5
-			// 		}else if(h=='350px'){
-			// 			this.options.xAxis.offset=-125.5
-			// 		}
-			// 	})
-			// }
+			/* eta1.4.1增加了主题色
+			仍然以defaultOpts为最底层配置 外层配置在这里统一设置了如legend chart背景色
+			x轴y轴系列等样式还是需要在具体的options中单独设置 */
 
-			const options = {...defaultOpts,...this.options}
+			let themeOptions = this.setThemeOptions();
+			const options = {...defaultOpts,...themeOptions,...this.options}
+
+			console.log(themeOptions,this.options)
+			
 			let thatThis = this
-			//stock不支持线形图只支持时间图 画散点图用原始chart
+			//stock不支持线形图只支持时间图 部分图用原始chart
 			let is_linear = this.options.series 
-				? this.options.series.every(_ => _.type === 'scatter' ) || this.options.series.some(_ => _.chartType === 'linear'  )
+				? this.options.series.some(_ => _.chartType === 'linear')
 				: false ;
 
 			Highcharts.setOptions({ global: { useUTC: false } });
-			this.chart = is_linear ? 
-			Highcharts.chart(`container${this.index}`, options,function(chart) {
-				let {yAxis,xAxis} = chart
-				yAxis.map(item => {
-					if(item.axisTitle){
-						// 绑定竖轴标题的点击事件
-						Highcharts.addEvent(item.axisTitle.element,'click',thatThis.clickYAxisTitle)
-					}
-				})
-				xAxis.map(item => {
-					if(item.axisTitle){
-						// 绑定横轴标题的点击事件
-						Highcharts.addEvent(item.axisTitle.element,'click',thatThis.clickXAxisTitle)
-					}
-				})
-			}) 
-			: Highcharts.stockChart(`container${this.index}`,options,function(chart) {
-				let {yAxis} = chart
-				yAxis.map((item,index) => {
-					if(item.axisTitle){
-						// 绑定竖轴标题的点击事件
-						Highcharts.addEvent(item.axisTitle.element,'click',thatThis.clickYAxisTitle)
-					}
-				})
-			});
+			this.chart = is_linear 
+				? Highcharts.chart(`container${this.index}`, options) 
+				: Highcharts.stockChart(`container${this.index}`,options);
+
 			let that = this;
       if(!$('#right')[0]) return
 			erd.listenTo($('#right')[0], function (element) { //执行监听 
@@ -115,11 +90,32 @@ export default {
 		clickYAxisTitle(){
 			this.$emit('clickYAxisTitle')
 		},
+
 		// 点击X轴标题监听事件  散点图
 		clickXAxisTitle(){
 			// 目前点击Y轴标题和X轴都是同一个方法 所以直接派发跟Y轴点击的方法
 			this.$emit('clickYAxisTitle')
 		},
+
+		//主题色一些外层公用配置  目前只有绘图区和legend和colors
+		setThemeOptions() {
+			if(!this.chartInfo||!this.chartInfo.ChartThemeStyle) return {}
+
+			let chartTheme = JSON.parse(this.chartInfo.ChartThemeStyle)		
+			return {
+				legend: {
+					...defaultOpts.legend,
+					...chartTheme.legendOptions
+				},
+				chart: {
+					...defaultOpts.chart,
+					...chartTheme.drawOption,
+					spacing: chartTheme.legendOptions.verticalAlign==='bottom' ? [23,10,2,10] : [2,10,2,10],//图例在底部顶部空间留大点给单位
+				},
+				colors: chartTheme.colorsOptions
+			}
+		},
+
 		initHeight() {
 			/* 1550以下 */
 			if($(window).width() <= 1710) {

+ 105 - 0
src/views/dataEntry_manage/components/chartSourceEditDialog.vue

@@ -0,0 +1,105 @@
+<template>
+  <el-dialog
+    :visible.sync="isShow"
+		:close-on-click-modal="false"
+    :append-to-body="true"
+		@close="cancelHandle"
+		custom-class="marker-edit-dialog"
+		center
+		width="650px"
+		v-dialogDrag
+    top="8vh"
+    title="编辑数据来源"
+  >
+    <div style="padding-left: 20%">
+      <el-form
+        :model="chartSourceForm"
+        label-width="80px"
+        label-position="left"
+      >
+        <el-form-item label="数据来源">
+          <el-input
+            v-model="chartSourceForm.text"
+            placeholder="请输入内容"
+          />
+        </el-form-item>
+        <el-form-item label="颜色" style="margin-bottom:8px;">
+          <el-color-picker
+            v-model="chartSourceForm.color"
+            show-alpha
+            style="width:90px"
+          />
+        </el-form-item>
+        <el-form-item label="字号">
+          <el-input
+            v-model="chartSourceForm.fontSize"
+            style="width: 90px"
+            type="number"
+            :min="1"
+          />
+        </el-form-item>
+      </el-form>
+    </div>
+    <div slot="footer" style="margin-top: 20px;">
+      <el-button @click="saveSource" type="primary">保存</el-button>
+      <el-button @click="cancelHandle">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+<script>
+export default {
+  props: {
+    isShow: {
+      type: Boolean
+    },
+    chartInfo: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+      
+      if(this.chartInfo.SourcesFrom) { //回显
+        let { text,color,fontSize } = JSON.parse(this.chartInfo.SourcesFrom);
+        this.chartSourceForm = {
+          text,
+          color,
+          fontSize
+        }
+      }else {
+        this.chartSourceForm = {
+          text: '',
+          color: JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.color,
+          fontSize: JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.fontSize
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      chartSourceForm: {
+        text: '',
+        color: '',
+        fontSize: ''
+      }
+    }
+  },
+  methods:{
+    saveSource() {
+      if(!this.chartSourceForm.text) return this.$message.warning('数据来源不能为空')
+
+      this.$emit('update',this.chartSourceForm)
+      this.cancelHandle()
+    },
+    
+    cancelHandle() {
+      this.$emit('update:isShow',false)
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+
+</style>

+ 300 - 0
src/views/dataEntry_manage/components/markersSection.vue

@@ -0,0 +1,300 @@
+<template>
+  <div class="chart-markers-section">
+    <!-- 标示线 -->
+    <div class="section-item">
+      <ul class="marker-list"  v-if="markerLinesArr.length">
+        <li class="marker-item" v-for="(item,index) in markerLinesArr" :key="index">
+          <span>{{item.axisName}}: {{item.value}}</span>
+          <div style="flex-shrink:0">
+            <i class="el-icon-view icon" :style="item.isShow?'color:#0052D9':'color:#999'" @click="item.isShow=!item.isShow;updateChartHandle()"/>
+            <i class="el-icon-edit icon" style="margin:0 6px" @click="openMarkerDiaHandle('line',index+1)"/>
+            <i class="el-icon-delete icon" @click="markerLinesArr.splice(index,1);updateChartHandle()"/>
+          </div>
+        </li>
+      </ul>
+
+      <div
+        class="add-cont"
+        @click="openMarkerDiaHandle('line')"
+      >
+        <img
+          src="~@/assets/img/set_m/add_ico.png"
+          alt=""
+          style="width: 16px; height: 16px; margin-right: 10px"
+        />
+        <span>添加标识线</span>
+      </div>
+
+    </div>
+
+    <!-- 标识区 -->
+    <div class="section-item">
+      <ul class="marker-list" v-if="markerAreasArr.length">
+        <li class="marker-item" v-for="(item,index) in markerAreasArr" :key="index">
+          <span>{{item.axisName}}: {{`${item.fromValue}至${item.toValue}`}}</span>
+          <div style="flex-shrink:0">
+            <i class="el-icon-view icon" :style="item.isShow?'color:#0052D9':'color:#999'" @click="item.isShow=!item.isShow;updateChartHandle()"/>
+            <i class="el-icon-edit icon" style="margin:0 6px" @click="openMarkerDiaHandle('area',index+1)"/>
+            <i class="el-icon-delete icon" @click="markerAreasArr.splice(index,1);updateChartHandle()"/>
+          </div>
+        </li>
+      </ul>
+      <div
+        class="add-cont"
+        @click="openMarkerDiaHandle('area')"
+      >
+        <img
+          src="~@/assets/img/set_m/add_ico.png"
+          alt=""
+          style="width: 16px; height: 16px; margin-right: 10px"
+        />
+        <span>添加标识区</span>
+      </div>
+
+    </div>
+
+    <!-- 图表说明 -->
+    <div class="section-item">
+      <div class="induction-item" v-if="chartInstruction.text">
+        <div v-text="chartInstruction.text" class="text_oneLine text"></div>
+         <div>
+            <i class="el-icon-view icon" :style="chartInstruction.isShow?'color:#0052D9':'color:#999'" @click="chartInstruction.isShow=!chartInstruction.isShow;updateChartHandle()"/>
+            <i class="el-icon-edit icon" style="margin:0 6px" @click="addChartInductionHandle"/>
+            <i class="el-icon-delete icon" @click="chartInstruction.text=''; updateChartHandle()"/>
+          </div>
+      </div>
+
+      <div
+        class="add-cont"
+        v-if="!chartInstruction.text"
+        @click="addChartInductionHandle('add')"
+      >
+        <img
+          src="~@/assets/img/set_m/add_ico.png"
+          alt=""
+          style="width: 16px; height: 16px; margin-right: 10px"
+        />
+        <span>添加图表说明</span>
+      </div>
+
+    </div>
+
+    
+    <!-- 标识线标识区弹窗 -->
+    <addMarkerDialog
+      :isShow.sync="isOpenMarkerDialog"
+      :form="markerForm"
+      :chartInfo="chartInfo"
+      :axisInfo="{
+        leftIndex: $parent.leftIndex,
+        rightIndex: $parent.rightIndex,
+        rightTwoIndex: $parent.rightTwoIndex
+      }"
+      @add="addMarkerItem"
+      @edit="editMarkerItem"
+    />
+
+    <!-- 图表说明弹窗 -->
+    <m-dialog
+      :title="'添加图表说明'"
+      class="marker-edit-dialog"
+      :show.sync="chartInductionDiaForm.show" 
+      width="650px"
+    >
+      <div style="padding-left: 20%">
+        <el-form
+          :model="chartInductionDiaForm"
+          label-width="80px"
+          label-position="left"
+        >
+          <el-form-item label="图表说明">
+            <el-input
+              v-model="chartInductionDiaForm.text"
+              placeholder="请输入内容"
+            />
+          </el-form-item>
+          <el-form-item label="颜色" style="margin-bottom:8px;">
+            <el-color-picker
+              v-model="chartInductionDiaForm.color"
+              show-alpha
+              style="width:90px"
+            />
+          </el-form-item>
+          <el-form-item label="字号">
+            <el-input
+              v-model="chartInductionDiaForm.fontSize"
+              style="width: 90px"
+              type="number"
+              :min="1"
+            />
+          </el-form-item>
+        </el-form>
+      </div>
+      <div slot="footer" style="margin-top: 20px;">
+        <el-button @click="saveInductionDiaForm" type="primary">保存</el-button>
+        <el-button @click="chartInductionDiaForm.show=false">取消</el-button>
+      </div>
+    </m-dialog>
+
+  </div>  
+</template>
+<script>
+import addMarkerDialog from './addMarkerDialog.vue'
+import mDialog from '@/components/mDialog.vue'
+export default {
+  components: { addMarkerDialog,mDialog },
+  props: {
+    chartInfo: {
+      type: Object
+    }
+  },
+  data() {
+    return {
+      markerLinesArr: [],
+      markerAreasArr: [],
+      chartInstruction:{
+        text: '',
+        isShow: true,
+        color: '',
+        fontSize: ''
+      } ,
+
+      /* 标识线区弹窗 */
+      isOpenMarkerDialog: false,
+      markerForm: {
+        markerType: 'line',
+        title:''
+      },
+
+      /* 图表说明弹窗 */
+      chartInductionDiaForm: {
+        show: false,
+        text: '',
+      }
+    }
+  },
+  methods:{
+    /* 打开弹窗 */
+    openMarkerDiaHandle(markerType,index=null) {
+      this.isOpenMarkerDialog = true
+      if(index) { //编辑
+        let editItem = markerType==='line' ? this.markerLinesArr[index-1] : this.markerAreasArr[index-1];
+
+        this.markerForm = {
+          markerType,
+          editIndex: index,
+          title: `编辑标识${markerType==='line'?'线':'区'}`,
+          data: editItem
+        }
+      }else {
+        this.markerForm = {
+          markerType,
+          title: `添加标识${markerType==='line'?'线':'区'}`
+        }
+        
+      }
+    },
+
+    /* 添加标识线/区 */
+    addMarkerItem(item) {
+      this.markerForm.markerType==='line' 
+        ? this.markerLinesArr.push(item)
+        : this.markerAreasArr.push(item)
+
+      this.updateChartHandle()
+    },
+
+    /* 编辑标识线/区 */
+    editMarkerItem({index,item}) {
+      this.markerForm.markerType==='line'
+        ? this.$set(this.markerLinesArr,[index-1],item) 
+        : this.$set(this.markerAreasArr,[index-1],item)
+
+      this.updateChartHandle()
+    },
+
+    addChartInductionHandle(type='') {
+      const { text,color,fontSize } = this.chartInstruction;
+      this.chartInductionDiaForm = {
+        show: true,
+        text,
+        color:type==='add'?JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.color:color,
+        fontSize: type==='add'?JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.fontSize:fontSize
+      }
+    },
+
+    saveInductionDiaForm() {
+      if(!this.chartInductionDiaForm.text) return this.$message.warning('图表说明不能为空')
+      const { text,color,fontSize } = this.chartInductionDiaForm;
+      this.chartInstruction = {
+        text,
+        isShow: this.chartInstruction.isShow,
+        color,
+        fontSize
+      };
+      this.chartInductionDiaForm.show = false;
+       this.updateChartHandle()
+    },
+
+    //更新图表标识区/线/说明
+    updateChartHandle() {
+      this.$emit('update',{
+        markerLinesArr: this.markerLinesArr,
+        markerAreasArr: this.markerAreasArr,
+        chartInstruction: this.chartInstruction
+      })
+    },
+
+    /* 数据回显 */
+    initData(data) {
+      const { MarkersLines,MarkersAreas,Instructions } = data;
+      this.markerLinesArr = MarkersLines ? JSON.parse(MarkersLines) : [];
+      this.markerAreasArr = MarkersAreas ? JSON.parse(data.MarkersAreas) : [];
+      this.chartInstruction = Instructions ? JSON.parse(data.Instructions) : {
+        text: '',
+        isShow: true,
+        color: this.chartInfo.ChartThemeStyle?JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.color:'#333',
+        fontSize: this.chartInfo.ChartThemeStyle?JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.fontSize:12
+      };
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.chart-markers-section {
+  .section-item {
+    margin-top: 30px;
+    .marker-list {
+      margin-bottom: 15px;
+      border: 1px solid #DCDFE6;
+      background: #F0F2F5;
+      .marker-item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 12px 15px;
+      }
+    }
+    .icon {font-size: 18px;cursor: pointer;}
+    .el-icon-delete{
+      color: #f00;
+    }
+    .induction-item {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 15px;
+      .text {
+        width: 160px;
+      }
+    }
+    .add-cont {
+      color: #409eff;
+      font-size: 16px;
+      cursor: pointer;
+      display: flex;
+      align-items: center;
+    }
+  }
+}
+</style>

+ 3 - 0
src/views/dataEntry_manage/components/satterSeriesDia.vue

@@ -403,6 +403,9 @@ export default {
         //遍历请求xEdbs yEdbs的指标详情,获取最新日期和值
         this.getEdbData()
         this.getEdbNewInfo()
+      }else {
+        let themeOpt = this.$parent.chartInfo.ChartThemeStyle ? JSON.parse(this.$parent.chartInfo.ChartThemeStyle) : null;      
+        this.form.color = themeOpt&&themeOpt.colorsOptions[0] || defaultOpts.colors[0];
       }
     }
   },

+ 6 - 1
src/views/dataEntry_manage/components/sectionalScatterOption.vue

@@ -174,6 +174,9 @@ export default {
         type:Array,
         default:[]
     },
+    chartInfo: {
+      type: Object
+    },
     IsNameDefault:{
         type:Boolean,
         default:true
@@ -320,8 +323,10 @@ export default {
 
     /* 新增系列弹窗 */
     addSeriesHandle() {
+
+      let themeOpt = this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
       this.dialogForm.show = true;
-      this.dialogForm.color = defaultOpts.colors[this.seriesArr.length];
+      this.dialogForm.color = themeOpt&&themeOpt.colorsOptions[this.seriesArr.length] || defaultOpts.colors[this.seriesArr.length];
     },
 
     /* 保存新增系列 */

+ 3 - 1
src/views/dataEntry_manage/css/chartfit.scss

@@ -142,6 +142,7 @@ $font-normal:14px;
 		}
 		.main-right {
 			width: 80%;
+			overflow: hidden;
 			.mx-datepicker {
 				width: 220px !important;
 			}
@@ -261,12 +262,13 @@ $font-normal:14px;
 					}
 					/* =================== */
 					.chart-show-cont {
-						padding: 0 160px 0 120px;
+						padding: 10px 160px 0 120px;
 						position: relative;
 						.chart-title {
 							font-size: 16px;
 							font-weight: normal;
 							text-align: center;
+							margin-bottom: 10px;
 						}
 						.chart-author {
 							font-size: 14px;

+ 15 - 15
src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue

@@ -60,7 +60,7 @@
 		</div>
 		<div class="min-wrapper">
 			<div class="chartWrapper" id="chartWrapper" v-if="showChart">
-				<Chart :options="options" ref="chartRef" @clickYAxisTitle="clickYAxisTitle"/>
+				<Chart :options="options" :chartInfo="chartInfo" ref="chartRef"/>
 				<div class="range-cont left" v-if="leftIndex != -1">
 					<el-input
 						style="width: 80px; display: block"
@@ -505,8 +505,10 @@ export default {
 					text: yTitleText,
 					align: 'high',
 					rotation: 0,
-					y: -15,
-					offset: 0,
+					y: -12,
+					x: 0,
+					textAlign: 'left',
+					reserveSpace: false,
 					style:yTitleStyle
 				},
 				labels: {
@@ -600,10 +602,6 @@ export default {
           );
           const s_yItem = {
             labels: {
-              formatter: function () {
-                let val = this.value;
-                return index !== 0 ? '' : val;
-              },
               align: 'center',
             },
             title: {
@@ -611,12 +609,15 @@ export default {
 							!this.chartInfo.UnitEn && this.chartInfo.Unit && this.chartInfo.Unit!='无' ? '英文单位':this.chartInfo.UnitEn,
               align: 'high',
               rotation: 0,
-              y: -15,
-              offset: -(12 * this.chartInfo.Unit.length),
+							y: -12,
+							x: 0,
+							textAlign: 'left',
+							reserveSpace: false,
             },
             max: Number(this.chartInfo.MaxValue),
             min: Number(this.chartInfo.MinValue),
             ...seasonOptions.yAxis,
+						visible: index===0
           };
           seasonData.push(serie_item);
           seasonYdata.push(s_yItem);
@@ -644,10 +645,6 @@ export default {
           const index = filterArr.findIndex((item) => item.Year === j.Year);
           const s_yItem = {
             labels: {
-              formatter: function () {
-                let val = this.value;
-                return index !== 0 ? '' : val;
-              },
               align: 'center',
             },
             title: {
@@ -655,12 +652,15 @@ export default {
 							!this.chartInfo.UnitEn && this.chartInfo.Unit && this.chartInfo.Unit!='无' ? '英文单位':this.chartInfo.UnitEn,
               align: 'high',
               rotation: 0,
-              y: -15,
-              offset: -(12 * this.chartInfo.Unit.length),
+              y: -12,
+							x: 0,
+							textAlign: 'left',
+							reserveSpace: false,
             },
             max: Number(this.chartInfo.MaxValue),
             min: Number(this.chartInfo.MinValue),
             ...seasonOptions.yAxis,
+						visible: index===0
           };
           seasonData.push(serie_item);
           seasonYdata.push(s_yItem);

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

@@ -50,7 +50,7 @@
 		</div>
 		<div class="min-wrapper">
 			<div class="chartWrapper" id="chartWrapper" v-if="showChart">
-				<Chart :options="options" ref="chartRef" @clickYAxisTitle="clickYAxisTitle" />
+				<Chart :options="options" ref="chartRef"/>
 				<div class="range-cont left" v-if="leftIndex != -1">
 					<el-input
 						style="width: 80px; display: block"

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

@@ -165,7 +165,7 @@ export default {
       const res = await dataBaseInterface.insertData({
         EdbInfoId: edbId,
         Date: date,
-        value: Number(value)
+        value: value
       })
 
       if(res.Ret !== 200) return

+ 7 - 7
src/views/dataEntry_manage/databaseList.vue

@@ -241,7 +241,7 @@
 							<el-button v-if="activeTab==='Chart'&&isEdbBtnShow('saveEdb')"
 								type="text" @click.stop="saveEdbLimit">保存</el-button>
 							<el-button v-if="EdbData.EdbType===2&&isEdbBtnShow('toSource')"
-								type="text" @click="isLookHistory=true;lookEdbId=selected_edbid">指标溯源</el-button>
+								type="text" @click="toHistoryPage(selected_edbid,$route.matched);lookEdbId=selected_edbid">指标溯源</el-button>
 							<el-popover v-if="showPopver"
 								placement="bottom-end" 
 								trigger="hover"
@@ -356,7 +356,7 @@
 			@cancel="computed_type=0"
 			@addCallBack="addComputedCallBack"
 			@openPrev="isOpenComputed=true"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 		/>
 		<!-- 计算弹窗控制 -->
 		<el-dialog
@@ -403,7 +403,7 @@
 			@cancel="computed_type=0"
 			@addCallBack="addComputedCallBack"
 			@openPrev="isOpenComputed=true"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 			@changeSource="changeComputedType"
 		/>
 		<!-- 一键成图弹窗 -->
@@ -454,7 +454,7 @@
 			@cancel="computed_type=0"
 			@addCallBack="addComputedCallBack"
 			@openPrev="isOpenComputed=true"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 			@changeSource="changeComputedType"
 		/>
 
@@ -477,10 +477,10 @@
 		/>
 
 		 <!-- 指标历史记录 -->
-    <edbHistoryDialog
+    <!-- <edbHistoryDialog
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
-    />
+    /> -->
 		<!-- 指数修匀弹窗 -->
 		<SmoothEdbDialog 
 			:is-open-smooth="computed_type==='alpha'"
@@ -489,7 +489,7 @@
 			@cancel="computed_type=0"
 			@openPrev="isOpenComputed=true"
 			@addCallBack="addComputedCallBack"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 		/>
 	</div>
 </template>

+ 165 - 71
src/views/dataEntry_manage/editChart.vue

@@ -32,7 +32,7 @@
 					:model="chartInfo"
 					:rules="chartRules"
 				>
-					<el-form-item label="图表生成样式" prop="ChartType">
+					<el-form-item label="生成图表类型" prop="ChartType">
 						<el-select
 							v-model="chartInfo.ChartType"
 							placeholder="请选择生成样式"
@@ -48,6 +48,61 @@
 							</el-option>
 						</el-select>
 					</el-form-item>
+
+					<el-form-item label="图表主题" prop="Theme">
+						<el-select
+							v-model="chartInfo.ChartThemeId"
+							placeholder="请选择图表主题"
+							style="width: 90%"
+							@change="changeThemeHandle"
+						>
+							<el-option
+								v-for="item in chartThemeArr"
+								:key="item.ChartThemeId"
+								:label="item.ChartThemeName"
+								:value="item.ChartThemeId"
+							>
+							</el-option>
+						</el-select>
+					</el-form-item>
+
+					<el-form-item label="">
+						<div class="search-cont" v-if="chartInfo.ChartType!==10">
+							<div>
+								<label>选择指标:</label>
+								<el-radio-group v-model="edbFromType">
+									<el-radio :label="0" style="margin-right: 15px">ETA指标</el-radio>
+									<el-radio :label="1">ETA预测指标</el-radio>
+								</el-radio-group>
+							</div>
+							<el-select
+								v-model="search_txt"
+								v-loadMore="searchLoad"
+								ref="searchRef"
+								:filterable="!search_txt"
+								remote
+								clearable
+								placeholder="指标ID/指标名称"
+								style="width:90%;margin-top: 10px;display: block;"
+								:remote-method="searchHandle"
+								@click.native="inputFocusHandle"
+								@change="selectTarget($event && searchOptions.find(_ => _.EdbInfoId === $event))"
+							>
+								<i slot="prefix" class="el-input__icon el-icon-search"></i>
+								<el-option
+									v-for="item in searchOptions"
+									:key="item.EdbInfoId"
+									:label="chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
+									:value="item.EdbInfoId"
+								>
+									<edbDetailPopover :info="item">
+										<div slot="reference">{{chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName }}</div>
+									</edbDetailPopover>
+								</el-option>
+							</el-select>
+						</div>
+					</el-form-item>
+
 					<el-form-item label="图表名称" prop="ChartName">
 						<el-input
 							v-model="chartInfo.ChartName"
@@ -66,13 +121,6 @@
 						/>
 					</el-form-item>
 					<el-form-item label="图表单位" prop="Unit" v-if="chartInfo.ChartType===7">
-						<!-- <el-input
-							v-model="chartInfo.Unit"
-							style="width: 90%"
-							placeholder="请输入图表单位"
-							clearable
-							@change="changeUnit"
-						/> -->
 						<el-select
 							v-model="chartInfo.Unit"
 							filterable
@@ -91,41 +139,6 @@
 					</el-form-item>
 				</el-form>
 
-				<div class="search-cont" v-if="chartInfo.ChartType!==10">
-					<div>
-						<label>选择指标:</label>
-						<el-radio-group v-model="edbFromType">
-							<el-radio :label="0" style="margin-right: 15px">ETA指标</el-radio>
-							<el-radio :label="1">ETA预测指标</el-radio>
-						</el-radio-group>
-					</div>
-					<el-select
-						v-model="search_txt"
-						v-loadMore="searchLoad"
-						ref="searchRef"
-						:filterable="!search_txt"
-						remote
-						clearable
-						placeholder="指标ID/指标名称"
-						style="width:90%;margin-top: 10px;display: block;"
-						:remote-method="searchHandle"
-						@click.native="inputFocusHandle"
-						@change="selectTarget($event && searchOptions.find(_ => _.EdbInfoId === $event))"
-					>
-						<i slot="prefix" class="el-input__icon el-icon-search"></i>
-						<el-option
-							v-for="item in searchOptions"
-							:key="item.EdbInfoId"
-							:label="chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
-							:value="item.EdbInfoId"
-						>
-							<edbDetailPopover :info="item">
-								<div slot="reference">{{chart_lang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName }}</div>
-							</edbDetailPopover>
-						</el-option>
-					</el-select>
-				</div>
-
 				<div class="xaxis-range-cont" v-if="chartInfo.ChartType===2 && tableData && tableData.length>0">
 					<!-- 仅用于季节性图配置 -->
 					<div style="margin-bottom: 12px;" class="xaxis-range-tip">
@@ -172,7 +185,7 @@
 						<!-- 仅用于散点图配置提出 -->
 					<div class="scatter-setting" v-if="chartInfo.ChartType === 5 && tableData.length">
 						<div style="display: flex;margin-right: 15px;">
-							<span style="margin-right: 3px">线条颜色:</span>
+							<span style="margin-right: 3px">散点颜色:</span>
 							<el-color-picker
 								v-model="tableData[0].ChartColor"
 								size="mini"
@@ -306,6 +319,7 @@
 					<bar-option
 						v-if="chartInfo.ChartType===7"
 						ref="BarOptRef"
+						:chartInfo="chartInfo"
 						:edblist="tableData"
 						:datedata="barDateList"
 						:initData="initBarOptions"
@@ -316,12 +330,21 @@
 					<sectional-scatter-option
 						v-if="chartInfo.ChartType===10"
 						ref="SectionScatterOptRef"
+						:chartInfo="chartInfo"
 						:initData="chartInfo.ExtraConfig?JSON.parse(chartInfo.ExtraConfig):null"
 						:edbInfoData="tableData"
 						:IsNameDefault="IsNameDefault"
 						@getData="getSectionScatterData"
 						@modifySeriesName="IsNameDefault = false"
 					/>
+
+					<!-- 标识区 标记线 图表说明 -->
+					<markersSection
+						ref="markerSectionRef"
+						:chartType="chartInfo.ChartType"
+						:chartInfo="chartInfo"
+						@update="setChartMarkerInfo"
+					/>
         </div>
 			</div>
       <span
@@ -372,8 +395,18 @@
 				<div class="cont-bottom">
 					<div class="chart-show-cont" v-if="!chartInfo.WarnMsg&&options.series">
 						<div class="chartWrapper" id="chartWrapper">
-							<h2 class="chart-title" v-show="chartInfo.ChartName">{{ chartInfo.ChartName }}</h2>
-							<Chart :options="options" ref="chartRef" />
+							<h2 
+								class="chart-title" 
+								v-show="chartInfo.ChartName"
+								:style="`
+									textAlign:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.align};
+									fontSize:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.fontSize}px;
+									color:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.color}
+								`"
+							>
+								{{ chartInfo.ChartName }}
+							</h2>
+							<Chart :options="options" :chartInfo="chartInfo" ref="chartRef" />
 							<div class="range-cont left" v-if="leftIndex != -1">
 								<el-input
 									style="width: 60px; display: block"
@@ -465,21 +498,53 @@
 								</div>
 							</template>
 						</div>
-						<span class="chart-author"
-							>作者:{{ chartInfo.SysUserRealName }}</span
-						>
 
-						<!-- 公历农历切换 只用于季节性图 -->
-						<el-radio-group
-							v-model="calendar_type"
-							class="calendar-cont"
-							v-if="chartInfo.ChartType === 2"
-							@change="getPreviewSplineInfo"
-						>
-							<el-radio-button label="公历" />
-							<el-radio-button label="农历" />
-						</el-radio-group>
-					</div>
+						<div class="chart-bottom-insruction-info">
+
+							<div class="chart-source">
+									<span
+										v-if="chartInfo.SourcesFrom"
+										:style="`
+										color: ${JSON.parse(chartInfo.SourcesFrom).isShow ? JSON.parse(chartInfo.SourcesFrom).color : '#999'};
+										fontSize: ${ JSON.parse(chartInfo.SourcesFrom).fontSize }px;
+									`"
+									>来源:{{ JSON.parse(chartInfo.SourcesFrom).text}}</span>
+								<el-switch
+									v-if="chartInfo.SourcesFrom"
+									v-model="chartInfo.SourcesFromVisable"
+									:active-value="true"
+									:inactive-value="false"
+									style="margin:0 15px;"
+									@change="changeSourceVisable"
+								/>
+								<span class="editsty" @click="isShowSourceDialog=true">编辑</span>
+							</div>
+
+							<!-- 公历农历切换 只用于季节性图 -->
+							<el-radio-group
+								v-model="calendar_type"
+								class="calendar-cont"
+								v-if="chartInfo.ChartType === 2"
+								@change="getPreviewSplineInfo"
+							>
+								<el-radio-button label="公历" />
+								<el-radio-button label="农历" />
+							</el-radio-group>
+
+							<!-- 图表说明 -->
+							<div 
+								class="chart-instruction" 
+								v-if="chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow"
+								v-text="JSON.parse(chartInfo.Instructions).text"
+								:style="`
+									color: ${JSON.parse(chartInfo.Instructions).color};
+									fontSize: ${ JSON.parse(chartInfo.Instructions).fontSize }px
+								`"
+							></div>
+						</div>
+
+						<span class="chart-author">作者:{{ chartInfo.SysUserRealName }}</span>
+					</div>	
 
 					<!-- 异常显示 -->
           <p class="error-tip" style="min-height: 400px" v-if="chartInfo.WarnMsg">{{chartInfo.WarnMsg}}</p>
@@ -498,13 +563,12 @@
 							align="center"
 						>
 							<template slot-scope="scope">
-								<div v-if="item.key === 'EdbName' && chartInfo.ChartType === 7">
+								<div v-if="item.key === 'EdbName' && [1,4,6,7].includes(chartInfo.ChartType)">
 									<!-- 奇怪柱状图用别名 -->
 									<el-input 
 										v-model="scope.row.EdbAliasName"
 										placeholder="指标别名"
 										class="target-other-name"
-										v-if="chartInfo.ChartType === 7"
 										clearable
 									/>
 								</div>
@@ -562,6 +626,13 @@
       :show.sync="isShowSaveOther" 
       :data="chartInfo"
     />
+
+		<!-- 数据来源编辑弹窗 -->
+		<chartSourceEditDia
+			:isShow.sync="isShowSourceDialog"
+			:chartInfo="chartInfo"
+			@update="value => {chartInfo.SourcesFrom=JSON.stringify({...value,isShow:chartInfo.SourcesFromVisable})}"
+		/>
   </div>
 </template>
 
@@ -577,9 +648,10 @@ import SaveChartOther from './components/SaveChartOther';
 import barOption from './components/barOptionSection.vue';
 import sectionalScatterOption from './components/sectionalScatterOption.vue';
 import LegendEditDia from './components/LegendEditDia.vue';
-
+import markersSection from './components/markersSection.vue';
+import chartSourceEditDia from './components/chartSourceEditDialog.vue';
 export default {
-  components: { Chart,DateChooseDia,SaveChartOther,barOption,sectionalScatterOption,LegendEditDia },
+  components: { Chart,DateChooseDia,SaveChartOther,barOption,sectionalScatterOption,LegendEditDia,markersSection,chartSourceEditDia },
 	directives: {
     drag(el, bindings) {
       el.onmousedown = function (e) {
@@ -657,11 +729,17 @@ export default {
 					const {IsNameDefault=true} = SeriesList.length?SeriesList[0]:[]
 					this.IsNameDefault = IsNameDefault
 
-           this.chartInfo = {
+          this.chartInfo = {
 						...ChartInfo,
 						classify: [ChartInfo.ChartClassify[0].ParentId,...ChartInfo.ChartClassify.map(item => item.ChartClassifyId)],
-						Unit: BarChartInfo ? BarChartInfo.Unit : ''
+						Unit: BarChartInfo ? BarChartInfo.Unit : '',
+						SourcesFromVisable: ChartInfo.SourcesFrom ? JSON.parse(ChartInfo.SourcesFrom).isShow : true
 					};
+					//处理下历史默认来源
+					this.setDefaultSourceFrom();
+
+					this.$refs.markerSectionRef.initData(ChartInfo);
+
           this.tableData = EdbInfoList;
 
 					this.calendar_type = this.chartInfo.Calendar; //日历类型
@@ -680,6 +758,8 @@ export default {
 
 					//截面散点图
 					this.chartInfo.ChartType === 10 && this.initSectionScatterData(res.Data);
+					
+					this.getThemeList();
 
         });
 		},
@@ -764,6 +844,7 @@ export default {
 							ChartStyle: item.ChartStyle,
 							ChartWidth: Number(item.ChartWidth),
 							EdbInfoId: item.EdbInfoId,
+							EdbAliasName: item.EdbAliasName,
 							EdbInfoType: item.EdbInfoType,
 							IsAxis: item.IsAxis,
 							IsOrder: item.IsOrder,
@@ -774,12 +855,19 @@ export default {
 						})
 					)
 
+					const { ChartType,ChartName,ChartThemeId,SourcesFrom,Instructions,MarkersLines,MarkersAreas,ChartThemeStyle } = this.chartInfo;
 					let public_param = {
 						ChartClassifyId: this.chartInfo.classify.length ? this.chartInfo.classify[this.chartInfo.classify.length - 1] : 0,
-						ChartName: this.chartInfo.ChartName,
-						ChartType: this.chartInfo.ChartType,
 						ChartInfoId: this.chartInfo.ChartInfoId,
 						ChartEdbInfoList: db_arr,
+						ChartName,
+						ChartType,
+						ChartThemeId,
+						SourcesFrom,
+						Instructions,
+						MarkersLines,
+						MarkersAreas,
+						ChartThemeStyle
 					}
 
 					//提交参数
@@ -797,6 +885,13 @@ export default {
 							EndDate: this.year_select === 5 ? this.select_date[1] : '',
 						} 
 					: typePrams
+					
+					let svg = this.$refs.chartRef.chart.getSVG({
+						chart: {
+							width: 340,
+							height: 230,
+						}
+					});
 
 					dataBaseInterface.chartEdit(params).then(res => {
 						if(res.Ret !== 200) return;
@@ -902,7 +997,6 @@ export default {
 			overflow-y: auto;
 			.search-cont {
 				color: #606266;
-				margin-top: 10px;
 			}
 			.xaxis-range-cont{
 				color: #606266;
@@ -1085,7 +1179,7 @@ export default {
 				}
 				/* =================== */
 				.chart-show-cont {
-					padding: 0 150px 20px 120px;
+					padding: 0 150px 60px 120px;
 					position: relative;
 					.chart-title {
 						font-size: 16px;
@@ -1124,7 +1218,7 @@ export default {
 								justify-content: space-between;
 								top: auto;
 								right: 0;
-								bottom: -3%;
+								bottom: -2%;
 								.left {
 									width: 60px;
 									display: block;

+ 202 - 25
src/views/dataEntry_manage/mixins/addOreditMixin.js

@@ -1,5 +1,6 @@
 import { dataBaseInterface } from '@/api/api.js';
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
+import * as chartThemeInterface from '@/api/modules/chartThemeApi';
 import { defaultOpts } from '@/utils/defaultOptions';
 import { mapState } from 'vuex';
 
@@ -12,7 +13,14 @@ export default {
 				ChartType: 1,
 				Source:1,
 				Unit: '',
-				ChartName: ''
+				ChartName: '',
+				ChartThemeId: 0,
+				SourcesFrom: '',
+				SourcesFromVisable: true,//数据来源开关,来源现存Json字符串 额外加个属性绑定
+				Instructions: '',
+				MarkersLines: "", //标识线
+				MarkersAreas: "",//标识区
+				ChartThemeStyle:'',//主题样式
 			},
 			chartRules: {
 				ChartType:[
@@ -65,6 +73,14 @@ export default {
 			isSpanYear:false,
 			isSpanYearDisable:false,
 			legendEditDiaShow:false,
+
+			chartThemeArr: [],//主题列表
+
+			/* 来源编辑弹窗 */
+			isShowSourceDialog: false,
+			sourceEditForm: {
+
+			}
 		}
 	},
 	computed: {
@@ -118,18 +134,23 @@ export default {
 					})
 				}
 
+				//获取对应主题列表
+				this.getThemeList('init')
+
 				//柱形图 截面散点切换到普通图 依赖的指标信息其实只有信息无数据 需清空
 				if([7,10].includes(oldval)&&![7,10].includes(newval)) {
 					this.tableData = [];
 					this.chartInfo.LeftMax = '';
 					this.chartInfo.LeftMin = '';
+					this.chartInfo.MarkersLines = "";
+					this.chartInfo.MarkersAreas = "";
 				}
 
 				this.initStatus();
 
 				//共用结构的类型切换可以直接画图
 				if(![7,10].includes(newval)) {
-					//单指标允许相互切换
+					//单指标允许切换到季节图需药重新请求数据
 					this.tableData.length===1 && this.selectTarget(this.tableData[0],'switch');
 					this.tableData.length > 1 && this.setChartOptionHandle(this.tableData);
 				}
@@ -143,7 +164,7 @@ export default {
 			if(!item) return
 
 			/* 正常图获取指标数据 柱形图不获取 */
-			if(this.chartInfo.ChartType !== 7) {
+			if(this.chartInfo.ChartType === 7) return this.setBarEdbList(item);
 				// let params = this.sameOptionType.includes(this.chartInfo.ChartType) 
 				// 	? {
 				// 		EdbInfoId: item.EdbInfoId,
@@ -178,7 +199,9 @@ export default {
 				} 
 				dataBaseInterface.chartInfo(params).then((res) => {
 					if(res.Ret !== 200) return;
-						let [ tableItem ] = res.Data.EdbInfoList;
+						let tableItem = res.Data.EdbInfoList[0];
+						tableItem.EdbAliasName = tableItem.EdbName;
+
 						// 同一指标切换图表类型
 						if(type) {
 							this.tableData = [ tableItem ];
@@ -200,6 +223,25 @@ export default {
 							this.tableData.push(tableItem);
 							this.isSetExtremeValue = true;
 							// console.log(this.tableData)
+							
+							//默认拼接来源
+							if(!this.chartInfo.SourcesFrom) {
+
+								this.chartInfo.SourcesFrom = JSON.stringify({
+									isShow: this.chartInfo.SourcesFromVisable,
+									text: res.Data.ChartInfo.ChartSource,
+									color: JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.color,
+									fontSize: JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.fontSize
+								});
+							}else {
+								let sourceObj = JSON.parse(_.cloneDeep(this.chartInfo.SourcesFrom));
+								let concatSourceArr = `${sourceObj.text},${res.Data.ChartInfo.ChartSource}`.split(',');
+								let sourceStr = Array.from(new Set(concatSourceArr)).join(',');
+								this.chartInfo.SourcesFrom = JSON.stringify({
+									...sourceObj,
+									text: sourceStr
+								});
+							}
 
 							this.$nextTick(()=>{
 								// 等待 tableData的 监听里面的获取到 起始时间和最近日期
@@ -210,9 +252,6 @@ export default {
 							this.$message.warning('录入指标已存在');
 						}
 				})
-			}else {
-				this.setBarEdbList(item);
-			}
 
 		},
 
@@ -248,7 +287,11 @@ export default {
 			dataBaseInterface.getBarData(params).then(res => {
 				if(res.Ret !== 200) return
 
-				const { EdbInfoList,XEdbIdValue,YDataList } = res.Data;
+				const { EdbInfoList,XEdbIdValue,YDataList,ChartInfo } = res.Data;
+				this.chartInfo = {
+					...this.chartInfo,
+					ChartSource: ChartInfo.ChartSource
+				}
 
 				let xData = XEdbIdValue.map(_ => EdbInfoList.find(edb => edb.EdbInfoId===_).EdbAliasName)
 
@@ -265,6 +308,9 @@ export default {
 						max: Math.max(...value_arr)
 					}
 				}
+				
+				//默认来源搞一下
+				this.setDefaultSourceFrom();
 			})
 		},
 
@@ -383,11 +429,6 @@ export default {
 			this.getPreviewSplineInfo();
 		},
 
-			/* 季节图切换年份  保持当前配置 */
-		// seasonYearChange() {
-		// 	this.getPreviewSplineInfo();
-		// },
-
 		/* 切换图重置状态 */
 		initStatus() {
 			this.year_select = this.chartInfo.ChartType === 2?20:3;
@@ -409,14 +450,16 @@ export default {
 
 		/* 添加指标时 配置默认颜色 线条等 */
 		setAddChartDefault() {
+
+			let themeOpt = this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
 			this.tableData.forEach((item,index) => {
-				item.ChartColor = item.ChartColor || defaultOpts.colors[index];
-				item.PredictChartColor = item.PredictChartColor || defaultOpts.colors[index];
-				item.ChartStyle = item.ChartStyle || 'spline';
-				if (index === 0)
-					this.tableData[index].ChartWidth = this.tableData[index].ChartWidth || 3;
-				if (index >= 1)
-					this.tableData[index].ChartWidth = this.tableData[index].ChartWidth || 1;
+				item.ChartColor = item.ChartColor || (themeOpt&&themeOpt.colorsOptions[index]||defaultOpts.colors[index]);
+				item.PredictChartColor = item.PredictChartColor || (themeOpt&&themeOpt.colorsOptions[index]||defaultOpts.colors[index]);
+				item.ChartStyle = item.ChartStyle || (themeOpt&&themeOpt.lineOptions.lineType||'spline');
+				
+				let configLineWid = index===0?3:1;//兼容预测指标绘图无主题配置
+				this.tableData[index].ChartWidth = this.tableData[index].ChartWidth || (themeOpt&&themeOpt.lineOptions.lineWidth||configLineWid);
 			})
 		},
 
@@ -476,10 +519,16 @@ export default {
 
 		/* 移除表格指标 */
 		delTarget(item) {
-			if(this.tableData.length) {
-				let index = this.tableData.findIndex(obj => obj.EdbInfoId === item.EdbInfoId);
-				this.tableData.splice(index, 1);
-				this.$message.success('删除成功')
+			let index = this.tableData.findIndex(obj => obj.EdbInfoId === item.EdbInfoId);
+			this.tableData.splice(index, 1);
+			this.$message.success('删除成功')
+
+			//添加图表时重置默认样式
+			this.$route.path==='/addchart' && this.resetChartEdbDefault();
+			
+			if(!this.tableData.length) {
+				this.chartInfo.MarkersLines = ""
+				this.chartInfo.MarkersAreas = ""
 			}
 		},
 
@@ -529,7 +578,11 @@ export default {
 			}).then(res => {
 				if(res.Ret !== 200) return
 				
-				const { EdbInfoList,DataResp } = res.Data;
+				const { EdbInfoList,DataResp,ChartInfo } = res.Data;
+				this.chartInfo = {
+					...this.chartInfo,
+					ChartSource: ChartInfo.ChartSource
+				}
 
 				this.sectionScatterData = DataResp;
 				this.tableData = EdbInfoList;
@@ -545,6 +598,9 @@ export default {
 						x_max: Math.max(...x_value_arr)
 					}
 				}
+
+				//默认来源搞一下
+				this.setDefaultSourceFrom();
 			})
 		},
 
@@ -698,6 +754,127 @@ export default {
 				this.getPreviewSplineInfo()
 				this.legendEditDiaShow=false
 			}
+		},
+
+		/* 重置指标相关样式 颜色 粗细 */
+		resetChartEdbDefault() {
+			if(!this.tableData.length) return
+
+			let themeOpt = JSON.parse(this.chartInfo.ChartThemeStyle);
+			this.tableData.forEach((item,index) => {
+				item.ChartColor = themeOpt.colorsOptions[index];
+				item.PredictChartColor = themeOpt.colorsOptions[index];
+				item.ChartStyle = themeOpt.lineOptions.lineType||'spline';
+				item.isAxis = item.isAxis||1;
+
+				this.tableData[index].ChartWidth = themeOpt.lineOptions.lineWidth;
+			})
+
+		},
+
+		/* 获取主题列表  type init时重新设置默认样式和主题*/
+		async getThemeList(type=null) {
+			let res =  await chartThemeInterface.getThemeBySource({ChartType: this.chartInfo.ChartType,Source:1})
+
+			if(res.Ret !== 200) return
+      this.chartThemeArr = res.Data || []
+			
+			if(type==='init') {
+				this.chartInfo.ChartThemeId = res.Data[0].DefaultChartThemeId;
+				this.chartInfo.ChartThemeStyle = this.chartThemeArr.find(_ => _.ChartThemeId===this.chartInfo.ChartThemeId).Config
+
+				this.reLoadChartOption();
+			}
+		},
+
+		/* 改变主题时 */
+		changeThemeHandle() {
+			this.chartInfo.ChartThemeStyle = this.chartThemeArr.find(_ => _.ChartThemeId===this.chartInfo.ChartThemeId).Config;
+
+			//重置指标样式
+			this.resetChartEdbDefault();
+
+			//重置标识线区来源样式
+			this.resetMarkerThemeStyle();
+
+			this.reLoadChartOption();
+		},
+
+		//切换主题重置标示线,区,来源,说明等配置样式
+		resetMarkerThemeStyle() {
+			let themeOpt = JSON.parse(this.chartInfo.ChartThemeStyle);
+
+			if(this.chartInfo.Instructions) {
+				let instructionObj = JSON.parse(_.cloneDeep(this.chartInfo.Instructions))
+				this.chartInfo.Instructions = JSON.stringify({
+					...instructionObj,
+					color: themeOpt.markerOptions.style.color,
+      		fontSize: themeOpt.markerOptions.style.fontSize,
+				})
+
+				this.$refs.markerSectionRef&&this.$refs.markerSectionRef.initData(this.chartInfo);
+			}
+
+			if(this.chartInfo.SourcesFrom) {
+				let sourceObj = JSON.parse(_.cloneDeep(this.chartInfo.SourcesFrom))
+				this.chartInfo.SourcesFrom = JSON.stringify({
+					...sourceObj,
+					color: themeOpt.markerOptions.style.color,
+      		fontSize: themeOpt.markerOptions.style.fontSize,
+				})
+			}
+
+			if(this.chartInfo.MarkersLines&&JSON.parse(this.chartInfo.MarkersLines).length) {
+				let markerLines = JSON.parse(_.cloneDeep(this.chartInfo.MarkersLines))
+				this.chartInfo.MarkersLines = JSON.stringify(markerLines.map(_ => ({
+					..._,
+					textColor: themeOpt.markerOptions.style.color,
+          textFontSize: themeOpt.markerOptions.style.fontSize,
+				})))
+
+				this.$refs.markerSectionRef&&this.$refs.markerSectionRef.initData(this.chartInfo);
+			}
+			
+			if(this.chartInfo.MarkersAreas&&JSON.parse(this.chartInfo.MarkersAreas).length) {
+				let markerAreas = JSON.parse(_.cloneDeep(this.chartInfo.MarkersAreas))
+				this.chartInfo.MarkersAreas = JSON.stringify(markerAreas.map(_ => ({
+					..._,
+					textColor: themeOpt.markerOptions.style.color,
+          textFontSize: themeOpt.markerOptions.style.fontSize,
+				})))
+
+				this.$refs.markerSectionRef&&this.$refs.markerSectionRef.initData(this.chartInfo);
+			}
+		},
+
+		/* 更新图表标识区,标识线,图表说明 */
+		setChartMarkerInfo({ markerLinesArr,markerAreasArr,chartInstruction }) {
+			this.chartInfo.MarkersLines = JSON.stringify(markerLinesArr);
+			this.chartInfo.MarkersAreas = JSON.stringify(markerAreasArr);
+			this.chartInfo.Instructions = JSON.stringify(chartInstruction);
+
+			this.reLoadChartOption();
+		},
+		
+		//更新标识线,区 重绘图 不用重新获取数据 
+		reLoadChartOption() {
+			if(!this.options.series) return
+			
+			const chartTypeMap = {
+        7: this.setBarChart, //柱形图
+        10: this.setSectionScatterChart //截面散点
+      }
+      chartTypeMap[this.chartInfo.ChartType] 
+				? chartTypeMap[this.chartInfo.ChartType]() 
+				: this.setChartOptionHandle(this.tableData);
+		},
+
+		/* 数据来源显示隐藏 */
+		changeSourceVisable() {
+			this.chartInfo.SourcesFrom = JSON.stringify({
+				...JSON.parse(this.chartInfo.SourcesFrom),
+				isShow:this.chartInfo.SourcesFromVisable
+			})
 		}
 	}
 }

文件差异内容过多而无法显示
+ 317 - 263
src/views/dataEntry_manage/mixins/chartPublic.js


+ 159 - 103
src/views/dataEntry_manage/thirdBase/ysTargetBase.vue

@@ -1,32 +1,37 @@
 <template>
   <div id="YS-data-container" v-loading="dataLoading" element-loading-text="指标数据加载中,请勿切换到其他页面">
-    <div class="search-zone">
+    <div class="search-zone" v-loading="listLoading" element-loading-text="列表加载中,请稍后">
       <div class="search-row">
-        <el-cascader @change="searchList" :options="classifyList" v-model="typesList" clearable
-          placeholder="请选择分类" class="search-item"
-          :props="{
-            value:'Type',
-            label:'Type',
-            children:'Child'
-          }"></el-cascader>
-        <el-select v-model="searchParams.Frequency" class="search-item" placeholder="请选择频度" clearable @change="searchList">
-          <el-option :label="item" :value="item" v-for="item in frequencyList" :key="item"></el-option>  
+        <el-cascader @change="searchList" :options="classifyList" v-model="typeChecks" 
+        clearable placeholder="请选择分类" class="search-item" collapse-tags	
+        :props="{
+          value:'Type',
+          label:'Type',
+          children:'Child',
+          multiple:true
+        }"></el-cascader>
+        <el-select v-model="frequencyChecks" class="search-item" placeholder="请选择频度" 
+        multiple collapse-tags clearable @change="searchListDelay">
+          <el-option :label="item" :value="item" v-for="item in frequencyList" :key="item" ></el-option>  
         </el-select>
-        <el-select v-model="searchParams.DataState" class="search-item" placeholder="请选择指标数据状态" clearable @change="searchList">
+        <el-select v-model="dataStateChecks" class="search-item" placeholder="请选择指标数据状态" 
+        multiple collapse-tags clearable @change="searchListDelay">
           <el-option :label="item.label" :value="item.value" v-for="item in dataStatusList" :key="item.value"></el-option>  
         </el-select>
-        <el-select v-model="edbCheckList" multiple filterable remote clearable collapse-tags class="search-item edb-filter"
+        <el-input v-model="searchParams.Keyword" placeholder="请输入指标ID/指标名称" class="search-item" clearable 
+        @blur="searchListDelay(!keyWordChanged)" @keyup.enter.native="searchListDelay(!keyWordChanged)" @clear="searchList"></el-input>
+        <!-- <el-select v-model="edbCheckList" multiple filterable remote clearable collapse-tags class="search-item edb-filter"
           reserve-keyword placeholder="指标ID/指标名称" :remote-method="remoteMethod" 
           v-loadMore="searchLoad" @clear="searchList" @remove-tag="removeEdbFilterTag" ref="edbFilterRef" >
           <el-option v-for="item in edbFilterDataList" :key="item.IndexCode"
             :label="item.IndexName" :value="item.IndexCode">
           </el-option>
-        </el-select>
+        </el-select> -->
         <el-checkbox label="列表全选" v-model="isCheckAll" :indeterminate="isCheckIndeterminate" style="margin: 0 20px 10px 0;"
         @change="listCheckAllChange"></el-checkbox>
       </div>
       <el-button type="primary" style="margin: 0 0 10px 0;padding:12px 18px ;" @click="addToEdbBase" 
-      :disabled="addBaseDisable">添加到指标库</el-button>
+      :disabled="addBaseDisable"  v-permission="permissionBtn.dataSourcePermission.ysTarget_addBatch">添加到指标库</el-button>
     </div>
     <div class="table-zone">
       <el-table :data="tableData" border @sort-change="sortChange"  @selection-change="selectionChange"
@@ -191,16 +196,20 @@ import { frequencyArr} from '../databaseComponents/util';
     data() {
       return {
         searchParams:{
-          Types:'',
+          Types:[],
           Frequency:'',
           DataState:'',
           CurrentIndex:1,
           PageSize:10,
           SortParam:'',
           SortType:'',
-          IndexCodes:''
+          Keyword:'',
+          // IndexCodes:''
         },
-        typesList:[],
+        keyWordChanged:false,
+        typeChecks:[],
+        frequencyChecks:[],
+        dataStateChecks:[],
         options:[],
         isCheckAll:false,
         isCheckIndeterminate:false,
@@ -210,17 +219,17 @@ import { frequencyArr} from '../databaseComponents/util';
         frequencyList: ["日度", "周度", "月度", "季度", "半年", "年度"],
         edbFrequencyList:frequencyArr,
         dataStatusList:[{value:'normal',label:'正常更新'},{value:'ceased',label:'已停更'},{value:'irregular',label:'更新依赖外部会有不定期延迟'}],
-        forSearchParams:{
-          Keyword:'',
-          CurrentIndex:1,
-          PageSize:20,
-        },
-        searchHaveMore: false,
-        edbFilterDataList:[],
+        // forSearchParams:{
+        //   Keyword:'',
+        //   CurrentIndex:1,
+        //   PageSize:20,
+        // },
+        // searchHaveMore: false,
+        // edbFilterDataList:[],
         // 选择的指标名称筛选项
-        edbCheckList:[],
+        // edbCheckList:[],
         // edb的过滤选项是否有变化,用于失焦是判断是否需要请求
-        hasEdbFilterChange:false,
+        // hasEdbFilterChange:false,
         selectionReactCancel:false, // 是否不触发 selection的逻辑
         tableData:[],
         tableDataIds:[],
@@ -249,24 +258,42 @@ import { frequencyArr} from '../databaseComponents/util';
         BatchList:[],
         addToEbdDiaShow:false,
         highLightIndex:[],
-        saveLoading:false
+        saveLoading:false,
+        listLoading:false
       }
     },
     computed:{
       addBaseDisable(){
         return !(this.isCheckAll || this.isCheckIndeterminate ) || (!(this.tableData && this.tableData.length>0))
+      },
+      isCanView(){
+        return this.permissionBtn.isShowBtn('dataSourcePermission','ysTarget_view')
       }
     },
     watch:{
-      edbCheckList(value){
-        this.hasEdbFilterChange=true
+      // edbCheckList(value){
+      //   this.hasEdbFilterChange=true
+      // },
+      typeChecks(value){
+        // console.log(value);
+        this.searchParams.Types = value.map(item => item.join(','))
       },
-      typesList(value){
+      frequencyChecks(value){
         if(value && value.length>0){
-          this.searchParams.Types = value.join(',')
+          this.searchParams.Frequency = value.join(',')
         }else{
-          this.searchParams.Types=''
+          this.searchParams.Frequency=''
         }
+      },
+      dataStateChecks(value){
+        if(value && value.length>0){
+          this.searchParams.DataState = value.join(',')
+        }else{
+          this.searchParams.DataState=''
+        }
+      },
+      'searchParams.Keyword'(value){
+        this.keyWordChanged=true
       }
     },
     created() {
@@ -275,21 +302,28 @@ import { frequencyArr} from '../databaseComponents/util';
     },
     mounted(){
       // el-select 的@blur绑定事件不生效代替方法
-      this.$refs.edbFilterRef.$refs.input.blur=()=>{
-        if(this.hasEdbFilterChange){
-          this.searchList()
-          this.hasEdbFilterChange=false
-        }
-      }
+      // this.$refs.edbFilterRef.$refs.input.blur=()=>{
+      //   if(this.hasEdbFilterChange){
+      //     this.searchList()
+      //     this.hasEdbFilterChange=false
+      //   }
+      // }
     },
     methods: {
       //获取有色数据库数据列表
       getList(type){
-        if(this.edbCheckList && this.edbCheckList.length>0){
-          this.searchParams.IndexCodes = this.edbCheckList.join(',')
-        }else{
-          this.searchParams.IndexCodes = ''
-        }
+        // return 
+        // 无权限查看
+        if(!this.isCanView) return 
+        // if(this.edbCheckList && this.edbCheckList.length>0){
+        //   this.searchParams.IndexCodes = this.edbCheckList.join(',')
+        // }else{
+        //   this.searchParams.IndexCodes = ''
+        // }
+        this.searchParams.Keyword = this.searchParams.Keyword.trim()
+        this.listLoading=true
+
+        // return 
         smmDataInterface.getYsDataList(this.searchParams).then(res=>{
           if(res.Ret == 200){
             this.tableData=res.Data.List || []
@@ -302,7 +336,7 @@ import { frequencyArr} from '../databaseComponents/util';
             if(type == 'adjustSelection'){
               this.adjustSelection()
             }else{
-              if(this.searchParams.Types || this.searchParams.Frequency || this.searchParams.DataState || this.searchParams.IndexCodes){
+              if((this.searchParams.Types && this.searchParams.Types.length>0) || this.searchParams.Frequency || this.searchParams.DataState || this.searchParams.Keyword){
                 this.isCheckAll=true
                 this.checkAllStatus=true
                 this.isCheckIndeterminate=false
@@ -313,11 +347,17 @@ import { frequencyArr} from '../databaseComponents/util';
               }
               this.listCheckAllChange(this.isCheckAll)
             }
+            this.keyWordChanged=false
           }
         })
+        .finally(()=>{
+          this.listLoading=false
+        })
       },
       // 获取有色数据库分类列表
       getYsClassifyList(){
+        // 无权限查看
+        if(!this.isCanView) return 
         smmDataInterface.getYsTypeDataList().then(res=>{
           if(res.Ret == 200){
             this.classifyList=res.Data || []
@@ -325,34 +365,43 @@ import { frequencyArr} from '../databaseComponents/util';
         })
 
       },
-      // 指标名称的远程搜索方法
-      remoteMethod(text){
-        this.forSearchParams.Keyword = text.trim()
-        this.forSearchParams.CurrentIndex = 1;
-        if(this.forSearchParams.Keyword){
-          this.searchApi()
-        }else{
-          this.edbFilterDataList = [];
-        }
-      },
-      searchApi(){
-        smmDataInterface.getYsDataList(this.forSearchParams).then(res=>{
-          if(res.Ret == 200){
-            let arr=res.Data.List || []
-            let {Paging}=res.Data
-            this.searchHaveMore = this.forSearchParams.CurrentIndex < Paging.Pages;
-            this.edbFilterDataList = this.forSearchParams.CurrentIndex === 1 ? arr : this.edbFilterDataList.concat(arr);
-          }
-        })
-      },
-      searchLoad(){
-        if(!this.searchHaveMore) return;
-        this.forSearchParams.CurrentIndex++
-			  this.searchApi();
+      // // 指标名称的远程搜索方法
+      // remoteMethod(text){
+      //   this.forSearchParams.Keyword = text.trim()
+      //   this.forSearchParams.CurrentIndex = 1;
+      //   if(this.forSearchParams.Keyword){
+      //     this.searchApi()
+      //   }else{
+      //     this.edbFilterDataList = [];
+      //   }
+      // },
+      // searchApi(){
+      //   // 无权限查看
+      //   if(!this.isCanView) return 
+      //   smmDataInterface.getYsDataList(this.forSearchParams).then(res=>{
+      //     if(res.Ret == 200){
+      //       let arr=res.Data.List || []
+      //       let {Paging}=res.Data
+      //       this.searchHaveMore = this.forSearchParams.CurrentIndex < Paging.Pages;
+      //       this.edbFilterDataList = this.forSearchParams.CurrentIndex === 1 ? arr : this.edbFilterDataList.concat(arr);
+      //     }
+      //   })
+      // },
+      // searchLoad(){
+      //   if(!this.searchHaveMore) return;
+      //   this.forSearchParams.CurrentIndex++
+			//   this.searchApi();
+      // },
+	    // removeEdbFilterTag: _.throttle(function() {
+      //   this.searchList()
+		  // },1000),
+      // watch回调是异步的 延迟执行搜索 
+      searchListDelay(cancel){
+        if(cancel+'' == 'true') return 
+        setTimeout(()=>{
+          this.searchList()
+        },0)
       },
-	    removeEdbFilterTag: _.throttle(function() {
-        this.searchList()
-		  },1000),
       searchList(type){
         this.searchParams.CurrentIndex=1
         this.getList(type)
@@ -477,38 +526,40 @@ import { frequencyArr} from '../databaseComponents/util';
         },50)
       },
       // 添加指标库
-      addToEdbBase:_.throttle(function() {
-        if(this.dataLoading || this.addBaseDisable) return 
-        let params={
-          Types:this.searchParams.Types,
-          Frequency:this.searchParams.Frequency,
-          DataState:this.searchParams.DataState,
-          SelectAll:this.checkAllStatus,
-          SelectCode:this.searchParams.IndexCodes,
-          EdbCode:this.tableDataCheckedList.join(',')
-        }
-        // return 
-        smmDataInterface.getYsEdbCodeCheck(params).then(res=>{
-          if(res.Ret == 200){
-            // console.log(res,'res');
-            if(res.Data.IndexExist){
-              // 有重复
-              this.existIndexList=[]
-              let existEdbInfo=res.Data.ExistEdbInfo || []
-              let text=''
-              existEdbInfo.map(item =>{
-                text=`${item.EdbName}(${item.EdbCode})`
-                this.existIndexList.push({text,code:item.UniqueCode,id:item.EdbInfoId,Types:item.ClassifyId,edbCode:item.EdbCode})
-              })
-              this.checkFailShow=true
-              this.indexAllExist=res.Data.ExistAll+'' =='false' ? false :res.Data.ExistAll || true
-            }else{
-              // 没有重复
-              this.getTargetData()
-            }
+      addToEdbBase() {
+        setTimeout(()=>{
+          if(this.dataLoading || this.addBaseDisable) return 
+          let params={
+            Types:this.searchParams.Types,
+            Frequency:this.searchParams.Frequency,
+            DataState:this.searchParams.DataState,
+            SelectAll:this.checkAllStatus,
+            Keyword:this.searchParams.Keyword,
+            EdbCode:this.tableDataCheckedList.join(',')
           }
-        })
-      },300),
+          // return 
+          smmDataInterface.getYsEdbCodeCheck(params).then(res=>{
+            if(res.Ret == 200){
+              // console.log(res,'res');
+              if(res.Data.IndexExist){
+                // 有重复
+                this.existIndexList=[]
+                let existEdbInfo=res.Data.ExistEdbInfo || []
+                let text=''
+                existEdbInfo.map(item =>{
+                  text=`${item.EdbName}(${item.EdbCode})`
+                  this.existIndexList.push({text,code:item.UniqueCode,id:item.EdbInfoId,classifyId:item.ClassifyId,edbCode:item.EdbCode})
+                })
+                this.checkFailShow=true
+                this.indexAllExist=res.Data.ExistAll+'' =='false' ? false :res.Data.ExistAll || true
+              }else{
+                // 没有重复
+                this.getTargetData()
+              }
+            }
+          })
+        },50)
+      },
       edbCheckFinished(){
         if(!this.indexAllExist){
           this.getTargetData()
@@ -533,7 +584,7 @@ import { frequencyArr} from '../databaseComponents/util';
           Frequency:this.searchParams.Frequency,
           DataState:this.searchParams.DataState,
           SelectAll:this.checkAllStatus,
-          SelectCode:this.searchParams.IndexCodes,
+          Keyword:this.searchParams.Keyword,
           EdbCode:afterFilterList.join(',')
         }
         smmDataInterface.getYsEdbCodeSearch(params).then(res => {
@@ -693,6 +744,11 @@ import { frequencyArr} from '../databaseComponents/util';
     }
     .edb-table-box{
       padding: 0 40px;
+      .sticky {
+        position: sticky;
+        border-right: 1px solid #dcdfe6;
+        z-index: 10;
+      }
       .edb-table-preview {
         overflow: auto;
         height: calc(100% - 124px);

+ 4 - 3
src/views/dataSource_manage/components/DelEDBTable.vue

@@ -149,11 +149,12 @@ export default {
         // 设置列的宽度
         getColWidth(key){
             const widthMap={
-                DataUpdateTime:'150px',
-                ErDataUpdateDate:'200px',
+                EdbCode:'180px',
+                CreateTime:'150px',
                 StartDate:'150px',
                 LatestDate:'150px',
-                CreateTime:'150px'
+                DataUpdateTime:'150px',
+                ErDataUpdateDate:'120px',
             }
 
             return widthMap[key]

+ 5 - 8
src/views/dataSource_manage/components/DetailTable.vue

@@ -143,7 +143,7 @@ export default {
             checkAll:false,
             tableColOpts:[],
             tableData:[],
-            pageSize:15,
+            pageSize:10,
             page:1,
             total:0,
             tableLoading:false,
@@ -260,14 +260,11 @@ export default {
         // 设置列的宽度
         getColWidth(key){
             const widthMap={
-                EdbNameSource:'120px',
-                DataUpdateTime:'120px',
+                EdbCode:'150px',
+                LatestDate:'150px',
+                DataUpdateTime:'180px',
                 ErDataUpdateDate:'200px',
-                NeedRefresh:'200px',
-                HasRefresh:'200px',
-                SourceUpdateTime:'120px',
-                DataUpdateResult:'120px',
-                SourceUpdateFailedReason:'120px'
+                UpdateTime:'180px'
             }
 
             return widthMap[key]

+ 68 - 10
src/views/dataSource_manage/components/EDBInfoChangeTable.vue

@@ -1,6 +1,22 @@
 <template>
     <div class="edbinfo-table-wrap">
-        <div>
+        <div class="top-wrap">
+            <div class="filter-box">
+                <el-select
+                    v-model="filterState.changeType"
+                    placeholder="请选择变更类型"
+                    clearable
+                    style="width:250px"
+                    @change="handleRefreshList"
+                >
+                    <el-option
+                        v-for="item in changeTypeOpt"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                    />
+                </el-select> 
+            </div>
             <img src="~@/assets/img/data_m/set_icon.png" alt="" style="cursor: pointer;float:right" @click="showSetTableCols=true">
         </div>
         <el-table
@@ -30,6 +46,10 @@
                         <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
                     </el-tooltip>
                 </template>
+                <template slot-scope="scope">
+                    <span v-if="col.ColumnKey==='UpdateType'">{{getUpdateTypeText(scope.row)}}</span>
+                    <span v-else>{{scope.row[col.ColumnKey]}}</span>
+                </template>
             </el-table-column>
             <div slot="empty">
                 <tableNoData text="暂无数据"/>
@@ -68,7 +88,22 @@ export default {
                 dateVal:this.$moment().format('YYYY-MM-DD')||'',
                 sortKey:'',
                 sortType:'',
+                changeType:''
             },
+            changeTypeOpt:[
+                {
+                    label:'基础信息变更',
+                    value:1,
+                },
+                {
+                    label:'数据明细变更',
+                    value:0,
+                },
+                {
+                    label:'新增指标',
+                    value:2,
+                }
+            ],
 
             showSetTableCols:false,
         }
@@ -86,6 +121,7 @@ export default {
                 SortParam:this.filterState.sortKey,
                 SortType:this.filterState.sortType,
                 CreateTime:this.filterState.dateVal,
+                UpdateType:this.filterState.changeType===''?-1:this.filterState.changeType
             }).then(res=>{
                 this.tableLoading=false
                 if(res.Ret===200){
@@ -140,6 +176,16 @@ export default {
             this.handleRefreshList()
         },
 
+        getUpdateTypeText(e){
+            let str=''
+            this.changeTypeOpt.forEach(item=>{
+                if(item.value===e.UpdateType){
+                    str=item.label
+                }
+            })
+            return str
+        },
+
         // table说明文案
         getTableHeadTips(key){
             const tipsMap={
@@ -153,13 +199,12 @@ export default {
         // 设置列的宽度
         getColWidth(key){
             const widthMap={
-                EdbName:'150px',
-                DataUpdateTime:'150px',
-                ErDataUpdateDate:'200px',
+                EdbCode:'150px',
+                CreateTime:'150px',
                 StartDate:'150px',
                 LatestDate:'150px',
-                CreateTime:'150px',
-                EdbNameSource:'150px'
+                DataUpdateTime:'150px',
+                ErDataUpdateDate:'200px',
             }
 
             return widthMap[key]
@@ -172,11 +217,24 @@ export default {
 .edbinfo-table-wrap{
     .top-wrap{
         display: flex;
-        justify-content: flex-end;
+        justify-content: space-between;
+        align-items: flex-start;
         margin-bottom: 30px;
-        .set-icon{
-            width: 40px;
-            cursor: pointer;
+        .filter-box{
+            margin-right: 100px;
+            display: flex;
+            flex-wrap: wrap;
+            align-items: center;
+            gap: 10px 20px;
+        }
+        .right-opt-box{
+            display: flex;
+            align-items: center;
+            gap: 20px;
+            .set-icon{
+                width: 40px;
+                cursor: pointer;
+            }
         }
     }
 }

+ 138 - 4
src/views/dataSource_manage/components/GLRefreshFailDetail.vue

@@ -1,4 +1,4 @@
-<template>
+ <template>
     <el-dialog
         title="更新失败指标详情"
         :visible.sync="show"
@@ -40,6 +40,9 @@
                     prop="Num"
                     align="center"
                 >
+                    <template slot-scope="scope">
+                        <span style="color:#409EFF;cursor: pointer;" @click="handleShowFailDetail(scope.row)">{{scope.row.Num}}</span>
+                    </template>
                 </el-table-column>
                 <el-table-column
                     label="原因"
@@ -71,6 +74,51 @@
                 <div>5、打开文件目录下的一个Excel,选中“钢联数据2.0”插件,点击“更新所有页”按钮后,等待十几秒,查看Excel左下角是否提示额度超限。</div>
             </div>
         </el-dialog>
+
+        <!-- 失败详情 -->
+        <el-dialog
+            title="指标详情"
+            :visible.sync="showEDBList"
+            :close-on-click-modal="false"
+            :center="true"
+            v-dialogDrag
+            :append-to-body="true"
+            width="80vw"
+        >
+            <div class="gl-refresh-fail-edb-list-wrap">
+                <p class="info"> 
+                    <span>终端名称:{{info.Name}} </span>
+                    <span>文件夹路径:{{info.DirPath}} </span>
+                    <span>频度:{{activeFrequency}} </span>
+                    <span>原因:{{activeReason}} </span>
+                </p>
+                <el-table
+                    :data="edbList"
+                    border
+                    height="700"
+                >
+                    <el-table-column
+                        v-for="col in edbListTableCol"
+                        :key="col.key"
+                        :label="col.label"
+                        :prop="col.key"
+                        align="center"
+                    />
+                    <div slot="empty">
+                        <tableNoData text="暂无数据"/>
+                    </div>
+                </el-table>
+                <el-pagination
+                    layout="total,prev,pager,next,jumper"
+                    background
+                    @current-change="handleCurrentChange"
+                    :page-size="pageSize"
+                    :total="total"
+                    style="float: right;margin-top:20px"
+                />
+            </div>
+        </el-dialog>
+
     </el-dialog>
     
 </template>
@@ -106,7 +154,53 @@ export default {
     data() {
         return {
             info:{},
-            showBZ:false
+            showBZ:false,
+
+            showEDBList:false,
+            edbList:[],
+            edbListTableCol:[
+                {
+                    label:'指标全称',
+                    key:'EdbName'
+                },
+                {
+                    label:'指标编码',
+                    key:'EdbCode'
+                },
+                {
+                    label:'起始时间',
+                    key:'StartDate'
+                },
+                {
+                    label:'最新日期',
+                    key:'LatestDate'
+                },
+                {
+                    label:'最新值',
+                    key:'LatestValue'
+                },
+                {
+                    label:'终端编码',
+                    key:'TerminalCode'
+                },
+                {
+                    label:'创建人',
+                    key:'SysUserRealName'
+                },
+                {
+                    label:'频度',
+                    key:'Frequency'
+                },
+                {
+                    label:'单位',
+                    key:'Unit'
+                },
+            ],
+            activeFrequency:'',
+            activeReason:'',
+            page:1,
+            pageSize:10,
+            total:0
         }
     },
     methods: {
@@ -123,7 +217,37 @@ export default {
                     this.info=res.Data
                 }
             })
-        }
+        },
+
+        handleShowFailDetail(e){
+            this.page=1
+            this.edbList=[]
+            this.activeFrequency=e.Frequency
+            this.activeReason=e.SourceUpdateFailedReason
+            this.getFailDetailList()
+            this.showEDBList=true
+        },
+
+        async getFailDetailList(){
+            const res=await apiDataSource.updateFailDetailList({
+                CreateTime:this.date,
+                TerminalCode:this.TerminalCode,
+                Frequency:this.activeFrequency,
+                SourceUpdateFailedReason:this.activeReason,
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+            })
+            if(res.Ret===200){
+                const arr=res.Data.List||[]
+                this.edbList=arr
+                this.total=res.Data.Paging.Totals
+            }
+        },
+
+        handleCurrentChange(e){
+            this.page=e
+            this.getFailDetailList()
+        },
     },
 }
 </script>
@@ -133,5 +257,15 @@ export default {
     color: #333;
     padding-bottom: 30px;
 }
-
+.gl-refresh-fail-edb-list-wrap{
+    padding-bottom: 80px;
+    .info{
+        color: #000;
+        margin-bottom: 20px;
+        span{
+            display: inline-block;
+            margin-right: 20px;
+        }
+    }
+}
 </style>

+ 3 - 3
src/views/dataSource_manage/components/StatisticTable.vue

@@ -22,10 +22,10 @@
                     <span>{{col.ColumnName}}</span>
                     <el-tooltip 
                         effect="dark" 
-                        :content="getTableHeadTips(col.ColumnKey)" 
                         placement="top-start"
                     >
                         <i class="el-icon-info" v-if="tipsKeysArr.includes(col.ColumnKey)"></i>
+                        <div slot="content" v-html="getTableHeadTips(col.ColumnKey)"></div>
                     </el-tooltip>
                 </template>
                 <template slot-scope="scope">
@@ -147,8 +147,8 @@ export default {
         // table说明文案
         getTableHeadTips(key){
             const tipsMap={
-                NeedRefreshNum:'今日该终端需定时刷新的指标数量',
-                HasRefreshNum:'今日该终端发起刷新任务的指标数量',
+                NeedRefreshNum:'1、今日该终端需定时刷新的指标数量<br>2、今日需刷新指标数=今日已更新指标数+今日更新失败指标数',
+                HasRefreshNum:'1、今日该终端发起刷新任务的指标数量<br>2、今日发起刷新任务指标数=今日已刷新成功指标数+今日刷新失败指标数',
                 RefreshSuccessNum:'今日该终端刷新成功的指标数量',
                 RefreshFailedNum:'今日该终端刷新失败的指标数量',
                 UpdateFailedNum:'今日该终端成功发起刷新任务,但指标数据未变化的指标数量',

+ 127 - 0
src/views/edbHistoryPage.vue

@@ -0,0 +1,127 @@
+<template>
+    <!-- 指标溯源页 -->
+    <div class="edb-history-page-wrap">
+        <div class="edb-title">{{treeData.EdbName||''}}</div>
+        <div class="edb-source-wrap">
+            <vue2-org-tree
+                :data="treeData"
+                :props="{
+                    label: 'EdbName',
+                    children: 'Child',
+                }"
+                :horizontal="false"
+                :render-content="renderContent"
+                @on-node-click="handleClickNode"
+            />
+        </div>
+    </div>
+</template>
+
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+export default {
+    data() {
+        return {
+            treeData:{}
+        };
+    },
+    methods: {
+        renderContent(h, data) {
+            return (
+                <el-tooltip content={data.RuleTitle} placement='top' popper-class='node-tooltip'>
+                    <span class='node'>{data.EdbName}</span>
+                </el-tooltip>
+            )
+        },
+        handleClickNode(e, data) {
+            //EdbInfoType=1 跳预测指标详情,=0跳指标库详情
+            const { ClassifyId, UniqueCode, EdbInfoId, EdbInfoType } = data
+            let { href } =
+            this.$router.resolve({ path: EdbInfoType === 1 ? '/predictEdb' : '/database', query: { code: UniqueCode, id:
+            EdbInfoId, classifyId: ClassifyId } });
+            window.open(href, '_blank');
+        },
+        async getData() {
+            const res = await dataBaseInterface.getEdbCreateHistory({ EdbInfoId: Number(this.$route.query.edbId) })
+            if (res.Ret !== 200) return
+            this.treeData = res.Data;
+        }
+    },
+    mounted(){
+        if(this.$route.query.edbId){
+            this.getData()
+        }
+    }
+};
+</script>
+
+<style scoped lang="scss">
+.edb-history-page-wrap{
+    display: flex;
+    flex-direction: column;
+    height: calc(100vh - 120px);
+    overflow:hidden ;
+    background-color: #fff;
+    border-radius: 4px;
+    border:1px solid #C8CDD9;
+    box-sizing: border-box;
+    padding:30px;
+    .edb-title{
+        margin:0 -30px;
+        text-align: center;
+        padding-bottom: 30px;
+        border-bottom: 1px solid #C8CDD9;
+        font-size: 16px;
+    }
+    .edb-source-wrap{
+        text-align: center;
+    }
+    .edb-source-wrap{
+        flex: 1;
+        overflow: auto;
+    }
+}
+</style>
+<style lang="scss">
+.edb-history-page-wrap{
+  .org-tree-container {
+    margin: 0 auto;
+    /* .org-tree-node-label {  } */
+    .org-tree-node-label-inner{
+        cursor: pointer;
+        background-color: #F2F6FA;
+        color: #333333;
+        padding:20px;
+        border-radius: 4px;
+        font-size: 16px;
+        max-width: 100px;
+        &:hover{
+            color:#0052D9;
+            text-decoration: underline;
+            background-color: #ECF5FF;
+        }
+    }
+    .org-tree{
+        >.org-tree-node{
+            >.org-tree-node-label{
+                .org-tree-node-label-inner{
+                    background-color: #0052D9;
+                    color: white;
+                }
+            }
+        }
+    }
+    .org-tree-node-children {
+        .org-tree-node ~ .org-tree-node{
+            padding-left: 40px;
+        }
+    }
+    
+  }
+}
+.node-tooltip{
+    font-size: 14px;
+    padding:10px;
+    text-align: center;
+}
+</style>

+ 9 - 2
src/views/futures_manage/chartEditor.vue

@@ -100,6 +100,7 @@
 					<bar-option
 						v-if="!chart_code || (chart_code&&chartInfo.ChartType)"
 						ref="BarOptRef"
+						:chartInfo="chartInfo"
 						:edblist="tableData"
 						:datedata="commodityChartData"
 						:initData="initDateOptions"
@@ -122,7 +123,13 @@
 					<div class="chart-show-cont" v-show="options.series">
 						<div class="chartWrapper" id="chartWrapper">
 							<h2 class="chart-title" v-show="chartInfo.ChartName">{{ chartInfo.ChartName }}</h2>
-							<Chart :options="options" minHeight="440px" height="500px" ref="chartRef" />
+							<Chart 
+								:options="options" 
+								:chartInfo="chartInfo" 
+								minHeight="440px" 
+								height="500px" 
+								ref="chartRef" 
+							/>
 
 							<!-- 上下限  -->
 							<div class="range-cont left">
@@ -325,7 +332,7 @@ export default {
 			let params = {
 				EdbInfoIdList: [
 					...this.tableData.map(_ => ({EdbInfoId: _.EdbInfoId,Name:'',Source: 1})),
-					{ EdbInfoId: this.chartInfo.futures_id,Name: '',Source: 2 }
+					{ EdbInfoId: Number(this.chartInfo.futures_id),Name: '',Source: 2 }
 				],
 				DateList: dateList.map(_ => ({
 					Type: _.Type,

+ 1 - 0
src/views/futures_manage/commodityChartBase.vue

@@ -152,6 +152,7 @@
                     <h2 class="chart-title">{{ chartInfo.ChartName }}</h2>
                     <Chart 
 											:options="options"
+											:chartInfo="chartInfo"
 											minHeight="440px" 
 											height="500px"
 											ref="chartRef"

+ 57 - 19
src/views/mychart_manage/components/chartDetailDia.vue

@@ -212,7 +212,7 @@
           <div class="chart-show-cont">
             <div class="chartWrapper" id="chartWrapper">
               <template v-if="!chartInfo.WarnMsg">
-                <Chart :options="options" ref="chartRef"/>
+                <Chart :options="options" :chartInfo="chartInfo" ref="chartRef"/>
                 <!-- 上下限 -->
                 <div class="range-cont left" v-if="leftIndex != -1">
                   <el-input
@@ -326,16 +326,42 @@
                 <img :src="$icons.chart_right_arrow" alt="" class="arrow right"  @click="switchChart('next')">
               </template>
             </div>
-            <!-- 公历农历切换 只用于季节性图 -->
-            <el-radio-group
-              v-if="chartInfo.ChartType === 2 && !chartInfo.WarnMsg"
-              v-model="calendar_type"
-              class="calendar-cont"
-              @change="getPreviewChartInfo"
-            >
-              <el-radio-button label="公历" />
-              <el-radio-button label="农历" />
-            </el-radio-group>
+
+            <!-- 底部图表说明 -->
+            <div class="chart-bottom-insruction-info">
+
+              <div class="chart-source" v-if="chartInfo.SourcesFrom&&JSON.parse(chartInfo.SourcesFrom).isShow">
+                  <span
+                    :style="`
+                    color: ${ JSON.parse(chartInfo.SourcesFrom).color };
+                    fontSize: ${ JSON.parse(chartInfo.SourcesFrom).fontSize }px;
+                  `"
+                  >来源:{{JSON.parse(chartInfo.SourcesFrom).text}}</span>
+              </div>
+
+               <!-- 公历农历切换 只用于季节性图 -->
+              <el-radio-group
+                v-if="chartInfo.ChartType === 2 && !chartInfo.WarnMsg"
+                v-model="calendar_type"
+                class="calendar-cont"
+                @change="getPreviewChartInfo"
+              >
+                <el-radio-button label="公历" />
+                <el-radio-button label="农历" />
+              </el-radio-group>
+
+              <!-- 图表说明 -->
+              <div 
+                class="chart-instruction" 
+                v-if="chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow"
+                v-text="JSON.parse(chartInfo.Instructions).text"
+                :style="`
+                  color: ${JSON.parse(chartInfo.Instructions).color};
+                  fontSize: ${ JSON.parse(chartInfo.Instructions).fontSize }px
+                `"
+              ></div>
+            </div>
+
           </div>
           <el-table
             :data="tableData"
@@ -480,7 +506,7 @@
                   <i 
                     class="el-icon-tickets" 
                     style="color:#409EFF;font-size:18px" 
-                    @click="isLookHistory=true;lookEdbId=scope.row.EdbInfoId"
+                    @click="toHistoryPage(scope.row.EdbInfoId,$route.matched);lookEdbId=scope.row.EdbInfoId"
                     v-if="scope.row.EdbType===2"
                   />
                 </span>
@@ -540,10 +566,10 @@
     />
 
     <!-- 指标历史记录 -->
-    <edbHistoryDialog
+    <!-- <edbHistoryDialog
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
-    />
+    /> -->
   </div>
 </template>
 
@@ -562,6 +588,7 @@ import DateChooseDia from '@/views/dataEntry_manage/components/DateChooseDia';
 import changeLang from "@/views/dataEntry_manage/components/changeLang"
 import setEnNameDia from "@/views/dataEntry_manage/components/setEnNameDia"
 import { chartSetMixin } from '@/views/dataEntry_manage/mixins/chartPublic'
+import { copyFit } from '@/utils/svgToblob.js';
 
 export default {
   components: { Chart, DateChooseDia,SaveChartOther,changeLang,setEnNameDia },
@@ -698,9 +725,11 @@ export default {
           this.refreshLoading = false;
           if (res.Ret !== 200) return;
           this.chartInfo = res.Data.ChartInfo;
-          
 
           if(this.chartInfo.Source===1) {
+            //处理下历史默认来源
+            this.setDefaultSourceFrom();
+            
             this.tableData = res.Data.EdbInfoList;
             //eta图
             this.setDefaultDateSelect(); //设置默认的日期选中
@@ -897,7 +926,7 @@ export default {
     async refreshHandle() {
       // 清除缓存配置项
       this.refreshLoading = true;
-      const { Source,ChartInfoId,UniqueCode } = this.chartInfo;
+      const { Source,ChartInfoId,UniqueCode,ChartType } = this.chartInfo;
 
       let res=null
       if(Source===1){
@@ -917,7 +946,10 @@ export default {
         this.refreshLoading = false;
         if (res.Ret !== 200) return
         this.$message.success(res.Msg);
-        Source === 1 ? this.getPreviewChartInfo() : this.getChartDetail(UniqueCode);
+
+        Source===1&&![7,10].includes(ChartType)  
+          ? this.getPreviewChartInfo() 
+          : this.getChartDetail(UniqueCode);
     },
     // 英文面板时候的判断
     copyChartConfirm(type){
@@ -1353,7 +1385,7 @@ export default {
     },
 
     copyTitleText() {
-      let clipboard = new this.Clipboard('.my-chart-title')
+      /* let clipboard = new this.Clipboard('.my-chart-title')
       clipboard.on('success', e => {
         this.$message.success('复制标题成功')
         e.clearSelection() // 释放内存
@@ -1364,7 +1396,13 @@ export default {
         this.$message.warning('浏览器暂不支持')
         // 释放内存
         clipboard.destroy()
-      })
+      }) */
+      try{
+        copyFit(this.chartInfo.ChartName||'')
+        this.$message.success("复制标题成功")
+      }catch(e){
+        this.$message.warning("复制标题失败")
+      }
     },
 
     init() {

+ 2 - 1
src/views/ppt_manage/mixins/layerMixins.js

@@ -54,9 +54,10 @@ export default {
       }
       //计算图层元素的百分比化的单位:基于.total-wrap而不是基于ppt-item
       const width = $('.total-wrap').width(),height = $('.total-wrap').height()
+      this.activeLayerEl = {...this.activeLayerEl,...options}
       const percentageShape = caclShapePercentage({layerWidth:width,layerHeight:height},this.activeLayerEl)
-      this.activeLayerEl = {...this.activeLayerEl,...percentageShape,...options}
       this.activeLayerEl.id = createRandomCode()
+      this.activeLayerEl = {...this.activeLayerEl,...percentageShape}
       layerEls.push(this.activeLayerEl)
       this.refleshLayerEl(layerEls)
     },

+ 372 - 229
src/views/ppt_manage/mixins/mixins.js

@@ -97,6 +97,10 @@ export default {
 
     /* 曲线 */
     setDefaultChart() {
+
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //拼接标题 数据列
       let data = [],
         ydata = [];
@@ -115,10 +119,12 @@ export default {
             text: item.Unit,
             textCh:item.Unit,//中文单位
             textEn:item.Unit?item.UnitEn:'',//英文单位,但如果无中文单位则不显示
-            // text: null,
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
             align: 'high',
             rotation: 0,
-            y: -15,
+            y: -12,
             x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
             textAlign: item.IsAxis===1 ? 'left' : 'right',
             reserveSpace: false
@@ -131,15 +137,17 @@ export default {
             align: 'center',
             x: [0,2].includes(item.IsAxis) ? 5 : -5,
             style: {
-              fontSize: '10px',
-            },
+              ...chartTheme&&chartTheme.yAxisOptions.style,
+            }
           },
           opposite: [0,2].includes(item.IsAxis),
           reversed: item.IsOrder,
           min: Number(item.MinData),
           max: Number(item.MaxData),
           tickWidth: 1,
-          visible: sameSideIndex === index
+          visible: sameSideIndex === index,
+          plotBands: this.setAxisPlotAreas(item.IsAxis),
+          plotLines: this.setAxisPlotLines(item.IsAxis)
         };
 
         // //拼接标题 判断相同指标名称拼接来源
@@ -157,19 +165,20 @@ export default {
 
         //中英文名称
         const nameCh = dynamic_arr.length > 1
-        ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
-        : `${item.EdbName}${dynamic_tag}`
+        ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
+        : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`
         const nameEn = item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
         //数据列
         let obj = {
           data: [],
-          type: 'spline',
+          type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
           yAxis: sameSideIndex,
           name:nameCh,
           nameCh:nameCh,
           nameEn:nameEn,
           color: item.ChartColor,
-          lineWidth: Number(item.ChartWidth),
+          lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptions.lineWidth),
           ...predict_params
         };
         item.DataList = item.DataList || [];
@@ -191,7 +200,12 @@ export default {
               ? Highcharts.dateFormat('%m/%d', ctx.value)
               : Highcharts.dateFormat('%y/%m', ctx.value);
           },
-        }
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        plotBands: this.setAxisPlotAreas(3,'datetime'),
+        plotLines: this.setAxisPlotLines(3,'datetime')
       }
 
       this.options = {
@@ -230,6 +244,9 @@ export default {
       };
       let chartStyle = chartTypeMap[this.chartInfo.ChartType];
 
+       /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //拼接标题 数据列
       let data = [],
       ydata = [];
@@ -260,14 +277,15 @@ export default {
         let yItem = {
           ...basicYAxis,
           title: {
-            //text: sameSideIndex !== index ? '' : `${item.Unit}`,
             text:item.Unit,
             textCh:item.Unit,//中文单位
             textEn:item.Unit?item.UnitEn:'',//英文单位,但如果无中文单位则不显示
-            // text: null,
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
             align: 'high',
             rotation: 0,
-            y: -15,
+            y: -12,
             x: (item.IsAxis===0 && rightTwoIndex>-1) ? -chartData[rightTwoIndex].Unit.length*12 : 0,
             textAlign: item.IsAxis===1 ? 'left' : 'right',
             reserveSpace: false
@@ -280,15 +298,17 @@ export default {
             align: 'center',
             x: [0,2].includes(item.IsAxis) ? 5 : -5,
             style: {
-              fontSize: '10px',
-            },
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            }
           },
           opposite: [0,2].includes(item.IsAxis),
           reversed: item.IsOrder,
           min: Number(chartData[sameSideIndex].MinData),
           max: Number(chartData[sameSideIndex].MaxData),
           tickWidth: sameSideIndex !== index ? 0 : 1,
-          visible: serie_yIndex === index && sameSideIndex ===index
+          visible: serie_yIndex === index && sameSideIndex ===index,
+          plotBands: this.setAxisPlotAreas(item.IsAxis),
+          plotLines: this.setAxisPlotLines(item.IsAxis)
         };
 
         // //拼接标题 判断相同指标名称拼接来源
@@ -306,8 +326,8 @@ export default {
         
         //中英文名称
         const nameCh = dynamic_arr.length > 1
-        ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
-        : `${item.EdbName}${dynamic_tag}`
+        ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
+        : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`
         const nameEn = item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:''
 
         //数据列
@@ -319,11 +339,11 @@ export default {
           nameCh:nameCh,
           nameEn:nameEn,
           color: item.ChartColor,
-          lineWidth: (this.chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? Number(item.ChartWidth) : 0,
-          fillColor: (this.chartInfo.ChartType === 3 || (this.chartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
+          lineWidth: Number(item.ChartWidth),
+          // fillColor: (this.chartInfo.ChartType === 3 || (this.chartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
           borderWidth: 1,
           borderColor: item.ChartColor,
-          zIndex: (this.chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? 1 : 0, //防止组合图曲线被遮住
+          zIndex: (this.chartInfo.ChartType === 6 && ['line','spline'].includes(item.ChartStyle)) ? 1 : 0, //防止组合图曲线被遮住
           ...predict_params
         };
         item.DataList = item.DataList || [];
@@ -339,13 +359,18 @@ export default {
        let isLessThanOneYear = this.xTimeDiffer();
        let xAxis = {
          ...defaultOpts.xAxis,
-         labels: {
+        labels: {
            formatter: function (ctx) {
              return isLessThanOneYear
                ? Highcharts.dateFormat('%m/%d', ctx.value)
                : Highcharts.dateFormat('%y/%m', ctx.value);
            },
-         }
+           style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        plotBands: this.setAxisPlotAreas(3,'datetime'),
+        plotLines: this.setAxisPlotLines(3,'datetime')
        }
 
       this.options = {
@@ -360,6 +385,9 @@ export default {
       /* 季节性图的图表配置 */
       const chartData = this.dataList[0];
 
+       /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
 
       // 农历数据需要去除第一项 在ETA1.0.5之后,除了这里 农历和公历处理逻辑一样
       const temChartDataList=chartData.DataList||[]
@@ -367,115 +395,64 @@ export default {
       temChartDataList.filter((item, index) => index > 0):
       temChartDataList
       let seasonYdata = [],
-        seasonData = [],
-        chart = {
-          spacing: [5, 8, 2, 8],
-        };
+        seasonData = []
 
-      /* 公历数据处理 处理数据列 y轴 */
-      // if (this.chartInfo.Calendar === '公历')
-        for (let j of chartDataHandle) {
-           //预测指标配置
-          let predict_params =  chartData.EdbInfoCategoryType === 1 ? this.getSeasonPredictParams(j.CuttingDataTimestamp) : {};
-
-          let serie_item = {
-            data: [],
-            type: chartData.ChartStyle,
-            yAxis: 0,
-            name: j.ChartLegend,
-            ...predict_params
-          };
-          const data_array = _.cloneDeep(j.DataList);
-          data_array &&
-            data_array.forEach((item) => {
-              serie_item.data.push([item.DataTimestamp, item.Value]);
-            });
-          const index = chartDataHandle.findIndex(
-            (item) => item.ChartLegend === j.ChartLegend
-          );
-          const s_yItem = {
-            title: {
-              text:  `${chartData.Unit}`,
-              textCh:chartData.Unit,
-              textEn:chartData.Unit?chartData.UnitEn:'',
-              // text: null,
-              align: 'high',
-              rotation: 0,
-              y: -15,
-              offset: -(12 * chartData.Unit.length),
-            },
-            labels: {
-              formatter: function (ctx) {
-                let val = ctx.value;
-                return index !== 0 ? '' : val;
-              },
-              align: 'center',
-              style: {
-                fontSize: '10px',
-              },
-              x: -5,
-            },
-            max: Number(chartData.MaxData),
-            min: Number(chartData.MinData),
-            ...seasonOptions.yAxis,
-          };
-          seasonData.push(serie_item);
-          seasonYdata.push(s_yItem);
-        }
+      //数据列
+      for (let j of chartDataHandle) {
+          //预测指标配置
+        let predict_params =  chartData.EdbInfoCategoryType === 1 ? this.getSeasonPredictParams(j.CuttingDataTimestamp) : {};
 
-      /* 农历数据处理  */
-      // let filterArr =
-      //   this.chartInfo.Calendar === '农历'
-      //     ? chartData.DataList.List.filter((item, index) => index > 0)
-      //     : [];
-      // if (this.chartInfo.Calendar === '农历')
-      //   for (let j of filterArr) {
-      //      //预测指标配置
-      //     let predict_params =  chartData.EdbInfoCategoryType === 1 ? this.getSeasonPredictParams(j.CuttingDataTimestamp) : {};
-          
-      //     let serie_item = {
-      //       data: [],
-      //       type: chartData.ChartStyle,
-      //       yAxis: 0,
-      //       name: j.Year,
-      //       ...predict_params
-      //     };
-      //     const data_array = _.cloneDeep(j.Items);
-      //     data_array &&
-      //       data_array.forEach((item) => {
-      //         serie_item.data.push([item.DataTimestamp, item.Value]);
-      //       });
-      //     const index = filterArr.findIndex((item) => item.Year === j.Year);
-
-      //     const s_yItem = {
-      //       title: {
-      //         text:  `${chartData.Unit}`,
-      //         textCh:chartData.Unit,
-      //         textEn:chartData.Unit?chartData.UnitEn:'',
-      //         // text: null,
-      //         align: 'high',
-      //         rotation: 0,
-      //         y: -15,
-      //         offset: -(12 * chartData.Unit.length),
-      //       },
-      //       labels: {
-      //         formatter: function (ctx) {
-      //           let val = ctx.value;
-      //           return index !== 0 ? '' : val;
-      //         },
-      //         align: 'center',
-      //         style: {
-      //           fontSize: '10px',
-      //         },
-      //         x: -5,
-      //       },
-      //       max: Number(chartData.MaxData),
-      //       min: Number(chartData.MinData),
-      //       ...seasonOptions.yAxis,
-      //     };
-      //     seasonData.push(serie_item);
-      //     seasonYdata.push(s_yItem);
-      //   }
+        let serie_item = {
+          data: [],
+          type: (chartTheme&&chartTheme.lineOptions.lineType) || chartData.ChartStyle,
+          dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
+          yAxis: 0,
+          name: j.ChartLegend,
+          lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 1,
+          ...predict_params
+        };
+        const data_array = _.cloneDeep(j.DataList);
+        data_array &&
+          data_array.forEach((item) => {
+            serie_item.data.push([item.DataTimestamp, item.Value]);
+          });
+        seasonData.push(serie_item);
+      }
+
+      //y轴
+      seasonYdata = [{
+        ...seasonOptions.yAxis,
+        labels: {
+          formatter: function () {
+            let val = this.value;
+            return val;
+          },
+          align: 'center',
+          style: {
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          }
+        },
+        title: {
+          text:  `${chartData.Unit}`,
+          textCh:chartData.Unit, // 中文
+          // 中文不存在,无论英文有无都显示空
+          textEn:chartData.UnitEn||chartData.Unit, // 英文
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+          // text:  null,
+          align: 'high',
+          rotation: 0,
+          y: -12,
+          x: 0,
+          textAlign: 'left',
+          reserveSpace: false
+        },
+        max: Number(chartData.MaxData),
+        min: Number(chartData.MinData),
+        plotBands: this.setAxisPlotAreas(1),
+        plotLines: this.setAxisPlotLines(1)
+      }];
 
       // 季节图x轴显示月/日 周度指标额外处理时间轴显示
       const xAxis = {
@@ -485,15 +462,15 @@ export default {
             return Highcharts.dateFormat('%m/%d', ctx.value);
           },
           style: {
-            fontSize: '10px',
-          },
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
         },
+        plotBands: this.setAxisPlotAreas(3,'datetime'),
+        plotLines: this.setAxisPlotLines(3,'datetime')
       };
 
-      // 季节图提示框显示 月/日
-      defaultOpts.tooltip = {
-        split: false,
-        shared: true,
+      const tooltip = {
+        ...defaultOpts.tooltip,
         dateTimeLabelFormats: {
           // 时间格式化字符
           day: '%m/%d',
@@ -502,53 +479,15 @@ export default {
           year: '%m/%d',
         },
         xDateFormat: '%m/%d',
-        valueDecimals: 2,
-      };
-
-      //农历默认选中一年数据并隐藏按钮  公历显示全部数据
-      // let rangeSelector =
-      //   this.chartInfo.Calendar === '农历'
-      //     ? {
-      //         enabled: true,
-      //         selected: 0,
-      //         inputStyle: {
-      //           display: 'none',
-      //         },
-      //         labelStyle: {
-      //           display: 'none',
-      //         },
-      //         buttonTheme: {
-      //           style: {
-      //             display: 'none',
-      //           },
-      //         },
-      //         buttons: [
-      //           {
-      //             type: 'month',
-      //             count: 12,
-      //             text: '12月',
-      //           },
-      //           {
-      //             type: 'month',
-      //             count: 15,
-      //             text: '15月',
-      //           },
-      //           {
-      //             type: 'all',
-      //             text: '全部',
-      //           },
-      //         ],
-      //       }
-      //     : {
-      //         enabled: false,
-      //       };
+      }
 
+      let colors = chartTheme&&chartTheme.colorsOptions.reverse();
       this.options = {
-        colors:seasonOptions.colors.slice(-chartDataHandle.length),
+        colors: colors.slice(-chartDataHandle.length),
         series: seasonData,
         yAxis: seasonYdata,
         xAxis,
-        // rangeSelector
+        tooltip
       };
     },
 
@@ -556,6 +495,9 @@ export default {
     setScatterChart() {
       const chartData = _.cloneDeep(this.dataList);
 
+      /* 主题样式*/
+      const chartTheme = this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       // 取2个指标中日期相同的数据
       let real_data = [];
       let tmpData_date = {};//用来取点对应的日期
@@ -617,10 +559,12 @@ export default {
           text:  `${chartData[1].Unit}`,
           textCh:chartData[1].Unit,
           textEn:chartData[1].Unit?chartData[1].UnitEn:'',
-          // text: null,
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
           align: 'high',
           rotation: 0,
-          y: -15,
+          y: -12,
           offset: -(12 * chartData[1].Unit.length),
         },
         labels: {
@@ -628,6 +572,9 @@ export default {
             return ctx.value;
           },
           align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         opposite: false,
         reversed: IsOrder,
@@ -645,7 +592,9 @@ export default {
         endOnTick: false,
         startOnTick: false,
         showLastLabel: true,
-        tickPixelInterval: 50
+        tickPixelInterval: 50,
+        plotBands: this.setAxisPlotAreas(1),
+        plotLines: this.setAxisPlotLines(1)
       }
 
       //数据列
@@ -655,8 +604,11 @@ export default {
         name: `${this.chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`,
         nameCh:`${this.chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`,
         nameEn:this.chartInfo.ChartNameEn?`${this.chartInfo.ChartNameEn}${IsOrder ? '(reverse)' : ''}`:'',
+        chartType: 'linear',
         color: ChartColor,
-        lineWidth: 0
+        marker: {
+          radius: (chartTheme&&chartTheme.lineOptions.radius)||5,
+        },
       }
       real_data.forEach(_ => {
         series.data.push([_.x,_.y])
@@ -674,12 +626,21 @@ export default {
             text:  `${chartData[0].Unit}`,
             textCh:chartData[0].Unit,
             textEn:chartData[0].Unit?chartData[0].UnitEn:'',
-            // text: null,
+            style: {
+              ...chartTheme&&chartTheme.xAxisOptions.style
+            },
             align: 'high',
             rotation: 0,
             x: 0,
             offset: 15,
           },
+          labels: {
+            style: {
+              ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+          },
+          plotBands: this.setAxisPlotAreas(3),
+          plotLines: this.setAxisPlotLines(3)
         },
         tooltip
       }
@@ -693,18 +654,19 @@ export default {
       let seriesData = [];
       const data = _.cloneDeep(this.barDateList);
 
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //x轴
       let xAxis = {
         ...scatterXAxis,
         categories: this.barXIdData.map(_ => this.barEdbData.find(edb => edb.EdbInfoId===_).EdbAliasName),
         tickWidth: 1,
-        title: {
-          text:  ``,
-          align: 'high',
-          rotation: 0,
-          x: 0,
-          offset: 20,
-        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        }
       }
 
       const { max,min } = this.chartLimit;
@@ -717,8 +679,13 @@ export default {
           textEn: this.chartInfo.UnitEn,
           align: 'high',
           rotation: 0,
-          y: -15,
-          offset: 0,
+          y: -12,
+          x:0,
+          textAlign: 'left',
+          reserveSpace: false,
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         labels: {
           formatter: function (ctx) {
@@ -726,11 +693,16 @@ export default {
             return val;
           },
           align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         min: Number(min),
         max: Number(max),
         opposite: false,
         tickWidth: 1,
+        plotBands: this.setAxisPlotAreas(1),
+        plotLines: this.setAxisPlotLines(1)
       }
 
       //数据列
@@ -786,18 +758,19 @@ export default {
       let seriesData = [];
       const data = _.cloneDeep(this.commodityChartData);
 
+       /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //x轴
       let xAxis = {
         ...scatterXAxis,
         categories: this.commodityXData.map(_ =>_.Name),
         tickWidth: 1,
-        title: {
-          text:  ``,
-          align: 'high',
-          rotation: 0,
-          x: 0,
-          offset: 20,
-        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        }
       }
 
       const { max,min } = this.chartLimit;
@@ -810,8 +783,12 @@ export default {
           textEn:   this.commodityEdbList[0].Unit?(this.commodityEdbList[0].UnitEn||'英文单位'):'',
           align: 'high',
           rotation: 0,
-          y: -15,
-          offset: 0,
+          y: -12,
+          textAlign: 'left',
+          reserveSpace: false,
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         labels: {
           formatter: function (ctx) {
@@ -819,6 +796,9 @@ export default {
             return val;
           },
           align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         min: Number(min),
         max: Number(max),
@@ -833,14 +813,15 @@ export default {
 
         let serie_item = {
           data: filterData,
-          type: 'spline',
+          type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
           yAxis: 0,
           name: item.Name,
           nameCh: item.Name,
           nameEn: item.NameEn,
           color: item.Color,
           chartType: 'linear',
-          lineWidth: 3,
+          lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 3,
           marker: {
             enabled: false
           }
@@ -981,6 +962,10 @@ export default {
 
     /* 相关性图表初始化 */
     initRelevanceChartData(){
+
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+      
       // 处理X轴
       let xAxis={
         categories: this.relevanceChartData.XEdbIdValue,
@@ -991,9 +976,14 @@ export default {
           textEn:this.relevanceChartData.ChartInfo.Source===3 ? `stage(${this.relevanceUnitEnMap[this.relevanceChartData.CorrelationChartInfo.LeadUnit]})`:null,
           align: 'high',
           rotation: 0,
-          x: 0,
-          y:10,
-          offset: 20,
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
         },
         tickInterval: 1,
         offset:0,
@@ -1009,8 +999,12 @@ export default {
           textEn: 'Correlation coefficient',
           align: 'high',
           rotation: 0,
-          y: -15,
-          offset: 0,
+          y: -12,
+          textAlign: 'left',
+          reserveSpace: false,
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         labels: {
           formatter: function (ctx) {
@@ -1018,12 +1012,12 @@ export default {
             return val;
           },
           align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
-        // min: -1,
-        // max: 1,
         opposite: false,
         tickWidth: 1,
-        // tickInterval:0.2,
       }
 
       //处理series
@@ -1031,14 +1025,15 @@ export default {
       this.relevanceChartData.YDataList.forEach(item=>{
         let serie_item = {
           data: item.Value,
-          type: 'spline',
+          type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
           yAxis: 0,
           name: item.Name,
           nameCh: item.Name,
           nameEn: item.NameEn,
           color: item.Color,
           chartType: 'linear',
-          lineWidth: 3,
+          lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 3,
           marker: {
             enabled: false
           }
@@ -1094,6 +1089,9 @@ export default {
       const { DataList,XName,XNameEn,XUnitName,XUnitNameEn,YName,YNameEn,YUnitName,YUnitNameEn } = this.sectionScatterData;
       const { min,max,x_min,x_max }  = this.chartLimit;
 
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //y轴
       let yAxis = {
         ...basicYAxis,
@@ -1101,15 +1099,23 @@ export default {
           text: YName,
           textCh:YName,// 中文
           textEn:YNameEn,
-          style:{},
-          styleEn:{cursor:'pointer'},
           align: 'middle',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+        },
+        labels: {
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         opposite: false,
         reversed: false,
         min: Number(min),
         max: Number(max),
         tickWidth: 1,
+        plotBands: this.setAxisPlotAreas(1),
+        plotLines: this.setAxisPlotLines(1)
       }
 
       //x轴
@@ -1119,12 +1125,20 @@ export default {
           text: XName,
           textCh:XName,// 中文
           textEn:XNameEn,
-          style:{},
-          styleEn:{cursor:'pointer'},
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          },
           align: 'middle',
         },
+        labels: {
+          style:{
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          },
+        },
         min: Number(x_min),
         max: Number(x_max),
+        plotBands: this.setAxisPlotAreas(3),
+        plotLines: this.setAxisPlotLines(3)
       }
 
       //数据列
@@ -1140,7 +1154,10 @@ export default {
           color: item.Color,
           lineWidth: 0,
           chartType: 'linear',
-          zIndex:1
+          zIndex:1,
+          marker: {
+            radius: (chartTheme&&chartTheme.lineOptions.radius)||5,
+          },
         }
         item.EdbInfoList.forEach(_ => {
           series_item.data.push({
@@ -1257,17 +1274,18 @@ export default {
     /* 统计频率图 */
     setStatisticFrequency() {
 
+       /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       const { DataList,LeftMaxValue,LeftMinValue,RightMaxValue,RightMinValue } = this.statisticFrequencyData;
       
       let xAxis = {
         ...scatterXAxis,
         tickWidth: 1,
-        title: {
-          text:  ``,
-          align: 'high',
-          rotation: 0,
-          x: 0,
-          offset: 20,
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
         }
       }
 
@@ -1282,8 +1300,16 @@ export default {
             textEn:item.UnitEn||item.Unit,
             align: 'high',
             rotation: 0,
-            y: -15,
-            offset: 0,
+            y: -12,
+            reserveSpace: false,
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
+          },
+          labels: {
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
           },
           opposite: item.IsAxis===1?false:true,
           min: index===0? Number(LeftMinValue):Number(RightMinValue),
@@ -1293,13 +1319,14 @@ export default {
 
         let series_item = {
           data: item.Value.map(_ =>[_.X,_.Y]),
-          type: 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
+          type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
           yAxis: index,
           name: item.Name,
           nameCh: item.Name,
           nameEn: item.NameEn||item.Name,
           color: item.Color,
-          lineWidth: 3,
+          lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth)||3,
           chartType: 'linear',
           zIndex:1
         }
@@ -1341,6 +1368,9 @@ export default {
 
       const { DataList,XName,YName,XNameEn,YNameEn } = this.crossVarietyChartData;
 
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //y轴
       let yAxis = {
         ...basicYAxis,
@@ -1349,6 +1379,14 @@ export default {
           textCh:YName,// 中文
           textEn:YNameEn||YName,
           align: 'middle',
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
         },
         opposite: false,
         reversed: false,
@@ -1365,6 +1403,14 @@ export default {
           textCh:XName,// 中文
           textEn:XNameEn || XName,
           align: 'middle',
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
         },
         min: Number(x_min),
         max: Number(x_max),
@@ -1381,7 +1427,6 @@ export default {
           nameCh: item.Name,
           nameEn: item.NameEn||item.Name,
           color: item.Color,
-          lineWidth: 0,
           chartType: 'linear',
           zIndex:1
         }
@@ -1548,6 +1593,104 @@ export default {
             }]
           }
         : {}
+    },
+
+    /* 处理轴的标识线结构 在指定轴位置上拼接标识线 
+      0:右轴 1:左轴 2:右2轴 x轴固定3
+      axisType表示x轴类型 处理时间轴的值 datetime/null 
+    */
+    setAxisPlotLines(axis,axisType=null) {
+      const { MarkersLines,ChartType } = this.chartInfo;
+      if(!MarkersLines) return []
+      
+      let markerLines = JSON.parse(MarkersLines);
+
+      let arr = markerLines.filter(_ => _.isShow&&_.axis===axis)
+      let plotLines = arr.map(_ => {
+        //是否是x时间轴
+        let isXDateAxis = axis===3&&axisType==='datetime';
+        let markerValue='';
+        if(isXDateAxis) {
+          //季节图x轴额外拼个年份
+          let nowYear = ChartType===2 ? new Date(this.dataList[0].DataList[1].DataList
+            [0].DataTimestamp).getFullYear() : '';
+          markerValue = ChartType===2 
+            ? new Date(`${nowYear}-${_.value}`).getTime()
+            : new Date(_.value).getTime()
+        }else {
+          markerValue = Number(_.value)
+        }
+
+        return { 
+          value: markerValue,
+          dashStyle: _.dashStyle,
+          width: Number(_.lineWidth),
+          color: _.color,
+          label: {
+            text: _.text||'',
+            verticalAlign: _.textPosition,
+            style: {
+              color: _.textColor,
+              fontSize: _.textFontSize
+            }
+          }
+        }
+      })
+      return plotLines
+    },
+
+    /* 处理标识区拼接 axisType表示x轴类型处理时间轴的值 datetime/null */
+    setAxisPlotAreas(axis,axisType=null) {
+      const { MarkersAreas,ChartType } = this.chartInfo;
+      if(!MarkersAreas) return []
+
+      let markerAreas = JSON.parse(MarkersAreas);
+
+      let arr = markerAreas.filter(_ => _.isShow&&_.axis===axis)
+      let plotBands = arr.map(_ => {
+        //是否是x时间轴
+        let isXDateAxis = axis===3&&axisType==='datetime';
+        let fromMarkerValue='',toMarkerValue='';
+        if(isXDateAxis) {
+          //季节图x轴额外拼个年份
+          let nowYear = ChartType===2 ? new Date(this.dataList[0].DataList[1].DataList
+            [0].DataTimestamp).getFullYear() : '';
+          fromMarkerValue = ChartType===2 
+            ? new Date(`${nowYear}-${_.fromValue}`).getTime()
+            : new Date(_.fromValue).getTime()
+
+          toMarkerValue = ChartType===2 
+            ? new Date(`${nowYear}-${_.toValue}`).getTime()
+            : new Date(_.toValue).getTime()
+        }else {
+          fromMarkerValue = Number(_.fromValue);
+          toMarkerValue = Number(_.toValue);
+        }
+
+         //默认label有些偏移 重新归正下
+        let positionMapValue = {
+          'top': 12,
+          'middle': 0,
+          'bottom': -10
+        }
+
+        return { 
+          from: fromMarkerValue,
+          to: toMarkerValue,
+          color: _.color,
+          label: {
+            text: _.text||'',
+            verticalAlign: _.textPosition,
+            style: {
+              color: _.textColor,
+              fontSize: _.textFontSize
+            },
+            y: positionMapValue[_.textPosition]
+          }
+        }
+      })
+
+      return plotBands
     }
   },
 };

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

@@ -16,6 +16,7 @@ export default{
       copyPages:[],//选中的ppt页
       copyPagesMap:{},//选中的ppt页Id
       savePagesArr:[],//存储上一次选中的ppt页
+      CoverContent:'',//自定义封面页内容
     }
   },
   directives: {
@@ -384,7 +385,14 @@ export default{
           //啥也不干
         }
       });
-    }
+    },
+    //保存修改的自定义封面页
+    saveCover2(info){
+        const {firstPage={},content=''} = info
+        this.firstPage = firstPage
+        this.CoverContent = content
+        this.isShowChooseCover = false
+    },
   },
   mounted(){
     document.addEventListener("keydown",this.handlePasteKey)

+ 166 - 40
src/views/ppt_manage/mixins/pptMixins.js

@@ -10,7 +10,7 @@ import futuresInterface from '@/api/modules/futuresBaseApi';
 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';
+import {formatPPTDate,checkPPTpageElemant,getStrSize,isShowPPTTitle,toTextProps,toJson,rgbaToHex} from '../newVersion/utils/untils.js';
 import FormatOne from '../newVersion/components/formatPage/FormatOne.vue';
 import FormatTwo from '../newVersion/components/formatPage/FormatTwo.vue';
 import FormatThree from '../newVersion/components/formatPage/FormatThree.vue';
@@ -41,9 +41,10 @@ export default {
       pptCoverList:[],//配置ppt封面
       pptBgImage:'',//ppt背景图
       pptBackImage:'',//ppt封底
-      pptCoverCompenyName:'',//封面公司名称
-      pptCoverDepartName:'',//封面部门名称
-      pptCoverTextColor:'',//控制上面两个字段展示的颜色
+      pptCoverCompenyName:'',//封面公司名称 ETA1.4.9后不再使用
+      pptCoverDepartName:'',//封面部门名称 ETA1.4.9后不再使用
+      pptCoverTextColor:'',//控制上面两个字段展示的颜色 ETA1.4.9后不再使用
+      pptCoverContent:'',//自定义封面页的内容
 
 
       setEnName:false,
@@ -60,6 +61,54 @@ export default {
     }
   },
   methods: {
+    //配置自定义封面内容
+    setPPTCover(cover,pptCoverContent='',title=''){
+        let contentList = []
+        try{
+            contentList = JSON.parse(pptCoverContent)
+        }catch(e){
+            contentList=[]
+        }
+        //将contentList的内容通过addText写入,方法与图层写入文字一致
+        for(let i=0;i<contentList.length;i++){
+            const {
+                percentageTop,
+                percentageLeft,
+                percentageWidth,
+                percentageHeight,
+                richContent
+            } = contentList[i]
+            const position = {
+                x:percentageLeft*100+'%',
+                y:percentageTop*100+'%',
+                w:percentageWidth*100+'%',
+                h:percentageHeight*100+'%'
+            }
+            let textData = toTextProps(toJson(richContent))
+            cover.addText(textData,{
+                ...position,
+                margin:10,
+                fontSize:16*0.75,
+                valign:'top'
+            })
+        }
+        //不需要显示了
+        //若contentList为空,则在右下的位置显示标题
+        /* if(!contentList.length){
+            cover.addText(
+                [{text:title,options:{fontSize:28*0.75,breakLine:true}}],
+                {
+                    x:'38%',
+                    y:'50%',
+                    w:'60%',
+                    h:'28%',
+                    color:'ffffff',
+                    align:'center',
+                    fontFace:'SimHei'
+                })
+        } */
+        return cover
+    },
     //获取基本配置-ppt配置
     async getpptConfig(){
         const res = await etaBaseConfigInterence.getBaseConfig()
@@ -90,37 +139,41 @@ export default {
       }):await pptEnInterface.getpptDetail({PptId:id})
       if(res.Ret===200){
         const {
-			Content,
-			Title,
-			ReportType,
-			BackgroundImg,
-			PptDate,
-			TemplateType,
-      ReportId,
-      ModifyTime,
-      PublishTime,
-      Editor
-		} = res.Data
-      const pptDate = formatPPTDate(this.currentLang,PptDate)
-      let legalContent = JSON.parse(Content)
-      legalContent = legalContent.map(page=>{
-        page.elements = checkPPTpageElemant(page)
-        return page
-      })
-      this.result = {
-			status: 200,
-			content: legalContent,
-			FirstPage: {
-				Title,
-				ReportType,
-				BackgroundImg,
-				PptDate:pptDate,
-				TemplateType,
-			},
-      ReportId,
-      ModifyTime,
-      PublishTime,Editor
-		}
+            Content,
+            Title,
+            ReportType,
+            BackgroundImg,
+            PptDate,
+            TemplateType,
+            ReportId,
+            ModifyTime,
+            PublishTime,
+            Editor,
+            CoverContent
+        } = res.Data
+        const pptDate = formatPPTDate(this.currentLang, PptDate)
+        let legalContent = JSON.parse(Content)
+        legalContent = legalContent.map(page => {
+            page.elements = checkPPTpageElemant(page)
+            return page
+        })
+        this.pptCoverContent = CoverContent
+        this.result = {
+            status: 200,
+            content: legalContent,
+            FirstPage: {
+                Title,
+                ReportType,
+                BackgroundImg,
+                PptDate: pptDate,
+                TemplateType,
+            },
+            ReportId,
+            ModifyTime,
+            PublishTime,
+            Editor,
+            CoverContent
+        }
       }else{
         this.result = {status:'',content:'获取ppt数据失败!'}
       }
@@ -149,6 +202,9 @@ export default {
       this.chartInfo = Data.ChartInfo;
       if(!this.chartInfo) return
       if(this.chartInfo.Source === 1) { //常规图
+        //处理下历史默认来源
+        this.setDefaultSourceFrom();
+        
         this.dataList = Data.EdbInfoList;
         //柱形图独立数据
         this.chartInfo.ChartType === 7 && this.initBarData(res.Data);
@@ -225,6 +281,9 @@ export default {
                             chartInfoId:this.chartInfo.ChartInfoId,//添加到我的图库,图表id
                             MyChartClassifyId:this.chartInfo.MyChartClassifyId,//添加到我的图库,图库Id
                             Source:this.chartInfo.Source,//图表来源,和MyChartType一起确定是什么图
+                            Instructions: this.chartInfo.Instructions,
+                            SourcesFrom: this.chartInfo.SourcesFrom,
+                            ChartThemeStyle: this.chartInfo.ChartThemeStyle
                           }
         this.optionMap[id] = { ...defaultOpts, ...this.options,...otherOpts };
       }else{
@@ -315,6 +374,19 @@ export default {
         this.options.xAxis.title.text=this.options.xAxis.title.textEn
     },
 
+    /* 历史图表默认显示图表来源 d毛后端不修复只能自己每次详情处理下*/
+		setDefaultSourceFrom() {
+			if(!this.chartInfo.SourcesFrom) {
+        let themeOpt = JSON.parse(this.chartInfo.ChartThemeStyle);
+				this.chartInfo.SourcesFrom = JSON.stringify({
+					isShow: true,
+					text: this.chartInfo.ChartSource,
+					color: themeOpt&&themeOpt.markerOptions.style.color,
+					fontSize: themeOpt&&themeOpt.markerOptions.style.fontSize
+				});
+			}
+		},
+
     //检查图表英文配置是否完整
     checkChartEnData(){
       let result = true
@@ -450,11 +522,15 @@ export default {
         Source:7 统计特征
         以上图表需要显示标题
       */
-     const {Source,MyChartType} = options
+     const {Source,MyChartType,ChartThemeStyle} = options
      const isShowTitle = isShowPPTTitle(Source,MyChartType)
+     
+    /* 主题样式*/
+    const chartTheme =  ChartThemeStyle ? JSON.parse(ChartThemeStyle) : null;
+
       this.$nextTick(() => {
         let is_linear = options.series 
-          ? options.series.every(_ => _.type === 'scatter' ) || options.series.some(_ => _.chartType === 'linear'  )
+          ? options.series.some(_ => _.chartType === 'linear')
           : false ;
         //title样式
         let titleHTML = null
@@ -464,22 +540,39 @@ export default {
         let {total,newStr} = getStrSize(options.MyChartTitle,count)
         const isPublish = this.$route.path==='/pptpublish'||this.$route.path==='/pptenpublish'
         if(isShowTitle){
-          titleHTML = `<div style="white-space: normal;font-size:18px;">${options.MyChartTitle}</div>`
+          titleHTML = `<div style="
+            textAlign:${chartTheme&&chartTheme.titleOptions.align};
+            fontSize:${chartTheme&&chartTheme.titleOptions.style.fontSize}px;
+            color:${chartTheme&&chartTheme.titleOptions.style.color}
+          ">
+            ${options.MyChartTitle}
+          </div>`
         }
+
         let SpecialOption = {
           chart: {
+            ...defaultOpts.chart,
+					  ...chartTheme&&chartTheme.drawOption,
+            spacing: chartTheme.legendOptions.verticalAlign==='bottom' ? [23,10,2,10] : [2,10,2,10],//图例在底部顶部空间留大点给单位
             animation: false,
             backgroundColor: "rgba(0,0,0,0)",
             renderTo:$(`#${refName}`)[0],
           },
+          legend: {
+            ...defaultOpts.legend,
+            ...chartTheme&&chartTheme.legendOptions
+          },
+          colors: options.colors||chartTheme&&chartTheme.colorsOptions||defaultOpts.colors,
           title: isPublish?{
             text: isShowTitle?newStr:null,
+            margin:0,
             useHTML:false,
-            style:{fontSize:'18px'},
-            align:total>count?'left':'center',
+            style:{...chartTheme&&chartTheme.titleOptions.style},
+            align: (chartTheme&&chartTheme.titleOptions.align) || (total>count?'left':'center'),
           }:{
             text: titleHTML,
             useHTML:true,
+            margin:0,
             style:{left:0}
           },
           plotOptions: {
@@ -836,6 +929,39 @@ export default {
 			})
 			this.setEnName = false
 		},
+
+    /* 生成ppt时图表追加底部文字 来源/说明 */
+    transChartBottomInfo(slide,{x,y,width,height},data) {
+      let chartData = data;
+      let yPercent = Number(Math.ceil(height.replace(/%/,''))+Math.ceil(y.replace(/%/,'')))+'%';
+      // console.log(yPercent)
+
+      if(chartData.SourcesFrom&&JSON.parse(chartData.SourcesFrom).isShow) {
+        let sourceObj = JSON.parse(chartData.SourcesFrom);
+        slide.addText(`来源:${sourceObj.text}`,{
+          x:x,
+          y: yPercent,
+          w: width,
+          margin:10,
+          fontSize: sourceObj.fontSize*0.75,
+          color: sourceObj.color.includes('rgb') ? rgbaToHex(sourceObj.color).color.substring(1) : sourceObj.color.indexOf('#')===0 ? sourceObj.color.substring(1): '666',
+        })
+      }
+
+      if(chartData.Instructions&&JSON.parse(chartData.Instructions).isShow) {
+        let instructObj = JSON.parse(chartData.Instructions);
+
+        slide.addText(instructObj.text,{
+          x:x,
+          y: yPercent,
+          w: width,
+          align:'right',
+          margin:10,
+          fontSize: instructObj.fontSize*0.75,
+          color: instructObj.color.includes('rgb') ? rgbaToHex(instructObj.color).color.substring(1) : instructObj.color.indexOf('#')===0 ? instructObj.color.substring(1): '666',
+        })
+      }
+    }
   },
   mounted(){
     this.getpptConfig()

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

@@ -1,4 +1,5 @@
 <template>
+    <!-- ETA1.4.9之前的展示封面组件,若该版本上线后无回滚需求,可删除 -->
     <div class="flex-column cover" :style="`width:100%;height:100%;color: ${$parent.pptCoverTextColor||'#fff'};`" v-if="pageInfo">
         <!-- <img :src="pageInfo.BackgroundImg" class="pptbg" /> -->
         <!-- <img :src="base64Url" class="pptbg" /> -->

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

@@ -1,4 +1,5 @@
 <template>
+    <!-- ETA1.4.9之前的展示封面组件,若该版本上线后无回滚需求,可删除 -->
     <div class="flex-column cover" style="width:100%;height:100%;" v-if="pageInfo">
         <img :src="pageInfo.BackgroundImg" class="pptbg"  style="width:100%;height:100%;object-fit: fill !important;"/>
         <div

+ 122 - 0
src/views/ppt_manage/newVersion/components/CustomCover.vue

@@ -0,0 +1,122 @@
+<template>
+    <!-- 自定义封面页渲染 -->
+    <div class="cover-new-wrap cover">
+        <!-- 封面图 -->
+        <img :src="pageInfo.BackgroundImg||''" class="cover-img" style="object-fit: fill !important;">
+        <!-- 自定义文本 -->
+        <div v-for="el in coverList" :key="el.id"
+            class="cover-el el-text" :id="`cover-el-${el.id}`" :style="{
+            top: el.percentageTop*100 + '%',
+            left: el.percentageLeft*100 + '%',
+            width: el.percentageWidth*100 + '%',
+            height: el.percentageHeight*100 + '%',
+            pointerEvents:'none'
+        }" >
+            <div class="layer-editor-wrap">
+                <div style="width:100%;height:100%;" :id="`${el.id}-editorDom`" @mousedown.stop>
+                        <div class="editor-content" :style="{width:el.width+'px'}" v-html="el.richContent"></div>
+                </div>
+            </div>
+        </div>
+        <!-- 不需要显示了 -->
+        <!-- 如果没有自定义文本,则在右下的位置显示标题 -->
+        <!-- <div class="cover-el default" v-if="!coverList.length">
+            <div class="editor-content"><p style="font-size:28px;color:#fff;">{{ pageInfo.Title }}</p></div>
+        </div> -->
+    </div>
+</template>
+
+<script>
+export default {
+    name:'CoverNew',
+    props: {
+        pageInfo: {
+            type: Object,
+            default:{}
+        },
+        CoverContent: {
+            type: String,
+            default: ''
+        }
+    },
+    watch:{
+        CoverContent(newval){
+            this.setCoverContent()
+        }
+    },
+    data() {
+        return {
+            coverList: [],
+        };
+    },
+    methods: {
+        setCoverContent() {
+            try{
+                this.coverList = JSON.parse(this.CoverContent)
+            }catch(e){
+                this.coverList = []
+            }
+        }
+    },
+    mounted() {
+        this.setCoverContent();
+    },
+};
+</script>
+
+<style lang="scss">
+    .cover-el {
+        .layer-editor-wrap {
+            .editor-content {
+                ul {
+                    margin-left: 1em;
+                    list-style-type: disc;
+                }
+
+                ol {
+                    margin-left: 1em;
+                    list-style-type: decimal;
+                }
+            }
+        }
+    }
+</style>
+<style scoped lang="scss">
+.cover-new-wrap{
+    width:100%;
+    height:100%;
+    position:relative;
+    .cover-img{
+        width: 100%;
+        height: 100%;
+    }
+    .cover-el{
+        position: absolute;
+        .layer-editor-wrap {
+            z-index: 2;
+            width: 100%;
+            height: 100%;
+            /* padding: 10px; */
+            box-sizing: border-box;
+            position: relative;
+            >div {
+                cursor: pointer;
+            }
+            .editor-content {
+                padding: 10px;
+                position: absolute;
+                transform-origin: 0 0;
+                word-wrap: break-word;
+            }
+        }
+        &.default{
+            width:62%; 
+            font-size:16px; 
+            text-align:center; 
+            line-height:1.6;
+            right:20px; 
+            top:50%;
+        }
+    }
+}
+</style>

+ 25 - 118
src/views/ppt_manage/newVersion/components/catalog/mergePPTDialog.vue

@@ -11,97 +11,9 @@
         <span style="fontsize: 16px">合并PPT</span>
       </div>
       <div class="dialog-container">
-      <!--  <div class="tree-container-wrap">
-          <div class="public-tree">
-            <h3>公共PPT</h3>
-            <div class="tree-container">
-              <div class="tree-list" :key="treeKey">
-                <div class="list-item" v-for="(item,index) in publicList" :key="item.nodeKeyId" @click.stop="expandList(index,'public')">
-                  <p class="item-label"><span @click.stop="expandList(index,'public')"><i :class="item.expand?'el-icon-caret-bottom':'el-icon-caret-right'"></i></span> {{item.label}}</p>
-                  <template v-if="item.expand">
-                    <div class="list-child" v-for="i in item.children" :key="i.nodeKeyId">
-                      <el-checkbox
-                        :disabled="disabled&&!choosedIdArr.includes(i.PptId)||i.disabled"
-                        v-model="i.checked"
-                        @change="(checked)=>{changeCheck(checked,i,'public')}"
-                      >{{i.label}}</el-checkbox>
-                    </div>
-                  </template>
-                </div>
-              </div>
-            </div>
-          </div>
-          <div class="private-tree">
-            <h3>我的PPT</h3>
-            <div class="tree-container">
-              <div class="tree-list" :key="treeKey">
-                <div class="list-item" v-for="(item,index) in privateList" :key="item.nodeKeyId" @click.stop="expandList(index,'private')">
-                  <p class="item-label"><span @click.stop="expandList(index,'private')"><i :class="item.expand?'el-icon-caret-bottom':'el-icon-caret-right'"></i></span> {{item.label}}</p>
-                  <template v-if="item.expand">
-                    <div class="list-child" v-for="i in item.children" :key="i.nodeKeyId">
-                      <el-checkbox
-                        :disabled="disabled&&!choosedIdArr.includes(i.PptId)||i.disabled"
-                        v-model="i.checked"
-                        @change="(checked)=>{changeCheck(checked,i,'private')}"
-                      >{{i.label}}</el-checkbox>
-                    </div>
-                  </template>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div> -->
         <div class="ppt-form">
           <div class="input-item" style="position:relative;">
             <h3>请选择PPT</h3>
-            <!-- <div class="select-node-show" @click.stop="showCatalog = !showCatalog">
-              <div class="select-node" v-for="item in choosedItemArr" :key="item.PptId">
-                <span>{{ item.Title }}</span>
-                <i class="el-icon-error" @click.stop="changeCheck(false,item,'unknow')"></i>
-              </div>
-              <div v-show="choosedItemArr.length===0" style="color:#606266;opacity:.54;margin-left:10px;">请选择PPT</div>
-              <span class="expand" @click.stop="showCatalog = !showCatalog"><i :class="showCatalog?'el-icon-arrow-up':'el-icon-arrow-down'"></i></span>
-            </div>
-            <div class="catalog-wrap" v-show="showCatalog">
-              <div class="public-tree">
-                <h3>公共PPT</h3>
-                <div class="tree-container">
-                  <div class="tree-list" :key="treeKey">
-                    <div class="list-item" v-for="(item,index) in publicList" :key="item.nodeKeyId" @click.stop="expandList(index,'public')">
-                      <p class="item-label"><span @click.stop="expandList(index,'public')"><i :class="item.expand?'el-icon-caret-bottom':'el-icon-caret-right'"></i></span> {{item.label}}</p>
-                      <template v-if="item.expand">
-                        <div class="list-child" v-for="i in item.children" :key="i.nodeKeyId">
-                          <el-checkbox
-                            :disabled="disabled&&!choosedIdArr.includes(i.PptId)||i.disabled"
-                            v-model="i.checked"
-                            @change="(checked)=>{changeCheck(checked,i,'public')}"
-                          >{{i.label}}</el-checkbox>
-                        </div>
-                      </template>
-                    </div>
-                  </div>
-                </div>
-              </div>
-              <div class="private-tree" style="margin-top:10px;">
-                <h3>我的PPT</h3>
-                <div class="tree-container">
-                  <div class="tree-list" :key="treeKey">
-                    <div class="list-item" v-for="(item,index) in privateList" :key="item.nodeKeyId" @click.stop="expandList(index,'private')">
-                      <p class="item-label"><span @click.stop="expandList(index,'private')"><i :class="item.expand?'el-icon-caret-bottom':'el-icon-caret-right'"></i></span> {{item.label}}</p>
-                      <template v-if="item.expand">
-                        <div class="list-child" v-for="i in item.children" :key="i.nodeKeyId">
-                          <el-checkbox
-                            :disabled="disabled&&!choosedIdArr.includes(i.PptId)||i.disabled"
-                            v-model="i.checked"
-                            @change="(checked)=>{changeCheck(checked,i,'private')}"
-                          >{{i.label}}</el-checkbox>
-                        </div>
-                      </template>
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </div> -->
             <div class="select-ppt-wrap select-wrap">
               <el-tabs value="public">
                 <el-tab-pane label="公共PPT" name="public">
@@ -165,21 +77,6 @@
             <h3>PPT标题</h3>
             <el-input  placeholder="请输入PPT标题" v-model="pptInfo.Title" required ></el-input>
           </div>
-          <div class="input-item">
-            <h3>PPT类型</h3>
-            <el-input  placeholder="请输入PPT类型" v-model="pptInfo.ReportType" required ></el-input>
-          </div>
-  <!--         <div class="input-item date-picker">
-            <h3>PPT日期</h3>
-            <el-date-picker
-              v-model="pptInfo.PptDate"
-              type="month"
-              ref="date_pic"
-              format="yyyy年M月"
-              value-format="yyyy年M月"
-              placeholder="请选择日期">
-            </el-date-picker>
-          </div> -->
         </div>
       </div>
       <div slot="footer" class="foot-container">
@@ -194,6 +91,7 @@
 <script>
 import {pptInterface} from '@/api/api.js';
 import {pptEnInterface} from '@/api/modules/pptEnApi.js';
+import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
 import {changeCatalogArr,createRandomCode} from '../../utils/untils';
 export default {
   props:{
@@ -201,18 +99,14 @@ export default {
       type:Boolean,
       default:false
     },
-/*     catalogId:{
-      type:Number,
-      default:0
-    } */
   },
   data() {
     return {
       pptInfo:{
         Title:'',
-        ReportType:'',
-        BackgroundImg:'https://hzstatic.hzinsights.com/ppt/bg3.jpg',
-        PptDate:(new Date().getFullYear())+'年'+(new Date().getMonth()+1)+'月',
+        //ReportType:'',
+        ImgUrl:'',//读取etaBaseConfig中封面页的第一个
+        //PptDate:(new Date().getFullYear())+'年'+(new Date().getMonth()+1)+'月',
         BackIndex:0,
         TemplateType:1
       },//PPT的标题信息
@@ -236,6 +130,7 @@ export default {
         this.init()
         this.getCatalogsList()
         this.getPrivateList()
+        this.getBaseConfig()
       }
       if(!newValue){
         if(this.saveLoading){
@@ -268,9 +163,17 @@ export default {
       }
       await this.addNewPpt()
       if(this.PptId!==0){
-        this.$emit('merged',{PptId:this.PptId,catalogId:this.selectedCatalogId})
+        //this.$emit('merged',{PptId:this.PptId,catalogId:this.selectedCatalogId})
+        this.saveLoading.close()
+        //跳转至ppt编辑页
+        const path = this.$parent.currentLang!=='en'?'/ppteditor':'/ppteneditor'
+        this.$router.push({
+            path,
+            query:{
+                id:this.PptId
+            }
+        })
       }
-        
     },
     //检查填写的信息是否合法
     checkForm(){
@@ -281,12 +184,12 @@ export default {
       if(!this.pptInfo.Title.length){
         return {result:false,msg:'请填写PPT标题'}
       }
-      if(!this.pptInfo.ReportType){
+      /* if(!this.pptInfo.ReportType){
         return {result:false,msg:'请填写PPT类型'}
       }
       if(!this.pptInfo.PptDate){
         return {result:false,msg:'请选择日期'}
-      }
+      } */
       if(this.selectedCatalogId===0){
         return {result:false,msg:'请选择一个目录'}
       }
@@ -440,12 +343,16 @@ export default {
     //重置data的值
     init(){
       Object.assign(this.$data,this.$options.data())
+    },
+    getBaseConfig(){
+        etaBaseConfigInterence.getBaseConfig().then(res=>{
+                if(res.Ret!==200) return
+                const {CnPptCoverImgs='',EnPptCoverImgs=''} = res.Data||{}
+                this.pptInfo.ImgUrl = this.$parent.currentLang!=='en'?CnPptCoverImgs.split(',')[0]:EnPptCoverImgs.split(',')[0]
+        })
     }
   },
-  mounted(){
-    //console.log('merge')
-    //this.getCatalogsList()
-  }
+  mounted(){}
 };
 </script>
 

+ 4 - 2
src/views/ppt_manage/newVersion/components/catalog/pptContent.vue

@@ -4,7 +4,8 @@
     <div class="ppt-scroll">
       <template  v-for="(item,index) in loadArr">
           <div class="ppt-item" id="cover" v-if="index===0" :key="item.id">
-            <Cover :pageInfo="firstPage" v-show="firstPage"></Cover>
+            <!-- <Cover :pageInfo="firstPage" v-show="firstPage"></Cover> -->
+            <CustomCover :pageInfo="firstPage" :CoverContent="pptCoverContent" v-show="firstPage"/>
             <!-- <div class="ppt-info">
               <p>作者:{{pptItem.AdminRealName}}</p>
               <p>{{pptItem.PptxUrl?'发布':'保存'}}时间:{{$moment(pptTime).format('YYYY-MM-DD')}}</p>
@@ -54,6 +55,7 @@ import Highcharts from "highcharts/highstock";
 import HighchartszhCN  from '@/utils/highcahrts-zh_CN'
 HighchartszhCN(Highcharts)
 import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyDia';
+import CustomCover from '../CustomCover.vue';
 export default {
   props:{
     pptItem:{ //ppt信息
@@ -61,7 +63,7 @@ export default {
     }
   },
   mixins:[pptmixin,mixins],
-  components:{Cover,addMyClassifyDia},
+  components:{ Cover, addMyClassifyDia, CustomCover },
   data() {
     return {
         pageList:[],//ppt数组

+ 4 - 2
src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue

@@ -3,7 +3,8 @@
     <div class="ppt-scroll">
       <template  v-for="(item,index) in loadArr">
           <div class="ppt-item" id="cover" v-if="index===0" :key="item.id">
-            <Cover :pageInfo="firstPage" v-show="firstPage"></Cover>
+            <!-- <Cover :pageInfo="firstPage" v-show="firstPage"></Cover> -->
+            <CustomCover :pageInfo="firstPage" :CoverContent="pptCoverContent" v-show="firstPage"/>
             <!-- <div class="ppt-info">
               <p>作者:{{pptItem.AdminRealName}}</p>
               <p>{{pptItem.PptxUrl?'发布':'保存'}}时间:{{$moment(pptTime).format('YYYY-MM-DD')}}</p>
@@ -53,6 +54,7 @@ import Highcharts from "highcharts/highstock";
 import HighchartszhCN  from '@/utils/highcahrts-zh_CN'
 HighchartszhCN(Highcharts)
 import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyDia';
+import CustomCover from '../CustomCover.vue';
 export default {
   props:{
     pptItem:{ //ppt信息
@@ -60,7 +62,7 @@ export default {
     }
   },
   mixins:[pptmixin,mixins],
-  components:{Cover,addMyClassifyDia},
+  components:{Cover,addMyClassifyDia,CustomCover},
   data() {
     return {
         pageList:[],//ppt数组

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

@@ -160,7 +160,7 @@
 							backgroundColor: 'rgba(255, 255, 255, 0)',
 						}
 						let is_linear = this.options.series 
-							? this.options.series.every(_ => _.type === 'scatter' ) || this.options.series.some(_ => _.chartType === 'linear'  )
+							? this.options.series.some(_ => _.chartType === 'linear'  )
 							: false ;
 						let chart = is_linear ? Highcharts.chart('container'+item.resource_id, new_options) : Highcharts.stockChart('container'+item.resource_id, new_options);
 						const svg = chart.getSVG();

+ 1 - 0
src/views/ppt_manage/newVersion/components/editor/ChooseCover.vue

@@ -1,4 +1,5 @@
 <template>
+    <!-- ETA1.4.9之前的选择封面组件,若该版本上线后无回滚需求,可删除 -->
     <div class="first_dialog">
         <div class="dialog-min">
             <header class="dialog-top">

+ 1 - 0
src/views/ppt_manage/newVersion/components/editor/ChooseCoverEn.vue

@@ -1,4 +1,5 @@
 <template>
+    <!-- ETA1.4.9之前的选择封面组件,若该版本上线后无回滚需求,可删除 -->
     <div class="first_dialog">
         <div class="dialog-min">
             <header class="dialog-top">

+ 325 - 0
src/views/ppt_manage/newVersion/components/editor/ChooseCoverNew.vue

@@ -0,0 +1,325 @@
+<template>
+    <!-- ppt自定义封面编辑 -->
+    <el-dialog
+        :visible.sync="isShowChooseCover" 
+        :close-on-click-modal="false" 
+        :modal-append-to-body="false"
+        title="自定义封面页"
+        custom-class="choose-cover-new-wrap"
+        v-dialogDrag center width="75%" top="5vh"
+        @close="$emit('close')"
+    >
+        <div class="container" v-loading="coverLoading">
+            <div class="edit-cover-wrap" @mousedown.stop="clickOutside">
+                <div class="cover">
+                    <!-- 封面图 -->
+                    <div class="editor-area" :style="`background-image:url(${pptCoverList[choosedIndex]});`">
+                        <!-- 封面内文本元素 -->
+                        <TextEl v-for="el in coverElList" :key="el.id"
+                            :element-info="el"
+                            :isCoverEdit="true"
+                            :isActive="el.id===activeEl.id"
+                            @click.stop.native="changeActEl(el)"
+                            @deleteEl="deleteEl"
+                            @copyEl="getCopyEl"
+                        />
+                    </div>
+                </div>
+                <div class="editor-tool">
+                    <div class="title-box box">
+                        <p><span style="color:#D54941;margin-left: 0;margin-right: 3px;">*</span>PPT标题</p>
+                        <el-input v-model="pageData.Title"
+                            placeholder="请输入PPT标题" style="width:100%;margin-top:10px;"></el-input>
+                    </div>
+                    <div class="el-box box">
+                        <p @click.stop="addTextEl">插入文本<span style="vertical-align: middle;"><img src="~@/assets/img/ppt_m/text-icon.png"></span></p>
+                    </div>
+                    <div class="el-tool-box box">
+                        <p style="margin-bottom: 10px;">文本设置 <span v-if="!activeEl.id" style="color:#B2B9CB;">请选择文本元素</span></p>
+                        <div class="cover-text-toolbar" @mousedown.stop></div>
+                    </div>
+                    <div class="dialog-btn">
+                        <el-button @click="changeBg">换一个模板</el-button>
+                        <el-button @click="saveCover">保存</el-button>
+                    </div>
+                </div>
+            </div>
+        </div>
+        
+    </el-dialog>
+
+</template>
+
+<script>
+import TextEl from './chooseCover/TextEl.vue';
+import { BaseTextShape } from '@/views/ppt_manage/newVersion/utils/config';
+import {createRandomCode,caclShapePercentage} from "@/views/ppt_manage/newVersion/utils/untils";
+import {pptInterface} from '@/api/api.js';
+import {pptEnInterface} from '@/api/modules/pptEnApi.js';
+import html2canvas from 'html2canvas';
+export default {
+    props: {
+        isShowChooseCover: {
+            type: Boolean,
+            default: false
+        },
+        firstPage: {
+            type: Object,
+            default: {}
+        },
+        pptCoverList: {
+            type: Array,
+            default: []
+        },
+        CoverContent: {
+            type: String,
+            default: ''
+        },
+        PptId:{
+            type:Number,
+            default:0
+        }
+    },
+    data() {
+        return {
+            coverElList: [], //封面自定义内容
+            activeEl:{}, //当前选择的元素
+            copyEl:{}, //当前copy的元素
+            pageData:{Title:''}, //封面标题,背景图等设置
+            searchIndex:0,
+            choosedIndex:0,
+            coverLoading:false,
+        };
+    },
+    watch:{
+        isShowChooseCover(newVal){
+            this.changeActEl({})
+            if(newVal){
+                this.setCoverInfo()
+            }
+        }
+    },
+    methods: {
+        setCoverInfo() {
+            this.pageData.Title = this.firstPage.Title||''
+            this.searchIndex = this.pptCoverList.findIndex(i=>i===this.firstPage.BackgroundImg)
+            //如果基本配置-封面图,没有当前ppt的封面图,则默认第一个
+            if(this.searchIndex===-1){
+                this.pageData.BackgroundImg = this.pptCoverList[0]
+            }
+            //如果封面页内容不是合法的json,置空
+            try{
+                this.coverElList = JSON.parse(this.CoverContent);
+            }catch(e){
+                this.coverElList = []
+            }
+        },
+        //保存封面配置
+        async saveCover() {
+            if(!this.pageData.Title.length){
+                return this.$message.warning("请输入PPT标题")
+            }
+            const coverContent = JSON.stringify(this.coverElList);
+            //this.coverLoading=true
+            //校验标题
+            const pptId = this.$route.query.id || this.PptId||0
+            const res = this.$parent.currentLang!=='en'
+                ?await pptInterface.pptTitleCheck({PptId:pptId,Title:this.pageData.Title})
+                :await pptEnInterface.pptTitleCheck({PptId:pptId,Title:this.pageData.Title})
+            if(res.Ret===200){
+                //const coverBase64 = await this.coverToCanvas()
+                //this.coverLoading=false
+                this.$emit('saveCover', {
+                        firstPage:Object.assign(this.firstPage,this.pageData),
+                        content:coverContent,
+                        //covetImg:coverBase64||''
+                    })
+            }
+        },
+        //封面截图
+        async coverToCanvas(){
+            console.log('start')
+            this.changeActEl({})
+            //editor-area
+            const canvasWrap = document.querySelector('.editor-area')
+            //将背景图清空,防止跨域的问题
+            if(!canvasWrap) return
+            canvasWrap.scrollTop = 0
+            canvasWrap.scrollLeft=0
+            const width = $('.editor-area').width()
+            const height = Number((width*0.7).toFixed(2))
+            console.log('width,height',width,height)
+            const cover = $('.editor-area')[0]
+            cover.style.backgroundImage = 'none'
+            let canvas = await html2canvas(
+                cover,
+                {
+                    useCORS: true,
+                    allowTaint:true,
+                    backgroundColor: `transparent`,
+                    /* scale: 2, */
+                    imageTimeout: 0,
+                    width:width,
+                    height:height
+                }
+            )
+            console.log('finished')
+            const url = canvas.toDataURL("image/png")
+            this.checkImg(url)
+            //转换完成后,将背景图设置回来
+            cover.style.backgroundImage = `url(${this.pptCoverList[this.choosedIndex]})`
+            return url
+        },
+            //测试用
+        checkImg(dataURL,fileType='png'){
+            let link = document.createElement('a')
+            link.href = dataURL
+            link.download = `test.${fileType}`
+            link.click()
+        },
+        changeActEl(el){
+            this.activeEl = el
+        },
+        clickOutside(){
+            this.changeActEl({})
+        },
+        changeBg(){
+            if(this.choosedIndex<this.pptCoverList.length-1){
+                this.choosedIndex++
+            }else{
+                this.choosedIndex=0
+            }
+            this.pageData.BackgroundImg = this.pptCoverList[this.choosedIndex]
+        },
+        addTextEl(options={}){
+            let el = _.cloneDeep(BaseTextShape)
+            el = {...el,...options}
+            const areaWidth = $(".editor-area").width()||0
+            const areaHeight = areaWidth*0.7
+            const percentageShape = caclShapePercentage({layerWidth:areaWidth,layerHeight:areaHeight},el)
+            el = {...el,...percentageShape}
+            el.id = createRandomCode()
+            this.coverElList.push(el)
+            this.changeActEl(el)
+        },
+        deleteEl(el){
+            this.changeActEl({})
+            const index = this.coverElList.findIndex(e=>e.id===el.id)
+            index!==-1&&(this.coverElList.splice(index,1))
+        },
+        getCopyEl(el){
+            this.copyEl = el
+            this.pasteEl("copy")
+        },
+        pasteEl(type="copy"){
+            const {width,height,left,top} = this.copyEl
+            const areaWidth = $(".editor-area").width()||0
+            const areaHeight = areaWidth*0.7
+            //在原先元素右下方渲染新元素
+            const points = {clientX:left+10,clientY:top+10}
+            const supplyValue = type==='copy'?10:0 //补值,防止渲染出边界
+            const new_left = ((points.clientX+width) - areaWidth)>0?(areaWidth - width - supplyValue):points.clientX
+            const new_top =  ((points.clientY+height) - areaHeight)>0?(areaHeight - height - supplyValue):points.clientY
+            const options = {...this.copyEl,...{
+                left:new_left,
+                top:new_top,
+                width,
+                height,
+                realWidth:width,
+                realHeight:height
+            }}
+            this.addTextEl(options)
+        },
+    },
+    components: { TextEl }
+};
+</script>
+
+<style lang="scss">
+.choose-cover-new-wrap{
+    max-width:1360px;
+    height: 90%;
+    overflow: hidden !important;
+    margin-bottom: 0;
+    display: flex;
+    flex-direction: column;
+    .el-dialog__body{
+        padding:25px !important;
+        flex: 1;
+        overflow: auto;
+        color: inherit;
+    }
+    .tox-menu.tox-swatches-menu.tox-selected-menu{
+      left:auto !important;
+      right:0;
+    }
+    .tox-menu{
+        max-height: 200px !important;
+      }
+}
+</style>
+<style scoped lang="scss">
+.choose-cover-new-wrap{
+    .container{
+        width:100%;
+        height:100%;
+        display: flex;
+        flex-direction: column;
+        .edit-cover-wrap{
+            display: flex;
+            flex: 1;
+            /* overflow: auto; */
+            .cover,.editor-tool{
+                box-sizing: border-box;
+            }
+            .cover{
+                min-width: 640px;
+                flex:1;
+                background-color: #c8cdd921;
+                display: flex;
+                align-items: center;
+                box-sizing: border-box;
+                border:1px solid #C8CDD9;
+                border-radius: 4px;
+                padding:10px;
+                overflow-y: visible;
+                .editor-area{
+                    position: relative;
+                    width:100%;
+                    height: 0;
+                    padding-bottom: 70%;
+                    /* background-color:bisque; */
+                    background-repeat: no-repeat;
+                    background-position: center;
+                    background-size: 100% 100%;
+                }
+            }
+            .editor-tool{
+                min-width:320px;
+                padding-left:20px;
+                position:relative;
+                /* background-color: burlywood; */
+                .box{
+                    margin-bottom: 10px;
+                    p{
+                        span{
+                            cursor: pointer;
+                            margin-left: 10px;
+                            img{
+                                width:23px;
+                                height:23px;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        .dialog-btn{
+            position:absolute;
+            right:0;
+            bottom: 0;
+        }
+        
+    }
+}
+</style>

+ 192 - 0
src/views/ppt_manage/newVersion/components/editor/chooseCover/TextEl.vue

@@ -0,0 +1,192 @@
+<template>
+    <!-- 自定义封面 文本编辑框 -->
+    <div class="cover-el el-text" :id="`cover-el-${elementInfo.id}`" :style="isCoverEdit?{
+        top: elementInfo.top + 'px',
+        left: elementInfo.left + 'px',
+        width: elementInfo.width + 'px',
+        height: elementInfo.height + 'px',
+      }:{
+        top: elementInfo.percentageTop*100 + '%',
+        left: elementInfo.percentageLeft*100 + '%',
+        width: elementInfo.percentageWidth*100 + '%',
+        height: elementInfo.percentageHeight*100 + '%',
+        pointerEvents:'none'
+      }" 
+      @mousedown.stop="(e)=>{handleMoveStart(e,'move')}" @contextmenu.stop="showContentMenu">
+        <!-- 裹一层,方便拖拽和移动 -->
+        <div class="layer-editor-wrap">
+            <div style="width:100%;height:100%;" :id="`${elementInfo.id}-editorDom`" @mousedown.stop>
+                <template v-if="isCoverEdit">
+                    <Editor v-model="elementInfo.richContent" :init="setting" ref="editor"></Editor>
+                </template>
+                <template v-else>
+                    <div class="editor-content" :style="{width:elementInfo.width+'px'}"
+                        v-html="elementInfo.richContent"></div>
+                </template>
+            </div>
+        </div>
+        <div class="borderline" v-if="isActive">
+            <div class="left-1 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'LEFT_TOP')}"></div>
+            <div class="left-2 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'LEFT')}"></div>
+            <div class="left-3 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'LEFT_BOTTOM')}"></div>
+            <div class="line-middle-1 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'TOP')}"></div>
+            <div class="line-middle-2 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'BOTTOM')}"></div>
+            <div class="right-1 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'RIGHT_TOP')}"></div>
+            <div class="right-2 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'RIGHT')}"></div>
+            <div class="right-3 resize-handle" @mousedown.stop="(e)=>{handleScaleStart(e,'RIGHT_BOTTOM')}"></div>
+        </div>
+        <!-- 自定义右键菜单 -->
+        <ContextMenu :menu="contextmenus" :menuId="elementInfo.id" @deleteShape="handleDeleteLayer"
+            @copyShape="handleCopyShape" />
+    </div>
+</template>
+
+<script>
+    import {
+        BaseTextShape
+    } from '@/views/ppt_manage/newVersion/utils/config';
+    import elMixin from './elMixin';
+    import Editor from "@tinymce/tinymce-vue";
+    import "tinymce/themes/silver";
+    import "tinymce/plugins/lists"; //列表插件
+    import "tinymce/plugins/quickbars"; //快速栏插件
+    import "tinymce/plugins/fullscreen"; //全屏插件
+    import "tinymce/plugins/paste"; //黏贴插件
+    import "tinymce/icons/default/icons";
+    export default {
+        mixins: [elMixin],
+        props: {
+            elementInfo: {
+                type: Object,
+                default: () => {
+                    return BaseTextShape
+                }
+            },
+            isCoverEdit:{
+                type:Boolean,
+                default:false,
+            },
+            isActive:{
+                type:Boolean,
+                default:false
+            }
+        },
+        components: {
+            Editor
+        },
+        data() {
+            return {
+                setting: {
+                    language: "zh_CN",
+                    language_url: require("../../../utils/zh_CN.js"),
+                    menubar: false,
+                    toolbar: [
+                        "indent outdent alignleft aligncenter alignright alignjustify forecolor",
+                        "bold italic underline strikethrough numlist bullist backcolor",
+                        "fontselect fontsizeselect",
+                    ],
+                    quickbars_selection_toolbar: false,
+                    quickbars_insert_toolbar: false,
+                    plugins: "lists quickbars paste",
+                    height: 350,
+                    inline: true,
+                    selector: `#${this.elementInfo.id}-editorDom`,
+                    paste_as_text: true,
+                    fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 36px 48px',
+                    font_formats: `微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';
+                        楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;
+                        Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;
+                        Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;
+                        Courier New=courier new,courier;Georgia=georgia,palatino;
+                        Helvetica=helvetica;Impact=impact,chicago;
+                        Webdings=webdings;Wingdings=wingdings`,
+                    fixed_toolbar_container: ".cover-text-toolbar", //将toolbar放到指定div上
+                    skin_url: "/static/css",
+                    content_url: "/static/css",
+                    //加placeholder
+                    placeholder: "点击输入文本内容"
+                }
+            };
+        },
+        methods: {
+            
+        },
+    };
+</script>
+<style lang="scss">
+    .cover-el {
+        .layer-editor-wrap {
+            .editor-content {
+                ul {
+                    margin-left: 1em;
+                    list-style-type: disc;
+                }
+
+                ol {
+                    margin-left: 1em;
+                    list-style-type: decimal;
+                }
+            }
+        }
+    }
+</style>
+<style scoped lang="scss">
+    .cover-el {
+        position: absolute;
+        .layer-editor-wrap {
+            z-index: 2;
+            width: 100%;
+            height: 100%;
+            padding: 10px; //空出可以移动的区域
+            box-sizing: border-box;
+            position: relative;
+            >div {
+                cursor: pointer;
+            }
+            .editor-content {
+                /* padding: 10px; */
+                font-size: 16px;
+                position: absolute;
+                transform-origin: 0 0;
+                word-wrap: break-word;
+            }
+            .mce-content-body{
+                padding: 0 !important;
+            }
+            .mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before {
+                left: 0px !important;
+            }
+        }
+        cursor:move;
+        .borderline{
+          z-index: 1;
+          position:absolute;
+          left:0;
+          right:0;
+          top:0;
+          bottom: 0;
+          border: 1px dashed black;
+          &.line{
+            border:none;
+          }
+          .resize-handle{
+            position:absolute;
+            margin: -5px;
+            width:10px;
+            height:10px;
+            border: 1px solid #6324d1;
+            box-sizing: content-box;
+            background-color: #fff;
+            &.left-1,&.left-2,&.left-3{left:0;}
+            &.left-1,&.right-1,&.line-middle-1{top:0;}
+            &.left-2,&.right-2{top:calc(50% + 5px);transform: translateY(-50%);}
+            &.left-3,&.right-3,&.line-middle-2{bottom:0;}
+            &.right-1,&.right-2,&.right-3{right:0;}
+            &.left-1,&.right-3,&.end,&.start{cursor: nwse-resize;}
+            &.left-2,&.right-2{cursor: ew-resize;}
+            &.left-3,&.right-1{cursor: nesw-resize;}
+            &.line-middle-1,&.line-middle-2{left:calc(50% + 5px);transform: translateX(-50%);cursor: ns-resize;}
+          }
+        }
+    }
+</style>

+ 204 - 0
src/views/ppt_manage/newVersion/components/editor/chooseCover/elMixin.js

@@ -0,0 +1,204 @@
+import{getBoundary,caclShapePercentage} from "@/views/ppt_manage/newVersion/utils/untils";
+import ContextMenu from "@/views/ppt_manage/newVersion/components/layer/Element/ShapeContextMenu.vue";
+export default{
+    components:{ContextMenu},
+    data(){
+        return {
+          movePoint:{ //移动时,记录鼠标的位置
+            startX:null,
+            startY:null,
+            moveX:null,
+            moveY:null,
+          },
+          scalePoint:{//缩放时,记录鼠标的位置
+            startX:null,
+            startY:null,
+            moveX:null,
+            moveY:null,
+          },
+          isMouseDown:false,//鼠标是否按下
+          eventType:'move',//当前进行的事件:move:移动元素,resize:缩放元素
+          contextmenus:[
+            {id:1,text:'删除元素',eventName:'deleteShape'},
+            {id:2,text:'复制元素',eventName:'copyShape'}
+          ],//右键菜单的菜单项
+          isContextMenusShow:false,//右键菜单是否显示
+        }
+    },
+    methods:{
+        //开始移动
+        handleMoveStart(event){
+          if(!this.isActive) return
+          //保存移动前的坐标
+          this.isMouseDown = true
+          this.eventType = 'move'
+          this.movePoint.startX = event.clientX
+          this.movePoint.startY = event.clientY
+          document.onmousemove=(e)=>{
+          //如果显示了右键菜单,隐藏掉
+            if(this.isContextMenusShow){
+              this.hideContextMenu()
+            }
+            this.handleMove(e)
+          }
+          document.onmouseup = ()=>{
+            this.isMouseDown = false
+            document.onmousemove = null
+            document.onmouseup = null
+          }
+        },
+        //移动中
+        handleMove(e){
+          if(!this.isMouseDown) return 
+          const {startX,startY} = this.movePoint
+          this.movePoint.moveX = e.clientX-startX
+          this.movePoint.moveY = e.clientY-startY
+          //设置移动的边界点:不能超出editor-area
+          const areaWidth = $(".editor-area").width()||0
+          const areaHeight = areaWidth*0.7
+          let moveInfo = {}
+          moveInfo.left = Math.min(Math.max(this.elementInfo.left+this.movePoint.moveX,0),areaWidth-this.elementInfo.width)
+          moveInfo.top = Math.min(Math.max(this.elementInfo.top+this.movePoint.moveY,0),areaHeight-this.elementInfo.height)
+          this.changeStyle(moveInfo,{})
+          //改变完后,更新movePoint的位置
+          this.movePoint.startX = e.clientX
+          this.movePoint.startY = e.clientY
+        },
+        //开始缩放
+        handleScaleStart(event,direction){
+          this.isMouseDown = true
+          this.eventType = 'resize'
+          this.scalePoint.startX = event.clientX
+          this.scalePoint.startY = event.clientY
+          document.onmousemove=(e)=>{
+            //如果显示了右键菜单,隐藏掉
+            if(this.isContextMenusShow){
+              this.hideContextMenu()
+            }
+            this.handleScale(e,direction)
+          }
+          document.onmouseup = ()=>{
+            this.isMouseDown = false
+            document.onmousemove = null
+            document.onmouseup = null
+          }
+        },
+        //缩放中
+        handleScale(e,direction){
+          if(!this.isMouseDown) return 
+          const {left,top,width,height} = this.elementInfo
+          let scaleInfo = {left:left,top:top,width:width,height:height}
+          //根据direction和moveX,moveY算出元素应该缩放+移动的参数
+          const {startX,startY} = this.scalePoint
+          this.scalePoint.moveX = e.clientX-startX
+          this.scalePoint.moveY = e.clientY-startY
+          //计算拖拽后位置和宽高
+          const areaWidth = $(".editor-area").width()||0
+          const areaHeight = areaWidth*0.7
+          //常规的八个点
+          //左上角:拖拽会改变left,top,width,height
+          if(direction==='LEFT_TOP'){
+            scaleInfo.left = getBoundary(Math.max(left + this.scalePoint.moveX,0),0,(areaWidth - (scaleInfo.width+5)))
+            scaleInfo.top = getBoundary(Math.max(top + this.scalePoint.moveY,0),0,(areaHeight-(scaleInfo.height+5)))
+            if(scaleInfo.left===0){
+             scaleInfo.width = getBoundary(width - this.scalePoint.moveX,25,width) 
+            }else{
+              scaleInfo.width = getBoundary(width - this.scalePoint.moveX,25,areaWidth)
+            }
+            if(scaleInfo.top===0){
+              scaleInfo.height = getBoundary(height - this.scalePoint.moveY,25,height)
+            }else{
+              scaleInfo.height = getBoundary(height - this.scalePoint.moveY,25,areaHeight)
+            }
+          }
+          //左中:拖拽会改变left,width
+          else if (direction==="LEFT"){
+            scaleInfo.width = getBoundary(width - this.scalePoint.moveX,25,areaWidth)
+            scaleInfo.left = getBoundary(Math.max(left + this.scalePoint.moveX,0),0,(areaWidth - (scaleInfo.width+5)))
+            
+          }
+          //左下:拖拽会改变left,width,height
+          else if(direction==="LEFT_BOTTOM"){
+            scaleInfo.width = getBoundary(width - this.scalePoint.moveX,25,areaWidth)
+            scaleInfo.height = getBoundary(height + this.scalePoint.moveY,25,areaHeight)
+            scaleInfo.left = getBoundary(Math.max(left + this.scalePoint.moveX,0),0,(areaWidth - (scaleInfo.width+5)))
+          }
+          //右上:拖拽会改变top,width,height
+          else if(direction==="RIGHT_TOP"){
+            scaleInfo.width = getBoundary(width + this.scalePoint.moveX,25,areaWidth-left)
+            scaleInfo.height = getBoundary(height - this.scalePoint.moveY,25,areaHeight-top)
+            scaleInfo.top = Math.max(top + this.scalePoint.moveY,0)
+          }
+          //右中:拖拽会改变width
+          else if(direction==="RIGHT"){
+            scaleInfo.width = getBoundary(width + this.scalePoint.moveX,25,areaWidth-left)
+          }
+          //右下:拖拽会改变width,height
+          else if(direction==="RIGHT_BOTTOM"){
+            scaleInfo.width = getBoundary(width + this.scalePoint.moveX,25,areaWidth-left)
+            scaleInfo.height = getBoundary(height + this.scalePoint.moveY,25,areaHeight-top)
+          }
+          //中上:拖拽会改变top,height
+          else if(direction==="TOP"){
+            scaleInfo.height = getBoundary(height - this.scalePoint.moveY,25,areaHeight)
+            scaleInfo.top = Math.max(top + this.scalePoint.moveY,0)
+          }
+          //中下:拖拽会改变height
+          else if(direction==="BOTTOM"){
+            scaleInfo.height = getBoundary(height + this.scalePoint.moveY,25,areaHeight)
+          }
+          this.changeStyle({},scaleInfo)
+          this.scalePoint.startX = e.clientX
+          this.scalePoint.startY = e.clientY
+        },
+        changeStyle(moveInfo,scaleInfo){
+          //const {moveX,moveY} = this.movePoint
+          if(this.eventType==='resize'){
+            const {left,top,width,height} = scaleInfo
+            this.elementInfo.left = left
+            this.elementInfo.top = top
+            this.elementInfo.width = width
+            this.elementInfo.height = height
+          }else if(this.eventType==='move'){
+            const {left,top} = moveInfo
+            this.elementInfo.left = left
+            this.elementInfo.top = top
+          }
+          //更新realWidth,realHeight
+          this.elementInfo.realWidth = this.elementInfo.width
+          this.elementInfo.realHeight = this.elementInfo.height
+          //更新percentage单位
+          const width = $('.editor-area').width(),height = width*0.7
+          const percentageShape = caclShapePercentage({layerWidth:width,layerHeight:height},this.elementInfo)
+          this.elementInfo.percentageLeft = percentageShape.percentageLeft
+          this.elementInfo.percentageTop = percentageShape.percentageTop
+          this.elementInfo.percentageWidth = percentageShape.percentageWidth
+          this.elementInfo.percentageHeight = percentageShape.percentageHeight
+        },
+        //显示右键菜单
+        showContentMenu(e){
+          e.preventDefault();
+          if(!this.isCoverEdit) {
+              this.$emit('chooseThis')
+          }
+          $(`#menu-${this.elementInfo.id}`).css({ "left": document.body.scrollLeft + e.clientX, "top": 
+           document.body.scrollTop + e.clientY}).show();
+           this.isContextMenusShow = true
+        },
+        //隐藏右键菜单
+        hideContextMenu(){
+          $(`#menu-${this.elementInfo.id}`).hide();
+          this.isContextMenuShow = false
+        },
+        //删除当前元素
+        handleDeleteLayer(){
+          this.$emit('deleteEl',this.elementInfo)
+          this.hideContextMenu()
+        },
+        //复制当前元素
+        handleCopyShape(){
+            this.$emit('copyEl',this.elementInfo)
+            this.hideContextMenu()
+        }
+      }
+}

+ 44 - 3
src/views/ppt_manage/newVersion/components/formatEl/ChartEl.vue

@@ -5,6 +5,7 @@
   <div
     class="chart-wrap"
     :id="`${$parent.isPreview?'preview_':''}chart_${index}_${position}`"
+    :style="(chartSourcesFrom&&chartSourcesFrom.isShow || chartInstructions&&chartInstructions.isShow) ? 'margin-bottom:20px' : ''"
   >
     <img :id="`${$parent.isPreview?'preview_':''}img_${index}_${position}`" />
   </div>
@@ -39,6 +40,30 @@
         v-if="isBtnShow"
       ></div>
   </div>
+
+  <!-- 底部来源,图表说明 -->
+  <div class="chart-bottom-insruction-info"
+  v-if="((chartSourcesFrom&&chartSourcesFrom.isShow) || (chartInstructions&&chartInstructions.isShow)) &&!this.$parent.isHintShow(position)">
+
+    <div class="chart-source text_oneLine" v-if="chartSourcesFrom&&chartSourcesFrom.isShow">
+        <span
+          :style="`
+          color: ${ chartSourcesFrom.color };
+          fontSize: ${ chartSourcesFrom.fontSize }px;
+        `"
+        >来源:{{ chartSourcesFrom.text}}</span>
+    </div>
+    <!-- 图表说明 -->
+    <div 
+      class="chart-instruction text_oneLine"
+      v-if="chartInstructions&&chartInstructions.isShow"
+      v-text="chartInstructions.text"
+      :style="`
+        color: ${chartInstructions.color};
+        fontSize: ${ chartInstructions.fontSize }px
+      `"
+    ></div>
+  </div>
  
 </div>
   
@@ -57,6 +82,8 @@ export default {
     chartInfoMap(newVal){
       if(this.item&&newVal[this.item.chartId]){
         this.chartTitle = newVal[this.item.chartId].chartTitle||''
+        this.chartSourcesFrom = this.chartInfoMap[this.item.chartId].SourcesFrom ? JSON.parse(this.chartInfoMap[this.item.chartId].SourcesFrom) : null
+        this.chartInstructions = this.chartInfoMap[this.item.chartId].Instructions ? JSON.parse(this.chartInfoMap[this.item.chartId].Instructions) : null
       }
     }
   },
@@ -67,11 +94,14 @@ export default {
   },
   data() {
     return {
-      chartTitle:''
+      chartTitle:'',
+      chartSourcesFrom:null,
+      chartInstructions: null
     };
   },
   methods:{
     copyChartName(position){
+        console.log(this.chartInfoMap[this.item.chartId])
       this.$parent.copyChartName(position)
     },
     addChart(position){
@@ -79,8 +109,11 @@ export default {
     }
   },
   mounted(){
-    if(this.item&&this.chartInfoMap[this.item.chartId])
-    this.chartTitle = this.chartInfoMap[this.item.chartId].chartTitle||''
+    if(this.item&&this.chartInfoMap[this.item.chartId]) {
+      this.chartTitle = this.chartInfoMap[this.item.chartId].chartTitle||''
+      this.chartSourcesFrom = this.chartInfoMap[this.item.chartId].SourcesFrom ? JSON.parse(this.chartInfoMap[this.item.chartId].SourcesFrom) : null
+      this.chartInstructions = this.chartInfoMap[this.item.chartId].Instructions ? JSON.parse(this.chartInfoMap[this.item.chartId].Instructions) : null
+    }
   }
 };
 </script>
@@ -100,4 +133,12 @@ export default {
     margin-left: auto;
   }
 }
+.chart-bottom-insruction-info{
+  width: 90%;
+  position: absolute;
+  left: 5%;
+  bottom: 20px;
+  align-items: center;
+  justify-content: space-between;
+}
 </style>

+ 36 - 22
src/views/ppt_manage/newVersion/pptEditor.vue

@@ -2,7 +2,7 @@
   <div class="page-wrap">
     <div class="index-wrap ppt-page-wrap flex-column">
         <div class="cover-wrap" @click="openChooseCover">
-            <div class="cover" :style="'background: no-repeat center/cover url('+firstPage.BackgroundImg+');background-color:#F2F6FA;background-size:100% 100%;'">
+            <div class="cover" :style="`background: no-repeat center/cover url(${firstPage.BackgroundImg||''});background-color:#F2F6FA;background-size:100% 100%;`">
                 <img src="~@/assets/img/ppt_m/add_first.png" />
             </div>
             <p class="hint-text">选择封面页</p>
@@ -114,8 +114,8 @@
                 <el-button type="text" @click="handleChangeEditModal"><i class="el-icon-sort" style="transform: rotate(90deg);margin-right:5px;"></i>{{isEditLayer?'ppt编辑':'图层编辑'}}</el-button>
             </div>
             <div class="richtext-tool"></div>
-            <div class="addppt-right-box" v-if="!isEditLayer">
-
+            <!-- 防止el-tabs未渲染时触发scrollToActiveTab 报错,v-if改为v-show-->
+            <div class="addppt-right-box" v-show="!isEditLayer">
               <el-tabs v-model="tabsactive">
                 <el-tab-pane :label="tab" :name="tab" v-for="tab in panelTabs" :key="tab"></el-tab-pane>
               </el-tabs>
@@ -137,7 +137,7 @@
                 <div class="chart-list" v-infinite-scroll="loadReportHandle" :infinite-scroll-immediate="false" ref="chartListRef">
                     <template v-if="chartList.length">
                     <div v-for="(item, index) in chartList" :key="index" @click="chooseChart(item,'chart')" class="chart-item" :style="item.Disabled && 'cursor: not-allowed;'">
-                        <p class="chart_tit">{{ item.ChartName }}</p>
+                        <p class="chart_tit" style="word-break: break-all;">{{ item.ChartName }}</p>
                         <img :src="item.ChartImage" ref="insert_img" style="-webkit-user-drag:none;"/>
                     </div>
                     </template>
@@ -153,7 +153,6 @@
                     <div v-for="(item,index) in sandTableList" :key="index" class="sandTable-item" >
                       <p class="chart_tit">{{item.Name}}</p>
                       <img :src="item.PicUrl" style="width:100%;-webkit-user-drag:none;"  @click="chooseChart(item,'sandImage')"/>
-                      <!-- <p class="source-identification">来源:弘则研究</p> -->
                     </div>
                     <div v-loading = "sandTableLoading" class="loaded-text">{{loadedText}}</div>
                   </template>
@@ -182,7 +181,7 @@
               </div>
             </div>
             <!-- 图层编辑 -->
-            <div class="layer-edit-box" v-else>
+            <div class="layer-edit-box" v-show="isEditLayer">
               	<el-collapse v-model="activeNames" class="tool-list">
                   <el-collapse-item title="图层元素" name="el">
                     <div class="el-wrap">
@@ -225,12 +224,21 @@
     </div>
 
     <!-- 选择封面弹窗 -->
-    <choose-cover  v-if="isShowChooseCover"
+    <!-- <choose-cover  v-if="isShowChooseCover"
         :firstPage="firstPage"
         :pptCoverList="pptCoverList"
         :PptId="pptId"
         @close="closeChooseCover"
         @save="saveCover"
+    /> -->
+    <ChooseCoverNew 
+        :isShowChooseCover="isShowChooseCover"
+        :firstPage="firstPage"
+        :pptCoverList="pptCoverList"
+        :PptId="pptId"
+        :CoverContent="CoverContent"
+        @saveCover="saveCover2"
+        @close="isShowChooseCover=false"
     />
     <!-- 批量删除弹窗 -->
     <delete-page-dialog 
@@ -294,16 +302,18 @@ import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyD
 import InsertCharts from './components/editor/InsertCharts.vue';
 import ContextMenu from './components/ContextMenu.vue';
 import InsertSemantics from './components/editor/InsertSemantics.vue';
+import ChooseCoverNew from './components/editor/ChooseCoverNew.vue';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
           layerMixins,//图层操作逻辑
           pptEditorMixins,//编辑页共同逻辑
           ],
-  components: { 
-        IndexItem, ChooseCover, AddFormat,ShapePreview,
-    LayerEditTool,DeletePageDialog,ChangeFormatDialog,InsertPageDialog,addMyClassifyDia,InsertCharts,ContextMenu,InsertSemantics
-  },
+  components: {
+    IndexItem, ChooseCover, AddFormat, ShapePreview,
+    LayerEditTool, DeletePageDialog, ChangeFormatDialog, InsertPageDialog, addMyClassifyDia, InsertCharts, ContextMenu, InsertSemantics,
+    ChooseCoverNew
+},
   data() {
     return {
         pageList:[],//ppt数组
@@ -314,11 +324,11 @@ export default {
         chooseModalId:1,//上一次选择的版式Id
         firstPage:{
             Title:'',
-            ReportType:'',
+            ReportType:'',//ETA1.4.9不用了
             BackgroundImg:'',
-            PptDate:(new Date().getFullYear())+'年'+(new Date().getMonth()+1)+'月',
-            BackIndex:0,
-            TemplateType:1
+            PptDate:(new Date().getFullYear())+'年'+(new Date().getMonth()+1)+'月',//ETA1.4.9不用了
+            BackIndex:0,//ETA基本配置上线后不用了
+            TemplateType:1,//ETA基本配置上线后不用了
         },//封面信息
         key_word:'',//搜索图表关键字
         chartList:[],//图表数组
@@ -450,6 +460,7 @@ export default {
           this.firstPage.BackIndex = FirstPage.TemplateType-1
           this.currentItem = this.pageList[0]
           this.ReportId=ReportId
+          this.CoverContent = this.result.CoverContent
           //开启自动保存
           this.autoSave()
         }else{
@@ -997,7 +1008,8 @@ export default {
       pptInterface.addppt({
         FirstPage:FirstPage,
         Content:Content,
-        GroupId:this.catalogId
+        GroupId:this.catalogId,
+        CoverContent:this.CoverContent
       }).then(res=>{
         if(res.Ret===200){
           this.$message.success('新增成功')
@@ -1016,7 +1028,8 @@ export default {
       pptInterface.editppt({
         PptId:parseInt(ppt_id),
         FirstPage:FirstPage,
-        Content:Content
+        Content:Content,
+        CoverContent:this.CoverContent
       }).then(res=>{
         if(res.Ret===200){
           if(type==='save'){
@@ -1054,7 +1067,8 @@ export default {
         pptInterface.saveLog({
           PptId:parseInt(ppt_id),
           FirstPage:FirstPage,
-          Content:Content
+          Content:Content,
+          CoverContent:this.CoverContent
         }).then((res)=>{})
       },10000)
     },
@@ -1062,9 +1076,9 @@ export default {
     save_checkPPT(){
       if(!this.firstPage.Title){
         return {result:false,hintText:'请输入封面标题!'}
-      }else if(!this.firstPage.ReportType){
+      }/* else if(!this.firstPage.ReportType){
         return {result:false,hintText:'请输入ppt类型!'}
-      }
+      } */
       if(this.pageList.length===0){
         return {result:false,hintText:'请至少添加一张PPT!'}
       }
@@ -1075,9 +1089,9 @@ export default {
       //检验首页
       if(!this.firstPage.Title){
         return {result:false,hintText:'请输入封面标题!'}
-      }else if(!this.firstPage.ReportType){
+      }/* else if(!this.firstPage.ReportType){
         return {result:false,hintText:'请输入ppt类型!'}
-      }
+      } */
       if(this.pageList.length===0){
         return {result:false,hintText:'请至少添加一张PPT!'}
       }

+ 28 - 13
src/views/ppt_manage/newVersion/pptEnEditor.vue

@@ -2,7 +2,7 @@
   <div class="page-wrap">
     <div class="index-wrap ppt-page-wrap flex-column">
         <div class="cover-wrap" @click="openChooseCover">
-            <div class="cover" :style="'background: no-repeat center/cover url('+firstPage.BackgroundImg+');background-color:#F2F6FA;background-size:100% 100%;'">
+            <div class="cover" :style="`background: no-repeat center/cover url(${firstPage.BackgroundImg||''});background-color:#F2F6FA;background-size:100% 100%;`">
                 <img src="~@/assets/img/ppt_m/add_first.png" />
             </div>
             <p class="hint-text">选择封面页</p>
@@ -111,7 +111,7 @@
                 <el-button type="text" @click="handleChangeEditModal"><i class="el-icon-sort" style="transform: rotate(90deg);margin-right:5px;"></i>{{isEditLayer?'ppt编辑':'图层编辑'}}</el-button>
             </div>
             <div class="richtext-tool"></div>
-            <div class="addppt-right-box" v-if="!isEditLayer">
+            <div class="addppt-right-box" v-show="!isEditLayer">
 
               <el-tabs v-model="tabsactive">
                 <el-tab-pane :label="tab" :name="tab" v-for="tab in panelTabs" :key="tab"></el-tab-pane>
@@ -138,7 +138,7 @@
                           <span v-if="item.IsEnChart">En</span>
                           <i class="el-icon-edit" v-else style="font-size:15px"/>
                         </div>
-                        <p class="chart_tit">{{ chart_source===1 ? (item.ChartNameEn||item.ChartName) : item.ChartName }}</p>
+                        <p class="chart_tit" style="word-break: break-all;">{{ chart_source===1 ? (item.ChartNameEn||item.ChartName) : item.ChartName }}</p>
                         <img :src="item.ChartImage" ref="insert_img" />
                     </div>
                     </template>
@@ -186,7 +186,7 @@
               </div>
             </div>
             <!-- 图层编辑 -->
-            <div class="layer-edit-box" v-else>
+            <div class="layer-edit-box" v-show="isEditLayer">
               	<el-collapse v-model="activeNames" class="tool-list">
                   <el-collapse-item title="图层元素" name="el">
                     <div class="el-wrap">
@@ -225,12 +225,21 @@
     </div>
 
     <!-- 选择封面弹窗 -->
-    <choose-cover  v-if="isShowChooseCover"
+    <!-- <choose-cover  v-if="isShowChooseCover"
         :firstPage="firstPage"
         :pptCoverList="pptCoverList"
         :PptId="pptId"
         @close="closeChooseCover"
         @save="saveCover"
+    /> -->
+    <ChooseCoverNew 
+        :isShowChooseCover="isShowChooseCover"
+        :firstPage="firstPage"
+        :pptCoverList="pptCoverList"
+        :PptId="pptId"
+        :CoverContent="CoverContent"
+        @saveCover="saveCover2"
+        @close="isShowChooseCover=false"
     />
     <!-- 批量删除弹窗 -->
     <delete-page-dialog 
@@ -306,6 +315,7 @@ import InsertCharts from './components/editor/InsertCharts.vue';
 import setEnNameDia from '@/views/dataEntry_manage/components/setEnNameDia.vue';
 import ContextMenu from './components/ContextMenu.vue';
 import InsertSemantics from './components/editor/InsertSemantics.vue';
+import ChooseCoverNew from './components/editor/ChooseCoverNew.vue';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
@@ -325,7 +335,8 @@ export default {
     addMyClassifyDia,
     InsertCharts,
     ContextMenu,
-    InsertSemantics
+    InsertSemantics,
+    ChooseCoverNew
   },
   data() {
     return {
@@ -471,6 +482,7 @@ export default {
           this.firstPage.BackIndex = FirstPage.TemplateType-1
           this.currentItem = this.pageList[0]
           this.ReportId=ReportId
+          this.CoverContent = this.result.CoverContent
           //开启自动保存
           this.autoSave()
         }else{
@@ -984,7 +996,8 @@ export default {
       pptEnInterface.addppt({
         FirstPage:FirstPage,
         Content:Content,
-        GroupId:this.catalogId
+        GroupId:this.catalogId,
+        CoverContent:this.CoverContent
       }).then(res=>{
         if(res.Ret===200){
           this.$message.success('新增成功')
@@ -1001,7 +1014,8 @@ export default {
       pptEnInterface.editppt({
         PptId:parseInt(ppt_id),
         FirstPage:FirstPage,
-        Content:Content
+        Content:Content,
+        CoverContent:this.CoverContent
       }).then(res=>{
         if(res.Ret===200){
           if(type==='save'){
@@ -1032,7 +1046,8 @@ export default {
         pptEnInterface.saveLog({
           PptId:parseInt(ppt_id),
           FirstPage:FirstPage,
-          Content:Content
+          Content:Content,
+          CoverContent:this.CoverContent
         }).then((res)=>{})
       },10000)
     },
@@ -1040,9 +1055,9 @@ export default {
     save_checkPPT(){
       if(!this.firstPage.Title){
         return {result:false,hintText:'请输入封面标题!'}
-      }else if(!this.firstPage.ReportType){
+      }/* else if(!this.firstPage.ReportType){
         return {result:false,hintText:'请输入ppt类型!'}
-      }
+      } */
       if(this.pageList.length===0){
         return {result:false,hintText:'请至少添加一张PPT!'}
       }
@@ -1053,9 +1068,9 @@ export default {
       //检验首页
       if(!this.firstPage.Title){
         return {result:false,hintText:'请输入封面标题!'}
-      }else if(!this.firstPage.ReportType){
+      }/* else if(!this.firstPage.ReportType){
         return {result:false,hintText:'请输入ppt类型!'}
-      }
+      } */
       if(this.pageList.length===0){
         return {result:false,hintText:'请至少添加一张PPT!'}
       }

+ 6 - 3
src/views/ppt_manage/newVersion/pptEnPresent.vue

@@ -40,7 +40,8 @@
           <div class="ppt-wrap" @wheel.stop="normalMouseWheel">
             <!-- 封面 -->
             <div class="ppt-item" id="cover" v-if="currentIndex===0" style="background-size:20%;">
-              <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover>
+              <!-- <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover> -->
+              <CustomCover :pageInfo="coverInfo.page" :CoverContent="pptCoverContent" v-show="coverInfo.page"></CustomCover>
             </div>
             <!-- 封底 -->
             <div class="ppt-item" id="back" v-else-if="currentIndex===pageList.length+1" style="background-size:20%;">
@@ -98,7 +99,8 @@
           <div class="ppt-wrap">
             <!-- 封面 -->
             <div class="ppt-item" id="cover" v-if="currentIndex===0" style="background-size:20%;">
-              <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover>
+              <!-- <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover> -->
+              <CustomCover :pageInfo="coverInfo.page" :CoverContent="pptCoverContent" v-show="coverInfo.page"></CustomCover>
             </div>
             <!-- 封底 -->
             <div class="ppt-item" id="back" v-else-if="currentIndex===pageList.length+1" style="background-size:20%;">
@@ -166,6 +168,7 @@
 
 <script>
 import Cover from './components/CoverEn.vue';
+import CustomCover from './components/CustomCover.vue';
 import IndexItem from './components/IndexItem.vue';
 import {countComponentName,setFullscreen,isFullscreen,exitFullscreen,calcScale,countStrSize} from './utils/untils';
 import {pptCoverEn} from './utils/config'
@@ -181,7 +184,7 @@ const reloadPPTWid = ()=>{
   window.dispatchEvent(resizeEvent)
 }
 export default {
-  components: { IndexItem, Cover ,ContextMenu, DrawingBoardTool},
+  components: { IndexItem, Cover ,ContextMenu, DrawingBoardTool,CustomCover},
   mixins:[pptmixin,mixins],
   data() {
     return {

+ 25 - 11
src/views/ppt_manage/newVersion/pptEnPublish.vue

@@ -20,7 +20,8 @@
         <div class="ppt-wrap flex-center">
           <!-- 封面 -->
           <div class="ppt-item" id="cover" style="background-size:20%;">
-            <Cover :pageInfo="coverInfo.page"></Cover>
+            <!-- <Cover :pageInfo="coverInfo.page"></Cover> -->
+            <CustomCover :pageInfo="coverInfo.page" :CoverContent="pptCoverContent" v-show="coverInfo.page"></CustomCover>
           </div>
           <!-- 内容 -->
           <div class="ppt-item" v-for="(item,index) in pageList" :key="item.id">
@@ -47,8 +48,9 @@
 
 <script>
 import Cover from './components/CoverEn.vue';
+import CustomCover from './components/CustomCover.vue';
 import TransReport from './components/catalog/transReport.vue';
-import {countComponentName,pptInit,pptConfigInit,toTextProps,toJson,svg2Base64,getImgRealSize,calcScale,getShapeOptions,createRandomCode,getTableData} from './utils/untils';
+import {countComponentName,pptConfigInit,toTextProps,toJson,svg2Base64,getImgRealSize,calcScale,getShapeOptions,createRandomCode,getTableData,getChartInfo} from './utils/untils';
 import {marginTop,modelConfig,pptSlideMaster,pptSlideMasterEn,pptCoverEn} from './utils/config';
 import pptmixin from '../mixins/pptMixins';
 import mixins from '../mixins/mixins';
@@ -65,7 +67,7 @@ import {uploadFileDirect} from "@/utils/common.js"
 HightchartsExport(Highcharts)
 HighchartszhCN(Highcharts)
 export default {
-  components: {Cover,TransReport},
+  components: {Cover,TransReport,CustomCover},
   mixins:[pptmixin,mixins],
   data() {
     return {
@@ -147,6 +149,19 @@ export default {
         for(let i=0;i<this.pageList.length;i++){
           await this.initPageElements(this.pageList[i],'show')
         }
+
+        //获取已加载图表的信息
+        let chartInfoMap = {}
+        for(let i=0;i<this.pageList.length;i++){
+          this.pageList[i].elements.forEach(item=>{
+            if(item.type==='chart'){
+              let temp = getChartInfo(this.optionMap[item.chartId])
+              chartInfoMap[item.chartId] = temp
+            }
+          })
+        }
+        this.$store.commit('SET_CHART_INFO_MAP',chartInfoMap)
+
         this.dataLoading.close();
         $('.ppt-item').css('background-image',`url(${this.pptBgImage})`);
       }
@@ -214,7 +229,6 @@ export default {
     async pageToPptx(){
       //开始计时
       const start = Date.now()
-      //let pptx = pptInit(new pptxgen(),this.LayoutType,'en');
       const SlideMaster = _.cloneDeep(pptSlideMasterEn) 
       SlideMaster.objects[1] = {image: {x:0,y:0,w:10,h:7,path:this.pptBgImage}}
       let pptx = pptConfigInit(new pptxgen(),this.LayoutType,'en',SlideMaster,this.pptBgImage)
@@ -223,8 +237,6 @@ export default {
       const length = this.pageList.length;
       for (let i = 0; i < length; i++) {
         let slide = pptx.addSlide({ masterName: pptSlideMaster.title });
-        //添加背景图片
-        //slide.background = { path: "/static/pptnextimg.png" };
         slide.addText(this.pageList[i].title, {
           placeholder:"slideTitle",
           x:'8%',
@@ -294,6 +306,9 @@ export default {
                 size: { type: "contain" },
               });
             }
+
+            //追加生成图表底部文字
+            this.transChartBottomInfo(slide,{x,y,width,height},this.optionMap[this.pageList[i].elements[j].chartId])
             
           }else if (textData){
             slide.addText(textData,{
@@ -306,7 +321,6 @@ export default {
               valign:'top'
             })
           }else if(imgData2){
-            //console.log('src',imgData2)
             const realSize = getImgRealSize(imgData2Obj)
             const percentWidth = Number(width.substring(0,width.length-1))
             const percentHeight = Number(height.substring(0,height.length-1))
@@ -339,7 +353,6 @@ export default {
           if(['shape','line'].includes(layers[j].type)){
             const scale = calcScale({w:906,h:906*0.7},{w:$('.ppt-item').width(),h:$('.ppt-item').width()*this.coefficient})
             let options = getShapeOptions(layers[j],position,scale)
-            //console.log('options',options)
             if(layers[j].shapeType==='Circle'){ //circle的points太复杂,直接用插件预设的
                 slide.addShape('ellipse', options);
             }else{
@@ -377,7 +390,6 @@ export default {
       }
       //为了把封面放到第一页,操作pptx.slides达不成想要的效果,于是弄了个pptx2
       //将封面放在最后生成是因为htmlToCanvans占用太多内存会导致页面假死
-      //let pptx2 = pptInit(new pptxgen(),this.LayoutType,'en');
       let pptx2 = pptConfigInit(new pptxgen(),this.LayoutType,'en',SlideMaster,this.pptBgImage)
       //添加封面
       let cover = pptx2.addSlide()
@@ -393,7 +405,7 @@ export default {
         size: { type: "contain" },
       })
       //生成的ppt需要可以在封面页更改标题和类型,所以封面信息手动写入
-      const coverInfo = [
+      /* const coverInfo = [
         //{text:'—————————————————————————————————\n',options:{fontSize:16*0.75,breakLine:true}},
         {text:this.coverInfo.page.Title,options:{fontSize:28*0.75,breakLine:true}},
         {text:`\n${this.pptCoverCompenyName||'ETA'}`,
@@ -411,7 +423,9 @@ export default {
         color:(this.pptCoverTextColor||'#ffffff').slice(1),
         align:'center',
         fontFace:'SimHei'
-      })
+      }) */
+      //自定义封面页的内容
+      cover = this.setPPTCover(cover,this.pptCoverContent,this.coverInfo.page.Title)
       //遍历pptx.slides,重新给每一项的部分属性赋值,再推入pptx2.slides中
       //第一页不需要,因为是空白的
       for(let i=1;i<pptx.slides.length;i++){

+ 6 - 3
src/views/ppt_manage/newVersion/pptPresent.vue

@@ -40,7 +40,8 @@
           <div class="ppt-wrap" @wheel.stop="normalMouseWheel">
             <!-- 封面 -->
             <div class="ppt-item" id="cover" v-if="currentIndex===0" style="background-size:20%;">
-              <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover>
+              <!-- <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover> -->
+              <CustomCover :pageInfo="coverInfo.page" :CoverContent="pptCoverContent" v-show="coverInfo.page"></CustomCover>
             </div>
             <!-- 封底 -->
             <div class="ppt-item" id="back" v-else-if="currentIndex===pageList.length+1" style="background-size:20%;">
@@ -98,7 +99,8 @@
           <div class="ppt-wrap">
             <!-- 封面 -->
             <div class="ppt-item" id="cover" v-if="currentIndex===0" style="background-size:20%;">
-              <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover>
+              <!-- <Cover :pageInfo="coverInfo.page" v-show="coverInfo.page"></Cover> -->
+              <CustomCover :pageInfo="coverInfo.page" :CoverContent="pptCoverContent" v-show="coverInfo.page"></CustomCover>
             </div>
             <!-- 封底 -->
             <div class="ppt-item" id="back" v-else-if="currentIndex===pageList.length+1" style="background-size:20%;">
@@ -166,6 +168,7 @@
 
 <script>
 import Cover from './components/Cover.vue';
+import CustomCover from './components/CustomCover.vue';
 import IndexItem from './components/IndexItem.vue';
 import {countComponentName,setFullscreen,isFullscreen,exitFullscreen,calcScale,countStrSize} from './utils/untils';
 import pptmixin from '../mixins/pptMixins';
@@ -180,7 +183,7 @@ const reloadPPTWid = ()=>{
   window.dispatchEvent(resizeEvent)
 }
 export default {
-  components: { IndexItem, Cover ,ContextMenu, DrawingBoardTool},
+  components: { IndexItem, Cover ,ContextMenu, DrawingBoardTool, CustomCover},
   mixins:[pptmixin,mixins],
   data() {
     return {

+ 30 - 84
src/views/ppt_manage/newVersion/pptPublish.vue

@@ -21,7 +21,8 @@
         <div class="ppt-wrap flex-center">
           <!-- 封面 -->
           <div class="ppt-item" id="cover" style="background-size:20%;">
-            <Cover :pageInfo="coverInfo.page"></Cover>
+            <!-- <Cover :pageInfo="coverInfo.page"></Cover> -->
+            <CustomCover :pageInfo="coverInfo.page" :CoverContent="pptCoverContent" v-show="coverInfo.page"></CustomCover>
           </div>
           <!-- 内容 -->
           <div class="ppt-item" v-for="(item,index) in pageList" :key="item.id">
@@ -43,57 +44,6 @@
           </div>
         </div>
       </template>
-      <!-- 虚拟列表 -->
-      <template v-else>
-        <div class="list-wrap" id="scroller" @scroll="handleScroll">
-          <div class="ppt-wrap flex-center" id="scroller-inner">
-            <!-- <div class="ppt-item" v-for="(item,index) in loadList" :key="item.id" :data-set="item.title">
-              <span style="font-size:24px;">第{{index}}项,title{{item.title}}</span>
-            </div> -->
-            <template v-for="(item) in loadList">
-              <template v-if="item.index">
-                <!-- 是封面 -->
-                <div class="ppt-item" id="cover" v-if="coverInfo.page" :key="item.id" :data-set="item.title">
-                  <Cover :pageInfo="coverInfo.page"></Cover>
-                </div>
-              </template>
-              <template v-else-if="item.idName==='back'">
-                <!-- 是封底 -->
-                <div class="ppt-item" id="back" :key="item.id" :data-set="item.title">
-                  <img src="~@/assets/img/pptlastimg.png" class="pptbg" />
-                </div>
-              </template>
-              <template v-else>
-                <!-- 是内容 -->
-                <div class="ppt-item" :key="item.id" :data-set="item.title">
-                  <div class="title-wrap">
-                    {{item.title}} 
-                  </div>
-                  <component
-                    :is="getComponentName(item.modelId)"
-                    :ref="`pptPage_${item.sourceIndex}`"
-                    :pageIndex="item.sourceIndex"
-                    :pageItem="item" 
-                    type="show"
-                    >
-                  </component>
-                </div>
-              </template>
-          </template>
-          </div>
-        </div>
-      </template>
-      <!-- 封面封底 -->
-      <template v-if="isPublish&&!loadingAll">
-        <div class="fixed-wrap">
-          <div class="ppt-item" id="changecover">
-              <Cover :pageInfo="coverInfo.page"></Cover>
-          </div>
-          <div class="ppt-item" id="changeback" style="overflow:hidden;">
-              <img src="~@/assets/img/pptlastimg.png" class="pptbg" style="width:100%;"/>
-            </div>
-          </div>
-      </template>
       <!-- <trans-report
         v-if="coverInfo.page"
         :transReportShow="transReportShow"
@@ -106,9 +56,10 @@
 
 <script>
 import Cover from './components/Cover.vue';
+import CustomCover from './components/CustomCover.vue';
 import TransReport from './components/catalog/transReport.vue';
 //import {pageList} from './utils/mock';
-import {countComponentName,pptInit,pptConfigInit,toTextProps,toJson,svg2Base64,getImgRealSize,calcScale,getShapeOptions,createRandomCode,getTableData} from './utils/untils';
+import {countComponentName,pptConfigInit,toTextProps,toJson,svg2Base64,getImgRealSize,calcScale,getShapeOptions,createRandomCode,getTableData,getChartInfo,pptInit,rgbaToHex } from './utils/untils';
 import {marginTop,modelConfig,pptSlideMaster} from './utils/config';
 import pptmixin from '../mixins/pptMixins';
 import mixins from '../mixins/mixins';
@@ -125,7 +76,7 @@ import {uploadFileDirect} from "@/utils/common.js"
 HightchartsExport(Highcharts)
 HighchartszhCN(Highcharts)
 export default {
-  components: {Cover,TransReport},
+  components: {Cover,TransReport,CustomCover},
   mixins:[pptmixin,mixins,virtualScroll],
   data() {
     return {
@@ -184,12 +135,8 @@ export default {
       });
       this.isPublish = true
       if(this.loadingAll){
-        await this.pageToPptx()       
-      }else{
-        //将滚动条置顶
-        this.scroller.scrollTop = 0
-        await this.pageToPptx()
-      }  
+        await this.pageToPptx() 
+      }
       this.isPublish = false
     },
     //计算ppt的版式名称
@@ -210,6 +157,19 @@ export default {
         for(let i=0;i<this.pageList.length;i++){
           await this.initPageElements(this.pageList[i],'show')
         }
+
+         //获取已加载图表的信息
+        let chartInfoMap = {}
+        for(let i=0;i<this.pageList.length;i++){
+          this.pageList[i].elements.forEach(item=>{
+            if(item.type==='chart'){
+              let temp = getChartInfo(this.optionMap[item.chartId])
+              chartInfoMap[item.chartId] = temp
+            }
+          })
+        }
+        this.$store.commit('SET_CHART_INFO_MAP',chartInfoMap)
+
         this.dataLoading.close();
         $('.ppt-item').css('background-image',`url(${this.pptBgImage})`);
       }else{
@@ -281,7 +241,6 @@ export default {
     async pageToPptx(){
       //开始计时
       const start = Date.now()
-      //let pptx = pptInit(new pptxgen(),this.LayoutType);
       const SlideMaster = _.cloneDeep(pptSlideMaster) 
       SlideMaster.objects[1] = {image: {x:0,y:0,w:10,h:7,path:this.pptBgImage}}
       let pptx = pptConfigInit(new pptxgen(),this.LayoutType,'ch',SlideMaster,this.pptBgImage)
@@ -289,17 +248,7 @@ export default {
       pptx.addSlide()
       const length = this.pageList.length;
       for (let i = 0; i < length; i++) {
-        //console.log(`正在生成,第${i+1}页...`,`lastVisibleItemIndex:`,this.lastVisibleItemIndex)
-        if(!this.loadingAll){
-          if(this.lastVisibleItemIndex<=i+this.buffer+1){
-            //将滚动条触底,加载下一页
-            const {scrollHeight} = this.scroller
-            this.scroller.scrollTop = scrollHeight
-          }
-        }
         let slide = pptx.addSlide({ masterName: pptSlideMaster.title });
-        //添加背景图片
-        //slide.background = { path: "/static/pptnextimg.png" };
         slide.addText(this.pageList[i].title, {
           placeholder:"slideTitle",
           x:'10%',
@@ -349,7 +298,7 @@ export default {
             this.pageList[i].modelId,
             elements[j].position
           );
-          if (imgData) {
+          if (imgData) { //图表
             if(this.transChartType===1){
               slide.addImage({
                 path:imgData,
@@ -369,7 +318,9 @@ export default {
                 size: { type: "contain" },
               });
             }
-            
+
+            //追加生成图表底部文字
+            this.transChartBottomInfo(slide,{x,y,width,height},this.optionMap[this.pageList[i].elements[j].chartId])
           }else if (textData){
             slide.addText(textData,{
               x:x,
@@ -381,7 +332,6 @@ export default {
               valign:'top'
             })
           }else if(imgData2){
-            //console.log('src',imgData2)
             const realSize = getImgRealSize(imgData2Obj)
             const percentWidth = Number(width.substring(0,width.length-1))
             const percentHeight = Number(height.substring(0,height.length-1))
@@ -418,7 +368,6 @@ export default {
           if(['shape','line'].includes(layers[j].type)){
             const scale = calcScale({w:906,h:906*0.7},{w:$('.ppt-item').width(),h:$('.ppt-item').width()*this.coefficient})
             let options = getShapeOptions(layers[j],position,scale)
-            //console.log('options',options)
             if(layers[j].shapeType==='Circle'){ //circle的points太复杂,直接用插件预设的
                 slide.addShape('ellipse', options);
             }else{
@@ -458,7 +407,6 @@ export default {
       
       //为了把封面放到第一页,操作pptx.slides达不成想要的效果,于是弄了个pptx2
       //将封面放在最后生成是因为htmlToCanvans占用太多内存会导致页面假死
-      //let pptx2 = pptInit(new pptxgen(),this.LayoutType);
       let pptx2 = pptConfigInit(new pptxgen(),this.LayoutType,'ch',SlideMaster,this.pptBgImage)
       //添加封面
       let cover = pptx2.addSlide()
@@ -473,14 +421,14 @@ export default {
         size: { type: "contain" },
       })
       //生成的ppt需要可以在封面页更改标题和类型,所以封面信息手动写入
-      const coverInfo = [
-        //{text:'—————————————————————————————————\n',options:{fontSize:16*0.75,breakLine:true}},
+      /* const coverInfo = [
+        {text:'—————————————————————————————————\n',options:{fontSize:16*0.75,breakLine:true}},
         {text:this.coverInfo.page.Title,options:{fontSize:28*0.75,breakLine:true}},
         {text:`\n— ${this.pptCoverCompenyName||'ETA'} ● ${this.coverInfo.page.ReportType} —`,
          options:{fontSize:16*0.75,breakLine:false}},
         {text:`\n${this.pptCoverDepartName||'投研部'}`,options:{fontSize:16*0.75,breakLine:true}},
         {text:this.coverInfo.page.PptDate,options:{fontSize:16*0.75,breakLine:true}},
-        //{text:'\n—————————————————————————',options:{fontSize:16*0.75,breakLine:true}}
+        {text:'\n—————————————————————————',options:{fontSize:16*0.75,breakLine:true}}
       ]
       cover.addText(coverInfo,{
         x:'38%',
@@ -490,7 +438,9 @@ export default {
         color:(this.pptCoverTextColor||'#ffffff').slice(1),
         align:'center',
         fontFace:'SimHei'
-      })
+      }) */
+      //自定义封面页的内容
+      cover = this.setPPTCover(cover,this.pptCoverContent,this.coverInfo.page.Title)
       //遍历pptx.slides,重新给每一项的部分属性赋值,再推入pptx2.slides中
       //第一页不需要,因为是空白的
       for(let i=1;i<pptx.slides.length;i++){
@@ -746,10 +696,6 @@ export default {
   mounted(){
     this.init()
     this._scrollTop = 0
-    if(!this.loadingAll){
-      this.scroller = document.getElementById('scroller')
-      this.scrollerInner = document.getElementById("scroller-inner")
-    }
   },
   updated(){
     /*

+ 15 - 5
src/views/ppt_manage/newVersion/utils/untils.js

@@ -486,10 +486,10 @@ export const calcScale = (oldShap,newShap)=>{
 export const caclShapePercentage = (layer,el)=>{
   const {layerWidth,layerHeight} = layer
   const {left,top,width,height} = el
-  const percentageLeft = left/layerWidth
-  const percentageTop = top/layerHeight
-  const percentageWidth = width/layerWidth
-  const percentageHeight = height/layerHeight
+  const percentageLeft = Number((left/layerWidth).toFixed(5))
+  const percentageTop = Number((top/layerHeight).toFixed(5))
+  const percentageWidth = Number((width/layerWidth).toFixed(5))
+  const percentageHeight = Number((height/layerHeight).toFixed(5))
   return {percentageLeft,percentageTop,percentageWidth,percentageHeight}
 }
 //计算图层元素的真实宽高
@@ -626,11 +626,21 @@ export const checkAttribute = (el)=>{
 }
 //更新chartInfoMapItem
 export const getChartInfo = (options)=>{
-  let item = {chartInfoId:0,chartTitle:'',MyChartClassifyId:''}
+  let item = {
+    chartInfoId:0,
+    chartTitle:'',
+    MyChartClassifyId:'',
+    SourcesFrom:'',
+    Instructions: '',
+    ChartThemeStyle: ''
+  }
   if(options instanceof Object){
     item.chartInfoId = options.chartInfoId
     item.chartTitle = options.chartTitleCN
     item.MyChartClassifyId = options.MyChartClassifyId
+    item.SourcesFrom = options.SourcesFrom
+    item.Instructions = options.Instructions
+    item.ChartThemeStyle = options.ChartThemeStyle
   }
   return item
 }

+ 1 - 1
src/views/ppt_manage/pptdtl.vue

@@ -164,7 +164,7 @@
 							backgroundColor: 'rgba(255, 255, 255, 0)',
 						}
 						let is_linear = this.options.series 
-							? this.options.series.every(_ => _.type === 'scatter' ) || this.options.series.some(_ => _.chartType === 'linear'  )
+							? this.options.series.some(_ => _.chartType === 'linear')
 							: false ;
 						let chart = is_linear ? Highcharts.chart('container'+item.resource_id, new_options) : Highcharts.stockChart('container'+item.resource_id, new_options);
 	

+ 4 - 4
src/views/predictEdb_manage/addPredicEdb.vue

@@ -291,7 +291,7 @@
                     >
                     </el-option>
                   </el-select>
-                  <i class="el-icon-tickets" style="color:#409EFF;font-size:18px" @click="isLookHistory=true;lookEdbId=item.self_target;" v-if="item.self_target"/>
+                  <i class="el-icon-tickets" style="color:#409EFF;font-size:18px" @click="toHistoryPage(item.self_target,$route.matched);lookEdbId=item.self_target;" v-if="item.self_target"/>
                 </div>
                 <div class="item">
                   <span class="label">
@@ -406,14 +406,14 @@
       :edbList="dynamicDifferList"
       :info="dynamicDifferInfo"
       @ensureBack="saveDynamicDifferRule"
-      @lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+      @lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
     />
 
     <!-- 指标历史记录 -->
-    <edbHistoryDialog
+    <!-- <edbHistoryDialog
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
-    />
+    /> -->
     
   </div>
 </template>

+ 1 - 0
src/views/predictEdb_manage/components/chartInfo.vue

@@ -62,6 +62,7 @@
         <div class="chartWrapper">
             <Chart 
                 :options="options" 
+                :chartInfo="chartInfo"
                 ref="chartRef" 
             />
             <!-- 公历农历切换 只用于季节性图 -->

+ 7 - 27
src/views/predictEdb_manage/predictEdb.vue

@@ -193,7 +193,7 @@
 							<el-button type="text" @click="saveEdbHandle" 
 									v-if="detail_show_chart&&isEdbBtnShow('edbPreData_save')">保存</el-button>
 							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_edbSource"
-								type="text" @click="isLookHistory=true;lookEdbId=select_id">指标溯源</el-button>
+								type="text" @click="toHistoryPage(select_id,$route.matched);lookEdbId=select_id">指标溯源</el-button>
 							<el-popover v-if="showPopover"
 								placement="bottom-end" 
 								trigger="hover"
@@ -217,26 +217,6 @@
 								</div>
 							</el-popover>
 						</div>
-						<!-- <div class="edb-tool">
-							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_enNameSetting"
-								type="text" @click="clickEdbNameHandle" v-if="currentLang==='ch'||!edb_nameEn">
-								设置英文名称
-							</el-button>
-							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_edbSource"
-							type="text" @click="isLookHistory=true;lookEdbId=select_id">指标溯源</el-button>
-							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_update"
-								type="text" @click="updateEdbPartHandle">刷新</el-button>
-							<el-button type="text" @click="editEdbHandle('')" 
-								v-if="edbButton.OpButton&&isEdbBtnShow('edbPreData_edit')">编辑</el-button>
-							<el-button type="text" @click="saveEdbHandle" 
-								v-if="detail_show_chart&&isEdbBtnShow('edbPreData_save')">保存</el-button>
-							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_recalcu"
-								type="text" @click="updateEdbHandle">重新计算</el-button>
-							<el-button class="deletesty" @click="delEdbHandle" type="text"
-								v-if="edbButton.DeleteButton&&isEdbBtnShow('edbPreData_del')">删除</el-button>
-							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_copyData"
-								type="text" @click="copyData">复制数据</el-button>
-						</div> -->
 					</div>
 
 					<!--  -->
@@ -390,7 +370,7 @@
 			@cancel="computed_type=0"
 			@addCallBack="addComputedCallBack"
 			@openPrev="isOpenComputed=true"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 		/>
 
 		<!-- 同比同差计算弹窗 -->
@@ -402,7 +382,7 @@
 			@cancel="computed_type=0"
 			@addCallBack="addComputedCallBack"
 			@openPrev="isOpenComputed=true"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 			@changeSource="changeComputedType"
 		/>
 
@@ -421,7 +401,7 @@
 			@cancel="computed_type=0"
 			@addCallBack="addComputedCallBack"
 			@openPrev="isOpenComputed=true"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 			@changeSource="changeComputedType"
 		/>
 			
@@ -458,10 +438,10 @@
 		/>
 
 		 <!-- 指标历史记录 -->
-    <edbHistoryDialog
+    <!-- <edbHistoryDialog
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
-    />
+    /> -->
 	<!-- 指数修匀弹窗 -->
 	<SmoothEdbDialog 
 			:is-open-smooth="computed_type==='alpha'"
@@ -471,7 +451,7 @@
 			@cancel="computed_type=0"
 			@openPrev="isOpenComputed=true"
 			@addCallBack="addComputedCallBack"
-			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 		/>
 
 	</div>

+ 2 - 1
src/views/report_manage/reportdtl.vue

@@ -82,7 +82,8 @@
 					if(this.systemUserInfo){
 						waterMarkStr=`${this.systemUserInfo.RealName}${this.systemUserInfo.Mobile?this.systemUserInfo.Mobile:this.systemUserInfo.Email}`
 						const base64=new http.Base64()
-						waterMarkStr=base64.encode(waterMarkStr)
+						waterMarkStr=encodeURIComponent(waterMarkStr)
+						waterMarkStr=Base64.encode(waterMarkStr)
 					}
 					
 					if(this.$route.query.fromPage == 'en'){

+ 1 - 1
src/views/sandbox_manage/sandFlowNew/components/addLInkDia.vue

@@ -109,7 +109,7 @@
           </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" />
+            <Chart :options="options" :chartInfo="chartInfo" 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"

+ 3 - 3
src/views/smartReport/editReport.vue

@@ -68,7 +68,7 @@
                     </li>
                 </draggable>
 
-                <div class="report-content-box" id="report-content-box">
+                <div class="report-content-box" id="report-content-box" :style="{backgroundColor:bgColor}">
                     <div class="html-head-img-box">
                         <div class="opt-btn-box" style="display: none;">
                             <div class="del-btn" @click.stop="headImg=''"></div>
@@ -86,7 +86,6 @@
                         @add="handleParentAdd"
                         @remove="handleParentRemove"
                         :move="handleParentMove"
-                        :style="{backgroundColor:bgColor}"
                     >
                         <div 
                             :class="[
@@ -489,6 +488,7 @@ export default {
         handlePreviewReport(){
             const htmlStr=document.getElementById('report-content-box').outerHTML;
             sessionStorage.setItem('smartReportContent', htmlStr);
+            sessionStorage.setItem('smartReportContentBg', this.bgColor);
 			let { href } = this.$router.resolve({ 
                 path: '/smartReportDetail',
                 query:{
@@ -1317,7 +1317,7 @@ div{
         min-height: 100%;
         .report-drag-item-wrap{
             width: 100%;
-            padding: 3px;
+            padding: 6px;
             min-height: 80px;
             border: 1px dashed #0052D9;
             position: relative;

+ 8 - 1
src/views/smartReport/reportDetail.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="smart-report-detail">
-        <div class="main-box">
+        <div class="main-box" :style="{backgroundColor:bgColor}">
             <!-- <div class="top-box">
                 <div class="title">{{reportInfo&&reportInfo.Title}}</div>
                 <div class="flex">
@@ -83,6 +83,7 @@ export default {
         return {
             reportInfo:null,
             content:'',
+            bgColor:'',
             reportImgUrl:'',
             showReportImg:false
         }
@@ -104,8 +105,10 @@ export default {
                     this.reportInfo=res.Data
                     if(this.$route.query.type==='preview'){
                        this.content=sessionStorage.getItem('smartReportContent')
+                       this.bgColor=sessionStorage.getItem('smartReportContentBg')
                     }else{
                         this.content=res.Data.Content
+                        this.bgColor=res.Data.CanvasColor
                     }
                 }else{
                     this.$emit("reportError")
@@ -239,6 +242,10 @@ div{
         }
         .html-wrap{
             // padding: 30px;
+            .report-drag-item-wrap{
+                padding: 6px;
+                margin-bottom: 3px;
+            }
         }
     }
     .report-img-box{

+ 130 - 0
src/views/system_manage/chartTheme/common/config.js

@@ -0,0 +1,130 @@
+// 一些常量
+import { defaultOpts } from '@/utils/defaultOptions';
+
+export const predefineColors = defaultOpts.colors.slice(0, 2); //定义颜色蓝,红 默认颜色
+
+//可选线条样式
+export const lineStylesOpts = [
+  { value: 'Solid',svg:`<g clip-path="url(#clip0_2634_4692)"><rect x="-14" y="4" width="116" height="2" fill="#333333"/></g>
+  <defs><clipPath id="clip0_2634_4692"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+  { value: 'LongDash',svg:`<g clip-path="url(#clip0_2634_4883)">
+  <rect x="-4.5" y="4" width="13" height="2" rx="1" fill="#333333"/>
+  <rect x="9.5" y="4" width="13" height="2" rx="1" fill="#333333"/>
+  <rect x="23.5" y="4" width="13" height="2" rx="1" fill="#333333"/>
+  <rect x="37.5" y="4" width="13" height="2" rx="1" fill="#333333"/>
+  <rect x="51.5" y="4" width="13" height="2" rx="1" fill="#333333"/>
+  <rect x="65.5" y="4" width="13" height="2" rx="1" fill="#333333"/>
+  <rect x="79.5" y="4" width="13" height="2" rx="1" fill="#333333"/></g><defs><clipPath id="clip0_2634_4883"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+  { value: 'ShortDash',svg:`<g clip-path="url(#clip0_2634_4865)">
+  <rect x="-0.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="6.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="13.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="20.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="27.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="34.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="41.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="48.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="55.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="62.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="69.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="76.5" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <rect x="83.5" y="4" width="5" height="2" rx="1" fill="#333333"/></g><defs><clipPath id="clip0_2634_4865"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+  { value: 'Dash',svg:`<g clip-path="url(#clip0_2634_4706)">
+  <rect x="-0.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="6.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="13.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="20.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="27.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="34.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="41.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="48.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="55.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="62.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="69.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="76.5" y="4" width="5" height="2" fill="#333333"/>
+  <rect x="83.5" y="4" width="5" height="2" fill="#333333"/></g><defs><clipPath id="clip0_2634_4706"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+  { value: 'Dot',svg:`<g clip-path="url(#clip0_2634_4843)"><circle cx="2" cy="5" r="1" fill="#333333"/><circle cx="8" cy="5" r="1" fill="#333333"/><circle cx="14" cy="5" r="1" fill="#333333"/><circle cx="20" cy="5" r="1" fill="#333333"/><circle cx="26" cy="5" r="1" fill="#333333"/><circle cx="32" cy="5" r="1" fill="#333333"/><circle cx="38" cy="5" r="1" fill="#333333"/><circle cx="44" cy="5" r="1" fill="#333333"/><circle cx="50" cy="5" r="1" fill="#333333"/><circle cx="56" cy="5" r="1" fill="#333333"/><circle cx="62" cy="5" r="1" fill="#333333"/><circle cx="68" cy="5" r="1" fill="#333333"/><circle cx="74" cy="5" r="1" fill="#333333"/><circle cx="80" cy="5" r="1" fill="#333333"/><circle cx="86" cy="5" r="1" fill="#333333"/></g><defs><clipPath id="clip0_2634_4843"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+  { value: 'DashDot',svg:`<g clip-path="url(#clip0_2634_4893)">
+  <circle cx="2" cy="5" r="1" fill="#333333"/>
+  <rect x="4" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="11" cy="5" r="1" fill="#333333"/>
+  <rect x="13" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="20" cy="5" r="1" fill="#333333"/>
+  <rect x="22" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="29" cy="5" r="1" fill="#333333"/>
+  <rect x="31" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="38" cy="5" r="1" fill="#333333"/>
+  <rect x="40" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="47" cy="5" r="1" fill="#333333"/>
+  <rect x="49" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="56" cy="5" r="1" fill="#333333"/>
+  <rect x="58" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="65" cy="5" r="1" fill="#333333"/>
+  <rect x="67" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="74" cy="5" r="1" fill="#333333"/>
+  <rect x="76" y="4" width="5" height="2" rx="1" fill="#333333"/>
+  <circle cx="83" cy="5" r="1" fill="#333333"/>
+  <rect x="85" y="4" width="5" height="2" rx="1" fill="#333333"/></g><defs><clipPath id="clip0_2634_4893"><rect width="88" height="10" fill="white"/></clipPath></defs>` },
+]
+
+//垂直位置 上中下
+export const verticalPositions = [
+  { label: '顶部',value: 'top' },
+  { label: '居中',value: 'middle' },
+  { label: '底部',value: 'bottom' },
+]
+//水平位置
+export const alignPositions = [
+  { value: 'left',svg:`<path d="M96 128h832v96H96zM96 576h832v96H96zM96 352h576v96H96zM96 800h576v96H96z" p-id="4976"></path>` },
+  { value: 'center',svg:`<path d="M96 128h832v96H96zM96 576h832v96H96zM224 352h576v96H224zM224 800h576v96H224z" p-id="6951"></path>` },
+  { value: 'right',svg:`<path d="M96 128h832v96H96zM96 576h832v96H96zM352 352h576v96H352zM352 800h576v96H352z" p-id="5963"></path>` },
+]
+
+/* 当做标准化结构  eta默认值 几种类型图样式还区分开...*/
+export const defaultETAOptions = {
+  colorsOptions: defaultOpts.colors.slice(0,10),
+  lineOptions: { 
+    dashStyle: 'Solid',
+    lineWidth: 1,
+    lineType: 'spline',
+    radius: 5,
+  },
+  legendOptions: {
+    verticalAlign: 'top',
+    itemStyle: {
+      color: '#333',
+      fontSize: 13,
+      cursor: "pointer",
+      fontWeight: "bold",
+      textOverflow: "ellipsis"
+    }
+  },
+  titleOptions: {
+    align: 'center',
+    style: {
+      color: '#333',
+      fontSize: 16
+    }
+  },
+  markerOptions: {
+    style: {
+      color: '#333',
+      fontSize: 12
+    }
+  },
+  xAxisOptions: {
+    style: {
+      color: '#666',
+      fontSize: 11
+    }
+  },
+  yAxisOptions: {
+    style: {
+      color: '#333',
+      fontSize: 11
+    }
+  },
+  drawOption: {
+    plotBackgroundColor: 'rgba(255, 255, 255, 0)'
+  }
+}

+ 334 - 0
src/views/system_manage/chartTheme/components/optionsSection.vue

@@ -0,0 +1,334 @@
+<template>
+  <div class="charTheme-setting-option">
+    <ul class="options-wrapper">
+      <li v-for="key in Object.keys(themeOptions)" :key="key">
+        <label class="option-title">{{ key ==='lineOptions'?typeLabelMap[chartType].label:labelMap.get(key)}}</label>
+        
+          <ul class="option-list">
+             <!-- 线条设置 -->
+            <template v-if="key==='lineOptions'">
+                <li class="option-item">
+                  <label class="el-form-item__label">颜色</label>
+                  <el-color-picker
+                    v-model="themeOptions[key].colors[themeOptions[key].colorIndex]"
+                    show-alpha
+                    :predefine="predefineColors"
+                    style="width: 90px"
+                    @change="changeLineColor"
+                  />
+                </li>
+                <li class="option-item">
+                  <label class="el-form-item__label">顺序</label>
+                  <el-select 
+                    v-model="themeOptions[key].colorIndex"
+                    style="width: 90px"
+                  >
+                    <el-option 
+                      v-for="(item,index) in themeOptions[key].colors" 
+                      :key="index"
+                      :label="`第${index+1}${typeLabelMap[chartType].lineLabel}`"
+                      :value="index"
+                    />
+                  </el-select>
+                </li>
+
+                <!-- 曲线额外配置 -->
+                <template v-if="[1,2].includes(chartType)">
+                  <li class="option-item">
+                    <label class="el-form-item__label">线型</label>
+                    <el-select 
+                      v-model="themeOptions[key].dashStyle"
+                      style="width: 90px"
+                    >
+                      <el-option 
+                        v-for="item in lineStylesOpts" 
+                        :key="item.value"
+                        :value="item.value"
+                        :label="item.label"
+                      >
+                        <svg width="60" height="10" viewBox="0 0 60 10" fill="none" xmlns="http://www.w3.org/2000/svg" v-html="item.svg">
+                        </svg>
+                      </el-option>
+                    </el-select>
+                  </li>
+                  <li class="option-item">
+                    <label class="el-form-item__label">粗细</label>
+                    <el-input
+                      v-model="themeOptions[key].lineWidth"
+                      style="width: 90px"
+                      type="number"
+                      :min="1"
+                      @change="val => { themeOptions[key].lineWidth=Number(val)}"
+                    />
+                  </li>
+                  <li class="option-item">
+                    <label class="el-form-item__label">平滑线</label>
+                    <el-select 
+                      v-model="themeOptions[key].lineType"
+                      style="width: 90px"
+                    >
+                      <el-option label="是" value="spline"/>
+                      <el-option label="否" value="line"/>
+                    </el-select>
+                  </li>
+                </template>
+                
+                <!-- 散点额外配置 -->
+                <template v-else-if="[5,10].includes(chartType)">
+                  <li class="option-item">
+                    <label class="el-form-item__label">大小</label>
+                    <el-input
+                      v-model="themeOptions[key].radius"
+                      style="width: 90px"
+                      type="number"
+                      :min="3"
+                      @change="val => { themeOptions[key].radius=Number(val)}"
+                    />
+                  </li>
+                </template>
+            </template>
+
+             <!-- 图例设置 -->
+            <template v-else-if="key==='legendOptions'">
+                <li class="option-item">
+                  <label class="el-form-item__label">颜色</label>
+                  <el-color-picker
+                    v-model="themeOptions[key].itemStyle.color"
+                    show-alpha
+                    :predefine="predefineColors"
+                    style="width: 90px"
+                  />
+                </li>
+                <li class="option-item">
+                  <label class="el-form-item__label">位置</label>
+                  <el-select 
+                    v-model="themeOptions[key].verticalAlign"
+                    style="width: 90px"
+                  >
+                    <el-option 
+                      v-for="item in lengendPositions" 
+                      :key="item.value"
+                      :label="item.label"
+                      :value="item.value"
+                    />
+                  </el-select>
+                </li>
+                <li class="option-item">
+                  <label class="el-form-item__label">字号</label>
+                  <el-input
+                    v-model="themeOptions[key].itemStyle.fontSize"
+                    style="width: 90px"
+                    type="number"
+                    :min="1"
+                    @change="val => { themeOptions[key].itemStyle.fontSize=Number(val)}"
+                  />
+                </li>
+            </template>
+            
+            <!-- 标题设置 -->
+            <template v-else-if="key==='titleOptions'">
+                <li class="option-item">
+                  <label class="el-form-item__label">颜色</label>
+                  <el-color-picker
+                    v-model="themeOptions[key].style.color"
+                    show-alpha
+                    :predefine="predefineColors"
+                    style="width: 90px"
+                  />
+                </li>
+                <li class="option-item">
+                  <label class="el-form-item__label">字号</label>
+                  <el-input
+                    v-model="themeOptions[key].style.fontSize"
+                    style="width: 90px"
+                    type="number"
+                    :min="1"
+                    @change="val => { themeOptions[key].style.fontSize=Number(val)}"
+                  />
+                </li>
+                <li class="option-item">
+                  <label class="el-form-item__label">对齐方式</label>
+                  <el-radio-group v-model="themeOptions[key].align" size="small">
+                    <el-radio-button 
+                      v-for="item in alignPositions" 
+                      :key="item.value" 
+                      :label="item.value"
+                    >
+                      <svg t="1701940027445" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4975" width="14" height="14" v-html="item.svg" :fill="`${themeOptions[key].align===item.value?'#fff':'#333'}`">
+                      </svg>
+                    </el-radio-button>
+                  </el-radio-group>
+                </li>
+            </template>
+
+            <!-- 标记文字 横轴 纵轴设置 -->
+            <template v-else-if="['markerOptions','xAxisOptions','yAxisOptions'].includes(key)">
+                <li class="option-item">
+                  <label class="el-form-item__label">颜色</label>
+                  <el-color-picker
+                    v-model="themeOptions[key].style.color"
+                    show-alpha
+                    :predefine="predefineColors"
+                    style="width: 90px"
+                  />
+                </li>
+                <li class="option-item">
+                  <label class="el-form-item__label">字号</label>
+                  <el-input
+                    v-model="themeOptions[key].style.fontSize"
+                    style="width: 90px"
+                    type="number"
+                    :min="1"
+                    @change="val => { themeOptions[key].style.fontSize=Number(val)}"
+                  />
+                </li>
+            </template>  
+
+            <!-- 绘图区设置 -->
+            <template v-else-if="key==='drawOption'">
+                <li class="option-item">
+                  <label class="el-form-item__label">背景色</label>
+                  <el-color-picker
+                    v-model="themeOptions[key].plotBackgroundColor"
+                    show-alpha
+                    :predefine="predefineColors"
+                    style="width: 90px"
+                  />
+                </li>
+            </template>  
+          </ul>
+      </li>
+    </ul>
+  </div>
+</template>
+<script>
+import { defaultETAOptions,verticalPositions,predefineColors,lineStylesOpts,alignPositions } from '../common/config'
+import { seasonOptions } from '@/utils/defaultOptions';
+export default {
+  props: {
+    chartType: {
+      type:Number
+    }
+  },
+  watch: {
+    chartType() {
+    }
+  },
+  data() {
+    return {
+      predefineColors,
+      lineStylesOpts,
+      alignPositions,
+     /* 可配置options*/
+      themeOptions: {
+        lineOptions: {
+          dashStyle: defaultETAOptions.lineOptions.dashStyle,
+          colors: this.chartType===2?seasonOptions.colors:defaultETAOptions.colorsOptions,
+          color: defaultETAOptions.colorsOptions[0],
+          colorIndex:0,
+          lineWidth: defaultETAOptions.lineOptions.lineWidth,
+          lineType: defaultETAOptions.lineOptions.lineType,
+          radius: defaultETAOptions.lineOptions.radius,
+        },
+        legendOptions: defaultETAOptions.legendOptions,
+        titleOptions: defaultETAOptions.titleOptions,
+        markerOptions: defaultETAOptions.markerOptions,
+        xAxisOptions: defaultETAOptions.xAxisOptions,
+        yAxisOptions: defaultETAOptions.yAxisOptions,
+        drawOption: defaultETAOptions.drawOption
+      },
+      lengendPositions: verticalPositions.filter(_ => _.value!=='middle'),
+      typeLabelMap: {
+        1: {label:'线条设置',lineLabel: '条'},
+        2: {label:'线条设置',lineLabel: '条'},
+        4: {label:'柱形设置',lineLabel: '根'},
+        5: {label:'散点设置',lineLabel: '系列'},
+        6: {label:'线条、柱形设置',lineLabel: '系列'},
+        7: {label:'柱形设置',lineLabel: '根'},
+        10: {label:'散点设置',lineLabel: '系列'},
+      },
+      labelMap: new Map([
+        ['lineOptions','线条设置'],
+        ['scatterOptions','散点设置'],
+        ['legendOptions','图例设置'],
+        ['titleOptions','标题设置'],
+        ['markerOptions','标记文字设置(来源,标识)'],
+        ['xAxisOptions','横轴设置'],
+        ['yAxisOptions','纵轴设置'],
+        ['drawOption','绘图区设置'],
+      ]),
+      configOptions: []
+    }
+  },
+  mounted(){
+  },
+  methods:{
+    initOptions(options) {
+      console.log(options)
+      //给点页面反馈
+      this.loading = this.$loading({
+          lock: true,
+          text: '切换主题中...',
+          target: '.charTheme-setting-option',
+          spinner: 'el-icon-loading',
+          background: 'rgba(255, 255, 255, 0.8)'
+      });
+
+      this.themeOptions = {
+        lineOptions: {
+          dashStyle: options.lineOptions.dashStyle,
+          colors: options.colorsOptions,
+          color: options.colorsOptions[0],
+          colorIndex:0,
+          lineWidth: options.lineOptions.lineWidth,
+          lineType: options.lineOptions.lineType,
+          radius: options.lineOptions.radius,
+        },
+        legendOptions: options.legendOptions,
+        titleOptions: options.titleOptions,
+        markerOptions: options.markerOptions,
+        xAxisOptions: options.xAxisOptions,
+        yAxisOptions: options.yAxisOptions,
+        drawOption: options.drawOption
+      }
+
+      this.loading.close()
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.options-wrapper {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 40px;
+  .option-list {
+    margin-top: 20px;
+    .option-item {
+      margin: 10px 0;
+    }
+  }
+  .option-title{
+    position: relative;
+    &:before {
+      content: "*";
+      font-size: 18px;
+      color: #f00;
+      position: absolute;
+      left: -10px;
+      top: 2px;
+    }
+  }
+  .el-form-item__label {
+    width: 70px;
+    text-align: left;
+  }
+}
+</style>
+
+<style lang="scss">
+  .charTheme-setting-option {
+    .el-color-picker__trigger { width: 100%;padding: 0;border-radius: 4px; }
+    
+  }
+</style>

+ 285 - 0
src/views/system_manage/chartTheme/index.vue

@@ -0,0 +1,285 @@
+<template>
+  <div class="chartTheme-page">
+    <div class="header">
+      <div style="display: flex;gap:20px;">
+        <div class="select-item">
+          <div class="select-item">
+            <label>图表类型</label>
+            <el-select v-model="formData.chartType" style="margin-left: 15px;" @change="getThemeList();">
+              <el-option
+                v-for="item in chartTypeOpts"
+                :key="item.ChartThemeTypeId"
+                :label="item.ChartTypeName"
+                :value="item.ChartThemeTypeId"
+              />
+            </el-select>
+          </div>
+        </div>
+        <div class="select-item">
+          <label>ETA图库默认主题</label>
+          <el-select v-model="formData.theme" style="margin-left: 10px;">
+            <el-option
+              v-for="item in themeOpts"
+              :key="item.ChartThemeId"
+              :label="item.ChartThemeName"
+              :value="item.ChartThemeId"
+            />
+          </el-select>
+        </div>
+      </div>
+
+      <el-button type="primary" v-permission="permissionBtn.chartThemePermission.chartTheme_edit" @click="setConfigTheme">保存</el-button>
+    </div>
+
+    <!-- 主题列表 -->
+    <div class="main">
+      <ul class="list-wrap">
+        <li 
+          v-for="(item,index) in themeOpts" 
+          :key="item.ChartThemeId" 
+          class="theme-item"
+        >  
+          <el-card>
+            <div slot="header" class="item-top">
+              <span class="text_oneLine">{{item.ChartThemeName}}</span>
+              <div>
+                <el-button type="text" @click="editThemeHandle(item)" v-permission="permissionBtn.chartThemePermission.chartTheme_edit">编辑</el-button>
+                <span class="deletesty" @click="delThemeHandle(item,index)" v-permission="permissionBtn.chartThemePermission.chartTheme_del" v-if="!item.IsSystemTheme">删除</span>
+              </div>
+            </div>
+            <div class="chart-img" :style="`backgroundImage:url(${item.ChartImage})`"></div>
+          </el-card>
+        </li>
+        <li class="theme-item add-item" @click="addThemeHandle" v-permission="permissionBtn.chartThemePermission.chartTheme_add">
+          <div class="chart-img"></div>
+          <div class="add-cont">
+            <i class="el-icon-plus"/>
+            <el-button type="text" style="font-size:16px;">添加自定义主题</el-button>
+          </div>
+        </li>
+      </ul>
+
+    </div>
+
+
+   <!-- 弹窗 -->
+    <m-dialog 
+      :title="`${addThemeForm.id?'编辑':'添加'}自定义主题`" 
+      :show.sync="isOpenThemeDia" 
+      width="650px"
+    >
+      <div style="padding:30px 60px">
+        <div>
+          <label class="el-form-item__label">主题名称</label>
+          <el-input 
+            v-model="addThemeForm.themeName" 
+            placeholder="请输入主题名称"
+          />
+        </div>
+      </div>
+      <div slot="footer" style="margin: 20px 0;">
+        <el-button
+          @click="saveThemeHandle"
+          type="primary"
+          style="width: 132px; height: 40px"
+          >保存</el-button>
+        <el-button
+        @click="isOpenThemeDia=false"
+        style="width: 132px; height: 40px"
+        >取消</el-button>
+      </div>
+    </m-dialog>
+
+  </div>
+</template>
+<script>
+import * as chartThemeInterface from '@/api/modules/chartThemeApi';
+import mDialog from '@/components/mDialog.vue';
+export default {
+  components: { mDialog },
+  data() {
+    return {
+      chartTypeOpts:[],
+      formData: {
+        chartType: 0,
+        theme: 0
+      },
+
+      themeOpts: [],
+
+      isOpenThemeDia: false,
+      addThemeForm: {
+        themeName: '',
+      }
+    };
+  },
+  mounted() {
+    this.getChartType()
+  },
+  methods: {
+    /* 获取图表类型 */
+    async getChartType() {
+      let res = await chartThemeInterface.getThemeChartType()
+
+      if(res.Ret !== 200) return
+
+      this.chartTypeOpts = res.Data||[];
+      this.formData.chartType = res.Data[0].ChartThemeTypeId;
+      this.getThemeList()
+    },
+
+    /* 主题列表 */
+    async getThemeList() {
+      let res = await chartThemeInterface.getThemeByType({ChartThemeTypeId: this.formData.chartType})
+
+      if(res.Ret !== 200) return
+      this.themeOpts = res.Data || []
+      this.formData.theme = res.Data[0].DefaultChartThemeId
+    },
+
+    /* 设置默认主题 */
+    async setConfigTheme() {
+      const { chartType,theme } = this.formData
+      let res = await chartThemeInterface.setConfigTheme({
+        ChartThemeId: theme,
+        ChartThemeTypeId: chartType
+      })
+      
+      if(res.Ret !== 200) return
+      this.$message.success('默认主题设置成功')
+
+    },
+
+    // 添加主题
+    addThemeHandle() {
+      this.isOpenThemeDia = true;
+      this.addThemeForm= {
+        themeName: '',
+      }
+    },
+
+    async delThemeHandle(item,index) {
+      await this.$confirm('删除后,所有采用该主题的图表,将采用ETA主题,是否确定删除?',
+       '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+      })
+
+      let res = await chartThemeInterface.delTheme({ ChartThemeId: item.ChartThemeId })
+      if(res.Ret!==200) return 
+
+      this.themeOpts.splice(index,1)
+      this.$message.success('删除成功')
+    },
+
+    editThemeHandle({ChartThemeId}) {
+      this.$router.push({
+        path: '/chartThemeSet',
+        query: {
+          type: this.formData.chartType,
+          themeId: ChartThemeId
+        }
+      })
+    },
+
+
+    async saveThemeHandle() {
+      if(!this.addThemeForm.themeName) return this.$message.warning('请输入主题名称')
+
+      let res = await chartThemeInterface.addTheme({
+        ChartThemeName: this.addThemeForm.themeName,
+        ChartThemeTypeId: this.formData.chartType
+      })
+
+      if(res.Ret !== 200) return
+      this.$message.success('添加成功')
+      this.isOpenThemeDia = false;
+
+      this.getThemeList()
+    }
+  },
+};
+</script>
+<style scoped lang="scss">
+* {
+  box-sizing: border-box;
+}
+.chartTheme-page {
+  .select-item {
+    display: flex;
+    align-items: center;
+  }
+  .header,.main {
+    padding: 20px 30px;
+    background: #fff;
+    position: relative;
+    border: 1px solid #ececec;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+  }
+  .header {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 30px;
+    gap: 20px;
+  }
+  .main {
+     min-height: calc(100vh - 240px);
+  }
+  .list-wrap {
+    display: flex;
+    flex-wrap: wrap;
+    margin-bottom: 30px;
+    gap: 15px 30px;
+    .theme-item {
+      width: 20%;
+      min-width: 230px;
+      position: relative;
+      .item-top {
+        display: flex;
+        height: 30px;
+        justify-content: space-between;
+        align-items: center;
+        font-size: 14px;
+      }
+      .chart-img {
+        width: 100%;
+        height: 0;
+        padding-bottom: 75%;
+        object-fit: cover ;
+        background-repeat: no-repeat;
+        background-size: 100%;
+      }
+    }
+    .add-item {
+      background: #F8F8F8;
+      border: 1px dashed #DCDFE6;
+      cursor: pointer;
+      text-align: center;
+      padding-top: 60px;
+      .el-icon-plus {
+        font-size: 30px;
+        display:block;
+        text-align: center;
+        font-weight: bold;
+        color: #0052D9;
+      }
+
+      .add-cont {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%,-50%);
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.chartTheme-page {
+  .el-card__header {
+    padding: 10px 20px;
+  }
+}
+</style>

+ 212 - 0
src/views/system_manage/chartTheme/themeSetting.vue

@@ -0,0 +1,212 @@
+<template>
+  <div class="themeSet-page">
+    <div class="header">
+      <div>
+        <el-select v-model="formData.chartType" @change="getThemeList('init');">
+            <el-option
+              v-for="item in chartTypeOpts"
+              :key="item.ChartThemeTypeId"
+              :label="item.ChartTypeName"
+              :value="item.ChartThemeTypeId"
+            />
+          </el-select>
+
+        <el-select v-model="formData.theme" style="margin-left: 10px;" @change="changeThemeHandle">
+          <el-option
+            v-for="item in themeOpts"
+            :key="item.ChartThemeId"
+            :label="item.ChartThemeName"
+            :value="item.ChartThemeId"
+          />
+        </el-select>
+      </div>
+      <div>
+        <el-button type="primary" plain @click="$router.go(-1)">取消</el-button>
+        <el-button type="primary" @click="setThemeOptions">保存</el-button>
+      </div>
+    </div> 
+
+    <div class="main">
+      <!-- 配置区 -->
+      <optionsSection 
+        ref="optionsSectionRef" 
+        :chartType="formData.chartType"
+      />
+
+      <!-- 预览区 -->
+      <div class="chart-render-wrapper">
+        <div 
+          class="title"
+          :style="`
+            textAlign:${chartInfo.ChartThemeStyle&&JSON.parse(chartInfo.ChartThemeStyle).titleOptions.align};
+            fontSize:${chartInfo.ChartThemeStyle&&JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.fontSize}px;
+            color:${chartInfo.ChartThemeStyle&&JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.color}
+          `"
+        >
+          图表标题
+        </div>
+        <Chart :options="options" :chartInfo="chartInfo" ref="chartRef" height="400px" minHeight="350px"/>
+      </div>
+    </div>
+    
+  </div>
+</template>
+<script>
+import * as chartThemeInterface from '@/api/modules/chartThemeApi';
+import { dataBaseInterface } from '@/api/api.js';
+import { chartSetMixin } from '@/views/dataEntry_manage/mixins/chartPublic';
+import Chart from '@/views/dataEntry_manage/components/chart.vue';
+import optionsSection from './components/optionsSection.vue'
+export default {
+  components: { optionsSection,Chart },
+  mixins: [ chartSetMixin ],
+  data() {
+    return {
+      formData: {
+        chartType: Number(this.$route.query.type),
+        theme: Number(this.$route.query.themeId)
+      },
+      chartTypeOpts: [],
+      themeOpts: [],
+      chartInfo: {}
+    }
+  },
+  mounted(){
+    this.getChartType()
+  },
+  methods:{
+
+    /* 获取图表类型 */
+    async getChartType() {
+      let res = await chartThemeInterface.getThemeChartType()
+
+      if(res.Ret !== 200) return
+
+      this.chartTypeOpts = res.Data||[];
+
+      this.getThemeList()
+    },
+
+     /* 主题列表 */
+    async getThemeList(type=null) {
+      let res = await chartThemeInterface.getThemeByType({ChartThemeTypeId: this.formData.chartType})
+
+      if(res.Ret !== 200) return
+      this.themeOpts = res.Data || []
+      this.formData.theme = type==='init' ? res.Data[0].DefaultChartThemeId : this.formData.theme
+
+      this.changeThemeHandle()
+    },
+
+    /* 预览图数据 */
+    async getPreviewData() {
+      let res = await chartThemeInterface.previewChartData({
+        ChartThemeTypeId: this.formData.chartType,
+      })
+      if(res.Ret !==200) return
+
+      let themeItem = this.themeOpts.find(_ => _.ChartThemeId===this.formData.theme)
+
+      this.chartInfo = {
+        ...res.Data.ChartInfo,
+        ChartThemeStyle: themeItem.Config
+      };
+      this.tableData = res.Data.EdbInfoList;
+      if(this.chartInfo.ChartType === 7) return this.initBarData(res.Data);
+      if(this.chartInfo.ChartType === 10) return this.initSectionScatterData(res.Data);
+
+      this.setChartOptionHandle(this.tableData)
+    },
+
+    changeThemeHandle() {
+      let themeItem = this.themeOpts.find(_ => _.ChartThemeId===this.formData.theme)
+      this.$refs.optionsSectionRef.initOptions(JSON.parse(themeItem.Config))
+      this.getPreviewData()
+    },
+
+    /* 保存配置 处理成标准化结构 */
+    async setThemeOptions() {
+      const { lineOptions,legendOptions,titleOptions,markerOptions,xAxisOptions,yAxisOptions,drawOption } = this.$refs.optionsSectionRef.themeOptions;
+      
+      let options = {
+        colorsOptions: lineOptions.colors,
+        lineOptions: { 
+          dashStyle: lineOptions.dashStyle,
+          lineWidth: lineOptions.lineWidth,
+          lineType: lineOptions.lineType,
+          radius: lineOptions.radius,
+        },
+        legendOptions,
+        titleOptions,
+        markerOptions,
+        xAxisOptions,
+        yAxisOptions,
+        drawOption
+      }
+
+      const { theme } = this.formData;
+
+      let ChartImage = await this.setChartImage();
+
+      let res= await chartThemeInterface.saveTheme({
+        ChartThemeName: this.themeOpts.find(_ => _.ChartThemeId===this.formData.theme).ChartThemeName,
+        ChartThemeId: theme,
+        ChartImage,
+        Config: JSON.stringify(options)
+      })
+
+      if(res.Ret !==200) return
+      this.getThemeList()
+      this.$message.success('保存成功')
+    },
+
+    /* 设置封面图片 */
+    async setChartImage() {
+      let svg = this.$refs.chartRef.chart.getSVG({
+        chart: {
+          width: 340,
+          height: 230,
+        }
+      });
+      let form = new FormData();
+      form.append('Img', svg);
+
+      let { Data } = await dataBaseInterface.uploadImgSvg(form);
+      return Data.ResourceUrl;
+    },
+  },
+}
+</script>
+<style scoped lang='scss'>
+* {
+  box-sizing: border-box;
+}
+.themeSet-page {
+  .header,.main {
+    padding: 20px 30px;
+    background: #fff;
+    position: relative;
+    border: 1px solid #ececec;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+  }
+  .header {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 30px;
+  }
+  .main {
+    min-height: calc(100vh - 230px);
+    .chart-render-wrapper {
+      width: 620px;
+      padding: 10px;
+      border: 1px solid #C8CDD9;
+      border-radius: 6px;
+      margin-left: auto;
+      .title {
+        margin-bottom: 10px;
+      }
+    }
+  }
+}
+</style>

+ 1 - 1
src/views/system_manage/components/smartReportImgSet.vue

@@ -6,7 +6,7 @@
                 <el-option label="版头" :value="1"></el-option>
                 <el-option label="版尾" :value="2"></el-option>
             </el-select>
-            <el-button type="primary" style="float:right" @click="handleShowUploadPop">上传图片</el-button>
+            <el-button type="primary" style="float:right" @click="handleShowUploadPop" v-permission="permissionBtn.baseConfigPermission.etaBaseConfig_source_upload">上传图片</el-button>
         </div>
 
         <div class="select-status-box" v-if="selectIds.length>0">

+ 35 - 9
src/views/system_manage/etaBaseConfig.vue

@@ -2,7 +2,7 @@
     <div class="eta-base-config">
         <div class="nav-type-box">
             <span :class="[sectionType===1?'active':'']" @click="sectionType=1">通用设置</span>
-            <span :class="[sectionType===2?'active':'']" @click="sectionType=2">资源库</span>
+            <span :class="[sectionType===2?'active':'']" @click="sectionType=2" v-if="isShowSource">资源库</span>
         </div>
         <!-- 通用设置 -->
         <template v-if="sectionType==1">
@@ -15,7 +15,7 @@
             ref="baseConfigForm"
         >
             <div class="part-type-box" style="margin-bottom:40px">
-                <el-button type="primary" :plain="partType===1?false:true" @click="partType=1" :style="{width:'120px',border:'none',color:partType==1?'#fff':'#333'}">登录设置</el-button>
+                <el-button v-if="isShowLoginConfig" type="primary" :plain="partType===1?false:true" @click="partType=1" :style="{width:'120px',border:'none',color:partType==1?'#fff':'#333'}">登录设置</el-button>
                 <el-button type="primary" :plain="partType===2?false:true" @click="partType=2" :style="{width:'120px',border:'none',color:partType==2?'#fff':'#333'}">研报设置</el-button>
                 <el-button type="primary" :plain="partType===3?false:true" v-if="isShowPPT||isShowEnPPT" @click="partType=3" :style="{width:'120px',border:'none',color:partType==3?'#fff':'#333'}">PPT配置</el-button>
                 <div class="btn-wrap" style="text-align: center;float:right">
@@ -24,7 +24,7 @@
                 </div>
             </div>
             <!-- 登录设置模块 -->
-            <div class="part" v-show="partType===1">
+            <div class="part" v-show="partType===1&&isShowLoginConfig">
                 <div class="side">
                     <!-- <el-form-item label="国内短信模板" prop="LoginSmsTpId" >
                         <div class="form-item-type-two sms-type">
@@ -97,7 +97,7 @@
                                 v-model="checkList" >
                                 <el-checkbox label="研报图表"></el-checkbox>
                             </el-checkbox-group>
-                            <div>
+                            <div v-if="isShowYBShare">
                                 <el-checkbox label="研报分享" v-model="formData.WatermarkReport"></el-checkbox>
                                 <el-tooltip 
                                     effect="dark" 
@@ -201,7 +201,7 @@
                     <el-radio-button label="en">英文PPT</el-radio-button>
                 </el-radio-group>
                 <div v-if="isShowPPT" v-show="pptLang === 'cn'" class="ppt-form-item-wrap">
-                    <div class="inner-input-wrap">
+                    <!-- <div class="inner-input-wrap">
                         <el-form-item label="公司名称" prop="PptCompanyName" class="inline-form-item">
                             <el-input type="text" v-model="formData.PptCompanyName"></el-input>
                         </el-form-item>
@@ -211,7 +211,7 @@
                         <el-form-item label="字体颜色" prop="PptFontColor" class="inline-form-item">
                             <el-input type="color" style="width:64px;" v-model="formData.PptFontColor"></el-input>
                         </el-form-item>
-                    </div>
+                    </div> -->
                     
                     <el-form-item label="PPT封面图" prop="CnPptCoverImgs" style="min-width:400px;">
                         <div class="input-line" style="display:flex;">
@@ -251,7 +251,7 @@
                     </el-form-item>
                 </div>
                 <div v-if="isShowEnPPT" v-show="pptLang === 'en'" class="ppt-form-item-wrap">
-                    <div class="inner-input-wrap">
+                    <!-- <div class="inner-input-wrap">
                         <el-form-item label="公司名称" prop="PptCompanyNameEn" class="inline-form-item">
                             <el-input type="text" v-model="formData.PptCompanyNameEn"></el-input>
                         </el-form-item>
@@ -261,7 +261,7 @@
                         <el-form-item label="字体颜色" prop="PptFontColorEn" class="inline-form-item">
                             <el-input type="color" style="width:64px;" v-model="formData.PptFontColorEn"></el-input>
                         </el-form-item>
-                    </div>
+                    </div> -->
                     <el-form-item label="PPT封面图" prop="EnPptCoverImgs" style="min-width:400px;">
                         <div class="input-line" style="display:flex;">
                             <ImgUpload 
@@ -304,7 +304,7 @@
         
         </template>
         <!-- 资源库 -->
-        <smartReportImgSet v-if="sectionType==2"/>
+        <smartReportImgSet v-if="sectionType==2&&isShowSource"/>
 
         <el-image-viewer 
             v-if="showViewer" 
@@ -494,6 +494,32 @@ export default {
             return this.permissionBtn.checkPermissionBtn(
                 this.permissionBtn.baseConfigPermission.etaBaseConfig_watermark_ybChart
             )
+        },
+        // 是否有登录设置
+        isShowLoginConfig(){
+            return this.permissionBtn.checkPermissionBtn(
+                this.permissionBtn.baseConfigPermission.etaBaseConfig_login
+            )
+        },
+        isShowYBShare(){
+            return this.permissionBtn.checkPermissionBtn(
+                this.permissionBtn.baseConfigPermission.etaBaseConfig_watermark_ybShare
+            )
+        },
+        isShowSource(){
+            return this.permissionBtn.checkPermissionBtn(
+                this.permissionBtn.baseConfigPermission.etaBaseConfig_source_see
+            )
+        },
+    },
+    watch: {
+        'isShowLoginConfig':{
+            handler(){
+                if(!this.isShowLoginConfig&&this.partType==1){
+                    this.partType=2
+                }
+            },
+            immediate:true
         }
     },
     methods: {

+ 6 - 5
src/views/system_manage/operateAuthManage.vue

@@ -417,6 +417,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+@import "~@/styles/theme-vars.scss";
 .container {
   box-sizing: border-box;
   min-height: calc(100vh - 120px);
@@ -440,15 +441,15 @@ export default {
         min-width: 120px;
         padding: 12px 0;
         text-align: center;
-        color: #409EFF;
-        border: 1px solid #B3D8FF;
-        background: #ECF5FF;
+        color: $theme-color;
+        border: 1px solid $theme-color;
+        background: #e6eefb;
         border-radius: 4px;
         cursor: pointer;
         &.act {
           color: #fff;
-          border: 1px solid #409EFF;
-          background: #409EFF;
+          border: 1px solid $theme-color;
+          background: $theme-color;
         }
       }
     }

+ 10 - 1
src/views/system_manage/outlinkList.vue

@@ -25,7 +25,8 @@ import {outlinkConfigInterence} from "@/api/modules/etaBaseConfigApi.js"
     data() {
       return {
         outlinkData:[],
-        colors:['#E3EAFD','#FBEBD5','#DEF4D8','#DEF2FC']
+        colors:['#E3EAFD','#FBEBD5','#DEF4D8','#DEF2FC'],
+        authCode:'',//认证code
       }
     },
     created(){
@@ -36,6 +37,7 @@ import {outlinkConfigInterence} from "@/api/modules/etaBaseConfigApi.js"
         outlinkConfigInterence.getOutlinkListAll().then(res=>{
           if(res.Ret == 200){
             this.outlinkData = res.Data.List || []
+            this.authCode=res.Data.UserCode
             // console.log(this.outlinkData);
             //ETA1.0.8 在数组开头增加一项培训视频链接
             this.outlinkData.unshift({
@@ -52,6 +54,13 @@ import {outlinkConfigInterence} from "@/api/modules/etaBaseConfigApi.js"
         item.Url.startsWith("ftps://") || item.Url.startsWith("file://") || item.Url.startsWith("\/"))){
           Url = "http://"+item.Url
         }
+        // 拼接认证code
+        if(Url.includes('?')){
+          Url=Url+'&authCode='+encodeURIComponent(this.authCode)
+        }else{
+          Url=Url+'?authCode='+encodeURIComponent(this.authCode)
+        }
+
         // console.log(Url);
         window.open(Url, '_blank')
       }

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