1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510 |
- <script setup name="ChartETAChartDetail">
- import {nextTick, onMounted,ref,reactive} from 'vue'
- import {showDialog, showToast} from 'vant'
- import apiChart from '@/api/chart'
- import { useRoute, useRouter } from 'vue-router'
- import { useWindowSize } from '@vueuse/core'
- import {yearSelectOpt,sameOptionType} from '@/hooks/chart/config'
- import {useChartRender} from '@/hooks/chart/render'
- import { getChartShareExpireToken } from './hooks/useChartSharedToken'
- import moment from 'moment'
- import EdbInfo from './components/EdbInfo.vue'
- import SourceDetail from './components/SourceDetail.vue'
- import TreeSelectPop from './components/TreeSelectPop.vue'
- import AddChartToMyETA from './components/AddChartToMyETA.vue'
- import SetChartEnName from './components/SetChartEnName.vue'
- import {useCachedViewsStore} from '@/store/modules/cachedViews'
- import { setExtremumDate } from '@/hooks/chart/commonFun.js'
- import {chartLibBtn,useAuthBtn} from '@/hooks/useAuthBtn'
- import {usePublicSettingStore} from '@/store/modules/publicSetting'
- import _ from 'lodash';
- import SaveToMaterial from '@/components/SaveToMaterial.vue'
- const {checkAuthBtn} = useAuthBtn()
- const publicSettingStore = usePublicSettingStore()
- const {options,axisLimitState,chartRender,setLimitData,isUseSelfLimit}=useChartRender()
- const { width } = useWindowSize()
- const cachedViewsStore=useCachedViewsStore()
- const route=useRoute()
- const router=useRouter()
- let routeQueryData=reactive({
- chartType:route.query.chartType,
- id:route.query.id,
- chartClassifyId:route.query.chartClassifyId,
- })
- let currentLang = ref('')
- //获取图详情
- let chartInfoData=null
- let chartInfo=ref(null)
- //highchart图表
- let highChart = ref(null)
- let edbList=ref([])//指标数据
- async function getChartDetail(e){
- const params=sameOptionType.includes(Number(routeQueryData.chartType))?{
- ChartInfoId:Number(routeQueryData.id),
- DateType: chartState.yearVal,
- StartDate: chartState.startTime,
- EndDate: chartState.endTime,
- StartYear:chartState.startYear
- }:{
- ChartInfoId:Number(routeQueryData.id),
- Calendar: chartState.calendarType,//this.calendar_type
- DateType: chartState.yearVal,
- StartDate: chartState.startTime,
- EndDate:chartState.endTime,
- StartYear:chartState.startYear
- }
- const res=await apiChart.chartInfoById(params)
- if(res.Ret!==200) return
- chartInfoData=res.Data
- chartInfo.value=res.Data.ChartInfo
- chartActions.value = getChartActions(res.Data.ChartInfo)
- if(res.Data.ChartInfo.Source===2){
- edbList.value=[res.Data.EdbInfoList[0]]
- }else{
- edbList.value=res.Data.EdbInfoList
- }
- if(e==='init'){
- chartState.yearVal=res.Data.ChartInfo.DateType
- }
- // 设置 起始日期 和 最新日期
- const extremumDate= setExtremumDate(edbList.value)
- minDate = new Date(extremumDate.earliestDate)
- earliestDate.value = extremumDate.earliestDate
- latestDate.value = extremumDate.latestDate
- setDateAppear()
- //初始化上下限
- isUseSelfLimit.value = true
- setLimitData(res.Data)
- nextTick(()=>{
- highChart.value = chartRender({
- data:{
- ...res.Data,
- ChartInfo:{
- ...res.Data.ChartInfo,
- Calendar:chartState.calendarType||'公历'
- },
- },
- renderId:'chart-box',
- lang:currentLang.value,
- changeLangIsCheck:false,
- showChartTitle:false,
- shouldUseSelfLimit:true,
- })
- })
-
- }
- function setDateAppear() {
- if(chartState.yearVal == 20){
- let latestYear = parseInt(latestDate.value.substring(0,4))
- chartState.startTime = `${latestYear-chartState.startYear+1}-01-01`
- chartState.endTime = `${latestYear}-12-31`
- }
- }
- // 是否面积图堆叠百分比
- function isChartHeap(info){
- let tag=true
- if(info.ChartType==3&&info.ExtraConfig){
- let ExtraConfig=JSON.parse(info.ExtraConfig)
- tag=ExtraConfig.HeapWay==2?false:true
- }
- return tag
- }
- onMounted(() => {
- currentLang.value = localStorage.getItem('chartETALange')==='EN'?'en':'zh'
- initChartState(route.query)
- getChartDetail('init')
- })
- let minDate=new Date(1970, 0, 1)
- const maxDate=new Date(2050, 11, 31)
- const cYear=moment().format('YYYY')
- const cMonth=moment().format('MM')
- const cDay=moment().format('dd')
- let temStartTime=ref([cYear,cMonth,cDay])
- let temEndTime=ref([cYear,cMonth,cDay])
- const latestDate = ref('')
- const earliestDate = ref('')
- let chartState=reactive({
- showTimePop:false,
- startTime:'',
- endTime:'',
- yearVal:'',
- calendarType:'公历',
- startYear:5
- })
- // 切换年份选项
- function handleYearChange(item){
- chartState.yearVal=item.value
- chartState.startTime=''
- chartState.endTime=''
- getChartDetail()
- }
- // 确定日期筛选
- function handleTimeChange(){
- chartState.startTime=temStartTime.value.join('-')
- chartState.endTime=temEndTime.value.join('-')
- chartState.yearVal=5
- getChartDetail()
- chartState.showTimePop=false
- }
- // 季节图公历\农历切换
- function handleSeasonTypeChange(type){
- chartState.calendarType=type
- getChartDetail()
- }
- // 上下限调整
- let showLimitPop=ref(false)
- let axisLimitDataTem=reactive({//左右轴极值
- min:'-99999999999999999',
- leftMin:0,
- leftMax:0,
- rightMin:0,
- rightMax:0,
- rightTwoMin:0,
- rightTwoMax:0,
- xMin:0,
- xMax:0,
- })
- function handleShowAxisLimitOpt(){
- axisLimitDataTem.leftMin=axisLimitState.leftMin
- axisLimitDataTem.leftMax=axisLimitState.leftMax
- axisLimitDataTem.rightMin=axisLimitState.rightMin
- axisLimitDataTem.rightMax=axisLimitState.rightMax
- axisLimitDataTem.rightTwoMin=axisLimitState.rightTwoMin
- axisLimitDataTem.rightTwoMax=axisLimitState.rightTwoMax
- axisLimitDataTem.xMin=axisLimitState.xMin
- axisLimitDataTem.xMax=axisLimitState.xMax
- showLimitPop.value=true
- }
- // 极限修改确定
- function handleConfirmLimitChange(){
- const data=_.cloneDeep(chartInfoData)
- // 修改左轴极限
- if(axisLimitState.hasLeftAxis){
- //基础图
- if(axisLimitState.leftIndex!==-1){
- axisLimitState.leftMin = axisLimitDataTem.leftMin
- axisLimitState.leftMax = axisLimitDataTem.leftMax
- }else{
- // 柱形图 取的ChartInfo中的极值
- if(data.ChartInfo.ChartType ===7){
- data.ChartInfo.LeftMin=axisLimitDataTem.leftMin
- data.ChartInfo.LeftMax=axisLimitDataTem.leftMax
- }
- // 商品价格曲线
- if(data.ChartInfo.ChartType ===8){
- data.ChartInfo.LeftMin=axisLimitDataTem.leftMin
- data.ChartInfo.LeftMax=axisLimitDataTem.leftMax
- }
- // 截面散点 取的DataResp
- if(data.ChartInfo.ChartType ===10){
- data.DataResp.YMinValue=axisLimitDataTem.leftMin
- data.DataResp.YMaxValue=axisLimitDataTem.leftMax
- }
- }
- }
- // 修改右轴极限
- if(axisLimitState.hasRightAxis){
- if(axisLimitState.rightIndex!==-1){
- axisLimitState.rightMin = axisLimitDataTem.rightMin
- axisLimitState.rightMax = axisLimitDataTem.rightMax
- }
- }
- //修改右2轴极限
- if(axisLimitState.hasRightTwoAxis){
- if(axisLimitState.rightTwoIndex!==-1){
- axisLimitState.rightMin = axisLimitDataTem.rightTwoMin
- axisLimitState.rightMax = axisLimitDataTem.rightTwoMax
- }
- }
- // 修改X轴极限
- if(axisLimitState.hasXAxis){
- // 截面散点 取的DataResp
- if(data.ChartInfo.ChartType ===10){
- data.DataResp.XMinValue=axisLimitDataTem.xMin
- data.DataResp.XMaxValue=axisLimitDataTem.xMax
- }
- }
- highChart.value = chartRender({
- data:data,
- renderId:'chart-box',
- lang:currentLang.value,
- changeLangIsCheck:false,
- showChartTitle:false,
- shouldUseSelfLimit:true,
- })
- showLimitPop.value=false
- }
- // 显示指标详情
- let showEDB=ref(false)
- let showEDBData=ref({})
- function handleShowEDBInfo(item){
- showEDBData.value=item
- showEDB.value=true
- }
- //显示数据来源详情
- let showSourceDetail = ref(false)
- function handleShowSourceDetail(){
- showSourceDetail.value = true
- }
- //显示更多操作栏
- let showMoreAction = ref(false)
- let chartActions = ref([])
- function getChartActions(chartInfo){
- //加上权限判断
- const actionsArr = [
- {
- type:'refresh',
- label:'刷新',
- show:true,
- btnCode:chartLibBtn.chartLib_refresh
- },
- {
- type:'share',
- label:'分享',
- show:!Boolean(chartInfo.Disabled),
- btnCode:chartLibBtn.chartLib_share
- },
- {
- type:'save',
- label:'保存',
- show:true,
- btnCode:chartLibBtn.chartLib_save
- },
- {
- type:'saveOther',
- label:'另存为',
- show:true,
- btnCode:chartLibBtn.chartLib_otherSave
- },
- {
- type:'savePic',
- label:'保存至相册',
- show:true,
- },
- {
- type:'saveToMaterial',
- label:'保存为素材',
- show:true,
- btnCode:chartLibBtn.chartLib_saveToMaterial
- },
- {
- type:'setEnName',
- label:'设置英文名称',
- show:true,
- btnCode:chartLibBtn.chartLib_enNameSetting
- },
- {
- type:'addToMyETA',
- label:'加入我的图库',
- show:true,
- btnCode:chartLibBtn.chartLib_addMy
- },
- {
- type:'delete',
- label:'删除',
- show:chartInfo.IsEdit,
- btnCode:chartLibBtn.chartLib_del
- }
- ]
- let currentArr=[]
- actionsArr.forEach(item=>{
- if(item.btnCode&&checkAuthBtn(item.btnCode)){
- currentArr.push(item)
- }
- if(item.type==='savePic'){
- if(checkAuthBtn(chartLibBtn.chartLib_copyWechat)&&checkAuthBtn(chartLibBtn.chartLib_copyOffice)){
- currentArr.push(item)
- }
- }
- })
- return currentArr
- }
- function handleActionClick(action){
- const eventMap = {
- 'refresh':refreshChart,
- 'share':getShareLink,
- 'saveOther':openSaveChartOtherDialog,
- 'savePic':saveChartPic,
- 'setEnName':openSetChartEnNameDialog,
- 'addToMyETA':openAddToMyETADialog,
- 'delete':deleteChart,
- 'save':saveChart,
- 'saveToMaterial':handleShowSaveToMaterial
- }
- eventMap[action.type]()
- //showMoreAction.value = false
- }
- //刷新图表
- function refreshChart(){
- apiChart.chartRefresh({
- ChartInfoId:chartInfo.value.ChartInfoId
- }).then(res=>{
- if(res.Ret!==200) return
- getChartDetail()
- showToast({message:'刷新成功',type:'success'})
- })
- }
- let confirmFlag = ref(true)
- //获取分享链接
- async function getShareLink(){
- const currentLang = localStorage.getItem('chartETALange')==='EN'?'en':'ch'
- //若当前语言设置为英文,则检测图表
- if(currentLang==='en') {
- !checkChartEnOption()&&(
- await showDialog({
- title: '提示',
- message: '英文名称未输入完整,分享图表上可能出现空名称的情况,确定继续分享吗?',
- showCancelButton:true
- }).then(() => {
- confirmFlag.value = true
- }).catch(()=>{
- confirmFlag.value = false
- })
- )
- }
- if(!confirmFlag.value) return
- // const linkUrl = `${import.meta.env.VITE_CHART_LINK}?code=${chartInfo.value.UniqueCode}&fromType=share&lang=${currentLang}`
- //临时权限token
- const res = await getChartShareExpireToken(chartInfo.value.UniqueCode);
- if(res.Ret !== 200) return
- const linkUrl = `${publicSettingStore.publicSetting.ChartViewUrl}/chartshow?code=${chartInfo.value.UniqueCode}&fromType=share&lang=${currentLang}&authToken=${res.Data}`
- //console.log('url',linkUrl)
- if(navigator.clipboard&&window.isSecureContext){
- try{
- await navigator.clipboard.writeText(linkUrl)
- showToast({message:'复制链接成功',type:'success'})
- }catch(err){
- console.log(err);
- showToast({message:'复制链接失败',type:'fail'})
- }
- }else{
- const input = document.createElement('input')
- input.setAttribute('readonly','readonly')
- input.value = linkUrl
- document.body.appendChild(input)
- input.select();
- document.execCommand('copy');
- document.body.removeChild(input);
- showToast({message:'复制链接成功',type:'success'})
- }
-
- }
- function checkChartEnOption(){
- if(!chartInfo.value.ChartNameEn) return false
- for(const data of chartInfoData.EdbInfoList){
- if(data.EdbNameEn==""||(data.UnitEn==""&&data.Unit!="")){
- return false
- }
- }
- return true
- }
- //保存图表
- function saveChart(){
- //获取每条线的指标配置
- let arr = edbList.value.map((item)=>{
- return {
- ChartColor: item.ChartColor,
- PredictChartColor: item.PredictChartColor,
- ChartStyle: item.ChartStyle,
- ChartWidth: Number(item.ChartWidth),
- EdbInfoId: item.EdbInfoId,
- EdbInfoType: item.EdbInfoType,
- IsAxis: item.IsAxis,
- IsOrder: item.IsOrder,
- LeadUnit: item.EdbInfoType ? '' : item.LeadUnit,
- LeadValue: item.EdbInfoType ? 0 : Number(item.LeadValue),
- MaxData: Number(item.MaxData),
- MinData: Number(item.MinData),
- }
- })
- //所有图表的公共参数
- let public_param = {
- ChartClassifyId: chartInfo.value.ChartClassifyId,
- ChartInfoId: chartInfo.value.ChartInfoId,
- ChartEdbInfoList: arr,
- }
- //根据ChartType决定剩余参数
- let type_param = {}
- switch(chartInfo.value.ChartType){
- case 2:
- type_param = {
- DateType: chartState.yearVal,
- StartYear:chartState.startYear || 0,
- Calendar: chartState.calendarType,
- StartDate: chartState.startTime||'',
- EndDate: chartState.endTime||'',
- }
- break
- case 7:
- case 11:
- type_param = {
- DateType: 6,
- LeftMin: String(axisLimitState.leftMin),
- LeftMax: String(axisLimitState.leftMax),
- }
- break
- case 10:
- type_param = {
- DateType: 6,
- Calendar: "公历",
- ExtraConfig: JSON.stringify({
- ...JSON.parse(chartInfo.value.ExtraConfig),
- XMinValue: String(axisLimitState.xMin),
- XMaxValue: String(axisLimitState.xMax),
- YMinValue: String(axisLimitState.leftMin),
- YMaxValue: String(axisLimitState.leftMax),
- })
- }
- break
- }
- if(sameOptionType.includes(chartInfo.value.ChartType)){
- type_param = {
- DateType: chartState.yearVal,
- StartYear:chartState.startYear || 0,
- StartDate:chartState.yearVal === 5 || chartState.yearVal === 6
- ? chartState.startTime
- : '',
- EndDate: chartState.yearVal === 5 ? chartState.endTime : '',
- }
- }
- let params = {...public_param,...type_param}
- if(![7,10,11].includes(chartInfo.value.ChartType)){
- params = {
- ...params,
- LeftMin:axisLimitState.leftMin+'',
- LeftMax:axisLimitState.leftMax+'',
- RightMin:axisLimitState.rightMin+'',
- RightMax:axisLimitState.rightMax+'',
- Right2Min:axisLimitState.rightTwoMin+'',
- Right2Max:axisLimitState.rightTwoMax+'',
- //手动保存视为更改过上下限
- MinMaxSave:1
- }
- }
- //保存
- apiChart.chartSave(params).then(async res=>{
- if(res.Ret!==200) return
- showToast("保存成功")
- //更新缩略图
- setChartImage()
- //保存成功后修改route.query防止刷新后请求旧参数
- router.replace({
- path:'/chartETA/chartdetail',
- query:{
- id:route.query.id,
- chartType:route.query.chartType,
- chartClassifyId:route.query.chartClassifyId,
- DateType:params.DateType,
- StartDate:chartState.startTime,
- EndDate:chartState.endTime,
- Calendar:chartState.calendarType,
- SeasonStartDate:chartState.startTime,
- SeasonEndDate:chartState.endTime,
- StartYear:chartState.startYear
- }
- })
- })
-
- }
- async function setChartImage(){
- const svgData = highChart.value.getSVG({
- chart: {
- width: 340,
- height: 230,
- }
- })
- let form = new FormData();
- form.append('Img', svgData);
- let {Data,Ret} = await apiChart.uploadChartImg(form)
- if(Ret!==200||!Data) return
- await apiChart.setChartImg({
- ChartInfoId:Number(route.query.id),
- ImageUrl:Data.ResourceUrl
- })
- }
- let isShowSaveOtherDialog = ref(false)
- let catalogNodes = ref([])
- //另存为
- async function openSaveChartOtherDialog(){
- const res = await apiChart.ETAChartClassifyList()
- if(res.Ret!==200) return
- catalogNodes.value = res.Data?res.Data.AllNodes:[]||[]
- isShowSaveOtherDialog.value = true
- }
- function saveOther(ClassifyId){
- apiChart.ETAChartSaveOther({
- ChartInfoId:chartInfo.value.ChartInfoId,
- ChartName:chartInfo.value.ChartName+'(1)',
- ChartClassifyId:ClassifyId
- }).then(res=>{
- if(res.Ret!==200) return
- showToast({message:'另存为成功',type:'success'})
- isShowSaveOtherDialog.value = false
- })
- }
- let savePicDialogShow = ref(false)
- let savePicSrc = ref('')
- //保存图片
- function saveChartPic(){
- const {chartWidth,chartHeight} = highChart.value
- //打开保存图片弹窗
- const svgData = highChart.value.getSVG({
- chart: {
- width: chartWidth,
- height: chartHeight,
- }
- })
- const canvas = document.createElement('canvas')
- const ctx = canvas.getContext('2d')
- canvas.width = chartWidth*2
- canvas.height = chartHeight*2
- const image = new Image()
- image.src = 'data:image/svg+xml;charset=utf-8,'+encodeURIComponent(svgData)
- image.onload = ()=>{
- ctx.drawImage(image, 0, 0,chartWidth*2,chartHeight*2);
- savePicSrc.value = canvas.toDataURL('image/png');
- savePicDialogShow.value = true
- }
- }
- let setChartEnDialogShow = ref(false)
- //设置英文名称
- function openSetChartEnNameDialog(){
- setChartEnDialogShow.value = true
- }
- function closeSetNameDialog(type){
- if(type==='save'){
- getChartDetail()
- }
- setChartEnDialogShow.value = false
- }
- let isShowAddToMyETADialog = ref(false)
- //加入我的图库
- function openAddToMyETADialog(){
- isShowAddToMyETADialog.value = true
- }
- //删除图表
- function deleteChart(){
- showDialog({
- title: '提示',
- message: '删除后该图表将不能再引用,确认删除吗?',
- showCancelButton:true
- }).then(() => {
- apiChart.deleteClassify({
- ChartClassifyId:Number(routeQueryData.chartClassifyId),
- ChartInfoId:Number(routeQueryData.id),
- }).then(res=>{
- if(res.Ret===200){
- cachedViewsStore.removeCaches('ChartETAList')
- cachedViewsStore.removeCaches('ChartETASearch')
- showToast('删除成功')
- setTimeout(() => {
- router.back()
- }, 1000);
- }
- })
- }).catch(()=>{
-
- })
- }
- // 保存至素材库
- const showSaveToMaterial=ref(false)
- function handleShowSaveToMaterial(){
- showSaveToMaterial.value=true
- }
- //获取图排序列表数据
- const chartSortListData=ref([])
- async function getChartSortList(){
- const res=await apiChart.chartLocate({
- KeyWord:route.query.keyword||'',
- ChartClassifyId:Number(route.query.chartClassifyId),
- IsShowMe:route.query.IsShowMe=='true'?true:false
- })
- if(res.Ret===200){
- chartSortListData.value=res.Data||[]
- }
- }
- getChartSortList()
- // 切换图
- async function handleSwitchChart(type){
- const index=chartSortListData.value.findIndex((item)=>item.ChartInfoId==routeQueryData.id)
- let item=null
- if(type==='prev'){
- item=index===0?chartSortListData.value[chartSortListData.value.length-1]:chartSortListData.value[index-1]
- }else{
- item=index===chartSortListData.value.length-1?chartSortListData.value[0]:chartSortListData.value[index+1]
- }
- //切换前重置chartState
-
- routeQueryData.id=item.ChartInfoId
- routeQueryData.chartType=item.ChartType
- routeQueryData.chartClassifyId=item.ChartClassifyId
- initChartState({...item,...routeQueryData})
- isUseSelfLimit.value = false
- getChartDetail('init')
- }
- function initChartState(data){
- chartState.showTimePop=false
- chartState.startTime=sameOptionType.includes(Number(data.chartType))?data.StartDate:data.SeasonStartDate
- chartState.endTime=sameOptionType.includes(Number(data.chartType))?data.EndDate:data.SeasonEndDate
- chartState.yearVal=data.DateType
- chartState.calendarType=data.Calendar
- chartState.startYear=Number(data.StartYear)
- }
- function openDateSelect(){
- // 回显
- switch (chartState.yearVal) {
- case 3:
- temStartTime.value = [2015,1,1]
- temEndTime.value = latestDate.value.split('-')
- break;
- case 9:
- temStartTime.value = [2020,1,1]
- temEndTime.value = latestDate.value.split('-')
- break;
- case 4:
- temStartTime.value = [2021,1,1]
- temEndTime.value = latestDate.value.split('-')
- break;
- case 11:
- temStartTime.value = [2022,1,1]
- temEndTime.value = latestDate.value.split('-')
- break;
- case '':
- temStartTime.value = earliestDate.value.split('-')
- temEndTime.value = latestDate.value.split('-')
- break;
- default:
- temStartTime.value = chartState.startTime.split('-')
- temEndTime.value = chartState.endTime.split('-')
- break;
- }
- chartState.showTimePop=true
- }
- </script>
- <template>
- <div class="chart-detail-page" v-if="chartInfo">
- <div
- class="chart-title"
- :style="chartInfo.ChartThemeStyle?`
- text-align:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.align};
- font-size:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.fontSize}px;
- color:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.color}
- `:''"
- >{{currentLang==='en'?(chartInfo.ChartNameEn||chartInfo.ChartName):chartInfo.ChartName}}</div>
- <!-- 一般曲线图选择时间区间或者季节图选择日期 -->
- <div
- class="select-time-box"
- v-if="sameOptionType.includes(chartInfo.ChartType)||chartInfo.ChartType===2"
- @click="openDateSelect"
- >
- <img class="left-icon" src="@/assets/imgs/icon_calendar.png" alt="">
- <span :class="['val-box',!chartState.startTime?'val-box_grey':'']">{{chartState.startTime||'开始日期'}} ~ {{chartState.endTime||'结束日期'}}</span>
- <van-icon class="right-icon" name="arrow" />
- </div>
- <!-- pad端时间和操作按钮模块 -->
- <div class="pad-time-action-wrap">
- <div class="left-time-box">
- <template v-if="sameOptionType.includes(chartInfo.ChartType)">
- <span :class="['item',chartState.yearVal==''?'active':'']" @click="handleYearChange({value:''})">全部</span>
- <span
- :class="['item',chartState.yearVal==item.value?'active':'']"
- v-for="item in yearSelectOpt"
- :key="item.value"
- @click="handleYearChange(item)"
- >{{item.name}}</span>
- </template>
- <span
- class="time-box"
- v-if="sameOptionType.includes(chartInfo.ChartType)||chartInfo.ChartType===2"
- @click="openDateSelect"
- >
- {{chartState.startTime?`${chartState.startTime} ~ ${chartState.endTime||'至今'}`:'请选择时间段'}}
- </span>
- </div>
- <div class="right-action-box">
- <div class="item" @click="showMoreAction=true" v-if="chartActions.length">
- <img src="@/assets/imgs/chartETA/more-icon.png" alt="">
- <span>更多设置</span>
- </div>
- </div>
- </div>
- <!-- 图渲染区域 -->
- <div class="chart-render-wrap">
- <!-- pad 切换上一张\下一张 -->
- <img class="pad-change-chart-btn" src="@/assets/imgs/icon_arrow2.png" alt="" @click="handleSwitchChart('prev')" v-if="chartSortListData.length>0">
- <img class="pad-change-chart-btn pad-change-chart-next-btn" src="@/assets/imgs/icon_arrow2.png" alt="" @click="handleSwitchChart('next')" v-if="chartSortListData.length>0">
- <div class="chart-box" id="chart-box"></div>
- <!-- 底部来源,图表说明 -->
- <div class="chart-bottom-insruction-info"
- v-if="(chartInfo.SourcesFrom&&JSON.parse(chartInfo.SourcesFrom).isShow) || (chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow)">
- <div
- class="chart-source"
- v-if="chartInfo.SourcesFrom&&JSON.parse(chartInfo.SourcesFrom).isShow"
- :style="`
- color: ${ JSON.parse(chartInfo.SourcesFrom).color };
- font-size: ${ JSON.parse(chartInfo.SourcesFrom).fontSize }px;
- `"
- >
- 数据来源:{{JSON.parse(chartInfo.SourcesFrom).text}}
- </div>
- <!-- 图表说明 -->
- <div
- class="chart-instruction text_oneLine"
- v-if="chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow"
- v-text="JSON.parse(chartInfo.Instructions).text"
- :style="`
- color: ${JSON.parse(chartInfo.Instructions).color};
- font-size: ${ JSON.parse(chartInfo.Instructions).fontSize }px
- `"
- ></div>
- </div>
- <!-- 作者 -->
- <div class="author-box" style="text-align:right">作者:{{chartInfo.SysUserRealName}}</div>
-
- </div>
- <!-- 手机端选择时间区间模块 -->
- <div class="select-year-box" v-if="sameOptionType.includes(chartInfo.ChartType)">
- <span :class="['item',chartState.yearVal==''?'active':'']" @click="handleYearChange({value:''})">全部</span>
- <span
- :class="['item',chartState.yearVal==item.value?'active':'']"
- v-for="item in yearSelectOpt"
- :key="item.value"
- @click="handleYearChange(item)"
- >{{item.name}}</span>
- </div>
- <!-- 季节图切换公/农历 -->
- <div class="calendar-type-box" v-if="chartInfo.ChartType === 2">
- <span
- :class="chartState.calendarType=='公历'?'active':''"
- @click="handleSeasonTypeChange('公历')"
- >公历</span>
- <span
- :class="chartState.calendarType=='农历'?'active':''"
- @click="handleSeasonTypeChange('农历')"
- >农历</span>
- </div>
- <!-- 指标模块 -->
- <div class="edb-list-box">
- <!-- pad 设置上下限按钮 -->
- <div class="pad-limit-set-btn" @click="handleShowAxisLimitOpt" v-if="![3,4,6,7,8,9].includes(chartInfo.Source)&&checkAuthBtn(chartLibBtn.chartLib_editLimit)&&isChartHeap(chartInfo)">设置上下限</div>
- <!-- <div class="list-lable">指标信息</div> -->
- <div class="list-box">
- <div class="list-item" v-for="item in edbList" :key="item.EdbInfoId" @click="handleShowEDBInfo(item)">
- <span class="date">{{item.LatestDate}}</span>
- <span class="edb-name van-ellipsis" :style="{color:item.ChartColor}">{{item.EdbName}}</span>
- <span class="value">{{item.LatestValue}}</span>
- </div>
- </div>
- </div>
- <!-- 底部悬浮操作模块 -->
- <div class="fix-bot-action-box">
- <div class="item" @click="handleSwitchChart('prev')" v-if="chartSortListData.length>0">
- <img class="icon" src="@/assets/imgs/icon_arrow.png" alt="">
- <div>上一张</div>
- </div>
- <div class="item" @click="handleSwitchChart('next')" v-if="chartSortListData.length>0">
- <img class="icon" style="transform: rotate(180deg);" src="@/assets/imgs/icon_arrow.png" alt="">
- <div>下一张</div>
- </div>
- <div class="item" @click="handleShowAxisLimitOpt" v-if="![3,4,6,7,8,9].includes(chartInfo.Source)&&checkAuthBtn(chartLibBtn.chartLib_editLimit)&&isChartHeap(chartInfo)">
- <img class="icon" src="@/assets/imgs/myETA/icon_limit.png" alt="">
- <div>上下限</div>
- </div>
- <div class="item" @click="showMoreAction=true" v-if="chartActions.length">
- <img class="icon" src="@/assets/imgs/myETA/icon_menu.png" alt="">
- <div>更多</div>
- </div>
- </div>
- <!-- 选择日期弹窗 -->
- <van-popup
- v-model:show="chartState.showTimePop"
- :position="width>650?'center':'bottom'"
- :style="width>650?{ width: '400px'}:''"
- round
- >
- <div class="time-picker-wrap">
- <van-picker-group
- title="选择起始时间"
- :tabs="['开始时间', '结束时间']"
- @cancel="chartState.showTimePop=false"
- @confirm="handleTimeChange"
- >
- <van-date-picker
- v-model="temStartTime"
- :min-date="minDate"
- :max-date="maxDate"
- :columns-type="['year','month','day']"
- />
- <van-date-picker
- v-model="temEndTime"
- :min-date="minDate"
- :max-date="maxDate"
- :columns-type="['year','month','day']"
- />
- </van-picker-group>
- </div>
- </van-popup>
- <!-- 指标详情弹窗 -->
- <van-popup
- v-model:show="showEDB"
- :position="width>650?'right':'bottom'"
- round
- closeable
- :style="width>650?{ width: '400px', height: '100%' }:''"
- >
- <EdbInfo
- :show="showEDB"
- :data="showEDBData"
- :tableData="edbList"
- @showSourceDetail="handleShowSourceDetail"
- />
- </van-popup>
- <!-- 数据来源弹窗-->
- <van-popup
- v-model:show="showSourceDetail"
- position="center"
- round
- closeable
- :style="{ width: '400px'}"
- >
- <SourceDetail
- :show="showSourceDetail"
- :EdbInfoId="showEDBData.EdbInfoId"
- />
- </van-popup>
- <!-- 上下限调整弹窗 -->
- <van-popup
- v-model:show="showLimitPop"
- :position="width>650?'center':'bottom'"
- round
- closeable
- :style="width>650?{ width: '400px'}:''"
- >
- <div class="global-pop-wrap_mobile chart-set-limit-wrap">
- <div class="head-box">
- <div class="title">上下限设置</div>
- </div>
- <div class="content">
- <!-- 左轴 -->
- <div class="item-box" v-if="axisLimitState.hasLeftAxis">
- <span class="lable-text">左轴</span>
- <div class="input-box">
- <div class="item">
- <div class="type-text">上限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.leftMax" />
- </div>
- </div>
- <div class="item">
- <div class="type-text">下限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.leftMin" />
- </div>
- </div>
- </div>
- </div>
- <!-- 右轴 -->
- <div class="item-box" v-if="axisLimitState.hasRightAxis">
- <span class="lable-text">右轴</span>
- <div class="input-box">
- <div class="item">
- <div class="type-text">上限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightMax" />
- </div>
- </div>
- <div class="item">
- <div class="type-text">下限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightMin" />
- </div>
- </div>
- </div>
- </div>
- <!-- 右二轴 -->
- <div class="item-box" v-if="axisLimitState.hasRightTwoAxis">
- <span class="lable-text">右2轴</span>
- <div class="input-box">
- <div class="item">
- <div class="type-text">上限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightTwoMax" />
- </div>
- </div>
- <div class="item">
- <div class="type-text">下限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightTwoMin" />
- </div>
- </div>
- </div>
- </div>
- <!-- x轴 -->
- <div class="item-box" v-if="axisLimitState.hasXAxis">
- <span class="lable-text">X轴</span>
- <div class="input-box">
- <div class="item">
- <div class="type-text">上限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.xMax" />
- </div>
- </div>
- <div class="item">
- <div class="type-text">下限</div>
- <div class="step-box">
- <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.xMin" />
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="bot-btn-box" @click="handleConfirmLimitChange">确定</div>
- </div>
- </van-popup>
- <!-- 更多设置弹窗 -->
- <van-popup
- v-model:show="showMoreAction"
- :position="width>650?'center':'bottom'"
- round
- closeable
- :style="width>650?{ width: '400px'}:''"
- >
- <div class="global-pop-wrap_mobile chart-more-action-wrap">
- <div class="head-box">
- <div class="title van-ellipsis">{{chartInfo.ChartName}}</div>
- </div>
- <div class="action-box">
- <template v-for="item in chartActions" :key="item.types">
- <div class="action-item" v-if="item.show" @click="handleActionClick(item)">
- {{item.label}}
- </div>
- </template>
-
- </div>
- </div>
- </van-popup>
- <!-- 另存为弹窗 -->
- <TreeSelectPop
- :isShowDialog="isShowSaveOtherDialog"
- :dialogPosition="width>650?'center':'bottom'"
- :catalogNodes="catalogNodes"
- :chartInfo="chartInfo"
- popTitle="另存为"
- @close="isShowSaveOtherDialog=false"
- @confirmMove="saveOther"
- />
- <!-- 加入我的图库弹窗 -->
- <AddChartToMyETA
- :isShowDialog="isShowAddToMyETADialog"
- :dialogPosition="width>650?'center':'bottom'"
- :chartInfo="chartInfo"
- @close="isShowAddToMyETADialog=false"
- />
- <!--保存图片弹窗 -->
- <van-popup
- v-model:show="savePicDialogShow"
- position="center"
- round
- closeable
- :style="{width:'80%',padding:'30px'}"
- >
- <img :src="savePicSrc" alt="" style="width:100%;box-sizing: border-box;">
- <p style="text-align: center;color:#999;margin-top: 10px;">长按保存图片</p>
- </van-popup>
- <!-- 设置英文名称弹窗 -->
- <van-popup
- v-model:show="setChartEnDialogShow"
- position="bottom"
- :style="{width:'100%',height:'100%'}"
- >
- <SetChartEnName
- :isShow="setChartEnDialogShow"
- :chartInfo="chartInfoData"
- :chartType="Number(route.query.chartType)"
- @close="closeSetNameDialog"
- />
- </van-popup>
- <!-- 保存至素材库 -->
- <SaveToMaterial
- v-model:show="showSaveToMaterial"
- source="chart"
- :sourceId="chartInfo.ChartInfoId"
- :defaultName="chartInfo.ChartName"
- />
- </div>
- </template>
- <style lang="scss">
- .chart-detail-page{
- .rename-wrap{
- padding:48px;
- input{
- padding: 24px 32px;
- border-radius: 12px;
- background-color: #F6F6F6;
- width: 100%;
- }
- .label{
- color: #666666;
- margin-bottom: 32px;
- text-align: center;
- }
- }
- @media screen and (min-width:$media-width){
- .rename-wrap{
- padding:24px;
- input{
- padding: 12px 16px;
- border-radius: 6px;
- background-color: #F6F6F6;
- width: 100%;
- }
- .label{
- margin-bottom: 16px;
- }
- }
- }
- }
- </style>
- <style scoped lang="scss">
- .chart-detail-page{
- padding: $page-padding;
- padding-bottom: 120px;
- .chart-title{
- font-size: 36px;
- margin-bottom: 56px;
- }
- .chart-render-wrap{
- .pad-change-chart-btn{
- display: none;
- }
- }
- .chart-box{
- width: 100%;
- height: 700px;
- }
- .chart-bottom-insruction-info {
- width: 100%;
- margin: 0 auto;
- }
- .select-time-box{
- display: flex;
- align-items: center;
- padding-bottom: 32px;
- border-bottom: 1px solid $border-color;
- .left-icon{
- width: 48px;
- height: 48px;
- }
- .right-icon{
- margin-left: auto;
- }
- .val-box{
- margin-left: 32px;
- font-size: 32px;
- &.val-box_grey{
- color: $font-grey_999;
- }
- }
- }
- .select-year-box{
- width: 100vw;
- position: relative;
- left: -$page-padding;
- margin-top: 30px;
- box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.08);
- height: 88px;
- display: flex;
- align-items: center;
- overflow-y: auto;
- padding: 0 $page-padding;
- &::-webkit-scrollbar{
- height: 0;
- }
- .item{
- line-height: 88px;
- position: relative;
- height: 100%;
- flex-shrink: 0;
- display: inline-block;
- margin-right: 40px;
- font-size: 32px;
- color: $font-grey_999;
- &.active{
- color: #333;
- &::after{
- content: '';
- display: block;
- width: 50px;
- height: 6px;
- border-radius: 3px;
- background-color: $theme-color;
- position: absolute;
- bottom: 0;
- left: 50%;
- transform: translateX(-50%);
- }
- }
- }
- }
- .calendar-type-box{
- width: 404px;
- margin: 30px auto;
- text-align: center;
- border: 1px solid $theme-color;
- border-radius: 12px;
- overflow: hidden;
- span{
- display: inline-block;
- width: 200px;
- height: 80px;
- line-height: 80px;
- color: $theme-color;
- font-weight: bold;
- &.active{
- background-color: $theme-color;
- color: #fff;
- }
- }
- }
- .pad-time-action-wrap{
- display: none;
- }
- .edb-list-box{
- .pad-limit-set-btn{
- display: none;
- }
- .list-lable{
- font-size: 36px;
- color: #000;
- margin-bottom: 20px;
- margin-top: 40px;
- }
- .list-item{
- padding:18px;
- display: flex;
- gap:0 20px;
- border-bottom: 1px solid #DCDFE6;
- &:last-child{
- border-bottom: none;
- }
- .edb-name{
- flex: 1;
- /* text-align: center; */
- }
- }
- }
- .fix-bot-action-box{
- position: fixed;
- left: 0;
- bottom: 0;
- right: 0;
- z-index: 99;
- background-color: #fff;
- border-top: 1px solid $border-color;
- height: 112px;
- display: flex;
- align-items: center;
- .item{
- height: 100%;
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- font-size: 20px;
- .icon{
- width: 40px;
- height: 40px;
- margin-bottom: 5px;
- }
- }
- }
- .chart-set-limit-wrap{
- .head-box{
- .title{
- padding: 0 $page-padding;
- font-size: 36px;
- font-weight: 600;
- line-height: 120px;
- }
- }
- .bot-btn-box{
- line-height: 112px;
- text-align: center;
- color: $theme-color;
- font-size: 32px;
- }
- .content{
- padding: $page-padding;
- .item-box{
- display: flex;
- align-items: flex-end;
- margin-bottom: 30px;
- .lable-text{
- width: 100px;
- }
- .input-box{
- flex: 1;
- display: flex;
- .item{
- flex: 1;
- text-align: center;
- .type-text{
- margin-bottom: 40px;
- }
- .step-box{
- display: inline-block;
- :deep(.van-stepper){
- display: flex;
- justify-content: center;
- }
- }
- }
- }
- }
- }
-
- }
- .chart-more-action-wrap{
- .head-box{
- .title{
- width: 100%;
- padding:34px 100px;
- box-sizing: border-box;
- font-size: 36px;
- font-weight: 600;
- text-align: center;
- }
- }
- .action-box{
- .action-item{
- text-align: center;
- padding:32px 84px;
- border-bottom: 1px solid #DCDFE6;
- &:last-child{
- border-bottom: none;
- }
- }
- }
- }
- @media screen and (min-width:$media-width){
- padding:30px;
- .chart-title{
- font-size: 16px;
- font-weight: bold;
- margin-bottom: 30px;
- }
- .chart-render-wrap{
- position: relative;
- .pad-change-chart-btn{
- display: block;
- width: 48px;
- height: 48px;
- position: absolute;
- top: 50%;
- transform: translateY(-50%);
- left: 0px;
- &.pad-change-chart-next-btn{
- right: 0;
- left: auto;
- transform: translateY(-50%) rotate(180deg);
- }
- }
- }
- .chart-box{
- width: 85%;
- height: 370px;
- margin: 0 auto;
- }
- .chart-bottom-insruction-info {
- width: 85%;
- margin: 0 auto;
- }
- .select-time-box,.select-year-box,.fix-bot-action-box{
- display: none;
- }
- .pad-time-action-wrap{
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- justify-content: space-between;
- .left-time-box{
- flex-shrink: 0;
- margin-bottom: 20px;
- .item{
- display: inline-block;
- width: 80px;
- height: 36px;
- text-align: center;
- line-height: 36px;
- border: 1px solid $theme-color;
- margin-right: 10px;
- border-radius: 3px;
- &.active{
- color: #fff;
- background-color: $theme-color;
- }
- }
- .time-box{
- display: inline-block;
- padding: 0 15px;
- height: 36px;
- line-height: 36px;
- border: 1px solid $theme-color;
- border-radius: 3px;
- background-color: #F2F3FF;
- color: $theme-color;
- }
- }
- .right-action-box{
- display: flex;
- margin-bottom: 20px;
- .item{
- display: flex;
- color: $theme-color;
- margin-left: 20px;
- img{
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
- }
- }
- }
- .calendar-type-box{
- width: 224px;
- margin: 20px auto;
- border-radius: 4px;
- span{
- width: 111px;
- height: 38px;
- line-height: 38px;
- }
- }
- .edb-list-box{
- position: relative;
- left: -30px;
- border-top: 1px solid $border-color;
- width: 100vw;
- padding: 0 30px;
- margin-top: 20px;
- .pad-limit-set-btn{
- display: block;
- text-align: right;
- margin: 20px 0;
- color: $theme-color;
- }
- .list-lable{
- margin-top: 20px;
- font-size: 16px;
- margin-bottom: 14px;
- }
- .list-box{
- //border: 1px solid $border-color;
- .list-item{
- padding: 18px;
- }
- }
- }
- .chart-set-limit-wrap{
- .head-box{
- .title{
- font-size: 18px;
- line-height: 50px;
- padding-left: 16px;
- }
- }
- .bot-btn-box{
- font-size: 16px;
- line-height: 56px;
- border-top-width: 8px;
- }
- .content{
- max-height: 500px;
- padding: 30px;
- .item-box{
- margin-bottom: 15px;
- .lable-text{
- width: 50px;
- }
- .input-box{
- .item{
- .type-text{
- margin-bottom: 20px;
- }
- }
- }
- }
- }
- }
- .chart-more-action-wrap{
- .head-box{
- .title{
- padding:17px 50px;
- font-size: 18px;
- }
- }
- .action-box{
- .action-item{
- padding:16px 42px;
- }
- }
- }
- }
- }
- </style>
|