ChartDetail.vue 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529
  1. <script setup name="ChartETAChartDetail">
  2. import {nextTick, onMounted,ref,reactive} from 'vue'
  3. import {showDialog, showToast} from 'vant'
  4. import apiChart from '@/api/chart'
  5. import { useRoute, useRouter } from 'vue-router'
  6. import { useWindowSize } from '@vueuse/core'
  7. import {yearSelectOpt,sameOptionType} from '@/hooks/chart/config'
  8. import {useChartRender} from '@/hooks/chart/render'
  9. import { getChartShareExpireToken } from './hooks/useChartSharedToken'
  10. import moment from 'moment'
  11. import EdbInfo from './components/EdbInfo.vue'
  12. import SourceDetail from './components/SourceDetail.vue'
  13. import TreeSelectPop from './components/TreeSelectPop.vue'
  14. import AddChartToMyETA from './components/AddChartToMyETA.vue'
  15. import SetChartEnName from './components/SetChartEnName.vue'
  16. import {useCachedViewsStore} from '@/store/modules/cachedViews'
  17. import { setExtremumDate } from '@/hooks/chart/commonFun.js'
  18. import {chartLibBtn,useAuthBtn} from '@/hooks/useAuthBtn'
  19. import {usePublicSettingStore} from '@/store/modules/publicSetting'
  20. import _ from 'lodash';
  21. import SaveToMaterial from '@/components/SaveToMaterial.vue'
  22. const {checkAuthBtn} = useAuthBtn()
  23. const publicSettingStore = usePublicSettingStore()
  24. const {options,axisLimitState,chartRender,setLimitData,isUseSelfLimit}=useChartRender()
  25. const { width } = useWindowSize()
  26. const cachedViewsStore=useCachedViewsStore()
  27. const route=useRoute()
  28. const router=useRouter()
  29. let routeQueryData=reactive({
  30. chartType:route.query.chartType,
  31. id:route.query.id,
  32. chartClassifyId:route.query.chartClassifyId,
  33. })
  34. let currentLang = ref('')
  35. //获取图详情
  36. let chartInfoData=null
  37. let chartInfo=ref(null)
  38. //highchart图表
  39. let highChart = ref(null)
  40. let edbList=ref([])//指标数据
  41. async function getChartDetail(e){
  42. const params=sameOptionType.includes(Number(routeQueryData.chartType))?{
  43. ChartInfoId:Number(routeQueryData.id),
  44. DateType: chartState.yearVal,
  45. StartDate: chartState.startTime,
  46. EndDate: chartState.endTime,
  47. StartYear:chartState.startYear
  48. }:{
  49. ChartInfoId:Number(routeQueryData.id),
  50. Calendar: chartState.calendarType,//this.calendar_type
  51. DateType: chartState.yearVal,
  52. StartDate: chartState.startTime,
  53. EndDate:chartState.endTime,
  54. StartYear:chartState.startYear
  55. }
  56. const res=await apiChart.chartInfoById(params)
  57. if(res.Ret!==200) return
  58. chartInfoData=res.Data
  59. chartInfo.value=res.Data.ChartInfo
  60. chartActions.value = getChartActions(res.Data.ChartInfo)
  61. if(res.Data.ChartInfo.Source===2){
  62. edbList.value=[res.Data.EdbInfoList[0]]
  63. }else{
  64. edbList.value=res.Data.EdbInfoList
  65. }
  66. if(e==='init'){
  67. chartState.yearVal=res.Data.ChartInfo.DateType
  68. }
  69. // 设置 起始日期 和 最新日期
  70. const extremumDate= setExtremumDate(edbList.value)
  71. minDate = new Date(extremumDate.earliestDate)
  72. earliestDate.value = extremumDate.earliestDate
  73. latestDate.value = extremumDate.latestDate
  74. setDateAppear()
  75. //初始化上下限
  76. isUseSelfLimit.value = true
  77. setLimitData(res.Data)
  78. nextTick(()=>{
  79. highChart.value = chartRender({
  80. data:{
  81. ...res.Data,
  82. ChartInfo:{
  83. ...res.Data.ChartInfo,
  84. Calendar:chartState.calendarType||'公历'
  85. },
  86. },
  87. renderId:'chart-box',
  88. lang:currentLang.value,
  89. changeLangIsCheck:false,
  90. showChartTitle:false,
  91. shouldUseSelfLimit:true,
  92. })
  93. })
  94. }
  95. function setDateAppear() {
  96. if(chartState.yearVal == 20){
  97. let latestYear = parseInt(latestDate.value.substring(0,4))
  98. chartState.startTime = `${latestYear-chartState.startYear+1}-01-01`
  99. chartState.endTime = `${latestYear}-12-31`
  100. }
  101. }
  102. // 是否面积图堆叠百分比
  103. function isChartHeap(info){
  104. let tag=true
  105. if(info.ChartType==3&&info.ExtraConfig){
  106. let ExtraConfig=JSON.parse(info.ExtraConfig)
  107. tag=ExtraConfig.HeapWay==2?false:true
  108. }
  109. return tag
  110. }
  111. onMounted(() => {
  112. currentLang.value = localStorage.getItem('chartETALange')==='EN'?'en':'zh'
  113. initChartState(route.query)
  114. getChartDetail('init')
  115. })
  116. let minDate=new Date(1970, 0, 1)
  117. const maxDate=new Date(2050, 11, 31)
  118. const cYear=moment().format('YYYY')
  119. const cMonth=moment().format('MM')
  120. const cDay=moment().format('dd')
  121. let temStartTime=ref([cYear,cMonth,cDay])
  122. let temEndTime=ref([cYear,cMonth,cDay])
  123. const latestDate = ref('')
  124. const earliestDate = ref('')
  125. let chartState=reactive({
  126. showTimePop:false,
  127. startTime:'',
  128. endTime:'',
  129. yearVal:'',
  130. calendarType:'公历',
  131. startYear:5
  132. })
  133. // 切换年份选项
  134. function handleYearChange(item){
  135. chartState.yearVal=item.value
  136. chartState.startTime=''
  137. chartState.endTime=''
  138. getChartDetail()
  139. }
  140. // 确定日期筛选
  141. function handleTimeChange(){
  142. chartState.startTime=temStartTime.value.join('-')
  143. chartState.endTime=temEndTime.value.join('-')
  144. chartState.yearVal=5
  145. getChartDetail()
  146. chartState.showTimePop=false
  147. }
  148. // 季节图公历\农历切换
  149. function handleSeasonTypeChange(type){
  150. chartState.calendarType=type
  151. getChartDetail()
  152. }
  153. // 上下限调整
  154. let showLimitPop=ref(false)
  155. let axisLimitDataTem=reactive({//左右轴极值
  156. min:'-99999999999999999',
  157. leftMin:0,
  158. leftMax:0,
  159. rightMin:0,
  160. rightMax:0,
  161. rightTwoMin:0,
  162. rightTwoMax:0,
  163. xMin:0,
  164. xMax:0,
  165. })
  166. function handleShowAxisLimitOpt(){
  167. axisLimitDataTem.leftMin=axisLimitState.leftMin
  168. axisLimitDataTem.leftMax=axisLimitState.leftMax
  169. axisLimitDataTem.rightMin=axisLimitState.rightMin
  170. axisLimitDataTem.rightMax=axisLimitState.rightMax
  171. axisLimitDataTem.rightTwoMin=axisLimitState.rightTwoMin
  172. axisLimitDataTem.rightTwoMax=axisLimitState.rightTwoMax
  173. axisLimitDataTem.xMin=axisLimitState.xMin
  174. axisLimitDataTem.xMax=axisLimitState.xMax
  175. showLimitPop.value=true
  176. }
  177. // 极限修改确定
  178. function handleConfirmLimitChange(){
  179. const data=_.cloneDeep(chartInfoData)
  180. // 修改左轴极限
  181. if(axisLimitState.hasLeftAxis){
  182. //基础图
  183. if(axisLimitState.leftIndex!==-1){
  184. axisLimitState.leftMin = axisLimitDataTem.leftMin
  185. axisLimitState.leftMax = axisLimitDataTem.leftMax
  186. }else{
  187. // 柱形图 取的ChartInfo中的极值
  188. if(data.ChartInfo.ChartType ===7){
  189. data.ChartInfo.LeftMin=axisLimitDataTem.leftMin
  190. data.ChartInfo.LeftMax=axisLimitDataTem.leftMax
  191. }
  192. // 商品价格曲线
  193. if(data.ChartInfo.ChartType ===8){
  194. data.ChartInfo.LeftMin=axisLimitDataTem.leftMin
  195. data.ChartInfo.LeftMax=axisLimitDataTem.leftMax
  196. }
  197. // 截面散点 取的DataResp
  198. if(data.ChartInfo.ChartType ===10){
  199. data.DataResp.YMinValue=axisLimitDataTem.leftMin
  200. data.DataResp.YMaxValue=axisLimitDataTem.leftMax
  201. }
  202. }
  203. }
  204. // 修改右轴极限
  205. if(axisLimitState.hasRightAxis){
  206. if(axisLimitState.rightIndex!==-1){
  207. axisLimitState.rightMin = axisLimitDataTem.rightMin
  208. axisLimitState.rightMax = axisLimitDataTem.rightMax
  209. }
  210. }
  211. //修改右2轴极限
  212. if(axisLimitState.hasRightTwoAxis){
  213. if(axisLimitState.rightTwoIndex!==-1){
  214. axisLimitState.rightMin = axisLimitDataTem.rightTwoMin
  215. axisLimitState.rightMax = axisLimitDataTem.rightTwoMax
  216. }
  217. }
  218. // 修改X轴极限
  219. if(axisLimitState.hasXAxis){
  220. // 截面散点 取的DataResp
  221. if(data.ChartInfo.ChartType ===10){
  222. data.DataResp.XMinValue=axisLimitDataTem.xMin
  223. data.DataResp.XMaxValue=axisLimitDataTem.xMax
  224. }
  225. }
  226. highChart.value = chartRender({
  227. data:data,
  228. renderId:'chart-box',
  229. lang:currentLang.value,
  230. changeLangIsCheck:false,
  231. showChartTitle:false,
  232. shouldUseSelfLimit:true,
  233. })
  234. showLimitPop.value=false
  235. }
  236. // 显示指标详情
  237. let showEDB=ref(false)
  238. let showEDBData=ref({})
  239. function handleShowEDBInfo(item){
  240. showEDBData.value=item
  241. showEDB.value=true
  242. }
  243. //显示数据来源详情
  244. let showSourceDetail = ref(false)
  245. function handleShowSourceDetail(){
  246. showSourceDetail.value = true
  247. }
  248. //显示更多操作栏
  249. let showMoreAction = ref(false)
  250. let chartActions = ref([])
  251. function getChartActions(chartInfo){
  252. //加上权限判断
  253. const actionsArr = [
  254. {
  255. type:'refresh',
  256. label:'刷新',
  257. show:true,
  258. btnCode:chartLibBtn.chartLib_refresh
  259. },
  260. {
  261. type:'share',
  262. label:'分享',
  263. show:!Boolean(chartInfo.Disabled),
  264. btnCode:chartLibBtn.chartLib_share
  265. },
  266. {
  267. type:'save',
  268. label:'保存',
  269. show:true,
  270. btnCode:chartLibBtn.chartLib_save
  271. },
  272. {
  273. type:'saveOther',
  274. label:'另存为',
  275. show:true,
  276. btnCode:chartLibBtn.chartLib_otherSave
  277. },
  278. {
  279. type:'savePic',
  280. label:'保存至相册',
  281. show:true,
  282. },
  283. {
  284. type:'saveToMaterial',
  285. label:'保存为素材',
  286. show:true,
  287. btnCode:chartLibBtn.chartLib_saveToMaterial
  288. },
  289. {
  290. type:'setEnName',
  291. label:'设置英文名称',
  292. show:true,
  293. btnCode:chartLibBtn.chartLib_enNameSetting
  294. },
  295. {
  296. type:'addToMyETA',
  297. label:'加入我的图库',
  298. show:true,
  299. btnCode:chartLibBtn.chartLib_addMy
  300. },
  301. {
  302. type:'delete',
  303. label:'删除',
  304. show:chartInfo.IsEdit,
  305. btnCode:chartLibBtn.chartLib_del
  306. }
  307. ]
  308. let currentArr=[]
  309. actionsArr.forEach(item=>{
  310. if(item.btnCode&&checkAuthBtn(item.btnCode)){
  311. currentArr.push(item)
  312. }
  313. if(item.type==='savePic'){
  314. if(checkAuthBtn(chartLibBtn.chartLib_copyWechat)&&checkAuthBtn(chartLibBtn.chartLib_copyOffice)){
  315. currentArr.push(item)
  316. }
  317. }
  318. })
  319. return currentArr
  320. }
  321. function handleActionClick(action){
  322. const eventMap = {
  323. 'refresh':refreshChart,
  324. 'share':getShareLink,
  325. 'saveOther':openSaveChartOtherDialog,
  326. 'savePic':saveChartPic,
  327. 'setEnName':openSetChartEnNameDialog,
  328. 'addToMyETA':openAddToMyETADialog,
  329. 'delete':deleteChart,
  330. 'save':saveChart,
  331. 'saveToMaterial':handleShowSaveToMaterial
  332. }
  333. eventMap[action.type]()
  334. //showMoreAction.value = false
  335. }
  336. //刷新图表
  337. function refreshChart(){
  338. apiChart.chartRefresh({
  339. ChartInfoId:chartInfo.value.ChartInfoId
  340. }).then(res=>{
  341. if(res.Ret!==200) return
  342. getChartDetail()
  343. showToast({message:'刷新成功',type:'success'})
  344. })
  345. }
  346. let confirmFlag = ref(true)
  347. //获取分享链接
  348. async function getShareLink(){
  349. const currentLang = localStorage.getItem('chartETALange')==='EN'?'en':'ch'
  350. //若当前语言设置为英文,则检测图表
  351. if(currentLang==='en') {
  352. !checkChartEnOption()&&(
  353. await showDialog({
  354. title: '提示',
  355. message: '英文名称未输入完整,分享图表上可能出现空名称的情况,确定继续分享吗?',
  356. showCancelButton:true
  357. }).then(() => {
  358. confirmFlag.value = true
  359. }).catch(()=>{
  360. confirmFlag.value = false
  361. })
  362. )
  363. }
  364. if(!confirmFlag.value) return
  365. // const linkUrl = `${import.meta.env.VITE_CHART_LINK}?code=${chartInfo.value.UniqueCode}&fromType=share&lang=${currentLang}`
  366. //临时权限token
  367. const res = await getChartShareExpireToken(chartInfo.value.UniqueCode);
  368. if(res.Ret !== 200) return
  369. const linkUrl = `${publicSettingStore.publicSetting.ChartViewUrl}/chartshow?code=${chartInfo.value.UniqueCode}&fromType=share&lang=${currentLang}&authToken=${res.Data}`
  370. //console.log('url',linkUrl)
  371. if(navigator.clipboard&&window.isSecureContext){
  372. try{
  373. await navigator.clipboard.writeText(linkUrl)
  374. showToast({message:'复制链接成功',type:'success'})
  375. }catch(err){
  376. console.log(err);
  377. showToast({message:'复制链接失败',type:'fail'})
  378. }
  379. }else{
  380. const input = document.createElement('input')
  381. input.setAttribute('readonly','readonly')
  382. input.value = linkUrl
  383. document.body.appendChild(input)
  384. input.select();
  385. document.execCommand('copy');
  386. document.body.removeChild(input);
  387. showToast({message:'复制链接成功',type:'success'})
  388. }
  389. }
  390. function checkChartEnOption(){
  391. if(!chartInfo.value.ChartNameEn) return false
  392. for(const data of chartInfoData.EdbInfoList){
  393. if(data.EdbNameEn==""||(data.UnitEn==""&&data.Unit!="")){
  394. return false
  395. }
  396. }
  397. return true
  398. }
  399. //保存图表
  400. function saveChart(){
  401. //获取每条线的指标配置
  402. let arr = edbList.value.map((item)=>{
  403. return {
  404. ChartColor: item.ChartColor,
  405. PredictChartColor: item.PredictChartColor,
  406. ChartStyle: item.ChartStyle,
  407. ChartWidth: Number(item.ChartWidth),
  408. EdbInfoId: item.EdbInfoId,
  409. EdbInfoType: item.EdbInfoType,
  410. IsAxis: item.IsAxis,
  411. IsOrder: item.IsOrder,
  412. LeadUnit: item.EdbInfoType ? '' : item.LeadUnit,
  413. LeadValue: item.EdbInfoType ? 0 : Number(item.LeadValue),
  414. MaxData: Number(item.MaxData),
  415. MinData: Number(item.MinData),
  416. }
  417. })
  418. //所有图表的公共参数
  419. let public_param = {
  420. ChartClassifyId: chartInfo.value.ChartClassifyId,
  421. ChartInfoId: chartInfo.value.ChartInfoId,
  422. ChartEdbInfoList: arr,
  423. }
  424. //根据ChartType决定剩余参数
  425. let type_param = {}
  426. switch(chartInfo.value.ChartType){
  427. case 2:
  428. type_param = {
  429. DateType: chartState.yearVal,
  430. StartYear:chartState.startYear || 0,
  431. Calendar: chartState.calendarType,
  432. StartDate: chartState.startTime||'',
  433. EndDate: chartState.endTime||'',
  434. }
  435. break
  436. case 7:
  437. case 11:
  438. type_param = {
  439. DateType: 6,
  440. LeftMin: String(axisLimitState.leftMin),
  441. LeftMax: String(axisLimitState.leftMax),
  442. }
  443. break
  444. case 10:
  445. type_param = {
  446. DateType: 6,
  447. Calendar: "公历",
  448. ExtraConfig: JSON.stringify({
  449. ...JSON.parse(chartInfo.value.ExtraConfig),
  450. XMinValue: String(axisLimitState.xMin),
  451. XMaxValue: String(axisLimitState.xMax),
  452. YMinValue: String(axisLimitState.leftMin),
  453. YMaxValue: String(axisLimitState.leftMax),
  454. })
  455. }
  456. break
  457. }
  458. if(sameOptionType.includes(chartInfo.value.ChartType)){
  459. type_param = {
  460. DateType: chartState.yearVal,
  461. StartYear:chartState.startYear || 0,
  462. StartDate:chartState.yearVal === 5 || chartState.yearVal === 6
  463. ? chartState.startTime
  464. : '',
  465. EndDate: chartState.yearVal === 5 ? chartState.endTime : '',
  466. }
  467. }
  468. let params = {...public_param,...type_param}
  469. if(![7,10,11].includes(chartInfo.value.ChartType)){
  470. params = {
  471. ...params,
  472. LeftMin:axisLimitState.leftMin+'',
  473. LeftMax:axisLimitState.leftMax+'',
  474. RightMin:axisLimitState.rightMin+'',
  475. RightMax:axisLimitState.rightMax+'',
  476. Right2Min:axisLimitState.rightTwoMin+'',
  477. Right2Max:axisLimitState.rightTwoMax+'',
  478. //手动保存视为更改过上下限
  479. MinMaxSave:1
  480. }
  481. }
  482. //保存
  483. apiChart.chartSave(params).then(async res=>{
  484. if(res.Ret!==200) return
  485. showToast("保存成功")
  486. //更新缩略图
  487. setChartImage()
  488. //保存成功后修改route.query防止刷新后请求旧参数
  489. router.replace({
  490. path:'/chartETA/chartdetail',
  491. query:{
  492. id:route.query.id,
  493. chartType:route.query.chartType,
  494. chartClassifyId:route.query.chartClassifyId,
  495. DateType:params.DateType,
  496. StartDate:chartState.startTime,
  497. EndDate:chartState.endTime,
  498. Calendar:chartState.calendarType,
  499. SeasonStartDate:chartState.startTime,
  500. SeasonEndDate:chartState.endTime,
  501. StartYear:chartState.startYear
  502. }
  503. })
  504. })
  505. }
  506. async function setChartImage(){
  507. const svgData = highChart.value.getSVG({
  508. chart: {
  509. width: 340,
  510. height: 230,
  511. }
  512. })
  513. let form = new FormData();
  514. form.append('Img', svgData);
  515. let {Data,Ret} = await apiChart.uploadChartImg(form)
  516. if(Ret!==200||!Data) return
  517. await apiChart.setChartImg({
  518. ChartInfoId:Number(route.query.id),
  519. ImageUrl:Data.ResourceUrl
  520. })
  521. }
  522. let isShowSaveOtherDialog = ref(false)
  523. let catalogNodes = ref([])
  524. //另存为
  525. async function openSaveChartOtherDialog(){
  526. const res = await apiChart.ETAChartClassifyList()
  527. if(res.Ret!==200) return
  528. catalogNodes.value = res.Data?res.Data.AllNodes:[]||[]
  529. isShowSaveOtherDialog.value = true
  530. }
  531. function saveOther(ClassifyId){
  532. apiChart.ETAChartSaveOther({
  533. ChartInfoId:chartInfo.value.ChartInfoId,
  534. ChartName:chartInfo.value.ChartName+'(1)',
  535. ChartClassifyId:ClassifyId
  536. }).then(res=>{
  537. if(res.Ret!==200) return
  538. showToast({message:'另存为成功',type:'success'})
  539. isShowSaveOtherDialog.value = false
  540. })
  541. }
  542. let savePicDialogShow = ref(false)
  543. let savePicSrc = ref('')
  544. //保存图片
  545. function saveChartPic(){
  546. const {chartWidth,chartHeight} = highChart.value
  547. //打开保存图片弹窗
  548. const svgData = highChart.value.getSVG({
  549. chart: {
  550. width: chartWidth,
  551. height: chartHeight,
  552. }
  553. })
  554. const canvas = document.createElement('canvas')
  555. const ctx = canvas.getContext('2d')
  556. canvas.width = chartWidth*2
  557. canvas.height = chartHeight*2
  558. const image = new Image()
  559. image.src = 'data:image/svg+xml;charset=utf-8,'+encodeURIComponent(svgData)
  560. image.onload = ()=>{
  561. ctx.drawImage(image, 0, 0,chartWidth*2,chartHeight*2);
  562. savePicSrc.value = canvas.toDataURL('image/png');
  563. savePicDialogShow.value = true
  564. }
  565. }
  566. let setChartEnDialogShow = ref(false)
  567. //设置英文名称
  568. function openSetChartEnNameDialog(){
  569. setChartEnDialogShow.value = true
  570. }
  571. function closeSetNameDialog(type){
  572. if(type==='save'){
  573. getChartDetail()
  574. }
  575. setChartEnDialogShow.value = false
  576. }
  577. let isShowAddToMyETADialog = ref(false)
  578. //加入我的图库
  579. function openAddToMyETADialog(){
  580. isShowAddToMyETADialog.value = true
  581. }
  582. //删除图表
  583. async function deleteChart(){
  584. const res = await apiChart.deleteCheck({
  585. ChartClassifyId:Number(routeQueryData.chartClassifyId),
  586. ChartInfoId:Number(routeQueryData.id),
  587. })
  588. if(res.Ret!==200) return
  589. const hintTextMap = {
  590. 0:'确定删除当前分类吗?',
  591. 1:'该分类下关联图表不可删除!',
  592. 2:'确认删除当前分类及包含的子分类吗?',
  593. 3:'删除后,该图表将从ETA投研资源库同步删除,影响客户的查看权限,是否确认删除?'
  594. }
  595. showDialog({
  596. title: '提示',
  597. message: hintTextMap[res.Data.DeleteStatus||0],
  598. showCancelButton:res.Data.DeleteStatus!==1
  599. }).then(() => {
  600. if(res.Data.DeleteStatus!==1){
  601. handleDeleteRequest()
  602. }
  603. }).catch(()=>{})
  604. }
  605. // 删除请求
  606. function handleDeleteRequest(){
  607. apiChart.deleteClassify({
  608. ChartClassifyId:Number(routeQueryData.chartClassifyId),
  609. ChartInfoId:Number(routeQueryData.id),
  610. }).then(res=>{
  611. if(res.Ret===200){
  612. cachedViewsStore.removeCaches('ChartETAList')
  613. cachedViewsStore.removeCaches('ChartETASearch')
  614. showToast('删除成功')
  615. setTimeout(() => {
  616. router.back()
  617. }, 1000);
  618. }
  619. })
  620. }
  621. // 保存至素材库
  622. const showSaveToMaterial=ref(false)
  623. function handleShowSaveToMaterial(){
  624. showSaveToMaterial.value=true
  625. }
  626. //获取图排序列表数据
  627. const chartSortListData=ref([])
  628. async function getChartSortList(){
  629. const res=await apiChart.chartLocate({
  630. KeyWord:route.query.keyword||'',
  631. ChartClassifyId:Number(route.query.chartClassifyId),
  632. IsShowMe:route.query.IsShowMe=='true'?true:false
  633. })
  634. if(res.Ret===200){
  635. chartSortListData.value=res.Data||[]
  636. }
  637. }
  638. getChartSortList()
  639. // 切换图
  640. async function handleSwitchChart(type){
  641. const index=chartSortListData.value.findIndex((item)=>item.ChartInfoId==routeQueryData.id)
  642. let item=null
  643. if(type==='prev'){
  644. item=index===0?chartSortListData.value[chartSortListData.value.length-1]:chartSortListData.value[index-1]
  645. }else{
  646. item=index===chartSortListData.value.length-1?chartSortListData.value[0]:chartSortListData.value[index+1]
  647. }
  648. //切换前重置chartState
  649. routeQueryData.id=item.ChartInfoId
  650. routeQueryData.chartType=item.ChartType
  651. routeQueryData.chartClassifyId=item.ChartClassifyId
  652. initChartState({...item,...routeQueryData})
  653. isUseSelfLimit.value = false
  654. getChartDetail('init')
  655. }
  656. function initChartState(data){
  657. chartState.showTimePop=false
  658. chartState.startTime=sameOptionType.includes(Number(data.chartType))?data.StartDate:data.SeasonStartDate
  659. chartState.endTime=sameOptionType.includes(Number(data.chartType))?data.EndDate:data.SeasonEndDate
  660. chartState.yearVal=data.DateType
  661. chartState.calendarType=data.Calendar
  662. chartState.startYear=Number(data.StartYear)
  663. }
  664. function openDateSelect(){
  665. // 回显
  666. switch (chartState.yearVal) {
  667. case 3:
  668. temStartTime.value = [2015,1,1]
  669. temEndTime.value = latestDate.value.split('-')
  670. break;
  671. case 9:
  672. temStartTime.value = [2020,1,1]
  673. temEndTime.value = latestDate.value.split('-')
  674. break;
  675. case 4:
  676. temStartTime.value = [2021,1,1]
  677. temEndTime.value = latestDate.value.split('-')
  678. break;
  679. case 11:
  680. temStartTime.value = [2022,1,1]
  681. temEndTime.value = latestDate.value.split('-')
  682. break;
  683. case '':
  684. temStartTime.value = earliestDate.value.split('-')
  685. temEndTime.value = latestDate.value.split('-')
  686. break;
  687. default:
  688. temStartTime.value = chartState.startTime.split('-')
  689. temEndTime.value = chartState.endTime.split('-')
  690. break;
  691. }
  692. chartState.showTimePop=true
  693. }
  694. </script>
  695. <template>
  696. <div class="chart-detail-page" v-if="chartInfo">
  697. <div
  698. class="chart-title"
  699. :style="chartInfo.ChartThemeStyle?`
  700. text-align:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.align};
  701. font-size:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.fontSize}px;
  702. color:${JSON.parse(chartInfo.ChartThemeStyle).titleOptions.style.color}
  703. `:''"
  704. >{{currentLang==='en'?(chartInfo.ChartNameEn||chartInfo.ChartName):chartInfo.ChartName}}</div>
  705. <!-- 一般曲线图选择时间区间或者季节图选择日期 -->
  706. <div
  707. class="select-time-box"
  708. v-if="sameOptionType.includes(chartInfo.ChartType)||chartInfo.ChartType===2"
  709. @click="openDateSelect"
  710. >
  711. <img class="left-icon" src="@/assets/imgs/icon_calendar.png" alt="">
  712. <span :class="['val-box',!chartState.startTime?'val-box_grey':'']">{{chartState.startTime||'开始日期'}} ~ {{chartState.endTime||'结束日期'}}</span>
  713. <van-icon class="right-icon" name="arrow" />
  714. </div>
  715. <!-- pad端时间和操作按钮模块 -->
  716. <div class="pad-time-action-wrap">
  717. <div class="left-time-box">
  718. <template v-if="sameOptionType.includes(chartInfo.ChartType)">
  719. <span :class="['item',chartState.yearVal==''?'active':'']" @click="handleYearChange({value:''})">全部</span>
  720. <span
  721. :class="['item',chartState.yearVal==item.value?'active':'']"
  722. v-for="item in yearSelectOpt"
  723. :key="item.value"
  724. @click="handleYearChange(item)"
  725. >{{item.name}}</span>
  726. </template>
  727. <span
  728. class="time-box"
  729. v-if="sameOptionType.includes(chartInfo.ChartType)||chartInfo.ChartType===2"
  730. @click="openDateSelect"
  731. >
  732. {{chartState.startTime?`${chartState.startTime} ~ ${chartState.endTime||'至今'}`:'请选择时间段'}}
  733. </span>
  734. </div>
  735. <div class="right-action-box">
  736. <div class="item" @click="showMoreAction=true" v-if="chartActions.length">
  737. <img src="@/assets/imgs/chartETA/more-icon.png" alt="">
  738. <span>更多设置</span>
  739. </div>
  740. </div>
  741. </div>
  742. <!-- 图渲染区域 -->
  743. <div class="chart-render-wrap">
  744. <!-- pad 切换上一张\下一张 -->
  745. <img class="pad-change-chart-btn" src="@/assets/imgs/icon_arrow2.png" alt="" @click="handleSwitchChart('prev')" v-if="chartSortListData.length>0">
  746. <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">
  747. <div class="chart-box" id="chart-box"></div>
  748. <!-- 底部来源,图表说明 -->
  749. <div class="chart-bottom-insruction-info"
  750. v-if="(chartInfo.SourcesFrom&&JSON.parse(chartInfo.SourcesFrom).isShow) || (chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow)">
  751. <div
  752. class="chart-source"
  753. v-if="chartInfo.SourcesFrom&&JSON.parse(chartInfo.SourcesFrom).isShow"
  754. :style="`
  755. color: ${ JSON.parse(chartInfo.SourcesFrom).color };
  756. font-size: ${ JSON.parse(chartInfo.SourcesFrom).fontSize }px;
  757. `"
  758. >
  759. 数据来源:{{JSON.parse(chartInfo.SourcesFrom).text}}
  760. </div>
  761. <!-- 图表说明 -->
  762. <div
  763. class="chart-instruction text_oneLine"
  764. v-if="chartInfo.Instructions&&JSON.parse(chartInfo.Instructions).isShow"
  765. v-text="JSON.parse(chartInfo.Instructions).text"
  766. :style="`
  767. color: ${JSON.parse(chartInfo.Instructions).color};
  768. font-size: ${ JSON.parse(chartInfo.Instructions).fontSize }px
  769. `"
  770. ></div>
  771. </div>
  772. <!-- 作者 -->
  773. <div class="author-box" style="text-align:right">作者:{{chartInfo.SysUserRealName}}</div>
  774. </div>
  775. <!-- 手机端选择时间区间模块 -->
  776. <div class="select-year-box" v-if="sameOptionType.includes(chartInfo.ChartType)">
  777. <span :class="['item',chartState.yearVal==''?'active':'']" @click="handleYearChange({value:''})">全部</span>
  778. <span
  779. :class="['item',chartState.yearVal==item.value?'active':'']"
  780. v-for="item in yearSelectOpt"
  781. :key="item.value"
  782. @click="handleYearChange(item)"
  783. >{{item.name}}</span>
  784. </div>
  785. <!-- 季节图切换公/农历 -->
  786. <div class="calendar-type-box" v-if="chartInfo.ChartType === 2">
  787. <span
  788. :class="chartState.calendarType=='公历'?'active':''"
  789. @click="handleSeasonTypeChange('公历')"
  790. >公历</span>
  791. <span
  792. :class="chartState.calendarType=='农历'?'active':''"
  793. @click="handleSeasonTypeChange('农历')"
  794. >农历</span>
  795. </div>
  796. <!-- 指标模块 -->
  797. <div class="edb-list-box">
  798. <!-- pad 设置上下限按钮 -->
  799. <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>
  800. <!-- <div class="list-lable">指标信息</div> -->
  801. <div class="list-box">
  802. <div class="list-item" v-for="item in edbList" :key="item.EdbInfoId" @click="handleShowEDBInfo(item)">
  803. <span class="date">{{item.LatestDate}}</span>
  804. <span class="edb-name van-ellipsis" :style="{color:item.ChartColor}">{{item.EdbName}}</span>
  805. <span class="value">{{item.LatestValue}}</span>
  806. </div>
  807. </div>
  808. </div>
  809. <!-- 底部悬浮操作模块 -->
  810. <div class="fix-bot-action-box">
  811. <div class="item" @click="handleSwitchChart('prev')" v-if="chartSortListData.length>0">
  812. <img class="icon" src="@/assets/imgs/icon_arrow.png" alt="">
  813. <div>上一张</div>
  814. </div>
  815. <div class="item" @click="handleSwitchChart('next')" v-if="chartSortListData.length>0">
  816. <img class="icon" style="transform: rotate(180deg);" src="@/assets/imgs/icon_arrow.png" alt="">
  817. <div>下一张</div>
  818. </div>
  819. <div class="item" @click="handleShowAxisLimitOpt" v-if="![3,4,6,7,8,9].includes(chartInfo.Source)&&checkAuthBtn(chartLibBtn.chartLib_editLimit)&&isChartHeap(chartInfo)">
  820. <img class="icon" src="@/assets/imgs/myETA/icon_limit.png" alt="">
  821. <div>上下限</div>
  822. </div>
  823. <div class="item" @click="showMoreAction=true" v-if="chartActions.length">
  824. <img class="icon" src="@/assets/imgs/myETA/icon_menu.png" alt="">
  825. <div>更多</div>
  826. </div>
  827. </div>
  828. <!-- 选择日期弹窗 -->
  829. <van-popup
  830. v-model:show="chartState.showTimePop"
  831. :position="width>650?'center':'bottom'"
  832. :style="width>650?{ width: '400px'}:''"
  833. round
  834. >
  835. <div class="time-picker-wrap">
  836. <van-picker-group
  837. title="选择起始时间"
  838. :tabs="['开始时间', '结束时间']"
  839. @cancel="chartState.showTimePop=false"
  840. @confirm="handleTimeChange"
  841. >
  842. <van-date-picker
  843. v-model="temStartTime"
  844. :min-date="minDate"
  845. :max-date="maxDate"
  846. :columns-type="['year','month','day']"
  847. />
  848. <van-date-picker
  849. v-model="temEndTime"
  850. :min-date="minDate"
  851. :max-date="maxDate"
  852. :columns-type="['year','month','day']"
  853. />
  854. </van-picker-group>
  855. </div>
  856. </van-popup>
  857. <!-- 指标详情弹窗 -->
  858. <van-popup
  859. v-model:show="showEDB"
  860. :position="width>650?'right':'bottom'"
  861. round
  862. closeable
  863. :style="width>650?{ width: '400px', height: '100%' }:''"
  864. >
  865. <EdbInfo
  866. :show="showEDB"
  867. :data="showEDBData"
  868. :tableData="edbList"
  869. @showSourceDetail="handleShowSourceDetail"
  870. />
  871. </van-popup>
  872. <!-- 数据来源弹窗-->
  873. <van-popup
  874. v-model:show="showSourceDetail"
  875. position="center"
  876. round
  877. closeable
  878. :style="{ width: '400px'}"
  879. >
  880. <SourceDetail
  881. :show="showSourceDetail"
  882. :EdbInfoId="showEDBData.EdbInfoId"
  883. :UniqueCode="showEDBData.UniqueCode"
  884. />
  885. </van-popup>
  886. <!-- 上下限调整弹窗 -->
  887. <van-popup
  888. v-model:show="showLimitPop"
  889. :position="width>650?'center':'bottom'"
  890. round
  891. closeable
  892. :style="width>650?{ width: '400px'}:''"
  893. >
  894. <div class="global-pop-wrap_mobile chart-set-limit-wrap">
  895. <div class="head-box">
  896. <div class="title">上下限设置</div>
  897. </div>
  898. <div class="content">
  899. <!-- 左轴 -->
  900. <div class="item-box" v-if="axisLimitState.hasLeftAxis">
  901. <span class="lable-text">左轴</span>
  902. <div class="input-box">
  903. <div class="item">
  904. <div class="type-text">上限</div>
  905. <div class="step-box">
  906. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.leftMax" />
  907. </div>
  908. </div>
  909. <div class="item">
  910. <div class="type-text">下限</div>
  911. <div class="step-box">
  912. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.leftMin" />
  913. </div>
  914. </div>
  915. </div>
  916. </div>
  917. <!-- 右轴 -->
  918. <div class="item-box" v-if="axisLimitState.hasRightAxis">
  919. <span class="lable-text">右轴</span>
  920. <div class="input-box">
  921. <div class="item">
  922. <div class="type-text">上限</div>
  923. <div class="step-box">
  924. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightMax" />
  925. </div>
  926. </div>
  927. <div class="item">
  928. <div class="type-text">下限</div>
  929. <div class="step-box">
  930. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightMin" />
  931. </div>
  932. </div>
  933. </div>
  934. </div>
  935. <!-- 右二轴 -->
  936. <div class="item-box" v-if="axisLimitState.hasRightTwoAxis">
  937. <span class="lable-text">右2轴</span>
  938. <div class="input-box">
  939. <div class="item">
  940. <div class="type-text">上限</div>
  941. <div class="step-box">
  942. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightTwoMax" />
  943. </div>
  944. </div>
  945. <div class="item">
  946. <div class="type-text">下限</div>
  947. <div class="step-box">
  948. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.rightTwoMin" />
  949. </div>
  950. </div>
  951. </div>
  952. </div>
  953. <!-- x轴 -->
  954. <div class="item-box" v-if="axisLimitState.hasXAxis">
  955. <span class="lable-text">X轴</span>
  956. <div class="input-box">
  957. <div class="item">
  958. <div class="type-text">上限</div>
  959. <div class="step-box">
  960. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.xMax" />
  961. </div>
  962. </div>
  963. <div class="item">
  964. <div class="type-text">下限</div>
  965. <div class="step-box">
  966. <van-stepper input-width="60px" :min="axisLimitDataTem.min" v-model.number="axisLimitDataTem.xMin" />
  967. </div>
  968. </div>
  969. </div>
  970. </div>
  971. </div>
  972. <div class="bot-btn-box" @click="handleConfirmLimitChange">确定</div>
  973. </div>
  974. </van-popup>
  975. <!-- 更多设置弹窗 -->
  976. <van-popup
  977. v-model:show="showMoreAction"
  978. :position="width>650?'center':'bottom'"
  979. round
  980. closeable
  981. :style="width>650?{ width: '400px'}:''"
  982. >
  983. <div class="global-pop-wrap_mobile chart-more-action-wrap">
  984. <div class="head-box">
  985. <div class="title van-ellipsis">{{chartInfo.ChartName}}</div>
  986. </div>
  987. <div class="action-box">
  988. <template v-for="item in chartActions" :key="item.types">
  989. <div class="action-item" v-if="item.show" @click="handleActionClick(item)">
  990. {{item.label}}
  991. </div>
  992. </template>
  993. </div>
  994. </div>
  995. </van-popup>
  996. <!-- 另存为弹窗 -->
  997. <TreeSelectPop
  998. :isShowDialog="isShowSaveOtherDialog"
  999. :dialogPosition="width>650?'center':'bottom'"
  1000. :catalogNodes="catalogNodes"
  1001. :chartInfo="chartInfo"
  1002. popTitle="另存为"
  1003. @close="isShowSaveOtherDialog=false"
  1004. @confirmMove="saveOther"
  1005. />
  1006. <!-- 加入我的图库弹窗 -->
  1007. <AddChartToMyETA
  1008. :isShowDialog="isShowAddToMyETADialog"
  1009. :dialogPosition="width>650?'center':'bottom'"
  1010. :chartInfo="chartInfo"
  1011. @close="isShowAddToMyETADialog=false"
  1012. />
  1013. <!--保存图片弹窗 -->
  1014. <van-popup
  1015. v-model:show="savePicDialogShow"
  1016. position="center"
  1017. round
  1018. closeable
  1019. :style="{width:'80%',padding:'30px'}"
  1020. >
  1021. <img :src="savePicSrc" alt="" style="width:100%;box-sizing: border-box;">
  1022. <p style="text-align: center;color:#999;margin-top: 10px;">长按保存图片</p>
  1023. </van-popup>
  1024. <!-- 设置英文名称弹窗 -->
  1025. <van-popup
  1026. v-model:show="setChartEnDialogShow"
  1027. position="bottom"
  1028. :style="{width:'100%',height:'100%'}"
  1029. >
  1030. <SetChartEnName
  1031. :isShow="setChartEnDialogShow"
  1032. :chartInfo="chartInfoData"
  1033. :chartType="Number(route.query.chartType)"
  1034. @close="closeSetNameDialog"
  1035. />
  1036. </van-popup>
  1037. <!-- 保存至素材库 -->
  1038. <SaveToMaterial
  1039. v-model:show="showSaveToMaterial"
  1040. source="chart"
  1041. :sourceId="chartInfo.ChartInfoId"
  1042. :defaultName="chartInfo.ChartName"
  1043. />
  1044. </div>
  1045. </template>
  1046. <style lang="scss">
  1047. .chart-detail-page{
  1048. .rename-wrap{
  1049. padding:48px;
  1050. input{
  1051. padding: 24px 32px;
  1052. border-radius: 12px;
  1053. background-color: #F6F6F6;
  1054. width: 100%;
  1055. }
  1056. .label{
  1057. color: #666666;
  1058. margin-bottom: 32px;
  1059. text-align: center;
  1060. }
  1061. }
  1062. @media screen and (min-width:$media-width){
  1063. .rename-wrap{
  1064. padding:24px;
  1065. input{
  1066. padding: 12px 16px;
  1067. border-radius: 6px;
  1068. background-color: #F6F6F6;
  1069. width: 100%;
  1070. }
  1071. .label{
  1072. margin-bottom: 16px;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. </style>
  1078. <style scoped lang="scss">
  1079. .chart-detail-page{
  1080. padding: $page-padding;
  1081. padding-bottom: 120px;
  1082. .chart-title{
  1083. font-size: 36px;
  1084. margin-bottom: 56px;
  1085. }
  1086. .chart-render-wrap{
  1087. .pad-change-chart-btn{
  1088. display: none;
  1089. }
  1090. }
  1091. .chart-box{
  1092. width: 100%;
  1093. height: 700px;
  1094. }
  1095. .chart-bottom-insruction-info {
  1096. width: 100%;
  1097. margin: 0 auto;
  1098. }
  1099. .select-time-box{
  1100. display: flex;
  1101. align-items: center;
  1102. padding-bottom: 32px;
  1103. border-bottom: 1px solid $border-color;
  1104. .left-icon{
  1105. width: 48px;
  1106. height: 48px;
  1107. }
  1108. .right-icon{
  1109. margin-left: auto;
  1110. }
  1111. .val-box{
  1112. margin-left: 32px;
  1113. font-size: 32px;
  1114. &.val-box_grey{
  1115. color: $font-grey_999;
  1116. }
  1117. }
  1118. }
  1119. .select-year-box{
  1120. width: 100vw;
  1121. position: relative;
  1122. left: -$page-padding;
  1123. margin-top: 30px;
  1124. box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.08);
  1125. height: 88px;
  1126. display: flex;
  1127. align-items: center;
  1128. overflow-y: auto;
  1129. padding: 0 $page-padding;
  1130. &::-webkit-scrollbar{
  1131. height: 0;
  1132. }
  1133. .item{
  1134. line-height: 88px;
  1135. position: relative;
  1136. height: 100%;
  1137. flex-shrink: 0;
  1138. display: inline-block;
  1139. margin-right: 40px;
  1140. font-size: 32px;
  1141. color: $font-grey_999;
  1142. &.active{
  1143. color: #333;
  1144. &::after{
  1145. content: '';
  1146. display: block;
  1147. width: 50px;
  1148. height: 6px;
  1149. border-radius: 3px;
  1150. background-color: $theme-color;
  1151. position: absolute;
  1152. bottom: 0;
  1153. left: 50%;
  1154. transform: translateX(-50%);
  1155. }
  1156. }
  1157. }
  1158. }
  1159. .calendar-type-box{
  1160. width: 404px;
  1161. margin: 30px auto;
  1162. text-align: center;
  1163. border: 1px solid $theme-color;
  1164. border-radius: 12px;
  1165. overflow: hidden;
  1166. span{
  1167. display: inline-block;
  1168. width: 200px;
  1169. height: 80px;
  1170. line-height: 80px;
  1171. color: $theme-color;
  1172. font-weight: bold;
  1173. &.active{
  1174. background-color: $theme-color;
  1175. color: #fff;
  1176. }
  1177. }
  1178. }
  1179. .pad-time-action-wrap{
  1180. display: none;
  1181. }
  1182. .edb-list-box{
  1183. .pad-limit-set-btn{
  1184. display: none;
  1185. }
  1186. .list-lable{
  1187. font-size: 36px;
  1188. color: #000;
  1189. margin-bottom: 20px;
  1190. margin-top: 40px;
  1191. }
  1192. .list-item{
  1193. padding:18px;
  1194. display: flex;
  1195. gap:0 20px;
  1196. border-bottom: 1px solid #DCDFE6;
  1197. &:last-child{
  1198. border-bottom: none;
  1199. }
  1200. .edb-name{
  1201. flex: 1;
  1202. /* text-align: center; */
  1203. }
  1204. }
  1205. }
  1206. .fix-bot-action-box{
  1207. position: fixed;
  1208. left: 0;
  1209. bottom: 0;
  1210. right: 0;
  1211. z-index: 99;
  1212. background-color: #fff;
  1213. border-top: 1px solid $border-color;
  1214. height: 112px;
  1215. display: flex;
  1216. align-items: center;
  1217. .item{
  1218. height: 100%;
  1219. flex: 1;
  1220. display: flex;
  1221. flex-direction: column;
  1222. justify-content: center;
  1223. align-items: center;
  1224. font-size: 20px;
  1225. .icon{
  1226. width: 40px;
  1227. height: 40px;
  1228. margin-bottom: 5px;
  1229. }
  1230. }
  1231. }
  1232. .chart-set-limit-wrap{
  1233. .head-box{
  1234. .title{
  1235. padding: 0 $page-padding;
  1236. font-size: 36px;
  1237. font-weight: 600;
  1238. line-height: 120px;
  1239. }
  1240. }
  1241. .bot-btn-box{
  1242. line-height: 112px;
  1243. text-align: center;
  1244. color: $theme-color;
  1245. font-size: 32px;
  1246. }
  1247. .content{
  1248. padding: $page-padding;
  1249. .item-box{
  1250. display: flex;
  1251. align-items: flex-end;
  1252. margin-bottom: 30px;
  1253. .lable-text{
  1254. width: 100px;
  1255. }
  1256. .input-box{
  1257. flex: 1;
  1258. display: flex;
  1259. .item{
  1260. flex: 1;
  1261. text-align: center;
  1262. .type-text{
  1263. margin-bottom: 40px;
  1264. }
  1265. .step-box{
  1266. display: inline-block;
  1267. :deep(.van-stepper){
  1268. display: flex;
  1269. justify-content: center;
  1270. }
  1271. }
  1272. }
  1273. }
  1274. }
  1275. }
  1276. }
  1277. .chart-more-action-wrap{
  1278. .head-box{
  1279. .title{
  1280. width: 100%;
  1281. padding:34px 100px;
  1282. box-sizing: border-box;
  1283. font-size: 36px;
  1284. font-weight: 600;
  1285. text-align: center;
  1286. }
  1287. }
  1288. .action-box{
  1289. .action-item{
  1290. text-align: center;
  1291. padding:32px 84px;
  1292. border-bottom: 1px solid #DCDFE6;
  1293. &:last-child{
  1294. border-bottom: none;
  1295. }
  1296. }
  1297. }
  1298. }
  1299. @media screen and (min-width:$media-width){
  1300. padding:30px;
  1301. .chart-title{
  1302. font-size: 16px;
  1303. font-weight: bold;
  1304. margin-bottom: 30px;
  1305. }
  1306. .chart-render-wrap{
  1307. position: relative;
  1308. .pad-change-chart-btn{
  1309. display: block;
  1310. width: 48px;
  1311. height: 48px;
  1312. position: absolute;
  1313. top: 50%;
  1314. transform: translateY(-50%);
  1315. left: 0px;
  1316. &.pad-change-chart-next-btn{
  1317. right: 0;
  1318. left: auto;
  1319. transform: translateY(-50%) rotate(180deg);
  1320. }
  1321. }
  1322. }
  1323. .chart-box{
  1324. width: 85%;
  1325. height: 370px;
  1326. margin: 0 auto;
  1327. }
  1328. .chart-bottom-insruction-info {
  1329. width: 85%;
  1330. margin: 0 auto;
  1331. }
  1332. .select-time-box,.select-year-box,.fix-bot-action-box{
  1333. display: none;
  1334. }
  1335. .pad-time-action-wrap{
  1336. display: flex;
  1337. flex-wrap: wrap;
  1338. align-items: center;
  1339. justify-content: space-between;
  1340. .left-time-box{
  1341. flex-shrink: 0;
  1342. margin-bottom: 20px;
  1343. .item{
  1344. display: inline-block;
  1345. padding: 0 12px;
  1346. //width: 80px;
  1347. height: 36px;
  1348. text-align: center;
  1349. line-height: 36px;
  1350. border: 1px solid $theme-color;
  1351. margin-right: 10px;
  1352. border-radius: 3px;
  1353. &.active{
  1354. color: #fff;
  1355. background-color: $theme-color;
  1356. }
  1357. }
  1358. .time-box{
  1359. display: inline-block;
  1360. padding: 0 15px;
  1361. height: 36px;
  1362. line-height: 36px;
  1363. border: 1px solid $theme-color;
  1364. border-radius: 3px;
  1365. background-color: #F2F3FF;
  1366. color: $theme-color;
  1367. }
  1368. }
  1369. .right-action-box{
  1370. display: flex;
  1371. margin-bottom: 20px;
  1372. .item{
  1373. display: flex;
  1374. color: $theme-color;
  1375. margin-left: 20px;
  1376. img{
  1377. width: 15px;
  1378. height: 15px;
  1379. margin-right: 4px;
  1380. }
  1381. }
  1382. }
  1383. }
  1384. .calendar-type-box{
  1385. width: 224px;
  1386. margin: 20px auto;
  1387. border-radius: 4px;
  1388. span{
  1389. width: 111px;
  1390. height: 38px;
  1391. line-height: 38px;
  1392. }
  1393. }
  1394. .edb-list-box{
  1395. position: relative;
  1396. left: -30px;
  1397. border-top: 1px solid $border-color;
  1398. width: 100vw;
  1399. padding: 0 30px;
  1400. margin-top: 20px;
  1401. .pad-limit-set-btn{
  1402. display: block;
  1403. text-align: right;
  1404. margin: 20px 0;
  1405. color: $theme-color;
  1406. }
  1407. .list-lable{
  1408. margin-top: 20px;
  1409. font-size: 16px;
  1410. margin-bottom: 14px;
  1411. }
  1412. .list-box{
  1413. //border: 1px solid $border-color;
  1414. .list-item{
  1415. padding: 18px;
  1416. }
  1417. }
  1418. }
  1419. .chart-set-limit-wrap{
  1420. .head-box{
  1421. .title{
  1422. font-size: 18px;
  1423. line-height: 50px;
  1424. padding-left: 16px;
  1425. }
  1426. }
  1427. .bot-btn-box{
  1428. font-size: 16px;
  1429. line-height: 56px;
  1430. border-top-width: 8px;
  1431. }
  1432. .content{
  1433. max-height: 500px;
  1434. padding: 30px;
  1435. .item-box{
  1436. margin-bottom: 15px;
  1437. .lable-text{
  1438. width: 50px;
  1439. }
  1440. .input-box{
  1441. .item{
  1442. .type-text{
  1443. margin-bottom: 20px;
  1444. }
  1445. }
  1446. }
  1447. }
  1448. }
  1449. }
  1450. .chart-more-action-wrap{
  1451. .head-box{
  1452. .title{
  1453. padding:17px 50px;
  1454. font-size: 18px;
  1455. }
  1456. }
  1457. .action-box{
  1458. .action-item{
  1459. padding:16px 42px;
  1460. }
  1461. }
  1462. }
  1463. }
  1464. }
  1465. </style>