ChartDetail.vue 54 KB

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