Karsa 1 жил өмнө
parent
commit
8215f86e69
42 өөрчлөгдсөн 3400 нэмэгдсэн , 736 устгасан
  1. 1 0
      src/App.vue
  2. 73 0
      src/api/modules/chartThemeApi.js
  3. 16 0
      src/routes/modules/oldRoutes.js
  4. 24 3
      src/styles/global.scss
  5. 10 1
      src/utils/buttonConfig.js
  6. 5 3
      src/utils/defaultOptions.js
  7. 1 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/chartEditor.vue
  8. 1 0
      src/views/chartRelevance_manage/crossVarietyAnalysis/list.vue
  9. 1 0
      src/views/chartRelevance_manage/fittingEquation/fittingEquationList.vue
  10. 1 0
      src/views/chartRelevance_manage/relevance/list.vue
  11. 1 0
      src/views/chartRelevance_manage/statistic/statisticFeatureList.vue
  12. 157 64
      src/views/dataEntry_manage/addChart.vue
  13. 48 14
      src/views/dataEntry_manage/chartSetting.vue
  14. 400 0
      src/views/dataEntry_manage/components/addMarkerDialog.vue
  15. 6 1
      src/views/dataEntry_manage/components/barOptionSection.vue
  16. 39 43
      src/views/dataEntry_manage/components/chart.vue
  17. 105 0
      src/views/dataEntry_manage/components/chartSourceEditDialog.vue
  18. 300 0
      src/views/dataEntry_manage/components/markersSection.vue
  19. 3 0
      src/views/dataEntry_manage/components/satterSeriesDia.vue
  20. 6 1
      src/views/dataEntry_manage/components/sectionalScatterOption.vue
  21. 2 1
      src/views/dataEntry_manage/css/chartfit.scss
  22. 1 1
      src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue
  23. 1 1
      src/views/dataEntry_manage/databaseComponents/createChart.vue
  24. 163 71
      src/views/dataEntry_manage/editChart.vue
  25. 153 25
      src/views/dataEntry_manage/mixins/addOreditMixin.js
  26. 407 248
      src/views/dataEntry_manage/mixins/chartPublic.js
  27. 9 2
      src/views/futures_manage/chartEditor.vue
  28. 1 0
      src/views/futures_manage/commodityChartBase.vue
  29. 37 11
      src/views/mychart_manage/components/chartDetailDia.vue
  30. 372 229
      src/views/ppt_manage/mixins/mixins.js
  31. 30 5
      src/views/ppt_manage/mixins/pptMixins.js
  32. 1 1
      src/views/ppt_manage/newVersion/components/catalog/pptContentOld.vue
  33. 44 3
      src/views/ppt_manage/newVersion/components/formatEl/ChartEl.vue
  34. 11 1
      src/views/ppt_manage/newVersion/utils/untils.js
  35. 1 1
      src/views/ppt_manage/pptdtl.vue
  36. 1 0
      src/views/predictEdb_manage/components/chartInfo.vue
  37. 1 1
      src/views/sandbox_manage/sandFlowNew/components/addLInkDia.vue
  38. 130 0
      src/views/system_manage/chartTheme/common/config.js
  39. 334 0
      src/views/system_manage/chartTheme/components/optionsSection.vue
  40. 285 0
      src/views/system_manage/chartTheme/index.vue
  41. 212 0
      src/views/system_manage/chartTheme/themeSetting.vue
  42. 6 5
      src/views/system_manage/operateAuthManage.vue

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

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

@@ -335,6 +335,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;
+    }
 }

+ 10 - 1
src/utils/buttonConfig.js

