Browse Source

Merge branch 'master' of http://8.136.199.33:3000/hongze/raiwechat_link_h5

bding 2 weeks ago
parent
commit
97ad560d32

+ 5 - 0
src/router/hzyb/index.js

@@ -65,6 +65,11 @@ export const hzybRoutes=[
                 path:"previewpdf",
                 name:"hzybPreviewPDF",
                 component:() => import("@/views/hzyb/report/PreviewPDF.vue")
+            },
+            {
+                path:"raiDetail",
+                name:"hzybReportRaiDetail",
+                component:() => import("@/views/hzyb/report/RaiDetail.vue")
             }
         ]
     },

File diff suppressed because it is too large
+ 27 - 1240
src/views/hzyb/chart/Detail.vue


+ 3 - 3
src/views/hzyb/chart/component/chartBox.vue

@@ -122,10 +122,10 @@ onMounted(() => {
 	let themeOptions = setThemeOptions();
 
 	console.log(themeOptions)
-
+	
 	let obj={...chartDefaultOpts,...themeOptions,...props.options}
 	console.log(obj);
-	
+	Highcharts.setOptions({ global: { useUTC:props.chartInfo.ChartType==2?true:false } });
 	//stock不支持线形图只支持时间图 某些用chart
 	let is_linear = props.options.series 
 			? props.options.series.some(_ => _.chartType === 'linear')
@@ -200,7 +200,7 @@ watch(
             >
 
 							<template v-if="!item.linkedTo">
-                <span class="color" :style="{background:item.visible?item.color:'#ccc'}"></span>
+                <span class="color" :style="{background:item.visible?(item.color||props.options.colors[index]):'#ccc'}"></span>
                 <span :style="{color:item.visible?'':'#ccc'}">{{item.name.length>20?item.name.replace(/<br>/g,''):item.name}}</span>
 							</template>	
             </div>

+ 22 - 1
src/views/hzyb/forexCalendar/Index.vue

@@ -163,6 +163,15 @@ async function renderCalendar(){
 function handleClickEvent(item){
     if(item.matter_type===1) return Toast("该事项未关联指标")
     const {activeStart,activeEnd} = baseCalendarRef.value?.calendarApi.view||{}
+    // 存一份数据到sessionStorage 回退时回显用
+    const obj={
+        permissionValue:permissionValue.value,
+        permissionName:permissionName.value,
+        monthValue:monthValue.value,
+        activeId:activeId.value,
+        activeIndex:activeIndex.value
+    }
+    sessionStorage.setItem('forexCalendarData',JSON.stringify(obj))
     //信息传到transIndex,在transIndex跳转
     window.parent.postMessage({
         path:'/hzyb/forex/detail',
@@ -178,7 +187,19 @@ function handleClickEvent(item){
     showEventList.value = false
 }
 onMounted(()=>{
-    monthValue.value = new Date()
+    const obj=sessionStorage.getItem('forexCalendarData')?JSON.parse(sessionStorage.getItem('forexCalendarData')):null
+    if(obj){
+        const d=moment(obj.monthValue).format('YYYY/MM/DD')
+        monthValue.value = new Date(d)
+        permissionValue.value=obj.permissionValue
+        permissionName.value=obj.permissionName
+        activeId.value=Number(obj.activeId) 
+        activeIndex.value= Number(obj.activeIndex)
+        changeMonth(monthValue.value)
+    }else{
+        monthValue.value = new Date()
+    }
+    
     getPermissionList()
 })
 </script>

+ 4 - 3
src/views/hzyb/forexCalendar/components/BaseCalendar.vue

@@ -68,7 +68,7 @@ defineExpose({ calendarApi });
             </template>
         </FullCalendar>
         <div class="water-mark" v-if="showMark">
-            <p>{{ moment(markText.date).format("YYYY-MM") }}</p>
+            <p>{{ moment(markText.date).format("YYYY年M月") }}</p>
             <p>{{ markText.type }}</p>
         </div>
     </div>
@@ -178,8 +178,9 @@ defineExpose({ calendarApi });
         flex-direction: column;
         justify-content: center;
         align-items: center;
-        font-size: 64px;
-        opacity: 0.3;
+        font-size: 60px;
+        opacity: 0.2;
+        color: #E3B377;
         p{
             margin:0;
             padding:0;

+ 2 - 2
src/views/hzyb/forexCalendar/transIndex.vue

@@ -86,7 +86,7 @@ watch(hasAuth,(newVal,oldVal)=>{
     }
 })
 
-const iframeURLBase = ref(process.env.NODE_ENV === 'development'?'/xcx_h5':'')
+const iframeURLBase = ref(import.meta.env.VITE_APP_BASE_URL)
 const route = useRoute()
 onMounted(()=>{
     localStorage.setItem('hzyb-token',route.query.token)
@@ -98,7 +98,7 @@ onMounted(()=>{
 <template>
     <!-- 直接将旋转作用在Index.vue上会导致日历插件dateClick不触发,vant组件滑动手势x,y轴相反 -->
     <!-- 包一层,iframe为可替换元素,内部元素不受父级样式影响,但overflow-x,overflow-y判断会对调 -->
-    <iframe :src="iframeURLBase+'/hzyb/forex/index'" class="iframe-class" v-if="hasAuth"></iframe>
+    <iframe :src="iframeURLBase+'hzyb/forex/index'" class="iframe-class" v-if="hasAuth"></iframe>
     <NoAuth v-else :data="noAuth"></NoAuth>
 </template>
 

+ 2446 - 0
src/views/hzyb/hooks/chartRender.js

@@ -0,0 +1,2446 @@
+import { reactive, toRefs, onMounted, ref,watch } from "vue";
+import _ from "lodash";
+import Highcharts from "highcharts";
+import moment from "moment";
+// import router from '@/router'
+
+
+// 散点x轴
+const scatterXAxis = {
+  tickPosition: 'inside',
+  lineColor: '#bfbfbf',
+  tickColor: '#bfbfbf',
+  tickLength:5,
+  ordinal: false,
+  type: 'linear',
+}
+
+// 基础y轴配置
+const basicYAxis = {
+  tickWidth: 1,
+  tickLength: 5,
+  lineWidth: 1,
+  lineColor: '#bfbfbf',
+  tickColor: '#bfbfbf',
+  // offset: 0,
+  visible: true,
+  gridLineWidth: 0,
+  tickPosition: 'inside',
+  endOnTick: false,
+  startOnTick: false,
+  showLastLabel: true,
+  tickPixelInterval: 50,
+}
+
+//基础x轴配置
+const basicXAxis={
+  tickPosition: 'inside',
+  lineColor: '#bfbfbf',
+  tickColor: '#bfbfbf',
+  tickLength:5,
+  type: 'datetime',
+  ordinal: false,
+  dateTimeLabelFormats: {
+      day: '%y/%m',
+      week: '%y/%m',
+      month: '%y/%m',
+      year: '%y/%m',
+  },
+  xDateFormat:'%Y-%m-%d'
+}
+//季节性图设置
+const seasonOptions = {
+  //默认颜色配置
+  colors:['#4B0082','#7FFFAA','#FF4500','#808000','#EEE8AA','#849EC1','#8A4294','#578B5A','#FDA8C7','#53B3FF','#999999','#000000','#FFDF0C','#FF0000','#0033FF'],
+  yAxis: {
+      lineWidth: 1,
+      lineColor: '#bfbfbf',
+      tickColor: '#bfbfbf',
+      offset: 0,
+      opposite: false,
+      reversed: false,
+      visible: true,
+      gridLineWidth: 0,
+      tickWidth: 1,
+      tickLength:5,
+      tickPosition: 'inside',
+      endOnTick: false,
+      startOnTick: false,
+      showLastLabel: true, //显示最后刻度值
+      tickPixelInterval: 50
+  }
+}
+
+
+
+/**
+ * useChartRender 处理图表渲染 返回options
+ * @param Data 详情数据
+ * @param {
+*  Source 1 //ETA图  ChartType: 1曲线图 2季节图 3面积图 4柱状图 5散点图 6组合图 7柱形 10截面散点 11雷达图
+* 2 商品价格
+* 3 相关性
+* 4 滚动相关性
+* 5 商品利润
+* 6 拟合方程
+* 7 统计特征/标准差
+* 8 统计特征/百分位
+* 9 统计特征/频率
+* 10 跨品种分析
+* 11 平衡表图
+* 12 区间分析图
+* }
+*
+*/
+//依赖数据
+const chartData = ref(null)
+let hasLeftAxis=ref(false)//是否有左轴
+let hasRightAxis=ref(false)//是否有右轴
+let hasRightTwoAxis=ref(false)//是否有右2轴
+let axisLimitData=reactive({//左右轴极值
+    leftMin:0,
+    leftMax:0,
+    rightMin:0,
+    rightMax:0,
+    rightTwoMin:0,
+    rightTwoMax:0,
+    xMin:0,
+    xMax:0,
+})
+
+export function userChartRenderState() {
+  return {
+    useChartRender,
+    hasLeftAxis,
+    hasRightAxis,
+    hasRightTwoAxis,
+    axisLimitData
+  }
+}
+
+export const useChartRender = (Data) => {
+
+  chartData.value = Data;
+
+  let chartOptions;
+
+  //eta图
+  if ([1,11,12].includes(Data.ChartInfo.Source)) {
+    setLimitData(Data)
+    const typeMap = {
+      1: setSplineOpt,
+      2: setSeasonOpt,
+      3: setStackOrCombinChart,
+      4: setStackOrCombinChart,
+      5: setScatterOptions,
+      6: setStackOrCombinChart,
+      7: initBarData,
+      10: initSectionScatterData,
+      11: initRadarData,
+      14: initSectionalCombinationChart,
+    };
+
+    chartOptions = typeMap[Data.ChartInfo.ChartType] && typeMap[Data.ChartInfo.ChartType](Data);
+  }else {
+    //其他source图
+    const sourceTypeMap = {
+      2: initCommodityData,
+      3: initRelevanceChart,
+      4: setSplineOpt,
+      5: initCommodityData,
+      6: setSplineOpt,
+      7: setSplineOpt,
+      8: setSplineOpt,
+      9: setStatisticFrequency,
+      10: initCrossVarietyChartData,
+      12: setSplineOpt
+    };
+  
+    chartOptions = sourceTypeMap[Data.ChartInfo.Source] &&
+      sourceTypeMap[Data.ChartInfo.Source](Data);
+  }
+
+
+  return chartOptions
+};
+
+
+// 设置常规图配置 曲线
+function setSplineOpt(e){
+  const isETASource = [1,11,12].includes(e.ChartInfo.Source)  
+  const data=[4,6,7,8].includes(e.ChartInfo.Source)?[e.DataResp]:e.EdbInfoList
+  let series=[]
+  let yAxis=[]
+  let xAxis = {}
+
+  let temYLeftArr=[]
+  let temYRightArr=[]
+  let temYLeftIndex=data.findIndex((item) => item.IsAxis===1)
+  let temYRightIndex=data.findIndex((item) => !item.IsAxis)
+  let temYRightTwoIndex = data.findIndex((item) => item.IsAxis===2)
+  hasLeftAxis.value=temYLeftIndex!==-1
+  hasRightAxis.value=temYRightIndex!==-1
+  hasRightTwoAxis.value=temYRightTwoIndex!==-1
+
+   /* 主题样式*/
+  const chartTheme =  e.ChartInfo.ChartThemeStyle ? JSON.parse(e.ChartInfo.ChartThemeStyle) : null;
+
+  let minAndMaxTimeTemArr=[]//存放所有指标的最大最小时间
+
+  //有右二轴时排个序 按照左 右 右2的顺序
+  let newData = data.some(_ =>_.IsAxis===2) ? changeEdbOrder(data) : data;
+  
+
+  newData.forEach((item,index)=>{
+
+       //轴位置值相同的下标
+      let sameSideIndex = newData.findIndex(i => i.IsAxis === item.IsAxis);
+
+      let dynamic_title = item.EdbName;
+      let dynamic_arr = newData.filter(
+        (item) => dynamic_title === item.EdbName
+      );
+      //处理数据列name
+      let temName= setDyncmicSerieName(item,dynamic_arr)  
+
+      //预测指标配置
+      let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item) : {};
+      // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+      const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+      let seriesItemObj={
+          data:[],
+          dataGrouping:{
+              enabled:false
+          },
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+          yAxis:index,
+          name:temName,
+          color: item.ChartColor,
+          lineWidth: Number(item.ChartWidth)|| (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth)||1,
+          visible:true,
+          LatestDate:item.LatestDate,
+          LatestValue:item.LatestValue,
+          marker: chartTheme && chartTheme.lineOptionList[lineIndex].dataMark && chartTheme.lineOptionList[lineIndex].dataMark!='none'?{
+              enabled:true,
+              symbol: chartTheme.lineOptionList[lineIndex].markType || 'circle',
+              fillColor:chartTheme.lineOptionList[lineIndex].markColor,
+              radius: chartTheme.lineOptionList[lineIndex].markSize
+          }:{},
+          ...predict_params
+      }
+      item.DataList = item.DataList || [];
+      for (let i of item.DataList) {
+        seriesItemObj.data.push([i.DataTimestamp, i.Value]);
+      }
+      series.push(seriesItemObj)
+      
+
+      // 设置y轴
+      if(item.IsAxis){
+          temYLeftArr.push(item)
+      }else{
+          temYRightArr.push(item)
+      }
+
+      //获取上下限
+      let minLimit = 0,maxLimit = 0;
+      if(isETASource){
+          const limitMap = {
+              0:['rightMin','rightMax'],
+              1:['leftMin','leftMax'],
+              2:['rightTwoMin','rightTwoMax']
+          }
+          if(limitMap[item.IsAxis]){
+              minLimit = axisLimitData[`${limitMap[item.IsAxis][0]}`]||0
+              maxLimit = axisLimitData[`${limitMap[item.IsAxis][1]}`]||0
+          }
+      }else {
+        minLimit =  item.MinData
+        maxLimit = item.MaxData
+      }
+      const textZh =e.ChartInfo.Source===12?item.ConvertUnit : item.ConvertUnit||item.Unit
+
+      let yItem={
+          ...basicYAxis,
+          IsAxis:item.IsAxis,
+          labels: {
+              formatter: function (ctx) {
+                  return sameSideIndex !== index ? '' : ctx.value;
+              },
+              align: 'center',
+              x: [0,2].includes(item.IsAxis) ? 5 : -5,
+              style:{
+                  ...chartTheme&&chartTheme.yAxisOptions.style
+              },
+          },
+          tickWidth: sameSideIndex !== index ? 0 : 1,
+          title: {
+              text:  sameSideIndex !== index ? '' : textZh,
+              align: 'high',
+              rotation: 0,
+              y: -15,
+              x: (item.IsAxis===0 && temYRightTwoIndex>-1) ? -newData[temYRightTwoIndex].Unit.length*12 : 0,
+              textAlign: item.IsAxis===1 ? 'left' : 'right',
+              reserveSpace: false,
+              style:{
+                  ...chartTheme&&chartTheme.yAxisOptions.style
+              },
+          },
+          opposite: [0,2].includes(item.IsAxis),
+          reversed: item.IsOrder,
+          min: Number(minLimit),
+          max: Number(maxLimit),
+          visible: sameSideIndex === index,
+          plotBands: setAxisPlotAreas(item.IsAxis),
+          plotLines: setAxisPlotLines(item.IsAxis),
+          chartEdbInfo:item//指标数据用于在保存时读取指标数据
+      }
+      yAxis.push(yItem)
+      
+      if(item.DataList.length>0){
+          minAndMaxTimeTemArr.push(item.DataList[0].DataTimestamp)
+          minAndMaxTimeTemArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
+      }
+      
+  })
+  
+  
+  // 设置x轴
+  // 找出所有指标的最大和最小时间 分成6段
+  let minTime=Math.min.apply(null,minAndMaxTimeTemArr)
+  let maxTime=Math.max.apply(null,minAndMaxTimeTemArr)
+
+
+  const isLessThanOneYear = xTimeDiffer(minTime,maxTime)
+  xAxis={
+      ...basicXAxis,
+      tickInterval:((maxTime-minTime)/6)/(24*3600*1000)>30?(maxTime-minTime)/6:24*3600*1000*30,
+      labels: {
+          formatter:  (ctx)=> {
+              return isLessThanOneYear
+              ? Highcharts.dateFormat('%m/%d', ctx.value)
+              : Highcharts.dateFormat('%y/%m', ctx.value);
+          },
+          style: {
+              ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+      },
+      plotBands: setAxisPlotAreas(3,'datetime'),
+      plotLines: setAxisPlotLines(3,'datetime')
+  }
+  
+
+  yAxis.forEach(item=>{
+      if(item.IsAxis===1){//左轴
+          hasLeftAxis.value=true
+          if(!isETASource){
+            item.min=data[temYLeftIndex].MinData
+            item.max=data[temYLeftIndex].MaxData
+            axisLimitData.leftMin=data[temYLeftIndex].MinData
+            axisLimitData.leftMax=data[temYLeftIndex].MaxData
+          }
+      }else if (item.IsAxis===2){ // 右2轴
+          hasRightTwoAxis.value=true
+          if(!isETASource){
+            item.min=data[temYRightTwoIndex].MinData
+            item.max=data[temYRightTwoIndex].MaxData
+            axisLimitData.rightTwoMin=data[temYRightTwoIndex].MinData
+            axisLimitData.rightTwoMax=data[temYRightTwoIndex].MaxData
+          }
+      }else{
+          hasRightAxis.value=true
+          if(!isETASource){
+            item.min=data[temYRightIndex].MinData
+            item.max=data[temYRightIndex].MaxData
+            axisLimitData.rightMin=data[temYRightIndex].MinData
+            axisLimitData.rightMax=data[temYRightIndex].MaxData
+          }
+      }
+  })
+
+   //滚动相关性独立tooltip
+  if(chartData.value.ChartInfo.Source === 4) {
+      const { LeadValue,LeadUnit } = chartData.value.CorrelationChartInfo;
+      chartData.value.tooltip = {
+        formatter: function() {
+          let str = `${Highcharts.dateFormat('%Y/%m/%d',this.x)}<br><p>相关性系数:${this.y.toFixed(4)}</p><br><p>领先${LeadValue+LeadUnit}</p>`
+         
+          return str
+        }
+      }
+  }
+
+  return {
+    xAxis: [xAxis],
+    yAxis,
+    series,
+    rangeSelector:{ enabled: false}
+  }
+}
+
+
+//设置季节图配置
+function setSeasonOpt(e){
+  hasLeftAxis.value=true
+  hasRightTwoAxis = false
+
+  const {RightAxis:SeasonRightConfig={}} = e.DataResp||{}
+  hasRightAxis.value=SeasonRightConfig.IsShow?true:false
+
+  /* 主题样式*/
+  const chartTheme =  e.ChartInfo.ChartThemeStyle ? JSON.parse(e.ChartInfo.ChartThemeStyle) : null;
+
+  let chartData={}
+  const data=e.EdbInfoList[0]
+  const calendarType=e.ChartInfo.Calendar||'公历'
+
+  const colorsArr=chartTheme&&chartTheme.colorsOptions.reverse();
+  let series=[],yAxis=[]
+
+  // 公历
+  // ETA1.0.5 农历数据需要去除第一项 除此之外 农历和公历处理逻辑一样
+  const chartDataHandle = calendarType === '农历'?
+                          data.DataList.slice(1,data.DataList.length)||[]:
+                          data.DataList
+
+  // 跟颜色对应
+  chartTheme && (chartTheme.lineOptionList=chartTheme.lineOptionList.reverse().slice(-chartDataHandle.length))
+
+  let maxDateRange=0;
+  //常规左轴
+  chartDataHandle.forEach((item,index)=>{
+          //预测指标配置
+      let predict_params =  data.EdbInfoCategoryType === 1 ? getSeasonPredictParams(item.CuttingDataTimestamp) : {};
+      // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+      const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+      let seriesItem={
+          data:[],
+          dataGrouping:{
+              enabled:false
+          },
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || data.ChartStyle,
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+          yAxis:0,
+          name:item.ChartLegend,
+          lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 1,
+          // color:colorsArr.slice(-chartDataHandle.length)[lineIndex],       
+          visible:true,
+          marker: chartTheme && chartTheme.lineOptionList[lineIndex].dataMark && chartTheme.lineOptionList[lineIndex].dataMark!='none'?{
+              enabled:true,
+              symbol: chartTheme.lineOptionList[lineIndex].markType || 'circle',
+              fillColor:chartTheme.lineOptionList[lineIndex].markColor,
+              radius: chartTheme.lineOptionList[lineIndex].markSize
+          }:{},
+          ...predict_params
+      }
+      item.DataList=item.DataList||[]
+
+      const data_array=item.DataList||[]
+      if(data_array.length>0){
+          let dateRange = item.DataList[item.DataList.length-1].DataTimestamp - item.DataList[0].DataTimestamp
+          // 时间范围
+          maxDateRange=Math.max(maxDateRange,dateRange)
+      }
+
+      for(let i of item.DataList){
+          seriesItem.data.push([i.DataTimestamp, i.Value])
+      }
+      series.push(seriesItem)
+
+  })
+  //同期上下限/均线/标准差
+  const {MaxMinLimits={},SamePeriodAverage={},SamePeriodStandardDeviation={}} = e.DataResp||{}
+  if(MaxMinLimits.IsShow&&MaxMinLimits.List&&MaxMinLimits.List.length){
+      let serieItem = {
+          type:'arearange',//上下限是一个范围
+          data:[],
+          name:MaxMinLimits.Legend||'同期上下限',
+          color:MaxMinLimits.Color||'#075EEE' ,
+          fillOpacity:parseRgbaColor(MaxMinLimits.Color||'')>0.75?0.75:parseRgbaColor(MaxMinLimits.Color||''), //透明度最高0.75 
+          visible:true,
+      }
+      MaxMinLimits.List.forEach(item=>{
+          serieItem.data.push([item.DataTimestamp,item.MinValue,item.MaxValue])
+      })
+      series.push(serieItem)
+  }
+  if(SamePeriodAverage.IsShow&&SamePeriodAverage.List){
+      let serieItem = {
+          type:'line',
+          data:[],
+          lineWidth:SamePeriodAverage.LineWidth,
+          dashStyle:SamePeriodAverage.LineType,
+          name:SamePeriodAverage.Legend||'同期均值',
+          color:SamePeriodAverage.Color||'#075EEE',
+          visible:true,
+      }
+      SamePeriodAverage.List.forEach(item=>{
+          serieItem.data.push([item.DataTimestamp,item.Value])
+      })
+      series.push(serieItem)
+  }
+  if(SamePeriodStandardDeviation.IsShow&&SamePeriodStandardDeviation.List){
+      let serieItem = {
+          type:'arearange',//标准差也是一个范围
+          data:[],
+          name:SamePeriodStandardDeviation.Legend||'同期标准差',
+          color:SamePeriodStandardDeviation.Color||'#075EEE',
+          fillOpacity:parseRgbaColor(SamePeriodStandardDeviation.Color||'')>0.75?0.75:parseRgbaColor(SamePeriodStandardDeviation.Color||''),
+          visible:true,
+      }
+      SamePeriodStandardDeviation.List.forEach(item=>{
+          serieItem.data.push([item.DataTimestamp,item.MinValue,item.MaxValue])
+      })
+      series.push(serieItem)
+  }
+  //右轴
+  if(SeasonRightConfig.IsShow){
+      //右轴的设置
+      let serieConfig = SeasonRightConfig.Style==='column'?{
+          //柱形
+          type:'column',
+          color:SeasonRightConfig.ChartColor,
+          visible:true,
+      }:{
+          //标记点
+          type:'spline',
+          lineWidth:SeasonRightConfig.LineWidth,
+          dashStyle:SeasonRightConfig.LineStyle,
+          color:SeasonRightConfig.IsConnected?SeasonRightConfig.LineColor:'rgba(255, 255, 255, 0)',//没有连线颜色设置为透明
+          marker:{
+              enabled:true,
+              symbol:SeasonRightConfig.Shape,
+              fillColor:SeasonRightConfig.ChartColor,
+              radius:SeasonRightConfig.Size
+          },
+          visible:true,
+      }
+      let serieItem = {
+          ...serieConfig,
+          name:SeasonRightConfig.Legend||'',
+          data:[],
+          yAxis:1,
+      }
+      const DataList = (SeasonRightConfig.IndicatorType===1?SeasonRightConfig.EdbInfoList[0].DataList:e.EdbInfoList[1]?.DataList)||[]
+      DataList.forEach(item=>{
+          serieItem.data.push([item.DataTimestamp,item.Value])
+      })
+      series.push(serieItem)
+  }
+
+  //获取上下限
+  let minLimit = 0,maxLimit = 0,rightMin = 0,rightMax = 0
+  //非ETA图库不使用自定义上下限 非ETA图库的季节性图也不能设置右轴
+  minLimit = axisLimitData.leftMin||0
+  maxLimit = axisLimitData.leftMax||0
+  //右轴上下限设置
+  if(SeasonRightConfig.IsShow){
+      rightMin = axisLimitData.rightMin||0
+      rightMax = axisLimitData.rightMax||0
+  }
+  const textZh = data.ConvertUnit||data.Unit
+
+  yAxis=[{
+      IsAxis:data.IsAxis,
+      labels: {
+          align: 'center',
+          y:5,
+          style: {
+              ...chartTheme&&chartTheme.yAxisOptions.style
+          }
+      },
+      title: {
+          text:  textZh,
+          align: 'high',
+          rotation: 0,
+          y: -15,
+          x: 0,
+          textAlign: 'left',
+          reserveSpace: false,
+          style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+      },
+      max: Number(maxLimit),
+      min: Number(minLimit),
+      plotBands: setAxisPlotAreas(1),
+      plotLines: setAxisPlotLines(1),
+      lineWidth: 1,
+      lineColor: '#bfbfbf',
+      tickColor: '#bfbfbf',
+      offset: 0,
+      opposite: false,
+      reversed: false,
+      visible: true,
+      gridLineWidth: 0,
+      tickWidth: 1,
+      tickLength:5,
+      tickPosition: 'inside',
+      endOnTick: false,
+      startOnTick: false,
+      showLastLabel: true, //显示最后刻度值
+      tickPixelInterval: 50,
+      // chartEdbInfo:item//指标数据
+  }]
+
+  //如果有右轴,yAxis加上右轴
+  if(SeasonRightConfig.IsShow){
+      const rightEdb = (SeasonRightConfig.IndicatorType===1?SeasonRightConfig.EdbInfoList[0]:e.EdbInfoList[1])||{Unit:''}
+      //左轴同比:text为空或% 右轴指标:取指标单位
+      if(SeasonRightConfig.IndicatorType===1){
+          rightEdb.Unit = SeasonRightConfig.NumFormat===1?'%':''
+      }else{
+          rightEdb.Unit = e.EdbInfoList[1]&&(e.EdbInfoList[1].ConvertUnit||e.EdbInfoList[1].Unit)||''
+      }
+      yAxis.push({
+          ...seasonOptions.yAxis,
+          opposite: true,//右轴
+          labels: {
+              align: 'center',
+              y:5,
+              style: {
+                ...chartTheme&&chartTheme.yAxisOptions.style
+              }
+            },
+            title: {
+              text: rightEdb.Unit||'',
+              style:{
+                ...chartTheme&&chartTheme.yAxisOptions.style
+              },
+              align: 'high',
+              rotation: 0,
+              y: -5,
+              x: 0,
+              textAlign: 'right',
+              reserveSpace: false,
+            },
+            max: Number(rightEdb.MaxData||''),
+            min: Number(rightEdb.MinData||''),
+      })
+  }
+
+  // 季节图x轴显示月/日
+  let xAxis={
+    tickPosition: 'inside',
+    lineColor: '#bfbfbf',
+    tickColor: '#bfbfbf',
+    tickLength:5,
+    type: 'datetime',
+    ordinal: false,
+    dateTimeLabelFormats: {
+      day: '%y/%m',
+      week: '%y/%m',
+      month: '%y/%m',
+      year: '%y/%m',
+    },
+    labels: {
+        formatter: (ctx)=> {
+            return Highcharts.dateFormat('%m/%d', ctx.value)
+        },
+        style: {
+            ...chartTheme&&chartTheme.xAxisOptions.style
+        }
+    },
+    tickInterval:24*3600*1000*60,//季节图
+    plotBands: setAxisPlotAreas(3,'datetime'),
+    plotLines: setAxisPlotLines(3,'datetime')
+  }
+
+  // 季节图提示框显示 月/日
+  let tooltip={
+      split: false,
+      shared: true,
+      dateTimeLabelFormats: {
+        // 时间格式化字符
+        day: '%m/%d',
+        week: '%m/%d',
+        month: '%m/%d',
+        year: '%m/%d',
+      },
+      xDateFormat: '%m/%d',
+  }
+
+  return {
+    colors:colorsArr.slice(-chartDataHandle.length),
+    xAxis:[xAxis],
+    series,
+    yAxis,
+    tooltip
+  }
+
+}
+
+
+/* 堆叠图/组合图设置  
+    本来和曲线图逻辑基本一致兼容下即可 为了以后便于维护和阅读还是拆开写吧
+*/
+function setStackOrCombinChart(e) {
+  const data = e.EdbInfoList;
+  //图表类型
+  const chartTypeMap = {
+      3: 'areaspline',
+      4: 'column',
+      6: ''
+  };
+  let chartStyle = chartTypeMap[e.ChartInfo.ChartType];
+
+  /* 主题样式*/
+  const chartTheme =  e.ChartInfo.ChartThemeStyle ? JSON.parse(e.ChartInfo.ChartThemeStyle) : null;
+
+  let series=[]
+  let yAxis=[]
+  let xAxis = {}
+  let ExtraConfig={}
+
+  let temYLeftArr=[]
+  let temYRightArr=[]
+  let temYLeftIndex,temYRightIndex,temYRightTwoIndex;
+
+  let minAndMaxTimeTemArr=[]//存放所有指标的最大最小时间
+
+  //有右二轴时排个序 按照左 右 右2的顺序
+  let newData = data.some(_ =>_.IsAxis===2) ? changeEdbOrder(data) : data;
+  if(e.ChartInfo.ChartType===3 && e.ChartInfo.ExtraConfig){
+    ExtraConfig=JSON.parse(e.ChartInfo.ExtraConfig)
+  }
+
+  newData.forEach((item,index)=>{
+
+      //轴位置值相同的下标
+      let sameSideIndex = newData.findIndex(i => i.IsAxis === item.IsAxis);
+
+      //堆叠图的yAxis必须一致 数据列所对应的y轴
+      let serie_yIndex = index;
+      if([4].includes(e.ChartInfo.ChartType) || (e.ChartInfo.ChartType ===3 && ExtraConfig.IsHeap==1)) {
+          // 类型为堆叠图时公用第一个指标y轴 
+          serie_yIndex =  0;
+      } else if(e.ChartInfo.ChartType ===6 && ['areaspline','column'].includes(item.ChartStyle)) {
+          // 组合图找第一个堆叠柱状或面积的作为公用
+          serie_yIndex = newData.findIndex(i => i.ChartStyle === item.ChartStyle);
+      }
+      //数据对应的y轴是公用轴则配置也共享
+      item.IsAxis = serie_yIndex === index ? item.IsAxis : newData[serie_yIndex].IsAxis;
+      item.IsOrder = serie_yIndex === index ? item.IsOrder : newData[serie_yIndex].IsOrder;
+
+      temYLeftIndex = [4].includes(e.ChartInfo.ChartType) 
+          ? (newData[serie_yIndex].IsAxis ? serie_yIndex : -1)
+          : data.findIndex((item) => item.IsAxis===1);
+      temYRightIndex = [4].includes(e.ChartInfo.ChartType) 
+          ? (newData[serie_yIndex].IsAxis ? -1 : serie_yIndex)
+          : data.findIndex((item) => !item.IsAxis);
+      temYRightTwoIndex = [4].includes(e.ChartInfo.ChartType) 
+          ? -1
+          : data.findIndex((item) => item.IsAxis===2);
+
+      let dynamic_title = item.EdbName;
+      let dynamic_arr = newData.filter(
+        (item) => dynamic_title === item.EdbName
+      );
+      //处理数据列name
+      let temName= setDyncmicSerieName(item,dynamic_arr)  
+
+      //预测指标配置
+      let predict_params = item.EdbInfoCategoryType === 1 ? getPredictParams(item,chartStyle) : {};
+      //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+      const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index;
+
+      //堆叠控制
+      let stacking = undefined;
+      if(e.ChartInfo.ChartType===4) {
+          stacking = 'normal';
+      }else if(e.ChartInfo.ChartType===6) {
+          stacking = !e.DataResp.IsHeap ? undefined:'normal';
+      }else if(e.ChartInfo.ChartType===3&&ExtraConfig.IsHeap) {
+          stacking = ExtraConfig.HeapWay===1?'normal':'percent';
+      }
+      let seriesItemObj={
+          data:[],
+          dataGrouping:{
+              enabled:false
+          },
+          type: e.ChartInfo.ChartType !== 3?(chartStyle || item.ChartStyle):ExtraConfig.IsHeap==1?'area':((chartTheme && chartTheme.lineOptionList[lineIndex].lineType) || item.ChartStyle),
+          yAxis:serie_yIndex,
+          name:temName,
+          color: item.ChartColor,
+          lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 1,
+          fillColor: (e.ChartInfo.ChartType === 3 || (e.ChartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
+          visible:true,
+          LatestDate:item.LatestDate,
+          LatestValue:item.LatestValue,
+          ...predict_params,
+          stacking,
+          threshold: (e.ChartInfo.ChartType==3&&item.ChartScale)
+            ? Number(item.ChartScale)
+            : 0
+      }
+      item.DataList = item.DataList || [];
+      for (let i of item.DataList) {
+        seriesItemObj.data.push([i.DataTimestamp, i.Value]);
+      }
+      series.push(seriesItemObj)
+      
+       //获取上下限
+      let minLimit = 0,maxLimit = 0
+      const limitMap = {
+          0:['rightMin','rightMax'],
+          1:['leftMin','leftMax'],
+          2:['rightTwoMin','rightTwoMax']
+      }
+      if(limitMap[item.IsAxis]){
+          minLimit = axisLimitData[`${limitMap[item.IsAxis][0]}`]||0
+          maxLimit = axisLimitData[`${limitMap[item.IsAxis][1]}`]||0
+      }
+
+      // 设置y轴
+      if(item.IsAxis){
+          temYLeftArr.push(item)
+      }else{
+          temYRightArr.push(item)
+      }
+      const textZh = item.ConvertUnit||item.Unit
+      let yItem={
+          ...basicYAxis,
+          IsAxis:item.IsAxis,
+          labels: {
+              formatter:  (ctx) =>{
+                  return sameSideIndex !== index ? '' : e.ChartInfo.ChartType===3&&ExtraConfig.HeapWay==2?ctx.value+'%':ctx.value;
+              },
+              align: 'center',
+              x: [0,2].includes(item.IsAxis) ? 5 : -5,
+              style:{
+                  ...chartTheme&&chartTheme.yAxisOptions.style
+              },
+          },
+          title: {
+              text:  textZh,
+              align: 'high',
+              rotation: 0,
+              y: -15,
+              x: (item.IsAxis===0 && temYRightTwoIndex>-1) ? -newData[temYRightTwoIndex].Unit.length*12 : 0,
+              textAlign: item.IsAxis===1 ? 'left' : 'right',
+              reserveSpace: false,
+              style:{
+                  ...chartTheme&&chartTheme.yAxisOptions.style
+              },
+          },
+          opposite: [0,2].includes(item.IsAxis),
+          reversed: item.IsOrder,
+          min: e.ChartInfo.ChartType===3&&ExtraConfig.HeapWay==2?null:Number(minLimit),
+          max: e.ChartInfo.ChartType===3&&ExtraConfig.HeapWay==2?null:Number(maxLimit),
+          tickWidth: sameSideIndex !== index ? 0 : 1,
+          visible: serie_yIndex === index && sameSideIndex ===index,
+          chartEdbInfo:item,//指标数据用于在保存时读取指标数据
+          plotBands: setAxisPlotAreas(item.IsAxis),
+          plotLines: setAxisPlotLines(item.IsAxis)
+      }
+      yAxis.push(yItem)
+      
+      if(item.DataList.length>0){
+          minAndMaxTimeTemArr.push(item.DataList[0].DataTimestamp)
+          minAndMaxTimeTemArr.push(item.DataList[item.DataList.length-1].DataTimestamp)
+      }
+      
+  })
+  
+  
+  // 设置x轴
+  // 找出所有指标的最大和最小时间 分成6段
+  let minTime=Math.min.apply(null,minAndMaxTimeTemArr)
+  let maxTime=Math.max.apply(null,minAndMaxTimeTemArr)
+
+
+  const isLessThanOneYear = xTimeDiffer(minTime,maxTime)
+  xAxis={
+      ...basicXAxis,
+      tickInterval:((maxTime-minTime)/6)/(24*3600*1000)>30?(maxTime-minTime)/6:24*3600*1000*30,
+      labels: {
+          formatter: (ctx)=> {
+              return isLessThanOneYear
+              ? Highcharts.dateFormat('%m/%d', ctx.value)
+              : Highcharts.dateFormat('%y/%m', ctx.value);
+          },
+          style: {
+              ...chartTheme&&chartTheme.xAxisOptions.style
+          }
+      },
+      plotBands: setAxisPlotAreas(3,'datetime'),
+      plotLines: setAxisPlotLines(3,'datetime')
+  }
+  
+
+  yAxis.forEach(item=>{
+      if(item.IsAxis === 1){//左轴
+          hasLeftAxis.value=true
+      }else if (item.IsAxis===2){ // 右2轴
+          hasRightTwoAxis.value=true
+      }else{
+          hasRightAxis.value=true
+      }
+  })
+
+  let options={
+    xAxis: [xAxis],
+    yAxis,
+    series,
+    rangeSelector:{ enabled: false}
+  }
+
+  //面积图百分比tooltip
+  if(e.ChartInfo.ChartType===3&&ExtraConfig.HeapWay == 2) {
+    //悬浮提示框
+	options.tooltip={
+		split: false,
+		shared: true,
+		dateTimeLabelFormats: {
+			// 时间格式化字符
+			day: '%Y/%m/%d',
+			week: "%Y/%m",
+			month: '%Y/%m',
+			year: '%Y/%m',
+		},
+		xDateFormat:'%Y/%m/%d',
+		className:'chart-tooltips-box',
+		pointFormat: '<span style=\"color:{point.color}\">●</span><span>{series.name}</span>' +':<b>{point.percentage:.1f}%</b> ({point.y:,.1f})<br/>'
+	}
+  }
+
+  return options
+}
+
+
+/* 散点图 第一个指标值为x轴 第二个指标为y轴*/
+function setScatterOptions(e) {
+  hasLeftAxis.value=true
+
+  const { ChartInfo,EdbInfoList } = e;
+  const dataList = EdbInfoList;
+
+   /* 主题样式*/
+  const chartTheme = ChartInfo.ChartThemeStyle ? JSON.parse(ChartInfo.ChartThemeStyle) : null;
+
+  // 取2个指标中日期相同的数据
+  const real_data = [];
+  let tmpData_date = {};//用来取点对应的日期
+  let data1 =  _.cloneDeep(dataList)[0].DataList || [];
+  let data2 =  _.cloneDeep(dataList)[1].DataList || [];
+  data1.forEach((_item) => {
+      data2.forEach((_item2) => {
+          if(_item.DataTimestamp === _item2.DataTimestamp) {
+              //日期
+              let itemIndex =_item.Value + "_" +_item2.Value
+              if(tmpData_date[itemIndex]) {
+                  tmpData_date[itemIndex].push( moment(_item.DataTimestamp).format('YYYY/MM/DD'))
+              } else {
+                  tmpData_date[itemIndex] = [moment(_item.DataTimestamp).format('YYYY/MM/DD')]
+              }
+          
+              //值
+              real_data.push({
+                  x: _item.Value,
+                  y: _item2.Value
+              })
+          }
+      })
+  })
+  real_data.sort((x,y) => x-y);
+
+  //悬浮窗 拼接日期 原始指标名称
+  let tooltip = {
+      formatter: function() {
+          return `<strong>${ tmpData_date[this.x+'_'+this.y].length > 4 ? tmpData_date[this.x+'_'+this.y].slice(0,4).join()+'...' : tmpData_date[this.x+'_'+this.y].join() }</strong><br>
+          ${dataList[0].EdbName}: <span style="font-weight: 600">	${this.x}</span><br>
+          ${dataList[1].EdbName}: <span style="font-weight: 600">	${this.y}</span>
+          `
+      }
+  }
+
+  const { IsOrder,ChartColor } = dataList[0];
+   //获取上下限
+  let minLimit = 0,maxLimit = 0
+    minLimit = axisLimitData.leftMin||0
+    maxLimit = axisLimitData.leftMax||0
+
+  //y轴
+  let yAxis = {
+      title: {
+          text:  `${dataList[1].ConvertUnit||dataList[1].Unit}`,
+          align: 'high',
+          rotation: 0,
+          y: -15,
+          x:0,
+          textAlign: 'left',
+          reserveSpace: false,
+          style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+      },
+      labels: {
+          formatter: function (ctx) {
+          return ctx.value;
+          },
+          align: 'center',
+          style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+      },
+      IsAxis:1,
+      opposite: false,
+      reversed: IsOrder,
+      min: Number(minLimit),
+      max: Number(maxLimit),
+      plotBands: setAxisPlotAreas(1),
+      plotLines: setAxisPlotLines(1),
+      tickWidth: 1,
+      tickLength: 5,
+      lineWidth: 1,
+      lineColor: '#bfbfbf',
+      tickColor: '#bfbfbf',
+      offset: 0,
+      visible: true,
+      gridLineWidth: 0,
+      tickPosition: 'inside',
+      endOnTick: false,
+      startOnTick: false,
+      showLastLabel: true,
+      tickPixelInterval: 50
+  }
+
+  //数据列
+  let series = {
+      data: [],
+      type: 'scatter',
+      name: `${ChartInfo.ChartName}${IsOrder ? '(逆序)' : ''}`,
+      color: ChartColor,
+      visible:true,
+      chartType: 'linear',
+      marker: {
+        radius: (chartTheme&&chartTheme.lineOptionList[0].radius)||5,
+      },
+  }
+  real_data.forEach(_ => {
+      series.data.push([_.x,_.y])
+  })
+  
+  return {
+      title: {
+          text:''
+      },
+      series: [ series ],
+      yAxis: [yAxis],
+      xAxis: {
+          ...scatterXAxis,
+          title: {
+              text:  `${dataList[0].ConvertUnit||dataList[0].Unit}`,
+              align: 'high',
+              rotation: 0,
+              x: 0,
+              offset: 20,
+              style: {
+                  ...chartTheme&&chartTheme.xAxisOptions.style
+              },
+          },
+          labels: {
+              style: {
+                ...chartTheme&&chartTheme.xAxisOptions.style
+              }
+          },
+          plotBands: setAxisPlotAreas(3),
+          plotLines: setAxisPlotLines(3)
+      },
+      tooltip
+  }
+}
+
+
+/* 奇怪柱形图 */
+const barDateList = ref([]);//柱形图的绘图数据
+const barXData = ref([]);//柱形图的x轴
+const barEdbData = ref([]);//柱形图的表格数据 只用于取值
+ /* 获取图表详情后赋值柱状图数据 */
+function initBarData (data) {
+    const { XEdbIdValue,YDataList,EdbInfoList,ChartInfo } = data;
+
+    let xData = XEdbIdValue.map(_ => EdbInfoList.find(edb => edb.EdbInfoId===_).EdbAliasName)
+
+    barDateList.value = YDataList;
+    barXData.value = xData;
+    barEdbData.value = EdbInfoList;
+
+    hasLeftAxis.value=true;
+    axisLimitData.leftMin=Number(ChartInfo.LeftMin)
+    axisLimitData.leftMax=Number(ChartInfo.LeftMax)
+
+    return setBarChart(data);
+}
+/* 奇怪柱状图 和其他逻辑无公用点 依赖数据为单独的数据
+    x轴为指标名称的柱形图 以日期作为series
+*/
+function setBarChart(e) {
+    let seriesData = [];
+    const data = _.cloneDeep(barDateList.value);
+    const { ChartInfo } = e;
+
+     /* 主题样式*/
+    const chartTheme =  ChartInfo.ChartThemeStyle ? JSON.parse(ChartInfo.ChartThemeStyle) : null;
+
+    //x轴
+    let xAxis = {
+        ...scatterXAxis,
+        categories: barXData.value,
+        tickWidth: 1,
+        labels: {
+            style: {
+              ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+        }
+    }
+
+    const { leftMin,leftMax } = axisLimitData;
+    //y轴
+    let yAxis = {
+        ...basicYAxis,
+        title: {
+            text: ChartInfo.Unit,
+            align: 'high',
+            rotation: 0,
+            y: -15,
+            textAlign: 'left',
+            reserveSpace: false,
+            style:{
+                ...chartTheme&&chartTheme.yAxisOptions.style
+            },
+        },
+        labels: {
+            formatter: function (ctx) {
+            let val = ctx.value;
+            return val;
+            },
+            align: 'center',
+            style:{
+                ...chartTheme&&chartTheme.yAxisOptions.style
+            },
+        },
+        min: Number(leftMin),
+        max: Number(leftMax),
+        opposite: false,
+        tickWidth: 1,
+        plotBands: setAxisPlotAreas(1),
+        plotLines: setAxisPlotLines(1)
+    }
+
+    //数据列
+    data.forEach(item => {
+        let serie_item = {
+            data: item.Value,
+            type: 'column',
+            yAxis: 0,
+            name: item.Name || item.Date,
+            color: item.Color,
+            chartType: 'linear',              
+            visible:true,
+        };
+        seriesData.push(serie_item)
+    })
+    
+    return {
+        title: {
+            text:''
+        },
+        plotOptions: {
+            column:{
+            stacking: null,
+            },
+        },
+        series: seriesData,
+        yAxis: [ yAxis ],
+        xAxis
+    }
+}
+
+
+
+/* 散点截面图 */
+const sectionScatterData = ref({});
+/* 截面散点图获取详情赋值 */
+const initSectionScatterData = (e) => {
+    const { DataResp } = e;
+    sectionScatterData.value = DataResp;
+
+    hasLeftAxis.value=true;
+    axisLimitData.leftMin=Number(DataResp.YMinValue)
+    axisLimitData.leftMax=Number(DataResp.YMaxValue)
+    axisLimitData.xMin=Number(DataResp.XMinValue)
+    axisLimitData.xMax=Number(DataResp.XMaxValue)
+    return setSectionScatterChart(e)
+}
+/* 截面散点图设置 sectionScatterData */
+const setSectionScatterChart = (e) => {
+    const { DataList,XName,XNameEn,XUnitName,XUnitNameEn,YName,YNameEn,YUnitName,YUnitNameEn } = sectionScatterData.value;
+    const { leftMin,leftMax,xMin,xMax }  = axisLimitData;
+    const { ChartInfo } = e;
+    
+     /* 主题样式*/
+    const chartTheme =  ChartInfo.ChartThemeStyle ? JSON.parse(ChartInfo.ChartThemeStyle) : null;
+
+    //y轴
+    let yAxis = {
+        ...basicYAxis,
+        title: {
+            text: YName,
+            align: 'middle',
+            style:{
+                ...chartTheme&&chartTheme.yAxisOptions.style
+            },
+        },
+        labels: {
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
+        },
+        opposite: false,
+        reversed: false,
+        min: Number(leftMin),
+        max: Number(leftMax),
+        tickWidth: 1,
+        plotBands: setAxisPlotAreas(1),
+        plotLines: setAxisPlotLines(1)
+    }
+
+    //x轴
+    let xAxis = {
+        ...scatterXAxis,
+        title: {
+            text: XName,
+            align: 'middle',
+            style: {
+                ...chartTheme&&chartTheme.xAxisOptions.style
+            },
+        },
+        labels: {
+            style:{
+              ...chartTheme&&chartTheme.xAxisOptions.style
+            },
+        },
+        min: Number(xMin),
+        max: Number(xMax),
+        plotBands: setAxisPlotAreas(3),
+        plotLines: setAxisPlotLines(3)
+    }
+
+    //数据列
+    let series = [];
+    DataList.forEach((item,index) => {
+        // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+        const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+        //数据列
+        let series_item = {
+            data: [],
+            type: 'scatter',
+            name: item.Name,
+            color: item.Color,
+            lineWidth: 0,
+            chartType: 'linear',
+            zIndex:1,
+            marker: {
+                radius: (chartTheme&&chartTheme.lineOptionList[lineIndex].radius)||5,
+            },
+            visible: true
+        }
+        item.EdbInfoList.forEach(_ => {
+            series_item.data.push({
+            x: _.XValue,
+            y: _.YValue,
+            dataLabels: {
+                enabled: _.IsShow,
+                allowOverlap: true,
+                align: 'left',
+                format: _.Name,
+                formatCh: _.Name,
+                formatEn: _.NameEn
+            }
+            })
+        })
+        series.push(series_item);
+
+    //趋势线
+    if(item.ShowTrendLine)  {
+        
+        let trend_data = item.TrendLimitData.map((_,_index) => (
+            _index === item.TrendLimitData.length-1 ? {
+                x: _.X,
+                y: _.Y,
+                dataLabels: {
+                enabled: item.ShowRSquare || item.ShowFitEquation,
+                align: 'left',
+                color: '#666',
+                x: 20,
+                y: 30,
+                zIndex: 9,
+                allowOverlap: true,
+                formatter: function(){
+                    let tag = '';
+                    item.ShowRSquare && item.ShowFitEquation
+                    ? tag =`<span>${item.TrendLine}</span><br><span>R²=${item.RSquare}</span>`
+                    : item.ShowRSquare && !item.ShowFitEquation
+                    ? tag =`<span>R²=${item.RSquare}</span>`
+                    : item.ShowFitEquation && !item.ShowRSquare
+                    ? tag =`<span>${item.TrendLine}</span>`
+                    : ''
+                    return tag
+                }
+                }
+            } : {
+                x: _.X,
+                y: _.Y,
+            }
+        ))
+
+        let trend_item = {
+            data: trend_data,
+            type: 'spline',
+            linkedTo: ':previous',
+            color: item.Color,
+            lineWidth: 1,
+            chartType: 'linear',
+            enableMouseTracking: false,
+            dashStyle:'Dash',
+            zIndex: 2,
+            visible: true,
+            marker: {
+                enabled: false
+            }
+        }
+        series.push(trend_item)
+    }
+    })
+
+    let tooltip = {
+        formatter: function() {
+            let series_obj = DataList.find(_ => _.Name === this.series.name);
+            let ponit_obj = series_obj.EdbInfoList.find(_ => _.XValue ===this.x && _.YValue===this.y);
+
+            let str=`<b>${ ponit_obj.Name }</b>`;
+            str += `<br><span style="color:${this.color}">\u25CF</span>${ponit_obj.XName}: ${this.x} ${ponit_obj.XDate}<br>`;
+            str += `<span style="color:${this.color}">\u25CF</span>${ponit_obj.YName}: ${this.y} (${ponit_obj.YDate})`;
+
+            return str
+        }
+    }
+    
+    return {
+        title: {
+            text:''
+        },
+        series,
+        yAxis: [yAxis],
+        xAxis,
+        tooltip
+    }
+}
+
+
+/* 雷达图 */
+const radarChartRenderData =  ref({})
+const initRadarData = (data) => {
+    const { DataResp,EdbInfoList,ChartInfo } = data;
+    
+    radarChartRenderData.value = {
+        YDataList: DataResp.YDataList,
+        XDataList: EdbInfoList.filter(_ => DataResp.XEdbIdValue.includes(_.EdbInfoId))
+    }
+
+    hasLeftAxis.value=true;
+    axisLimitData.leftMin=Number(ChartInfo.LeftMin)
+    axisLimitData.leftMax=Number(ChartInfo.LeftMax)
+
+    return setRadarChart(data);
+}
+const setRadarChart = (data) => {
+  const { YDataList,XDataList } = radarChartRenderData.value;
+
+  const { ChartInfo } = data;
+
+    /* 主题样式*/
+    const chartTheme =  ChartInfo.ChartThemeStyle ? JSON.parse(ChartInfo.ChartThemeStyle) : null;
+
+    let categories = XDataList.map(_ => _.EdbAliasName||_.EdbName);
+
+    //x轴
+    let xAxis = {
+      lineWidth: 0,
+      tickLength: 0,
+      tickmarkPlacement: 'on',
+      categories,
+      labels: {
+        allowOverlap: true,
+        autoRotationLimit: 40,
+        style: {
+          ...chartTheme&&chartTheme.xAxisOptions.style
+        }
+      }
+    }
+
+    //y轴
+    const { leftMin,leftMax } = axisLimitData;
+    let yAxis = [{
+      gridLineInterpolation: 'polygon',
+      gridLineWidth: 1,
+      lineWidth: 0,
+      endOnTick: false,
+      startOnTick: false,
+      showLastLabel: true,
+      // tickAmount:4,
+      title: {
+        text:  ChartInfo.Unit ,
+        align: 'high',
+        rotation: 0,
+        y: 5,
+        x:10,
+        textAlign: 'left',
+        reserveSpace: false,
+        style:{
+          ...chartTheme&&chartTheme.yAxisOptions.style
+        },
+      },
+      labels: {
+        allowOverlap: true,
+        style:{
+          ...chartTheme&&chartTheme.yAxisOptions.style
+        }
+      },
+      min: Number(leftMin),
+      max: Number(leftMax)
+    }]
+
+    //系列
+    let series = [];
+    YDataList.forEach((item,index) => {
+        // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+        const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+        let serie_item = {
+            data: item.Value,
+            pointPlacement: 'on',
+            type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'line',
+            dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+            yAxis: 0,
+            name: item.Name || item.Date,
+            color: item.Color,
+            lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 1,
+            chartType: 'linear',
+            visible: true
+        };
+        series.push(serie_item)
+    })
+
+    return {
+        chart: {
+            ...chartTheme.drawOption,
+            spacing: [2,10,2,10],
+            polar:true,
+        },
+        title: {
+            text:''
+        },
+        pane: {
+            size: '85%'
+        },
+        series,
+        yAxis,
+        xAxis
+    }
+}
+
+
+// 截面组合图初始化
+function initSectionalCombinationChart(e){
+  const {XDataList,UnitList,SeriesList,IsHeap}=e.DataResp
+  /* 主题样式*/
+  const chartTheme =  e.ChartInfo.ChartThemeStyle ? JSON.parse(e.ChartInfo.ChartThemeStyle) : null;
+    
+  let leftIndex = SeriesList.findIndex((item) => item.IsAxis===1);
+  let rightIndex = SeriesList.findIndex((item) => !item.IsAxis);
+  let rightTwoIndex = SeriesList.findIndex((item) => item.IsAxis ===2);
+  // axisLimitData.leftMin=data.ChartInfo.LeftMin
+  // axisLimitData.leftMax=data.ChartInfo.LeftMax
+  // axisLimitData.rightTwoMin=data.ChartInfo.Right2Min
+  // axisLimitData.rightTwoMax=data.ChartInfo.Right2Max
+  // axisLimitData.rightMin=data.ChartInfo.RightMin
+  // axisLimitData.rightMax=data.ChartInfo.RightMax
+  if(leftIndex!=-1) {
+      hasLeftAxis.value=true
+  }
+  if(rightIndex!=-1){
+      hasRightAxis.value=true
+  }
+  if(rightTwoIndex!=-1){
+      hasRightTwoAxis.value=true
+  }
+
+  //x轴
+  const xAxis={
+      categories:XDataList.map(_=>_.Name),
+      tickWidth: 1,
+      labels: {
+        style:{
+          ...chartTheme&&chartTheme.xAxisOptions.style
+        },
+      },
+      plotBands: setAxisPlotAreas(3),
+      plotLines: setAxisPlotLines(3)
+  }
+
+  let yAxis=[]
+  let seriesData=[]
+
+  //有右二轴时排个序 按照左 右 右2的顺序
+  const chartDataList = SeriesList.some(_ =>_.IsAxis===2) ? changeEdbOrder(SeriesList) : _.cloneDeep(SeriesList);
+  chartDataList.forEach((item,index)=>{
+      //轴位置值相同的下标
+      const sameSideIndex = chartDataList.findIndex(
+        (i) => i.IsAxis === item.IsAxis
+      );
+
+      const yTitleMap={
+        1:['LeftName','LeftNameEn'],
+        0:['RightName','RightNameEn'],
+        2:['RightTwoName','RightTwoNameEn'],
+      }
+
+      let minLimit = 0,maxLimit = 0
+      const limitMap = {
+          0:['rightMin','rightMax'],
+          1:['leftMin','leftMax'],
+          2:['rightTwoMin','rightTwoMax']
+      }
+      if(limitMap[item.IsAxis]){
+          minLimit = axisLimitData[`${limitMap[item.IsAxis][0]}`]||0
+          maxLimit = axisLimitData[`${limitMap[item.IsAxis][1]}`]||0
+      }
+
+      let yItem = {
+        ...basicYAxis,
+        title: {
+          text: UnitList[yTitleMap[item.IsAxis][0]],
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+          align: 'high',
+          rotation: 0,
+          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 ctx.value;
+          },
+          align: 'center',
+          x: [0,2].includes(item.IsAxis) ? 5 : -5,
+          style: {
+            ...chartTheme&&chartTheme.yAxisOptions.style,
+          }
+        },
+        IsAxis:item.IsAxis,
+        opposite: [0,2].includes(item.IsAxis),
+        min: Number(minLimit),
+        max: Number(maxLimit),
+        tickWidth: 1,
+        visible: sameSideIndex === index,
+        plotBands: setAxisPlotAreas(item.IsAxis),
+        plotLines: setAxisPlotLines(item.IsAxis)
+      };
+
+      //堆叠图的yAxis必须一致 数据列所对应的y轴
+      let serie_yIndex = index;
+      if(IsHeap==1) {
+        // 类型为堆叠图时公用第一个指标y轴 
+        serie_yIndex =  0;
+      }
+
+      //数据列
+      let dataArr=item.DataList||[]
+      // 根据NoDataEdbIndex 将对应位置的值置为null
+      dataArr.forEach((i,index)=>{
+        if(item.NoDataEdbIndex.includes(index)){
+          dataArr[index]=null
+        }
+      })
+      //图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+      const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+      let obj={
+        data:dataArr,
+        type: item.ChartStyle||'',
+        dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+        chartType:'linear',
+        yAxis: serie_yIndex,
+        name:item.SeriesName,
+        nameCh:item.SeriesName,
+        nameEn:item.SeriesNameEn,
+        color: item.ChartColor,
+        lineWidth: Number(item.ChartWidth)||(chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth),
+        borderWidth: 1,
+        borderColor: item.ChartColor,
+        marker: {//展示数据点
+          enabled:item.ChartStyle!='column'&&item.IsPoint?true:false,
+          radius: (chartTheme&&chartTheme.lineOptionList[lineIndex].radius)||5,
+        },
+        dataLabels: {//展示数值
+          enabled: item.IsNumber?true:false,
+          align:item.ChartStyle=='column'?'center':undefined,
+          y:item.ChartStyle=='column'?-20:0,
+          inside: item.ChartStyle=='column'?false:undefined,
+          crop: item.ChartStyle=='column'?false:true,
+        },
+        visible:true,
+        stacking:IsHeap==1?'normal':undefined,
+        zIndex: ['line','spline'].includes(item.ChartStyle) ? 1 : 0, //防止组合图曲线被遮住
+      }
+
+      yAxis.push(yItem)
+      seriesData.push(obj)
+  })
+  
+  console.log(seriesData);
+
+  const tooltip={
+      formatter:function () { 
+        let str=`<b>${this.points[0].x}</b>`
+        this.points.forEach(item=>{
+          const sObj=seriesData.find(_=>_.name===item.series.name)
+          str=str+`<br><span style="color:${item.color}">\u25CF</span>${sObj.name}:${item.y} ${sObj.unitNameCh}`
+        })
+        return str
+      },
+      shared:true
+  }
+  
+
+  return {
+      title: {
+          text:''
+      },
+      tooltip,
+      series: seriesData,
+      yAxis,
+      xAxis,
+  };
+
+    
+}
+
+
+/* 商品价格图 */
+const commodityChartData = ref([]);//商品价格图的绘图数据
+const commodityXData = ref([]);//商品价格图的x轴
+const commodityEdbList = ref([]);//商品价格图的表格数据 只用于取值
+ /* 商品价格曲线获取详情赋值 */
+const initCommodityData = (data) => {
+    const { XDataList,YDataList,EdbInfoList,ChartInfo,DataResp } = data;
+
+    commodityEdbList.value = EdbInfoList;
+    commodityChartData.value = ChartInfo.Source===5?DataResp.YDataList:YDataList;
+    commodityXData.value = ChartInfo.Source===5?DataResp.XDataList:XDataList;
+
+    hasLeftAxis.value=true;
+    axisLimitData.leftMin=Number(ChartInfo.LeftMin)
+    axisLimitData.leftMax=Number(ChartInfo.LeftMax)
+
+    return setCommodityChart(data);
+}
+/* 商品价格曲线设置 绘图逻辑同奇怪柱形图*/
+const setCommodityChart = (e) => {
+
+    const { ChartInfo } = e;
+    /* 主题样式*/
+    const chartTheme =  ChartInfo.ChartThemeStyle ? JSON.parse(ChartInfo.ChartThemeStyle) : null;
+    
+    let seriesData = [];
+    const data = _.cloneDeep(commodityChartData.value);
+
+    //x轴
+    let xAxis = {
+        ...scatterXAxis,
+        categories: commodityXData.value.filter(_=>_.IsHide===0).map(_ => _.Name),
+        tickWidth: 1,
+        labels: {
+            style: {
+              ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+        }
+    }
+
+    const { leftMin,leftMax } = axisLimitData;
+    //y轴
+    let yAxis = {
+        ...basicYAxis,
+        title: {
+            text: commodityEdbList.value[0].Unit,
+            align: 'high',
+            rotation: 0,
+            y: -15,
+            textAlign: 'left',
+            reserveSpace: false,
+            style:{
+              ...chartTheme&&chartTheme.yAxisOptions.style
+            },
+        },
+        labels: {
+            formatter: function (ctx) {
+            let val = ctx.value;
+            return val;
+            },
+            align: 'center',
+            style:{
+                ...chartTheme&&chartTheme.yAxisOptions.style
+            },
+        },
+        min: Number(leftMin),
+        max: Number(leftMax),
+        opposite: false,
+        tickWidth: 1,
+    }
+
+    //数据列
+    data.forEach((item,index) => {
+        //处理首或/尾全是无效数据的以null填充
+        let filterData = filterInvalidData(item)
+        // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+        const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+        let serie_item = {
+            data: filterData,
+            type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
+            dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+            yAxis: 0,
+            name: item.Name,
+            color: item.Color,
+            chartType: 'linear',
+            lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 3,
+            visible: true,
+            marker: {
+                enabled: false
+            }
+        };
+        seriesData.push(serie_item)
+    })
+
+    //tooltip
+    let tooltip = {
+        formatter: function() {
+            const ctx = this;
+            let str = '';
+            ctx.points.forEach(item => {
+              let obj_item = data.find(_ => _.Name === item.series.name);
+              let index = commodityXData.value.findIndex(_ => _.Name === ctx.x);
+
+                //合约显示
+                let haveContract = obj_item.XEdbInfoIdList[index];
+                
+                if(haveContract) {
+                    // 利润曲线指标名
+                    const isEdb=commodityEdbList.value.some(_=>_.EdbInfoId===haveContract)
+                    let edb_name = ChartInfo.Source === 5 
+                    ? (isEdb? obj_item.NameList[index] : `${DataResp.ProfitName}(${obj_item.NameList[index]})`)
+                    : commodityEdbList.value.find(_ => _.EdbInfoId === obj_item.XEdbInfoIdList[index]).EdbName;
+                    str+=`<b>${ edb_name }</b>`
+
+                    if(!obj_item.NoDataEdbList.includes(obj_item.XEdbInfoIdList[index])) {
+                        str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: ${item.y}<br>`
+                    }else {
+                        str += `<br><span style="color:${item.color}">\u25CF</span>${obj_item.Date}: 无<br>`
+                    }
+                }
+
+            })
+            return str||'无合约'
+        },
+        shared: true
+    }
+    
+    return {
+        title: {
+            text:''
+        },
+        series: seriesData,
+        yAxis: [ yAxis ],
+        xAxis,
+        tooltip
+    }
+};
+/* 处理无效数据为null */
+const filterInvalidData = (item)=> {
+    let validateArr = item.XEdbInfoIdList.filter(_ =>_&&!item.NoDataEdbList.includes(_));
+
+    let first_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[0]);
+    let last_index = item.XEdbInfoIdList.findIndex(_ => _ === validateArr[validateArr.length-1]);
+    console.log('first_index',first_index)
+    console.log('last_index',last_index)
+
+    let arr = item.Value.map((item,index) => {
+    if(index < first_index || index > last_index) {
+        return null
+    }else {
+        return item
+    }
+    })
+    // 根据设置的x轴显示隐藏去除值
+    let temArr=[]
+    commodityXData.value.forEach((i,index)=>{
+        if(i.IsHide!==1){
+            temArr.push(arr[index])
+        }
+    })
+
+    return temArr;
+}
+
+
+
+//相关性图表设置
+function initRelevanceChart(data){
+
+    /* 主题样式*/
+    const chartTheme =  data.ChartInfo.ChartThemeStyle ? JSON.parse(data.ChartInfo.ChartThemeStyle) : null;
+
+    // 处理X轴
+    let xAxis={
+        categories: data.ChartInfo.Source===3 ? data.XEdbIdValue : data.DataResp.XDateTimeValue,
+        tickWidth: 1,
+        title: {
+            text:  data.ChartInfo.Source===3 ? `期数(${data.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,
+        tickmarkPlacement:'on'
+    }
+
+    // 处理Y轴
+    let yAxis={
+        ...basicYAxis,
+        title: {
+          text: '相关性系数',
+          textCh: '相关性系数',
+          textEn: 'Correlation coefficient',
+          align: 'high',
+          rotation: 0,
+          y: -15,
+          textAlign: 'left',
+          reserveSpace: false,
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+        },
+        labels: {
+          formatter: function (ctx) {
+            let val = ctx.value;
+            return val;
+          },
+          align: 'center',
+          style:{
+            ...chartTheme&&chartTheme.yAxisOptions.style
+          },
+        },
+        opposite: false,
+        tickWidth: 1,
+    }
+
+    //处理series
+    let seriesData=[]
+    data.YDataList.forEach((item,index)=>{
+        // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+        const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+        let serie_item = {
+          data: item.Value,
+          type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
+          dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+          yAxis: 0,
+          name: item.Name||data.ChartInfo.ChartName,
+          nameCh: item.Name||data.ChartInfo.ChartName,
+          nameEn: item.NameEn||data.ChartInfo.ChartName,
+          color: item.Color||'#00f',
+          chartType: 'linear',
+          lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth) || 3,
+          visible:true,
+          marker: {
+            enabled: false
+          }
+        };
+        seriesData.push(serie_item)
+    })
+
+    const { LeadValue,LeadUnit } = data.CorrelationChartInfo;
+    let tooltip = {
+        formatter: function() {
+          let str = `<p>相关性系数:${this.y.toFixed(4)}</p><br><p>领先${ data.ChartInfo.Source===3 ?this.x+'期' : LeadValue+LeadUnit}</p>`
+          return str
+        }
+    }
+    
+
+  return {
+      isRelevanceChart:data.ChartInfo.Source===3,
+      title: {
+          text:''
+      },
+      series: seriesData,
+      yAxis: [yAxis] ,
+      xAxis:xAxis,
+      tooltip
+  }
+}
+
+
+
+/* 统计频率图 */
+function setStatisticFrequency(data) {
+    const { DataList,LeftMaxValue,LeftMinValue,RightMaxValue,RightMinValue } = data.DataResp;
+    const { ChartInfo } = data;
+
+     /* 主题样式*/
+    const chartTheme =  ChartInfo.ChartThemeStyle ? JSON.parse(ChartInfo.ChartThemeStyle) : null;
+    
+    let xAxis = {
+        ...scatterXAxis,
+        tickWidth: 1,
+        labels: {
+            style: {
+                ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+        }
+    }
+
+    //y和系列
+    let yAxis = [],series = [];
+    DataList.forEach((item,index) => {
+    let y_item = {
+        ...basicYAxis,
+        title: {
+            text: item.Unit,
+            align: 'high',
+            rotation: 0,
+            y: -15,
+            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),
+        max: index===0? Number(LeftMaxValue):Number(RightMaxValue),
+        tickWidth: 1,
+    }
+    // 图表可配置的线条数就10条,第11条用第1条的配置,索引取下模
+    const lineIndex = chartTheme ? index%chartTheme.lineOptionList.length : index
+    let series_item = {
+        data: item.Value.map(_ =>[_.X,_.Y]),
+        dashStyle: (chartTheme&&chartTheme.lineOptionList[lineIndex].dashStyle)||'Solid',
+        type: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineType) || 'spline',
+        yAxis: index,
+        name: item.Name,
+        color: item.Color,
+        lineWidth: (chartTheme&&chartTheme.lineOptionList[lineIndex].lineWidth)||3,
+        chartType: 'linear',
+        visible: true,
+        zIndex:1
+    }
+
+    series.push(series_item);
+    yAxis.push(y_item)
+    })
+
+    let tooltip = {
+      formatter: function() {
+          let that = this;
+          let xList = DataList[0].Value.map(_ =>_.X);
+          let step = xList[1]-xList[0];
+          let data_interval = `[${Number(that.x).toFixed(2)},${Number(that.x+step).toFixed(2)}]`;
+
+          let str=`<b>${ data_interval }</b>`;
+          that.points.forEach(item => {
+          str += `<br><span style="color:${item.color}">\u25CF</span>${item.series.name}: ${item.y}%<br>`
+          })
+          return str
+      },
+      shared: true
+    }
+
+    return {
+      title: {
+          text:''
+      },
+      tooltip,
+      series,
+      yAxis,
+      xAxis
+    }
+}
+
+
+/* 跨品种分析 */
+const crossVarietyChartData = ref({})
+const initCrossVarietyChartData = (data) => {
+    const {DataResp,ChartInfo} = data;
+    crossVarietyChartData.value = DataResp;
+
+    hasLeftAxis.value=true;
+
+    axisLimitData.leftMin=ChartInfo.LeftMin ? Number(ChartInfo.LeftMin) : Number(DataResp.YMinValue)
+    axisLimitData.leftMax=ChartInfo.LeftMax ? Number(ChartInfo.LeftMax) : Number(DataResp.YMaxValue)
+    axisLimitData.xMin=ChartInfo.XMin ? Number(ChartInfo.XMin) : Number(DataResp.XMinValue)
+    axisLimitData.xMax=ChartInfo.XMax ? Number(ChartInfo.XMax) : Number(DataResp.XMaxValue)
+
+    return setCrossVarietyChart(data)
+}
+const setCrossVarietyChart = (data) => {
+    const { EdbInfoList,ChartInfo } = data;
+    
+    const { leftMin,leftMax,xMin,xMax }  = axisLimitData;
+
+    const { DataList,XName,YName } = crossVarietyChartData.value;
+     /* 主题样式*/
+    const chartTheme =  ChartInfo.ChartThemeStyle ? JSON.parse(ChartInfo.ChartThemeStyle) : null;
+
+    //y轴
+    let yAxis = {
+        ...basicYAxis,
+        title: {
+            text: YName,
+            align: 'middle',
+            style: {
+                ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+        },
+        labels: {
+            style: {
+              ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+        },
+        opposite: false,
+        reversed: false,
+        min: Number(leftMin),
+        max: Number(leftMax),
+        tickWidth: 1,
+    }
+
+    // x轴
+    let xAxis = {
+        ...scatterXAxis,
+        title: {
+            text: XName,
+            align: 'middle',
+            style: {
+                ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+        },
+        labels: {
+            style: {
+                ...chartTheme&&chartTheme.xAxisOptions.style
+            }
+        },
+        min: Number(xMin),
+        max: Number(xMax),
+    }
+
+    //数据列
+    let series = [];
+    const tagMap = { //标签对应文字
+        1: '最新',
+        3: 'Fix'
+    }
+    DataList.forEach(item => {
+        //数据列
+        let series_item = {
+            data: [],
+            type: 'scatter',
+            name: item.Name,
+            color: item.Color,
+            lineWidth: 0,
+            chartType: 'linear',
+            zIndex:1,
+            visible: true
+        }
+        item.CoordinatePointData.forEach(_ => {
+            series_item.data.push({
+                x: _.X,
+                y: _.Y,
+                dataLabels: {
+                enabled: _.ShowTips===1,
+                allowOverlap: true,
+                align: 'left',
+                format: tagMap[_.DateType] || `-${_.DaysAgo}D`,
+                }
+            })
+        })
+        series.push(series_item);
+    })
+
+    let tooltip = {
+        formatter: function() {
+
+            let that = this;
+            let str = '';
+
+            let series_obj = DataList.find(_ => _.Name === that.series.name);
+            let ponit_obj = series_obj.CoordinatePointData.find(_ => _.X ===that.x && _.Y===that.y);
+            
+            let xEdbInfo = EdbInfoList.find(_ => _.EdbInfoId===ponit_obj.XEdbInfoId);
+            let yEdbInfo = EdbInfoList.find(_ => _.EdbInfoId===ponit_obj.YEdbInfoId);
+
+            str=`<b>${ that.series.name }</b>`;
+            str += `<br><span style="color:${that.color}">\u25CF</span>${xEdbInfo.EdbName}: ${that.x} ${ponit_obj.XDate}<br>`;
+            str += `<span style="color:${that.color}">\u25CF</span>${yEdbInfo.EdbName}: ${that.y} ${ponit_obj.YDate}`;
+
+            return str
+        }
+    }
+
+    return {
+        title: {
+            text:''
+        },
+        series,
+        yAxis: [yAxis],
+        xAxis,
+        tooltip
+    }
+}
+
+
+
+ /* 处理轴的标识线结构 在指定轴位置上拼接标识线 
+    0:右轴 1:左轴 2:右2轴 x轴固定3
+    axisType表示x轴类型 处理时间轴的值 datetime/null 
+*/
+function setAxisPlotLines(axis,axisType) {
+  const { MarkersLines,ChartType } = chartData.value.ChartInfo;
+  const { EdbInfoList } = chartData.value;
+  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(EdbInfoList[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 */
+function setAxisPlotAreas(axis,axisType) {
+  const { MarkersAreas,ChartType } = chartData.value.ChartInfo;
+  const { EdbInfoList } = chartData.value;
+  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(EdbInfoList[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,
+              y: positionMapValue[_.textPosition],
+              style: {
+                  color: _.textColor,
+                  fontSize: _.textFontSize
+              }
+          }
+      }
+  })
+
+  return plotBands
+}
+
+
+/* 预测配置 分区 */
+function getPredictParams ({LatestDate,PredictChartColor}) {
+  return {
+    zoneAxis: 'x',
+    zones: [{
+        value: new Date(LatestDate).getTime()+1
+    }, {
+        dashStyle: 'ShortDot',
+        color: PredictChartColor
+    }]
+  }
+}
+
+/* 季节图预测数据 年份=分割点年份做分割 年份>分割点年份全为预测 */
+function getSeasonPredictParams (timestamp){
+  return timestamp
+    ? {
+        zoneAxis: 'x',
+        zones: [{
+            value: new Date(timestamp).getTime()+1
+        }, {
+            dashStyle: 'ShortDot',
+        }]
+        }
+    : {}
+}
+
+// 查询范围为1年内 x轴显示为月/日 否则默认年/月
+function xTimeDiffer(minTime,maxTime,dateType){
+  //年限差
+  let year_differ=moment(maxTime).diff(moment(minTime),'years',true)
+  // console.log('年限差',year_differ)
+  if ([5, 6].includes(dateType) && year_differ <= 1) {
+      return true
+  } else {
+      return false
+  }
+}
+
+/* 拼接数据列动态name */
+function setDyncmicSerieName (item,dynamic_arr) {
+  const { IsAxis,IsOrder,EdbInfoType,LeadValue,LeadUnit }  = item;
+  // IsAxis左轴1 右轴0 2右2轴 
+    //IsOrder正序false 逆序true 
+    //EdbInfoType是否是领先指标
+  const axisLabelMap = {
+      0: '右轴',
+      2: '右2轴'
+  }
+  const orderLabelMap = {
+      1: '逆序'
+  }
+  const edbInfoMap = {
+      0: '领先'
+  }
+
+  let axis_tag = axisLabelMap[IsAxis] || '';
+    //逆序拼接
+  let order_tag = orderLabelMap[Number(IsOrder)] ? `${axis_tag ? ',': ''}${orderLabelMap[Number(IsOrder)]}` : ''
+    //领先拼接
+  let edb_tag = edbInfoMap[EdbInfoType] ? `${(axis_tag||order_tag) ? ',' : '' }${edbInfoMap[EdbInfoType]}${LeadValue}${LeadUnit}` : '';
+
+  let dynamic_tag = (axis_tag || order_tag || edb_tag) ? `(${axis_tag}${order_tag}${edb_tag})` : '';
+
+  let temName = dynamic_arr.length > 1
+              ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
+              : `${item.EdbName}${dynamic_tag}`
+  if(temName.length>20){
+      let temArr=[]
+      for(let i=0;i<temName.length/20;i++){
+          temArr.push(temName.slice(i*20,i*20+20))
+      }
+      // console.log(temArr);
+      temName=temArr.join('<br>')
+  }
+
+  return temName
+}
+
+/* 指标顺序调整  IsAxis: 0右轴 1左轴 2右2*/
+function changeEdbOrder (data){
+  // 左轴指标
+  let left_edbs = data.filter(_ => _.IsAxis===1);
+  //右轴指标
+  let right_edbs = data.filter(_ => !_.IsAxis);
+  // 右2轴指标
+  let right_two_edbs = data.filter(_ => _.IsAxis === 2);
+  // 按 左 右 右2顺序排列
+  return [left_edbs,right_edbs,right_two_edbs].flat(Infinity);
+}
+
+//获取RGBA的透明度
+function parseRgbaColor(color='rgba(51, 51, 51, 1)'){
+  const arr = color.match(/(\d(\.\d+)?)+/g) || ['','','',1];
+  return parseFloat(arr[3]||1)
+}
+/* ----自定义上下限相关--- */
+/* 计算y轴上下限 */
+function calcYAxislimit(tableData=[],ChartInfo,DataResp={}){
+  //散点图单独处理
+  if(ChartInfo.ChartType===5){
+      if(tableData[1]){
+          axisLimitData.leftMin = tableData[1].MinData
+          axisLimitData.leftMax = tableData[1].MaxData
+      }
+      return 
+  }
+  //分组
+  const leftData = tableData.filter(i => i.IsAxis === 1).map(i => [Number(i.MinData), Number(i.MaxData)])
+  const rightData = tableData.filter(i => !i.IsAxis).map(i => [Number(i.MinData), Number(i.MaxData)])
+  const rightTwoData = tableData.filter(i => i.IsAxis === 2).map(i => [Number(i.MinData), Number(i.MaxData)])
+  //计算最大最小值
+  if (leftData.length) {
+      const {
+          Max,
+          Min
+      } = calcLimit(leftData.flat())
+      axisLimitData.leftMin = Min
+      axisLimitData.leftMax = Max
+  } 
+  if (rightData.length) {
+      const {
+          Max,
+          Min
+      } = calcLimit(rightData.flat())
+      axisLimitData.rightMin = Min
+      axisLimitData.rightMax = Max
+  }
+  if (rightTwoData.length) {
+      const {
+          Max,
+          Min
+      } = calcLimit(rightTwoData.flat())
+      axisLimitData.rightTwoMin = Min
+      axisLimitData.rightTwoMax = Max
+  }
+  //季节性图-右轴单独处理
+  if(ChartInfo.ChartType===2){
+      if(DataResp.RightAxis&&DataResp.RightAxis.IsAdd&&DataResp.RightAxis.IsShow){
+          if(DataResp.RightAxis.IndicatorType===1){
+              axisLimitData.rightMin = DataResp.RightAxis.EdbInfoList[0].MinData||0
+              axisLimitData.rightMax = DataResp.RightAxis.EdbInfoList[0].MaxData||0
+          }else{
+              axisLimitData.rightMin = tableData[1].MinData||0
+              axisLimitData.rightMax = tableData[1].MaxData||0
+          }
+          
+      }
+  }
+}
+function calcLimit(arr) {
+  return {
+      Max: Math.max(...arr),
+      Min: Math.min(...arr)
+  }
+}
+//图表详情-设置图表上下限
+function setLimitData({EdbInfoList,ChartInfo,DataResp}){
+  const {
+      //左右轴极值字段 
+      LeftMin=0,LeftMax=0,
+      RightMin=0,RightMax=0,
+      Right2Min=0,Right2Max=0,
+      MinMaxSave
+  } = ChartInfo
+  if(MinMaxSave){
+      axisLimitData.leftMin = Number(LeftMin)
+      axisLimitData.leftMax = Number(LeftMax)
+      axisLimitData.rightMin = Number(RightMin)
+      axisLimitData.rightMax = Number(RightMax)
+      axisLimitData.rightTwoMin = Number(Right2Min)
+      axisLimitData.rightTwoMax = Number(Right2Max)
+      //若用户修改过,则检测轴的上下限是否为空,若为空,则需要计算对应轴的上下限
+      checkLimit(EdbInfoList,ChartInfo)
+      console.log('check',axisLimitData.leftMin,axisLimitData.leftMax)
+  }else{
+      calcYAxislimit(EdbInfoList,ChartInfo,DataResp?DataResp:{})
+  }
+}
+function checkLimit(tableData=[],ChartInfo){
+  //散点图单独处理
+  if(ChartInfo.ChartType===5){
+      if(tableData[1]){
+          if(Number(axisLimitData.leftMin)===0&&Number(axisLimitData.leftMax)===0){
+              axisLimitData.leftMin = tableData[1].MinData
+              axisLimitData.leftMax = tableData[1].MaxData
+          }
+      }
+      return 
+  }
+  //若轴的上下限均为0,则不管用户有没有修改过,都重新赋值
+  if(Number(axisLimitData.leftMin)===0&&Number(axisLimitData.leftMax)===0){
+      const leftData = tableData.filter(i=>i.IsAxis===1).map(i=>[Number(i.MinData),Number(i.MaxData)])
+      if(leftData.length){
+          const {Max,Min} = calcLimit(leftData.flat())
+          axisLimitData.leftMin = Min
+          axisLimitData.leftMax = Max
+      }
+  }
+  if(Number(axisLimitData.rightMin)===0&&Number(axisLimitData.rightMax)===0){
+      const rightData = tableData.filter(i => !i.IsAxis).map(i=>[Number(i.MinData),Number(i.MaxData)])
+      if(rightData.length){
+          const {Max,Min} = calcLimit(rightData.flat())
+          axisLimitData.rightMin = Min
+          axisLimitData.rightMax = Max
+      }
+  }
+  if(Number(axisLimitData.rightTwoMin)===0&&Number(axisLimitData.rightTwoMax)===0){
+      const rightTwoData = tableData.filter(i=>i.IsAxis===2).map(i=>[Number(i.MinData),Number(i.MaxData)])
+      if(rightTwoData.length){
+          const {Max,Min} = calcLimit(rightTwoData.flat())
+          axisLimitData.rightTwoMin = Min
+          axisLimitData.rightTwoMax = Max
+      }
+  }
+}
+/*-------------------- */

+ 30 - 27
src/views/hzyb/report/ChapterDetail.vue

@@ -44,11 +44,11 @@
               <span style="color: #e3b377; margin-left: 20px" @click="showDisclaimers = true">免责声明</span>
             </div>
           </div>
+          <span 
+            v-if="!info.report_chapter_item.report_video_url&&info.report_chapter_item.video_url&&info.report_chapter_item.video_play_seconds>0" 
+            style="float:right;background:#E3B377;color:#fff;border-radius:30px;padding:0 10px;font-size:0.9em" @click="handlePlayAudioBG"
+          >背景播放</span>
         </div>
-        <span 
-          v-if="!info.report_chapter_item.report_video_url&&info.report_chapter_item.video_url&&info.report_chapter_item.video_play_seconds>0" 
-          style="float:right;background:#E3B377;color:#fff;border-radius:30px;padding:0 10px;font-size:0.9em" @click="handlePlayAudioBG"
-        >背景播放</span>
         <div id="report-rich-content" class="rich-content" ref="richConBox">
           <div v-if="info.auth_ok">
             <ul>
@@ -89,18 +89,25 @@
 
 
       <!-- 无权限 -->
-      <div class="no-auth-wrap" v-if="!info.auth_ok">
-        <div class="apply-box" v-if="info.permission_check.type=='apply'">
-          <div>您暂无权限查看报告,若想查看请申请开通</div>
-          <div class="btn" @click="handleGoApply">立即申请</div>
-        </div>
-        <div class="apply-box" v-else>
-          <div>您暂无权限查看报告 </div>
-          <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
-          <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+      <div class="no-auth-wrap" v-if="userInfo?.is_bind==0">
+        <div class="apply-box">
+          <div>您尚未登录,请登录后查看更多信息</div>
+          <div class="btn" @click="handleGoLogin">立即登录</div>
         </div>
       </div>
-      
+      <template v-else>
+        <div class="no-auth-wrap" v-if="!info.auth_ok">
+          <div class="apply-box" v-if="info.permission_check.type=='apply'">
+            <div>您暂无权限查看报告,若想查看请申请开通</div>
+            <div class="btn" @click="handleGoApply">立即申请</div>
+          </div>
+          <div class="apply-box" v-else>
+            <div>您暂无权限查看报告 </div>
+            <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
+            <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+          </div>
+        </div>
+      </template>
     </div>
     <!-- 章节详情底部快速切换 -->
     <div class="chapter-list-wrap" v-if="fromPage=='reportdetail'">
@@ -337,17 +344,6 @@ export default {
       const res=await apiUserInfo()
       if(res.code===200){
         this.userInfo=res.data
-        if(this.userInfo.is_bind===0){
-            Dialog.confirm({
-                title:'温馨提示',
-                message:'为了优化您的用户体验,\n 请登录后查看更多信息!',
-                confirmButtonText:'去登录',
-                confirmButtonColor:'#E6B77D',
-                cancelButtonColor:'#666'
-            }).then(res=>{
-                wx.miniProgram.reLaunch({url:'/pages/login'})
-            })
-        }
         if(!iswatermark) return
         this.$nextTick(()=>{
           this.waterMark(res.data.mobile,this.$refs.richConBox)
@@ -454,8 +450,10 @@ export default {
             pars:JSON.stringify({
                 title:imgText,
                 time_format:moment(res.data.report_chapter_item.publish_time).format('YYYY/MM/DD'),
-                background_img:res.data.report_chapter_item.share_bg_img
-            })
+                background_img:res.data.report_chapter_item.share_bg_img,
+            }),
+            report_id:Number(res.data.report_chapter_item.report_id),
+            report_chapter_id:Number(this.chapterId)
         })
         if(rddpImgRes.code===200){
             shareImg=rddpImgRes.data
@@ -628,6 +626,11 @@ export default {
     //   });
     // },
 
+    //登录
+    handleGoLogin(){
+      wx.miniProgram.navigateTo({url:'/pages/login?from=tologin'})
+    },
+
     //点击申请
     async handleGoApply(){
       if(this.userInfo.is_bind===0){

+ 43 - 31
src/views/hzyb/report/Detail.vue

@@ -50,18 +50,27 @@
                 </div>
             </div>
             <!-- 无权限 -->
-            <div class="no-auth-box" v-if="!info.auth_ok">
+            <div class="no-auth-box" v-if="userInfo?.is_bind==0">
                 <img class="img" src="https://hzstatic.hzinsights.com/static/icon/hzyb/activity_no_auth.png" mode="widthFix" />
-                <div class="apply-box" v-if="info.permission_check.type=='apply'">
-                    <div>您暂无权限查看报告,若想查看请申请开通</div>
-                    <div class="btn" @click="handleGoApply">立即申请</div>
-                </div>
-                <div class="apply-box" v-else>
-                    <div>您暂无权限查看报告 </div>
-                    <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
-                    <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+                <div class="apply-box">
+                    <div>您尚未登录,请登录后查看更多信息</div>
+                    <div class="btn" @click="handleGoLogin">立即登录</div>
                 </div>
             </div>
+            <template v-else>
+                <div class="no-auth-box" v-if="!info.auth_ok">
+                    <img class="img" src="https://hzstatic.hzinsights.com/static/icon/hzyb/activity_no_auth.png" mode="widthFix" />
+                    <div class="apply-box" v-if="info.permission_check.type=='apply'">
+                        <div>您暂无权限查看报告,若想查看请申请开通</div>
+                        <div class="btn" @click="handleGoApply">立即申请</div>
+                    </div>
+                    <div class="apply-box" v-else>
+                        <div>您暂无权限查看报告 </div>
+                        <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
+                        <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+                    </div>
+                </div>
+            </template>
         </div>
 
         <!-- 报告详情 -->
@@ -149,17 +158,25 @@
             </div>
 
             <!-- 无权限 -->
-            <div class="no-auth-wrap" v-if="!info.auth_ok">
-                <div class="apply-box" v-if="info.permission_check.type=='apply'">
-                    <div>您暂无权限查看报告,若想查看请申请开通</div>
-                    <div class="btn" @click="handleGoApply">立即申请</div>
-                </div>
-                <div class="apply-box" v-else>
-                    <div>您暂无权限查看报告 </div>
-                    <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
-                    <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+            <div class="no-auth-wrap" v-if="userInfo?.is_bind==0">
+                <div class="apply-box">
+                    <div>您尚未登录,请登录后查看更多信息</div>
+                    <div class="btn" @click="handleGoLogin">立即登录</div>
                 </div>
             </div>
+            <template v-else>
+                <div class="no-auth-wrap" v-if="!info.auth_ok">
+                    <div class="apply-box" v-if="info.permission_check.type=='apply'">
+                        <div>您暂无权限查看报告,若想查看请申请开通</div>
+                        <div class="btn" @click="handleGoApply">立即申请</div>
+                    </div>
+                    <div class="apply-box" v-else>
+                        <div>您暂无权限查看报告 </div>
+                        <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
+                        <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+                    </div>
+                </div>
+            </template>
 
             <!-- 右侧悬浮操作栏 -->
             <div class="right-fix-box">
@@ -417,17 +434,6 @@ export default {
             const res=await apiUserInfo()
             if(res.code===200){
                 this.userInfo=res.data
-                if(this.userInfo.is_bind===0){
-                    Dialog.confirm({
-                        title:'温馨提示',
-                        message:'为了优化您的用户体验,\n 请登录后查看更多信息!',
-                        confirmButtonText:'去登录',
-                        confirmButtonColor:'#E6B77D',
-                        cancelButtonColor:'#666'
-                    }).then(res=>{
-                        wx.miniProgram.reLaunch({url:'/pages/login'})
-                    })
-                }
             }
         },
 
@@ -555,8 +561,9 @@ export default {
                     pars:JSON.stringify({
                         title:imgText,
                         time_format:moment(res.data.report_info.publish_time).format('YYYY/MM/DD'),
-                        background_img:res.data.report_info.share_bg_img
-                    })
+                        background_img:res.data.report_info.share_bg_img,
+                    }),
+                    report_id:Number(this.reportId),
                 })
                 if(rddpImgRes.code===200){
                     shareImg=rddpImgRes.data
@@ -712,6 +719,11 @@ export default {
         //     });
         // },
 
+        //登录
+        handleGoLogin(){
+            wx.miniProgram.navigateTo({url:'/pages/login?from=tologin'})
+        },
+
         //点击申请
         async handleGoApply(){
             if(this.userInfo.is_bind===0){

+ 285 - 0
src/views/hzyb/report/RaiDetail.vue

@@ -0,0 +1,285 @@
+<script setup>
+import { ref, } from "vue";
+import { apiReportDetail, apiRddpShareImg, } from '@/api/hzyb/report'
+import { apiApplyPermission, apiUserInfo } from '@/api/hzyb/user'
+import { useRoute } from "vue-router";
+import moment from "moment";
+import reportCancel from './components/reportCancel.vue'
+import {Dialog,Popup} from 'vant'
+
+const route = useRoute()
+
+// 获取详情如果为联系销售根据判断条件是否主动申请一次
+function validateAutoApply(info) {
+  if (info.permission_check.type == 'contact' && !info.permission_check.customer_info.has_apply) {
+    if (info.permission_check.customer_info.status == '冻结' || (info.permission_check.customer_info.status == '试用' && info.permission_check.customer_info.is_suspend == 1)) {
+      apiApplyPermission({
+        company_name: info.permission_check.customer_info.company_name,
+        real_name: info.permission_check.customer_info.name,
+        source: 4,
+        from_page: '报告详情'
+      }).then(res => {
+        if (res.code === 200) {
+          console.log('主动申请成功');
+        }
+      })
+    }
+  }
+}
+
+//向小程序发送分享数据
+async function handleGetShareData(info) {
+  let shareTitle = ''
+  let shareImg = ''
+  let imgText = ''//分享图上需要显示的内容
+  const shareTime = moment(info.report_info.publish_time).format('MMDD')
+  if (info.report_info.abstract) {
+    shareTitle = info.report_info.abstract
+    imgText = `<div style="font-size:78px">${info.report_info.title}(${shareTime})</div>`
+  } else {
+    shareTitle = info.report_info.title
+    imgText = `<div style="font-size:78px">${moment(info.report_info.publish_time).format('YYYY/MM/DD')}</div><div style="font-size:78px">${info.report_info.classify_name_second}</div>`
+  }
+  const rddpImgRes = await apiRddpShareImg({
+    pars: JSON.stringify({
+      title: imgText,
+      time_format: moment(info.report_info.publish_time).format('YYYY/MM/DD'),
+      background_img: info.report_info.share_bg_img,
+    }),
+    report_id: Number(route.query.reportId),
+  })
+  if (rddpImgRes.code === 200) {
+    shareImg = rddpImgRes.data
+  }
+
+  wx.miniProgram.postMessage({
+    data: {
+      title: shareTitle,
+      reportId: route.query.reportId,
+      shareImg: shareImg
+    }
+  });
+
+}
+
+const userInfo = ref(null)
+async function getUserInfo() {
+  const res = await apiUserInfo()
+  if (res.code === 200) {
+    userInfo.value = res.data
+  }
+}
+
+// 获取报告详情
+const isReportPublishCancel = ref(false)
+const reportInfo = ref(null)
+async function getReportDetail() {
+  const res = await apiReportDetail({
+    report_id: Number(route.query.reportId)
+  })
+  if (res.code === 200) {
+    reportInfo.value = res.data
+    if (!res.data.auth_ok) {
+      validateAutoApply(res.data)
+    }
+
+    handleGetShareData(res.data)
+  } else if (res.code === 4002) {
+    isReportPublishCancel.value = true
+  }
+
+}
+
+const pupData=ref({
+  show:false,
+  content:'',//弹窗html字符串
+})
+// 发起申请
+async function handleGoApply(){
+  if(userInfo.value.is_bind===0){
+    Dialog.confirm({
+      title:'温馨提示',
+      message:'为了优化您的用户体验,\n 请登录后查看更多信息!',
+      confirmButtonText:'去登录',
+      confirmButtonColor:'#E6B77D',
+      cancelButtonColor:'#666'
+    }).then(res=>{
+      wx.miniProgram.reLaunch({url:'/pages/login'})
+    })
+    return
+  }
+  if(reportInfo.value.permission_check.type=='apply'){
+    if(reportInfo.value.permission_check.customer_info.has_apply){// 已经申请过
+      pupData.value.show=true
+      pupData.value.content=`<p>您已提交过申请,请耐心等待</p>`
+    }else{
+      if(!reportInfo.value.permission_check.customer_info.status||reportInfo.value.permission_check.customer_info.status!='流失'||reportInfo.value.permission_check.customer_info.status!='关闭'){
+        wx.miniProgram.redirectTo({
+            url:"/pages-applyPermission/applyPermission?source=4&from_page=报告详情"
+        })
+      }else{//主动调一次申请权限接口 
+        const res=await apiApplyPermission({
+          company_name:reportInfo.value.permission_check.customer_info.company_name,
+          real_name:reportInfo.value.permission_check.customer_info.name,
+          source:4,
+          from_page:'报告详情'
+        })
+        if(res.code===200){
+          pupData.value.show=true
+          pupData.value.content=`<p>申请已提交</p><p>请等待销售人员与您联系</p>`
+          getReportDetail()
+        }
+      }
+    }
+  }
+}
+
+
+
+function initPage() {
+  if (route.query.token) {
+    localStorage.setItem('hzyb-token', route.query.token)
+    localStorage.setItem('hzyb-userId', route.query.userId)
+  }
+  getReportDetail()
+  getUserInfo()
+}
+initPage()
+
+
+
+
+</script>
+
+
+<template>
+  <div class="rai-report-detail-page" v-if="reportInfo">
+    <iframe :src="reportInfo.rai_report_url" class="iframe-wrap"></iframe>
+    <!-- 无权限 -->
+    <div class="no-auth-wrap" v-if="userInfo?.is_bind === 0">
+      <div class="apply-box">
+        <div>您尚未登录,请登录后查看更多信息</div>
+        <div class="btn" @click="handleGoLogin">立即登录</div>
+      </div>
+    </div>
+    <template v-else>
+      <div class="no-auth-wrap" v-if="!reportInfo.auth_ok">
+        <div
+          class="apply-box"
+          v-if="reportInfo.permission_check.type == 'apply'"
+        >
+          <div>您暂无权限查看报告,若想查看请申请开通</div>
+          <div class="btn" @click="handleGoApply">立即申请</div>
+        </div>
+        <div class="apply-box" v-else>
+          <div>您暂无权限查看报告</div>
+          <div>
+            若想查看请联系对口销售:{{ reportInfo.permission_check.name }}
+          </div>
+          <a
+            class="btn"
+            :href="'tel:' + reportInfo.permission_check.mobile"
+            tag="div"
+            >立即联系</a
+          >
+        </div>
+      </div>
+    </template>
+  </div>
+  <!-- 申请提示弹窗 -->
+  <Popup :show="pupData.show" @close="pupData.show=false" :close-on-click-overlay="false">
+    <div class="global-pup">
+      <div class="content">
+        <div v-html="pupData.content"></div>
+      </div>
+      <div class="flex bot">
+        <div @click="pupData.show=false">知道了</div>
+      </div>
+    </div>
+  </Popup>
+  <reportCancel v-if="isReportPublishCancel" />
+</template>
+
+
+
+<style lang="scss" scope>
+/* 公共弹窗 */
+.global-pup{
+  background-color: #fff;
+  width: 90vw;
+  min-height: 200px;
+  font-size: 32px;
+  .content{
+    padding: 34px;
+    text-align: center;
+    min-height: 250px;
+    display: flex;
+    align-items: center;
+    text-align: center;
+    line-height: 1.7;
+    div{
+      flex: 1;
+    }
+  }
+  .bot{
+    border-top: 1px solid #dedede;
+    div{
+      line-height: 96px;
+      flex: 1;
+      text-align: center;
+      border-right: 1px solid #dedede;
+      color:#E3B377;
+    }
+    div:last-child {
+      border: none;
+    }
+  }
+}
+.flex{
+  display: flex;
+}
+.rai-report-detail-page {
+  width: 100vw;
+  height: 100vh;
+  .iframe-wrap {
+    width: 100%;
+    height: 100%;
+    border: none;
+  }
+  .no-auth-wrap {
+    background: linear-gradient(
+      360deg,
+      #ffffff 60%,
+      rgba(255, 255, 255, 0) 88%
+    );
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    top: 0;
+    z-index: 99;
+    text-align: center;
+    font-size: 32px;
+    color: #e3b377;
+    overflow: hidden;
+    .apply-box {
+      padding-top: 250px;
+      position: absolute;
+      bottom: 100px;
+      left: 5%;
+      width: 90%;
+    }
+    .btn {
+      width: 100%;
+      margin-left: auto;
+      margin-right: auto;
+      line-height: 80px;
+      background-color: #e6b77d;
+      border-radius: 4px;
+      color: #fff;
+      margin-top: 100px;
+      display: block;
+    }
+  }
+}
+</style>

+ 34 - 20
src/views/ssbg/businessTrip/calendar.vue

@@ -177,26 +177,32 @@ function handleShowDetail(item){
         <div class="detail-wrap">
             <div class="content">
                 <h2 class="title">出差详情</h2>
-                <div>{{moment(detailInfo.ArriveDate).format('MM.DD (ddd)')}}--{{moment(detailInfo.ReturnDate).format('MM.DD (ddd)')}}</div>
-                <div class="item-info">
-                    <span>申请人:</span>
-                    <span>{{detailInfo.ApplyRealName}}</span>
-                </div>
-                <div class="item-info">
-                    <span>目的地:</span>
-                    <span>{{detailInfo.Province}}{{detailInfo.City}}</span>
-                </div>
-                <div class="item-info">
-                    <span>出差事由:</span>
-                    <span>{{detailInfo.Reason}}</span>
-                </div>
-                <div class="item-info">
-                    <span>交通工具:</span>
-                    <span>{{detailInfo.Transportation}}</span>
-                </div>
-                <div class="item-info" v-if="detailInfo.PeerPeopleName">
-                    <span>同行人:</span>
-                    <span>{{detailInfo.PeerPeopleName}}</span>
+                <div class="content-box">
+                    <div>{{moment(detailInfo.ArriveDate).format('MM.DD (ddd)')}}--{{moment(detailInfo.ReturnDate).format('MM.DD (ddd)')}}</div>
+                    <div class="item-info">
+                        <span>申请人:</span>
+                        <span>{{detailInfo.ApplyRealName}}</span>
+                    </div>
+                    <div class="item-info">
+                        <span>目的地:</span>
+                        <span>{{detailInfo.Province}}{{detailInfo.City}}</span>
+                    </div>
+                    <div class="item-info">
+                        <span>出差事由:</span>
+                        <span>{{detailInfo.Reason}}</span>
+                    </div>
+                    <div class="item-info">
+                        <span>交通工具:</span>
+                        <span>{{detailInfo.Transportation}}</span>
+                    </div>
+                    <div class="item-info">
+                        <span>行程说明:</span>
+                        <span>{{detailInfo.Itinerary}}</span>
+                    </div>
+                    <div class="item-info" v-if="detailInfo.PeerPeopleName">
+                        <span>同行人:</span>
+                        <span>{{detailInfo.PeerPeopleName}}</span>
+                    </div>
                 </div>
             </div>
             <div class="btn" @click="showDetail=false">知道了</div>
@@ -317,5 +323,13 @@ function handleShowDetail(item){
         text-align: center;
         line-height: 80px;
     }
+    
+    .content-box{
+        max-height: 600px;
+        overflow-y: auto;
+        &::-webkit-scrollbar {
+            width: 0;
+        }
+    }
 }
 </style>

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