@@ -661,6 +661,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  = {
@@ -676,7 +683,9 @@ const btnMap  = {
     productPricePermission,sysDepartPermission,
     operateAuthPermission,baseConfigPermission,
     outlinkConfigPermission,approveFlowPermission,
-    approvePermission
+    approvePermission,
+    outlinkConfigPermission,
+    chartThemePermission
 }
 
 /**

+ 5 - 3
src/utils/defaultOptions.js

@@ -2,6 +2,7 @@ export const defaultOpts = {
 	//图表配置
 	chart: {
 
+		spacing: [2,10,2,10]
 	},
 	title: {
 		enabled: false
@@ -80,7 +81,7 @@ export const defaultOpts = {
 	legend: {
 		enabled: true,
 		verticalAlign: 'top',
-		margin:20,
+		margin:5,
 		// layout: 'vertical'
 	},
 	//滚动条
@@ -164,12 +165,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,

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

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

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

@@ -168,6 +168,7 @@
                   </h2>
                   <Chart
                     :options="options"
+                    :chartInfo="chartInfo"
                     minHeight="440px"
                     height="500px"
                     ref="chartRef"

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

+ 48 - 14
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,40 @@
                     >作者:{{ 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" 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-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>
 
                 <!-- 异常显示 -->
@@ -2873,7 +2907,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 +2947,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"
+      >
+        <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: 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
+      } ,
+
+      /* 标识线区弹窗 */
+      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() {
+      const { text,color,fontSize } = this.chartInstruction;
+      this.chartInductionDiaForm = {
+        show: true,
+        text,
+        color,
+        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];
     },
 
     /* 保存新增系列 */

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

@@ -261,12 +261,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;

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

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

+ 163 - 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,15 @@ 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.$refs.markerSectionRef.initData(ChartInfo);
+
           this.tableData = EdbInfoList;
 
 					this.calendar_type = this.chartInfo.Calendar; //日历类型
@@ -680,6 +756,8 @@ export default {
 
 					//截面散点图
 					this.chartInfo.ChartType === 10 && this.initSectionScatterData(res.Data);
+					
+					this.getThemeList();
 
         });
 		},
@@ -764,6 +842,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 +853,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 +883,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 +995,6 @@ export default {
 			overflow-y: auto;
 			.search-cont {
 				color: #606266;
-				margin-top: 10px;
 			}
 			.xaxis-range-cont{
 				color: #606266;
@@ -1085,7 +1177,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 +1216,7 @@ export default {
 								justify-content: space-between;
 								top: auto;
 								right: 0;
-								bottom: -3%;
+								bottom: -2%;
 								.left {
 									width: 60px;
 									display: block;

+ 153 - 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,7 @@ 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;
 
 				let xData = XEdbIdValue.map(_ => EdbInfoList.find(edb => edb.EdbInfoId===_).EdbAliasName)
 
@@ -265,6 +304,9 @@ export default {
 						max: Math.max(...value_arr)
 					}
 				}
+				
+				//默认来源搞一下
+				this.setDefaultSourceFrom(ChartInfo);
 			})
 		},
 
@@ -383,11 +425,6 @@ export default {
 			this.getPreviewSplineInfo();
 		},
 
-			/* 季节图切换年份  保持当前配置 */
-		// seasonYearChange() {
-		// 	this.getPreviewSplineInfo();
-		// },
-
 		/* 切换图重置状态 */
 		initStatus() {
 			this.year_select = this.chartInfo.ChartType === 2?20:3;
@@ -409,14 +446,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 +515,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 +574,7 @@ export default {
 			}).then(res => {
 				if(res.Ret !== 200) return
 				
-				const { EdbInfoList,DataResp } = res.Data;
+				const { EdbInfoList,DataResp,ChartInfo } = res.Data;
 
 				this.sectionScatterData = DataResp;
 				this.tableData = EdbInfoList;
@@ -545,6 +590,9 @@ export default {
 						x_max: Math.max(...x_value_arr)
 					}
 				}
+
+				//默认来源搞一下
+				this.setDefaultSourceFrom(ChartInfo);
 			})
 		},
 
@@ -698,6 +746,86 @@ 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.reLoadChartOption();
+		},
+
+		/* 更新图表标识区,标识线,图表说明 */
+		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);
+		},
+
+		/* 添加图表默认显示图表来源 */
+		setDefaultSourceFrom(ChartInfo) {
+			if(!this.chartInfo.SourcesFrom) {
+				this.chartInfo.SourcesFrom = JSON.stringify({
+					isShow: this.chartInfo.SourcesFromVisable,
+					text: ChartInfo.ChartSource,
+					color: JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.color,
+					fontSize: JSON.parse(this.chartInfo.ChartThemeStyle).markerOptions.style.fontSize
+				});
+			}
+		},
+
+		/* 数据来源显示隐藏 */
+		changeSourceVisable() {
+			this.chartInfo.SourcesFrom = JSON.stringify({
+				...JSON.parse(this.chartInfo.SourcesFrom),
+				isShow:this.chartInfo.SourcesFromVisable
+			})
 		}
 	}
 }

+ 407 - 248
src/views/dataEntry_manage/mixins/chartPublic.js

@@ -139,6 +139,7 @@ export const chartSetMixin = {
       
 			chartItemStyleArr:[
 				{ label: '曲线图', key: 1 ,value: 'spline'},
+				{ label: '折线图', key: 2 ,value: 'line'},
         // { label: '堆积面积图', key: 3 ,value: 'areaspline'},
         { label: '堆积柱状图', key: 4 ,value: 'column'},
 			],//组合图可选样式
@@ -547,7 +548,7 @@ export const chartSetMixin = {
         3: this.setStackOrCombinChart,
         4: this.setStackOrCombinChart,
         5: this.setScatterChart,
-        6: this.setStackOrCombinChart
+        6: this.setStackOrCombinChart,
       };
 
       chartSetMap[this.chartInfo.ChartType]&&chartSetMap[this.chartInfo.ChartType](newval)
@@ -570,10 +571,12 @@ export const chartSetMixin = {
         this.rightTwoIndex = newval.findIndex((item) => item.IsAxis ===2);
       }
 
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //拼接标题 数据列
       let data = [];
       let ydata = [];
-      // let chartData =  _.cloneDeep(newval);
       //有右二轴时排个序 按照左 右 右2的顺序
       let chartData = newval.some(_ =>_.IsAxis===2) ? this.changeEdbOrder(newval) : _.cloneDeep(newval);
 
@@ -591,11 +594,12 @@ export const chartSetMixin = {
             textCh:item.Unit, // 中文
             // 中文不存在,无论英文有无都显示空
             textEn:item.UnitEn||item.Unit, // 英文
-            style:{},
-            styleEn:{}, // 英文样式
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
             align: 'high',
             rotation: 0,
-            y: -15,
+            y: -12,
             x: (item.IsAxis===0 && this.rightTwoIndex>-1) ? -chartData[this.rightTwoIndex].Unit.length*12 : 0,
             textAlign: item.IsAxis===1 ? 'left' : 'right',
             reserveSpace: false
@@ -605,16 +609,19 @@ export const chartSetMixin = {
               return ctx.value;
             },
             align: 'center',
-            x: [0,2].includes(item.IsAxis) ? 5 : -5
+            x: [0,2].includes(item.IsAxis) ? 5 : -5,
+            style: {
+              ...chartTheme&&chartTheme.yAxisOptions.style,
+            }
           },
           opposite: [0,2].includes(item.IsAxis),
           reversed: item.IsOrder,
-          // // min: Number(chartData[sameSideIndex].MinData),
-          // // max: Number(chartData[sameSideIndex].MaxData),
           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)
         };
 
         //拼接标题 判断相同指标名称拼接来源
@@ -633,18 +640,19 @@ export const chartSetMixin = {
         //数据列
         let obj = {
           data: [],
-          type: 'spline',
+          type: (chartTheme&&chartTheme.lineOptions.lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
           yAxis: sameSideIndex,
           name:
             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}`,
           nameCh:dynamic_arr.length > 1
-          ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
-          : `${item.EdbName}${dynamic_tag}`,
-          nameEn:item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:`${item.EdbName}${dynamic_tag}`,
+          ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
+          : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
+          nameEn:item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:`${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
           color: item.ChartColor,
-          lineWidth: Number(item.ChartWidth),
+          lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptions.lineWidth),
           ...predict_params
         };
         item.DataList = item.DataList || [];
@@ -666,7 +674,12 @@ export const chartSetMixin = {
               ? 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 = {
@@ -675,8 +688,6 @@ export const chartSetMixin = {
         xAxis
       };
 
-      console.log(this.options)
-
       //滚动相关性独立tooltip
       if(this.chartInfo.Source === 4) {
         const { LeadValue,LeadUnit } = this.relevanceChartData.CorrelationChartInfo;
@@ -705,7 +716,7 @@ export const chartSetMixin = {
     本来和曲线图逻辑基本一致兼容下即可 为了以后便于维护和阅读还是拆开写吧
      */
     setStackOrCombinChart(newval) {
-
+      
       const chartTypeMap = {
         3: 'areaspline',
         4: 'column',
@@ -713,10 +724,12 @@ export const chartSetMixin = {
       };
       let chartStyle = chartTypeMap[this.chartInfo.ChartType];
 
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //拼接标题 数据列
       let data = [];
       let ydata = [];
-      // let chartData =  _.cloneDeep(newval);
       //有右二轴时排个序 按照左 右 右2的顺序
       let chartData = newval.some(_ =>_.IsAxis===2) ? this.changeEdbOrder(newval) : _.cloneDeep(newval);
 
@@ -754,35 +767,38 @@ export const chartSetMixin = {
         let yItem = {
           ...basicYAxis,
           title: {
-            // text: sameSideIndex !== index ? '' : `${item.Unit}`,
             text: item.Unit,
             textCh:item.Unit, // 中文
             // 中文不存在,无论英文有无都显示空
             textEn:item.UnitEn||item.Unit, // 英文
-            style:{},
-            styleEn:{}, // 英文样式
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
             align: 'high',
             rotation: 0,
-            y: -15,
+            y: -12,
             x: (item.IsAxis===0 && this.rightTwoIndex>-1) ? -chartData[this.rightTwoIndex].Unit.length*12 : 0,
             textAlign: item.IsAxis===1 ? 'left' : 'right',
             reserveSpace: false
           },
           labels: {
             formatter: function (ctx) {
-              // return sameSideIndex !== index ? '' : ctx.value;
               return ctx.value;
             },
             align: 'center',
-            x: [0,2].includes(item.IsAxis) ? 5 : -5
+            x: [0,2].includes(item.IsAxis) ? 5 : -5,
+            style: {
+              ...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,
           tickWidth: 1,
-          visible: serie_yIndex === index && sameSideIndex ===index
+          visible: serie_yIndex === index && sameSideIndex ===index,
+          plotBands: this.setAxisPlotAreas(item.IsAxis),
+          plotLines: this.setAxisPlotLines(item.IsAxis)
         };
 
         //拼接标题 判断相同指标名称拼接来源
@@ -805,18 +821,18 @@ export const chartSetMixin = {
           yAxis: serie_yIndex,
           name:
             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}`,
           nameCh:dynamic_arr.length > 1
-          ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
-          : `${item.EdbName}${dynamic_tag}`,
-          nameEn:item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:`${item.EdbName}${dynamic_tag}`,
+          ? `${item.EdbAliasName||item.EdbName}(${item.SourceName})${dynamic_tag}`
+          : `${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
+          nameEn:item.EdbNameEn?`${item.EdbNameEn}${dynamic_tag_en}`:`${item.EdbAliasName||item.EdbName}${dynamic_tag}`,
           color: item.ChartColor,
-          lineWidth: (this.chartInfo.ChartType === 6 && item.ChartStyle === 'spline') ? Number(item.ChartWidth) : 0,
+          lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptions.lineWidth),
           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 || [];
@@ -837,7 +853,12 @@ export const chartSetMixin = {
               ? 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 = {
@@ -864,115 +885,82 @@ export const chartSetMixin = {
                             this.isPredictorChart?chartData.DataList.List.filter((item, index) => index > 0):
                             chartData.DataList.filter((item, index) => index > 0):
                             chartData.DataList
+       /* 主题样式*/
+       const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
 
       let seasonYdata = [],
         seasonData = [];
-        /* 公历数据处理 处理数据列 y轴 */
-        // if (this.calendar_type === '公历')
-        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: this.isPredictorChart?j.Year:j.ChartLegend,
-            ...predict_params
-          };
-          const data_array = this.calendar_type === '农历' && this.isPredictorChart?_.cloneDeep(j.Items):_.cloneDeep(j.DataList);
-          data_array &&
-            data_array.forEach((item) => {
-              serie_item.data.push([item.DataTimestamp, item.Value]);
-            });
-          const index = chartDataHandle.findIndex(
-            (item) => this.isPredictorChart?item.Year === j.Year:item.ChartLegend === j.ChartLegend
-          );
-          const s_yItem = {
-            labels: {
-              formatter: function () {
-                let val = this.value;
-                return index !== 0 ? '' : val;
-              },
-              align: 'center',
-            },
-            title: {
-              text:  `${chartData.Unit}`,
-              textCh:chartData.Unit, // 中文
-              // 中文不存在,无论英文有无都显示空
-              textEn:chartData.UnitEn||chartData.Unit, // 英文
-              style:{},
-              styleEn:{}, // 英文样式
-              // text:  null,
-              align: 'high',
-              rotation: 0,
-              y: -15,
-              offset: -(12 * chartData.Unit.length),
-            },
-            max: Number(chartData.MaxData),
-            min: Number(chartData.MinData),
-            ...seasonOptions.yAxis,
-          };
-          seasonData.push(serie_item);
-          seasonYdata.push(s_yItem);
-        }
 
-      // /* 农历数据处理  */
-      // let filterArr =
-      //   this.calendar_type === '农历'
-      //     ? chartData.DataList.filter((item, index) => index > 0)
-      //     : [];
-      // if (this.calendar_type === '农历')
-      //   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.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 = filterArr.findIndex((item) => item.ChartLegend === j.ChartLegend);
-      //     const s_yItem = {
-      //       labels: {
-      //         formatter: function () {
-      //           let val = this.value;
-      //           return index !== 0 ? '' : val;
-      //         },
-      //         align: 'center',
-      //       },
-      //       title: {
-      //         text:  `${chartData.Unit}`,
-      //         textCh:chartData.Unit, // 中文
-      //         // 中文不存在,无论英文有无都显示空
-      //         textEn:chartData.UnitEn||chartData.Unit, // 英文
-      //         styleEn:{}, // 英文样式
-      //         // text:  null,
-      //         align: 'high',
-      //         rotation: 0,
-      //         y: -15,
-      //         offset: -(12 * chartData.Unit.length),
-      //       },
-      //       max: Number(chartData.MaxData),
-      //       min: Number(chartData.MinData),
-      //       ...seasonOptions.yAxis,
-      //     };
-      //     seasonData.push(serie_item);
-      //     seasonYdata.push(s_yItem);
-      //   }
-      /* x轴显示月日  提示框显示月日*/
-      defaultOpts.xAxis.labels = {
-        formatter: function () {
-          return Highcharts.dateFormat('%m/%d', this.value);
+      //数据列
+      for (let j of chartDataHandle) {
+        //预测指标配置
+        let predict_params =  chartData.EdbInfoCategoryType === 1 ? this.getSeasonPredictParams(j.CuttingDataTimestamp) : {};
+        
+        let serie_item = {
+          data: [],
+          type: (chartTheme&&chartTheme.lineOptions.lineType) || chartData.ChartStyle,
+          dashStyle: (chartTheme&&chartTheme.lineOptions.dashStyle)||'Solid',
+          yAxis: 0,
+          name: this.isPredictorChart?j.Year:j.ChartLegend,
+          lineWidth: (chartTheme&&chartTheme.lineOptions.lineWidth) || 1,
+          ...predict_params
+        };
+        const data_array = this.calendar_type === '农历' && this.isPredictorChart?_.cloneDeep(j.Items):_.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 = {
+        ...defaultOpts.xAxis,
+        labels: {
+          formatter: function () {
+            return Highcharts.dateFormat('%m/%d', this.value);
+          },
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        plotBands: this.setAxisPlotAreas(3,'datetime'),
+        plotLines: this.setAxisPlotLines(3,'datetime')
+      }
       
       const tooltip = {
         ...defaultOpts.tooltip,
@@ -985,49 +973,13 @@ export const chartSetMixin = {
         },
         xDateFormat: '%m/%d',
       }
-      let rangeSelector =
-        this.calendar_type === '农历' && this.isPredictorChart
-          ? {
-              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: '全部',
-                  type: 'all',
-                },
-              ],
-            }
-          : {
-              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,
-        rangeSelector,
+        xAxis,
         tooltip
       };
       if(this.currentLang=='en') this.changeOptions()
@@ -1045,6 +997,9 @@ export const chartSetMixin = {
       };
       console.log('===========:',this.isSetExtremeValue)
 
+      /* 主题样式*/
+       const chartTheme = this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       // 取2个指标中日期相同的数据
       let real_data = [];
       let tmpData_date = {};//用来取点对应的日期
@@ -1117,12 +1072,15 @@ export const chartSetMixin = {
           textCh:newval[1].Unit,// 中文
           // 中文不存在,无论英文有无都显示空
           textEn:newval[1].UnitEn||newval[1].Unit, // 英文
-          style:{},
-          styleEn:{}, // 英文样式
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
           align: 'high',
           rotation: 0,
-          y: -15,
-          offset: -(12 * newval[1].Unit.length),
+          y: -12,
+          x:0,
+          textAlign: 'left',
+          reserveSpace: false
         },
         labels: {
           formatter: function (ctx) {
@@ -1130,12 +1088,42 @@ export const chartSetMixin = {
             return val;
           },
           align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         opposite: false,
         reversed: IsOrder,
         min: Number(newval[0].MinData),
         max: Number(newval[0].MaxData),
         tickWidth: 1,
+        plotBands: this.setAxisPlotAreas(1),
+        plotLines: this.setAxisPlotLines(1)
+      }
+
+      //x轴
+      const xAxis = {
+        ...scatterXAxis,
+        title: {
+          text:  `${newval[0].Unit}`,
+          textCh:newval[0].Unit, // 中文
+          // 中文不存在,无论英文有无都显示空
+          textEn:newval[0].UnitEn||newval[0].Unit, // 英文
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          },
+          align: 'high',
+          rotation: 0,
+          x: 0,
+          offset: 20,
+        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        plotBands: this.setAxisPlotAreas(3),
+        plotLines: this.setAxisPlotLines(3)
       }
 
       //数据列
@@ -1146,7 +1134,10 @@ export const chartSetMixin = {
         nameCh: `${this.chartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`,
         nameEn: `${this.chartInfo.ChartNameEn||this.chartInfo.ChartName}${IsOrder ? '(reverse)' : ''}`,
         color: ChartColor,
-        lineWidth: 0
+        chartType: 'linear',
+        marker: {
+          radius: (chartTheme&&chartTheme.lineOptions.radius)||5,
+        },
       }
       real_data.forEach(_ => {
         series.data.push([_.x,_.y])
@@ -1158,22 +1149,7 @@ export const chartSetMixin = {
         },
         series: [ series ],
         yAxis,
-        xAxis: {
-          ...scatterXAxis,
-          title: {
-            text:  `${newval[0].Unit}`,
-            textCh:newval[0].Unit, // 中文
-            // 中文不存在,无论英文有无都显示空
-            textEn:newval[0].UnitEn||newval[0].Unit, // 英文
-            style:{},
-            styleEn:{}, // 英文样式
-            // text:  null,
-            align: 'high',
-            rotation: 0,
-            x: 0,
-            offset: 20,
-          },
-        },
+        xAxis,
         tooltip
       }
       if(this.currentLang=='en') this.changeOptions()
@@ -1186,18 +1162,19 @@ export const chartSetMixin = {
       let seriesData = [];
       const data = _.cloneDeep(this.barDateList);
 
+       /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       //x轴
       let xAxis = {
         ...scatterXAxis,
         categories: this.barXData,
         tickWidth: 1,
-        title: {
-          text:  ``,
-          align: 'high',
-          rotation: 0,
-          x: 0,
-          offset: 20,
-        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        }
       }
 
       const { max,min } = this.chartLimit;
@@ -1211,8 +1188,13 @@ export const chartSetMixin = {
           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) {
@@ -1220,11 +1202,16 @@ export const chartSetMixin = {
             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)
       }
 
       //数据列
@@ -1268,18 +1255,19 @@ export const chartSetMixin = {
       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;
@@ -1290,10 +1278,14 @@ export const chartSetMixin = {
           text:  this.commodityEdbList[0].Unit,
           textCh:  this.commodityEdbList[0].Unit,
           textEn:  this.commodityEdbList[0].UnitEn||this.commodityEdbList[0].Unit,
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
           align: 'high',
           rotation: 0,
-          y: -15,
-          offset: 0,
+          y: -12,
+          textAlign: 'left',
+          reserveSpace: false
         },
         labels: {
           formatter: function (ctx) {
@@ -1301,6 +1293,9 @@ export const chartSetMixin = {
             return val;
           },
           align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
         min: Number(min),
         max: Number(max),
@@ -1316,14 +1311,15 @@ export const chartSetMixin = {
       
         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
           }
@@ -1488,6 +1484,10 @@ export const chartSetMixin = {
       this.leftIndex = -1;
       this.rightIndex = -1;
       this.rightTwoIndex = -1;
+
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       // 处理X轴
       let xAxis={
         categories: this.relevanceChartData.XEdbIdValue,
@@ -1498,9 +1498,14 @@ export const chartSetMixin = {
           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,
@@ -1516,8 +1521,12 @@ export const chartSetMixin = {
           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) {
@@ -1525,12 +1534,12 @@ export const chartSetMixin = {
             return val;
           },
           align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
         },
-        // min: -1,
-        // max: 1,
         opposite: false,
         tickWidth: 1,
-        // tickInterval:0.2,
       }
 
       //处理series
@@ -1538,14 +1547,15 @@ export const chartSetMixin = {
       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
           }
@@ -1605,6 +1615,9 @@ export const chartSetMixin = {
       const { DataList,XName,XNameEn,YName,YNameEn } = 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,
@@ -1612,15 +1625,23 @@ export const chartSetMixin = {
           text: YName,
           textCh:YName,// 中文
           textEn:YNameEn||YName,
-          style:{},
-          styleEn:{},
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
           align: 'middle',
         },
+        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轴
@@ -1630,12 +1651,20 @@ export const chartSetMixin = {
           text: XName,
           textCh:XName,// 中文
           textEn:XNameEn || XName,
-          style:{},
-          styleEn:{},
+          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)
       }
 
       //数据列
@@ -1649,9 +1678,11 @@ export const chartSetMixin = {
           nameCh: item.Name,
           nameEn: item.NameEn||item.Name,
           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({
@@ -1773,17 +1804,18 @@ export const chartSetMixin = {
       this.rightIndex = -1;
       this.rightTwoIndex = -1;
 
+        /* 主题样式*/
+      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
+          }
         }
       }
 
@@ -1798,8 +1830,16 @@ export const chartSetMixin = {
             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),
@@ -1809,13 +1849,14 @@ export const chartSetMixin = {
 
         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
         }
@@ -1857,6 +1898,9 @@ export const chartSetMixin = {
       this.rightIndex = -1;
       this.rightTwoIndex = -1;
       
+      /* 主题样式*/
+      const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
+
       const { min,max,x_min,x_max }  = this.chartLimit;
 
       const { DataList,XName,YName,XNameEn,YNameEn } = this.crossVarietyChartData;
@@ -1869,6 +1913,14 @@ export const chartSetMixin = {
           textCh:YName,// 中文
           textEn:YNameEn||YName,
           align: 'middle',
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+        },
+        labels: {
+          style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+          }
         },
         opposite: false,
         reversed: false,
@@ -1885,6 +1937,14 @@ export const chartSetMixin = {
           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),
@@ -1901,7 +1961,6 @@ export const chartSetMixin = {
           nameCh: item.Name,
           nameEn: item.NameEn||item.Name,
           color: item.Color,
-          lineWidth: 0,
           chartType: 'linear',
           zIndex:1
         }
@@ -2278,6 +2337,7 @@ export const chartSetMixin = {
         sourceMap[this.chartInfo.Source]();
       }
     },
+
     // 设置 起始日期 和 最新日期
     setExtremumDate(){
       //过滤、排序 拿到起始日期
@@ -2291,6 +2351,105 @@ export const chartSetMixin = {
                                       .sort((a,b)=> new Date(b).getTime() - new Date(a).getTime())
       this.latestDate = endDateList[0]
       console.log(this.earliestDate,this.latestDate,'this.latestDate');
+    },
+
+    /* 处理轴的标识线结构 在指定轴位置上拼接标识线 
+      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.tableData[0].DataList[1].DataList
+[0].DataTimestamp).getFullYear() : '';
+          console.log(nowYear)
+          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.tableData[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 - 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"

+ 37 - 11
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"

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

+ 30 - 5
src/views/ppt_manage/mixins/pptMixins.js

@@ -277,6 +277,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{
@@ -502,11 +505,16 @@ 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;
+    console.log(chartTheme)
+
       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
@@ -516,22 +524,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: 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: {

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

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

+ 11 - 1
src/views/ppt_manage/newVersion/utils/untils.js

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

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

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

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

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

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