pptMixins.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. /** 图库9.0(智能PPT) 共通逻辑 */
  2. import Highcharts from "highcharts/highstock";
  3. import HighchartsMore from 'highcharts/highcharts-more';
  4. import HighchartszhCN from '@/utils/highcahrts-zh_CN'
  5. HighchartszhCN(Highcharts)
  6. HighchartsMore(Highcharts)
  7. import { dataBaseInterface,pptInterface } from "@/api/api.js";
  8. import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
  9. import {pptEnInterface} from '@/api/modules/pptEnApi.js';
  10. import * as sheetInterface from '@/api/modules/sheetApi.js';
  11. import futuresInterface from '@/api/modules/futuresBaseApi';
  12. import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
  13. import chartRelevanceApi from '@/api/modules/chartRelevanceApi.js';
  14. import { defaultOpts } from '@/utils/defaultOptions';
  15. import {formatPPTDate,checkPPTpageElemant,getStrSize,isShowPPTTitle,toTextProps,toJson,rgbaToHex} from '../newVersion/utils/untils.js';
  16. import FormatOne from '../newVersion/components/formatPage/FormatOne.vue';
  17. import FormatTwo from '../newVersion/components/formatPage/FormatTwo.vue';
  18. import FormatThree from '../newVersion/components/formatPage/FormatThree.vue';
  19. import FormatFour from '../newVersion/components/formatPage/FormatFour.vue';
  20. import FormatFive from '../newVersion/components/formatPage/FormatFive.vue';
  21. import FormatSix from '../newVersion/components/formatPage/FormatSix.vue';
  22. import FormatSeven from '../newVersion/components/formatPage/FormatSeven.vue';
  23. import FormatEight from '../newVersion/components/formatPage/FormatEight.vue';
  24. import FormatNine from '../newVersion/components/formatPage/FormatNine.vue';
  25. import FormatTen from '../newVersion/components/formatPage/FormatTen.vue';
  26. import FormatEle from '../newVersion/components/formatPage/FormatEle.vue';
  27. import FormatTwelve from '../newVersion/components/formatPage/FormatTwelve.vue';
  28. export default {
  29. components:{ FormatOne,FormatTwo,FormatThree,
  30. FormatFour,FormatFive,FormatSix,FormatSeven,FormatEight,FormatNine,FormatTen,FormatEle,FormatTwelve},
  31. data(){
  32. return{
  33. chartInfo:null,
  34. dataList:[],
  35. optionMap:{},
  36. options:{},
  37. sheetDataMap:{},//表格Table数据
  38. sheetHeightMap:{},//表格iframe的高
  39. pptInitType:'edit',//ppt模式,编辑页为edit,其他页面为show
  40. result:{
  41. status:''
  42. },//getpptDataById的结果
  43. dataLoading:null,//getPptData loading
  44. pageLoading:null,//演示时,切换page需要加载图表数据
  45. publishLoading:null,//发布时loading
  46. pptCoverList:[],//配置ppt封面
  47. pptBgImage:'',//ppt背景图
  48. pptBackImage:'',//ppt封底
  49. pptCoverCompenyName:'',//封面公司名称 ETA1.4.9后不再使用
  50. pptCoverDepartName:'',//封面部门名称 ETA1.4.9后不再使用
  51. pptCoverTextColor:'',//控制上面两个字段展示的颜色 ETA1.4.9后不再使用
  52. pptCoverContent:'',//自定义封面页的内容
  53. setEnName:false,
  54. // 传入的formItem所需内容
  55. formItemArray:[],
  56. addMyChartShow:false,//控制添加到 我的图库 弹窗是否显示
  57. addChartInfoId:0,//当前选择的图表InfoId,
  58. addChartClassifyIds:[],//当前选择的图表所在我的图库目录id
  59. addChartId:'',//当前选择的图表UnicodeId
  60. //截面散点设置英文props
  61. enChartInfo: {},
  62. enEdblist:[]
  63. }
  64. },
  65. methods: {
  66. //配置自定义封面内容
  67. setPPTCover(cover,pptCoverContent='',title=''){
  68. let contentList = []
  69. try{
  70. contentList = JSON.parse(pptCoverContent)
  71. }catch(e){
  72. contentList=[]
  73. }
  74. //将contentList的内容通过addText写入,方法与图层写入文字一致
  75. for(let i=0;i<contentList.length;i++){
  76. const {
  77. percentageTop,
  78. percentageLeft,
  79. percentageWidth,
  80. percentageHeight,
  81. richContent
  82. } = contentList[i]
  83. const position = {
  84. x:percentageLeft*100+'%',
  85. y:percentageTop*100+'%',
  86. w:percentageWidth*100+'%',
  87. h:percentageHeight*100+'%'
  88. }
  89. let textData = toTextProps(toJson(richContent))
  90. cover.addText(textData,{
  91. ...position,
  92. margin:10,
  93. fontSize:16*0.75,
  94. valign:'top'
  95. })
  96. }
  97. //不需要显示了
  98. //若contentList为空,则在右下的位置显示标题
  99. /* if(!contentList.length){
  100. cover.addText(
  101. [{text:title,options:{fontSize:28*0.75,breakLine:true}}],
  102. {
  103. x:'38%',
  104. y:'50%',
  105. w:'60%',
  106. h:'28%',
  107. color:'ffffff',
  108. align:'center',
  109. fontFace:'SimHei'
  110. })
  111. } */
  112. return cover
  113. },
  114. //获取基本配置-ppt配置
  115. async getpptConfig(){
  116. const res = await etaBaseConfigInterence.getBaseConfig()
  117. if(res.Ret!==200) return
  118. const {CnPptCoverImgs,CnPptBackgroundImg,CnPptBottomImg,PptCompanyName,PptTeamName,PptFontColor,
  119. EnPptCoverImgs,EnPptBackgroundImg,EnPptBottomImg,PptCompanyNameEn,PptTeamNameEn,PptFontColorEn
  120. } = res.Data
  121. if(this.currentLang==='en'){
  122. this.pptCoverList = EnPptCoverImgs.split(',')
  123. this.pptBgImage = EnPptBackgroundImg
  124. this.pptBackImage = EnPptBottomImg
  125. this.pptCoverCompenyName = PptCompanyNameEn
  126. this.pptCoverDepartName = PptTeamNameEn
  127. this.pptCoverTextColor = PptFontColorEn
  128. }else{
  129. this.pptCoverList = CnPptCoverImgs.split(',')
  130. this.pptBgImage = CnPptBackgroundImg
  131. this.pptBackImage = CnPptBottomImg
  132. this.pptCoverCompenyName = PptCompanyName
  133. this.pptCoverDepartName = PptTeamName
  134. this.pptCoverTextColor = PptFontColor
  135. }
  136. },
  137. //获取ppt详情
  138. async getpptDataById(id){
  139. const res = this.currentLang!=='en'?await pptInterface.getpptDetail({
  140. PptId:id
  141. }):await pptEnInterface.getpptDetail({PptId:id})
  142. if(res.Ret===200){
  143. const {
  144. Content,
  145. Title,
  146. ReportType,
  147. BackgroundImg,
  148. PptDate,
  149. TemplateType,
  150. ReportId,
  151. ModifyTime,
  152. PublishTime,
  153. Editor,
  154. CoverContent
  155. } = res.Data
  156. const pptDate = formatPPTDate(this.currentLang, PptDate)
  157. let legalContent = JSON.parse(Content)
  158. legalContent = legalContent.map(page => {
  159. page.elements = checkPPTpageElemant(page)
  160. return page
  161. })
  162. this.pptCoverContent = CoverContent
  163. this.result = {
  164. status: 200,
  165. content: legalContent,
  166. FirstPage: {
  167. Title,
  168. ReportType,
  169. BackgroundImg,
  170. PptDate: pptDate,
  171. TemplateType,
  172. },
  173. ReportId,
  174. ModifyTime,
  175. PublishTime,
  176. Editor,
  177. CoverContent
  178. }
  179. }else{
  180. this.result = {status:'',content:'获取ppt数据失败!'}
  181. }
  182. },
  183. //ppt设置相关,引用mixins.js里的setOptions chartType只有source是1才有用
  184. /* Source 1 ; chartType 1曲线 2季节 3面积 4堆积柱 5散点 6组合 7柱形 8截面散点
  185. * 2 商品价格
  186. * 3 相关性
  187. * 4 滚动相关性
  188. * 5 商品利润
  189. * 6 拟合方程
  190. * 7 统计特征/标准差
  191. * 8 统计特征/百分位
  192. * 9 统计特征/频率
  193. * 10 跨品种分析
  194. */
  195. //获取图表数据
  196. async getchartData(id,lang='ch') {
  197. const currentLang = this.currentLang || lang
  198. const res = await dataBaseInterface.getChartByCode({
  199. UniqueCode: id,
  200. IsCache:true
  201. });
  202. const { Data } = res;
  203. if(!Data) return
  204. this.chartInfo = Data.ChartInfo;
  205. if(!this.chartInfo) return
  206. if(this.chartInfo.Source === 1) { //常规图
  207. //处理下历史默认来源
  208. this.setDefaultSourceFrom();
  209. this.dataList = Data.EdbInfoList;
  210. //柱形图独立数据
  211. this.chartInfo.ChartType === 7 && this.initBarData(res.Data);
  212. //截面散点图
  213. this.chartInfo.ChartType === 10 && this.initSectionScatterData(res.Data);
  214. //雷达图
  215. this.chartInfo.ChartType === 11 && this.initRadarData(res.Data);
  216. Data.Status && ![7,10].includes(this.chartInfo.ChartType) && this.setOptions();
  217. Data.Status&&this.setOptionsLang(currentLang)
  218. }else if([2,5].includes(this.chartInfo.Source)) { //商品价格图
  219. this.chartInfo = Data.ChartInfo.Source===5 ? {
  220. ...Data.ChartInfo,
  221. ProfitNameEn: Data.DataResp.ProfitNameEn,
  222. ProfitName: Data.DataResp.ProfitName,
  223. } : Data.ChartInfo;
  224. this.dataList = [Data.EdbInfoList[0]];
  225. this.initCommodityData(res.Data)
  226. this.setCommodityLang(currentLang)
  227. }else if([3].includes(this.chartInfo.Source)){//相关性
  228. this.relevanceChartData={
  229. ChartInfo:res.Data.ChartInfo,
  230. EdbInfoList:res.Data.EdbInfoList,
  231. XEdbIdValue:this.chartInfo.Source === 3 ? res.Data.XEdbIdValue : res.Data.DataResp.XDateTimeValue,
  232. CorrelationChartInfo:res.Data.CorrelationChartInfo,
  233. YDataList:[
  234. {
  235. Value:this.chartInfo.Source === 3 ? res.Data.YDataList[0].Value : res.Data.DataResp.YDataList[0].Value,
  236. Color:'#00f',
  237. Name:res.Data.ChartInfo.ChartName,
  238. NameEn:res.Data.ChartInfo.ChartNameEn
  239. }
  240. ]
  241. }
  242. this.initRelevanceChartData()
  243. this.changeRelevanceOptions(currentLang)
  244. }else if(this.chartInfo.Source===4) {//滚动相关性换成曲线图绘图
  245. this.dataList = [res.Data.DataResp];
  246. this.relevanceChartData = {
  247. CorrelationChartInfo: res.Data.CorrelationChartInfo
  248. }
  249. this.setDefaultChart([res.Data.DataResp]);
  250. this.changeRelevanceOptions(currentLang)
  251. }else if([6,7,8].includes(this.chartInfo.Source)) {
  252. //拟合方程 标准差 百分比
  253. this.dataList = [res.Data.DataResp];
  254. this.setDefaultChart([res.Data.DataResp]);
  255. }else if(this.chartInfo.Source===9) { //统计频率
  256. this.dataList = res.Data.EdbInfoList;
  257. this.statisticFrequencyData = res.Data.DataResp;
  258. this.setStatisticFrequency();
  259. }else if(this.chartInfo.Source===10) {
  260. this.dataList = res.Data.EdbInfoList;
  261. this.crossVarietyChartData = res.Data.DataResp;
  262. this.chartLimit = {
  263. min: Number(res.Data.DataResp.YMinValue),
  264. max: Number(res.Data.DataResp.YMaxValue),
  265. x_min: Number(res.Data.DataResp.XMinValue),
  266. x_max: Number(res.Data.DataResp.XMaxValue)
  267. }
  268. this.setCrossVarietyChart();
  269. this.changeRelevanceOptions();//更改英文一样
  270. }
  271. //根据图表数据获取配置项
  272. if(Data.Status){
  273. const chartTitle = currentLang==='ch'?this.chartInfo.ChartName
  274. :this.chartInfo.ChartNameEn?this.chartInfo.ChartNameEn
  275. :this.chartInfo.ChartName
  276. //由于英文PPT复制图表名称时,使用MyChartTitle字段会复制英文名称(如果有),现需要复制中文名称,遂增加了chartTitleCN存储中文名称
  277. const otherOpts = {
  278. MyChartType:this.chartInfo.ChartType,//图表类型,和Source一起确定是什么图
  279. MyChartTitle:chartTitle,//ppt复制时的图表标题(个别类型图表渲染时也需要展示图表标题)
  280. chartTitleCN:this.chartInfo.ChartName,//英文ppt复制时,需要使用中文的图表标题......
  281. chartInfoId:this.chartInfo.ChartInfoId,//添加到我的图库,图表id
  282. MyChartClassifyId:this.chartInfo.MyChartClassifyId,//添加到我的图库,图库Id
  283. Source:this.chartInfo.Source,//图表来源,和MyChartType一起确定是什么图
  284. Instructions: this.chartInfo.Instructions,
  285. SourcesFrom: this.chartInfo.SourcesFrom,
  286. ChartThemeStyle: this.chartInfo.ChartThemeStyle
  287. }
  288. this.optionMap[id] = { ...defaultOpts, ...this.options,...otherOpts };
  289. }else{
  290. this.optionMap[id] = 'noSource'
  291. }
  292. //console.log("?", this.optionMap);
  293. },
  294. //设置图表中英文
  295. setOptionsLang(lang){
  296. console.log(lang)
  297. //中文图表不需要下面的设置
  298. if(lang==='ch') return
  299. //当 图表名称、指标名称、指标单位 有其一没有英文名称时,也不需要下面的设置
  300. if(!this.checkChartEnData()) return
  301. const {ChartType} = this.chartInfo
  302. if(ChartType!=5){
  303. this.options.yAxis.forEach(item=>{
  304. item.title.text = item.title.textEn?item.title.textEn:item.title.textCh
  305. })
  306. if(ChartType!=2)
  307. this.options.series.forEach(item=>{
  308. item.name = item.nameEn?item.nameEn:item.nameCh
  309. })
  310. if(ChartType === 7) this.options.xAxis.categories = this.barXIdData.map(_ => this.barEdbData.find(edb => edb.EdbInfoId===_).EdbNameEn);
  311. //截面散点 x轴标题
  312. if(ChartType === 10){
  313. this.options.xAxis.title.text = this.options.xAxis.title.textEn || this.options.xAxis.title.textCh;
  314. this.options.tooltip.formatter = this.options.tooltip.formatterEn || this.options.tooltip.formatterCh;
  315. this.options.series.forEach(item => {
  316. if(!item.linkedTo) {
  317. item.data.forEach(point => {
  318. point.dataLabels.format = point.dataLabels.formatEn || point.dataLabels.formatCh;
  319. })
  320. }
  321. });
  322. }
  323. }
  324. //散点图
  325. if(ChartType==5){
  326. this.options.yAxis.title.text = this.options.yAxis.title.textEn
  327. this.options.yAxis.title.style = this.options.yAxis.title.styleEn||{}
  328. this.options.xAxis.title.text = this.options.xAxis.title.textEn
  329. this.options.xAxis.title.style = this.options.xAxis.title.styleEn||{}
  330. this.options.series.forEach(item => {
  331. item.name = item.nameEn
  332. });
  333. this.options.tooltip.formatter = this.options.tooltip.formatterEn
  334. }
  335. },
  336. /* 设置价格曲线英文 */
  337. setCommodityLang(lang) {
  338. if(lang==='ch') return
  339. //当 图表名称、指标名称、指标单位 有其一没有英文名称时,也不需要下面的设置
  340. if(!this.checkChartEnData()) return
  341. this.options.yAxis.forEach(item => {
  342. item.title.text = item.title.textEn || item.title.textCh
  343. });
  344. //图例
  345. this.options.series.forEach(item => {
  346. item.name = item.nameEn || item.nameCh
  347. });
  348. //tooltip
  349. this.options.tooltip.formatter = this.options.tooltip.formatterEn
  350. //x轴
  351. this.options.xAxis.categories = this.commodityXData.map(_ => _.NameEn);
  352. },
  353. /* 切换相关性图中英文 */
  354. changeRelevanceOptions(lang){
  355. if(lang==='ch') return
  356. if(!this.checkChartEnData()) return
  357. console.log(this.options)
  358. this.options.yAxis.forEach(item => {
  359. item.title.text = item.title.textEn || item.title.textCh
  360. });
  361. //图例
  362. this.options.series.forEach(item => {
  363. item.name = item.nameEn || item.nameCh
  364. });
  365. //tooltip
  366. this.options.tooltip.formatter = this.options.tooltip.formatterEn
  367. this.options.xAxis.title.text=this.options.xAxis.title.textEn
  368. },
  369. /* 历史图表默认显示图表来源 d毛后端不修复只能自己每次详情处理下*/
  370. setDefaultSourceFrom() {
  371. if(!this.chartInfo.SourcesFrom) {
  372. let themeOpt = JSON.parse(this.chartInfo.ChartThemeStyle);
  373. this.chartInfo.SourcesFrom = JSON.stringify({
  374. isShow: true,
  375. text: this.chartInfo.ChartSource,
  376. color: themeOpt&&themeOpt.markerOptions.style.color,
  377. fontSize: themeOpt&&themeOpt.markerOptions.style.fontSize
  378. });
  379. }
  380. },
  381. //检查图表英文配置是否完整
  382. checkChartEnData(){
  383. let result = true
  384. //图表名称:this.chartInfo.ChartNameEn
  385. if(!this.chartInfo.ChartNameEn){
  386. result = false
  387. }
  388. if(this.chartInfo.Source === 10) {
  389. const { XNameEn,YNameEn,DataList } = this.crossVarietyChartData;
  390. let haveOneNoEn = DataList.some(_ =>!_.NameEn);
  391. if(haveOneNoEn || !XNameEn || !YNameEn) result = false
  392. }else {
  393. //指标名称:this.dataList[].EdbNameEn
  394. //指标单位:this.dataList[].UnitEn
  395. this.dataList.forEach(item=>{
  396. if(!item.EdbNameEn){
  397. result = false
  398. }
  399. if(this.chartInfo.ChartType!==10&&item.Unit&&!item.UnitEn){
  400. result = false
  401. }
  402. })
  403. }
  404. return result
  405. },
  406. //刷新图表数据
  407. async getRefreshChart(id){
  408. const res = await dataBaseInterface.chartRefresh({
  409. UniqueCode:id
  410. })
  411. if(res.Ret!==200){
  412. return
  413. }
  414. },
  415. //打开添加到我的图库弹窗
  416. async handleAddChartToGallery(chartId){
  417. const chartInfo = this.$store.state.ppt.chartInfoMap[chartId]
  418. this.addChartId = chartId
  419. this.addChartInfoId = chartInfo.chartInfoId
  420. this.addChartClassifyIds = chartInfo.MyChartClassifyId ? chartInfo.MyChartClassifyId.split(',').map(item => Number(item)) : [];
  421. this.addMyChartShow = true
  422. },
  423. //添加到我的图库,就是改一下chartInfo的MyChartClassifyId
  424. addChartToGallery({MyChartClassifyId}){
  425. let chartInfoMap = _.cloneDeep(this.$store.state.ppt.chartInfoMap)
  426. chartInfoMap[this.addChartId].MyChartClassifyId = MyChartClassifyId
  427. this.$store.commit('SET_CHART_INFO_MAP',chartInfoMap)
  428. this.addMyChartShow = false
  429. },
  430. //编辑ppt时,初始化相关
  431. async initPageElements(page,type="edit",only=false) {
  432. this.pptInitType = type
  433. const chartElements = page.elements.filter((item) => {
  434. return item.type === "chart";
  435. });
  436. const imageElements = page.elements.filter((item) => {
  437. return item.type === "image";
  438. });
  439. const textElements = page.elements.filter((item)=>{
  440. return item.type === 'text'
  441. })
  442. const sheetElements = page.elements.filter((item)=>{
  443. return item.type === 'sheet'
  444. })
  445. if(type==='edit'){
  446. this.initTexts(textElements,page)
  447. }
  448. this.initImages(imageElements,page);
  449. await this.sheetListHandle(sheetElements);
  450. this.initSheets(sheetElements,page,only)
  451. await this.listHandle(chartElements);
  452. this.initCharts(chartElements, page);
  453. },
  454. async listHandle(chartElements) {
  455. for(let i=0;i<chartElements.length;i++) {
  456. if(!this.optionMap[chartElements[i].chartId])
  457. await this.getchartData(chartElements[i].chartId);
  458. }
  459. },
  460. async sheetListHandle(sheetElements){
  461. for(let i=0;i<sheetElements.length;i++){
  462. if(!this.sheetDataMap[sheetElements[i].sheetId])
  463. await this.getsheetData(sheetElements[i].sheetId)
  464. }
  465. },
  466. async getsheetData(id){
  467. const res = await sheetInterface.getSheetData({
  468. UniqueCode: id
  469. })
  470. if(res.Ret !== 200) return 0
  471. const {TableInfo} = res.Data
  472. console.log('get')
  473. this.sheetDataMap[id] = _.cloneDeep(TableInfo.TableDataList)
  474. return 1
  475. },
  476. initCharts(elements, page) {
  477. const index = this.pageList.findIndex((i) => i.id === page.id)
  478. if(index===-1) return
  479. elements.forEach((item) => {
  480. if (this.optionMap[item.chartId] instanceof Object){
  481. this.initChart(
  482. `chart_${index}_${item.position}`,
  483. this.optionMap[item.chartId],
  484. page
  485. )
  486. }else{
  487. //显示图表已被删除
  488. this.initImage(
  489. `#img_${index}_${item.position}`,
  490. "https://hzstatic.hzinsights.com/static/ppt_default.png"
  491. )
  492. }
  493. });
  494. },
  495. initChart(refName, options, page) {
  496. console.log("refName", refName);
  497. const index = this.pageList.findIndex((i) => i.id === page.id)
  498. if(index===-1) return
  499. //if(!this.$refs[`pptPage_${index}`]||!this.$refs[`pptPage_${index}`][0]) return
  500. /* if(!$(`#${refName}`)[0]) return */
  501. /*
  502. Source:1
  503. MyChartType: 2 季节性图,7 柱形图, 10 截面散点图,
  504. Source:2
  505. MyChartType: 8 商品价格曲线图
  506. Source:5
  507. MyChartType: 8 利润曲线
  508. Source:6 拟合方程曲线
  509. Source:7 统计特征
  510. 以上图表需要显示标题
  511. */
  512. const {Source,MyChartType,ChartThemeStyle} = options
  513. const isShowTitle = isShowPPTTitle(Source,MyChartType)
  514. /* 主题样式*/
  515. const chartTheme = ChartThemeStyle ? JSON.parse(ChartThemeStyle) : null;
  516. this.$nextTick(() => {
  517. let is_linear = options.series
  518. ? options.series.some(_ => _.chartType === 'linear')
  519. : false ;
  520. //title样式
  521. let titleHTML = null
  522. //中英文发布页需设置title换行
  523. //一行可容纳的中文字体数
  524. let count = parseInt($(`#${refName}`)[0].offsetWidth / 19)*2;
  525. let {total,newStr} = getStrSize(options.MyChartTitle,count)
  526. const isPublish = this.$route.path==='/pptpublish'||this.$route.path==='/pptenpublish'
  527. if(isShowTitle){
  528. titleHTML = `<div style="
  529. text-align:${chartTheme&&chartTheme.titleOptions.align};
  530. font-size:${chartTheme&&chartTheme.titleOptions.style.fontSize}px;
  531. color:${chartTheme&&chartTheme.titleOptions.style.color};
  532. height:18px;
  533. ">
  534. ${options.MyChartTitle}
  535. </div>`
  536. }
  537. const titleOption = isPublish&&isShowTitle?{marginTop:25}:{}
  538. let SpecialOption = {
  539. chart: {
  540. ...defaultOpts.chart,
  541. ...chartTheme&&chartTheme.drawOption,
  542. spacing: chartTheme.legendOptions.verticalAlign==='bottom' ? [23,10,2,10] : [2,10,2,10],//图例在底部顶部空间留大点给单位
  543. animation: false,
  544. backgroundColor: "rgba(0,0,0,0)",
  545. renderTo:$(`#${refName}`)[0],
  546. ...options.chart||{},
  547. ...titleOption
  548. },
  549. legend: {
  550. ...defaultOpts.legend,
  551. ...chartTheme&&chartTheme.legendOptions
  552. },
  553. colors: options.colors||chartTheme&&chartTheme.colorsOptions||defaultOpts.colors,
  554. title: isPublish?{
  555. text: isShowTitle?newStr:null,
  556. margin:0,
  557. useHTML:false,
  558. floating:true,
  559. style:{...chartTheme&&chartTheme.titleOptions.style},
  560. align: (chartTheme&&chartTheme.titleOptions.align) || (total>count?'left':'center'),
  561. }:{
  562. text: titleHTML,
  563. useHTML:true,
  564. margin:0,
  565. style:{textAlign:chartTheme&&chartTheme.titleOptions.align,left:0,width:'100%'}
  566. },
  567. plotOptions: {
  568. ...defaultOpts.plotOptions,
  569. series: {
  570. animation: false,
  571. turboThreshold: 0, //不限制数据点个数
  572. dataGrouping: {
  573. enabled: false,
  574. }
  575. },
  576. },
  577. }
  578. //奇怪柱不堆叠
  579. let secialBarOpt = (options.series.some(_ => _.chartType === 'linear') && options.series.some(_ => _.chartType === 'linear')) ? {
  580. plotOptions: {
  581. ...defaultOpts.plotOptions,
  582. column:{
  583. stacking: null,
  584. },
  585. },
  586. } : {};
  587. if(!$(`#${refName}`)[0]) return
  588. if(is_linear)
  589. Highcharts.chart({
  590. // Highcharts 配置
  591. ...options,
  592. ...SpecialOption,
  593. ...secialBarOpt
  594. });
  595. else
  596. Highcharts.stockChart({
  597. // Highcharts 配置
  598. ...options,
  599. ...SpecialOption,
  600. ...secialBarOpt
  601. });
  602. });
  603. },
  604. initImages(elements,page){
  605. const index = this.pageList.findIndex((i) => i.id === page.id)
  606. elements.forEach((item)=>{
  607. this.initImage(`#image_${index}_${item.position}`,item.src)
  608. })
  609. },
  610. initImage(idName,url){
  611. //console.log('idName',idName,'url',url)
  612. $(`${idName}`).hide()
  613. this.$nextTick(()=>{
  614. $(`${idName}`).attr('src',url).attr('object-fit','scale-down')
  615. $(`${idName}`).show()
  616. })
  617. },
  618. initTexts(elements,page){
  619. const index = this.pageList.findIndex((i) => i.id === page.id)
  620. elements.forEach((item)=>{
  621. this.initText(index,`text_${index}_${item.position}`)
  622. })
  623. },
  624. initText(pageindex,refName){
  625. console.log(`pptPage_${pageindex}`,refName)
  626. this.$nextTick(()=>{
  627. this.$refs[`pptPage_${pageindex}`][0].$refs[refName].initTiny()
  628. })
  629. },
  630. initSheets(elements,page,only){
  631. const index = this.pageList.findIndex((i) => i.id === page.id)
  632. this.$nextTick(()=>{
  633. const formatRef = only?this.$refs[`pptPage_${index}`]:this.$refs[`pptPage_${index}`][0]
  634. elements.forEach((item)=>{
  635. this.initSheet(formatRef,`sheet_${index}_${item.position}`,item.sheetId)
  636. })
  637. })
  638. },
  639. initSheet($parent,refName,sheetId,type='init'){
  640. console.log('init sheet',refName)
  641. const $children = $parent.$children
  642. /* console.log('children',$children) */
  643. this.$nextTick(()=>{
  644. const sheet = $children.find(i=>i.$data.type==='sheet'&&i.item.sheetId===sheetId)
  645. sheet&&sheet.getSheetData(sheetId,this.sheetDataMap[sheetId])
  646. })
  647. if(this.pptInitType!=='edit'||refName.includes('preview')) return
  648. this.$nextTick(()=>{
  649. if(type==='init')
  650. !this.sheetHeightMap[sheetId]&&this.initSheetIframe(refName,sheetId)
  651. else
  652. this.initSheetIframe(refName,sheetId)
  653. this.sheetHeightMap[sheetId]&&this.setSheetElHeight(refName,sheetId)
  654. })
  655. },
  656. //加载iframe
  657. initSheetIframe(idName,sheetId){
  658. console.log('init sheet iframe',idName)
  659. const LINK_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/sheetshow';
  660. $(`#${idName}`).append(`<iframe
  661. src='${LINK_URL}?code=${sheetId}'
  662. width='100%'
  663. height='0'
  664. class='sheet-iframe-box'
  665. style='border-width:0px;'
  666. />
  667. `)
  668. },
  669. //获取表格iframe的高度,用于ppt转报告
  670. reInitIframe(e) {
  671. const LINK_URLS=[this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow',this.$setting.dynamicOutLinks.ChartViewUrl+'/sheetshow']
  672. if(!LINK_URLS.includes(e.origin)) return
  673. /* console.log('iframe加载完成',e.data) */
  674. const { height,code } = e.data;
  675. this.sheetHeightMap[code] = height
  676. this.pageList.forEach((page,pageIndex)=>{
  677. page.elements.map(el=>{
  678. if(el.type==='sheet'&&el.sheetId===code){
  679. el.sheetHeight = height+45+'px'
  680. //sheet_pageIndex_el.position
  681. const sheet = document.getElementById(`sheet_${pageIndex}_${el.position}`)
  682. //console.log(sheet.childNodes)
  683. sheet.childNodes&&sheet.childNodes.forEach(node=>{
  684. //iframe获取完高度就可以删除 留着占内存
  685. if(node.nodeName.toLocaleLowerCase()==='iframe'){
  686. sheet.removeChild(node)
  687. }
  688. })
  689. }
  690. })
  691. })
  692. },
  693. //设置表格元素的高,用于ppt转报告
  694. setSheetElHeight(idName,sheetId){
  695. const arr = idName.split('_')
  696. const pageIndex = arr[1],position = arr[2]
  697. this.pageList[pageIndex].elements.map(i=>{
  698. if(i.position==position){
  699. i.sheetHeight = this.sheetHeightMap[sheetId]+45+'px'
  700. }
  701. })
  702. },
  703. /* 设置英文配置 */
  704. async setEnHandle({UniqueCode}) {
  705. this.formItemArray={ chartInfo: [],chartsList: [] }
  706. const { Ret,Data } = await dataBaseInterface.getChartByCode({UniqueCode});
  707. if (Ret !== 200) return;
  708. let chartInfo = Data.ChartInfo;
  709. let tableData = chartInfo.Source===1 ? Data.EdbInfoList : [Data.EdbInfoList[0]];
  710. this.enChartInfo = chartInfo;
  711. this.enEdblist = tableData;
  712. this.formItemArray.chartInfo.push({
  713. label:'图表名称',
  714. value:chartInfo.ChartName,
  715. key:'ChartName',
  716. id:chartInfo.ChartInfoId,
  717. source: chartInfo.Source,
  718. notEdit:true
  719. },
  720. {
  721. label:'英文图表名称',
  722. value:chartInfo.ChartNameEn,
  723. key:'ChartNameEn',
  724. id:chartInfo.ChartInfoId,
  725. placeholder:'请输入英文图表名称'
  726. })
  727. if([1,2,5].includes(chartInfo.Source)){
  728. this.formItemArray.chartsList = tableData.map(item => {
  729. return item.Unit
  730. ? [
  731. {
  732. label:'指标名称',
  733. value:item.EdbName,
  734. key:'EdbName',
  735. id:item.EdbInfoId,
  736. notEdit:true
  737. },
  738. {
  739. label:'单位',
  740. value:item.Unit,
  741. key:'Unit',
  742. id:item.EdbInfoId,
  743. notEdit:true
  744. },
  745. {
  746. label:'英文指标名称',
  747. value:item.EdbNameEn,
  748. key:'EdbNameEn',
  749. id:item.EdbInfoId,
  750. placeholder:'请输入英文指标名称'
  751. },
  752. {
  753. label:'英文单位',
  754. value:item.UnitEn,
  755. key:'UnitEn',
  756. id:item.EdbInfoId,
  757. placeholder:'请输入英文单位'
  758. }
  759. ]
  760. : [
  761. {
  762. label:'指标名称',
  763. value:item.EdbName,
  764. key:'EdbName',
  765. id:item.EdbInfoId,
  766. notEdit:true
  767. },
  768. {
  769. label:'英文指标名称',
  770. value:item.EdbNameEn,
  771. key:'EdbNameEn',
  772. id:item.EdbInfoId,
  773. placeholder:'请输入英文指标名称'
  774. }
  775. ]
  776. })
  777. }
  778. //价格曲线
  779. if(chartInfo.Source===2) {
  780. this.formItemArray.chartInfo.push({
  781. label:'期货名称',
  782. value:Data.EdbInfoList[1].EdbName,
  783. key:'FutureGoodName',
  784. id:chartInfo.ChartInfoId,
  785. notEdit:true
  786. },
  787. {
  788. label:'英文期货名称',
  789. value:Data.EdbInfoList[1].EdbNameEn,
  790. key:'FutureGoodNameEn',
  791. id:chartInfo.ChartInfoId,
  792. placeholder:'请输入英文期货名称'
  793. })
  794. }
  795. //利润曲线
  796. else if(chartInfo.Source===5) {
  797. this.formItemArray.chartInfo.push({
  798. label:'盘面利润名称',
  799. value:Data.DataResp.ProfitName,
  800. key:'ProfitName',
  801. id:chartInfo.ChartInfoId,
  802. notEdit:true
  803. },
  804. {
  805. label:'英文盘面利润名称',
  806. value:Data.DataResp.ProfitNameEn,
  807. key:'ProfitNameEn',
  808. id:chartInfo.ChartInfoId,
  809. placeholder:'请输入英文盘面利润名称'
  810. })
  811. }
  812. //跨品种分析
  813. else if(chartInfo.Source===10) {
  814. let res = await crossVarietyInterface.chartLangOption({ChartInfoId: chartInfo.ChartInfoId})
  815. const { TagList,VarietyList } = res.Data;
  816. this.formItemArray.chartInfo.push({
  817. label:'X轴名称',
  818. value:Data.DataResp.XName,
  819. key:'XName',
  820. id:TagList[0].ChartTagId,
  821. notEdit:true
  822. },
  823. {
  824. label:'英文X轴名称',
  825. value:Data.DataResp.XNameEn,
  826. key:'XNameEn',
  827. id:TagList[0].ChartTagId,
  828. placeholder:'请输入英文X轴名称'
  829. },{
  830. label:'Y轴名称',
  831. value:Data.DataResp.YName,
  832. key:'YName',
  833. id:TagList[1].ChartTagId,
  834. notEdit:true
  835. },
  836. {
  837. label:'英文Y轴名称',
  838. value:Data.DataResp.YNameEn,
  839. key:'YNameEn',
  840. id:TagList[1].ChartTagId,
  841. placeholder:'请输入英文Y轴名称'
  842. })
  843. VarietyList.forEach(item => {
  844. this.formItemArray.chartsList.push([
  845. {
  846. label:'品种名称',
  847. value:item.ChartVarietyName,
  848. key:'ChartVarietyName',
  849. id:item.ChartVarietyId,
  850. notEdit:true
  851. },
  852. {
  853. label:'英文品种名称',
  854. value:item.ChartVarietyNameEn,
  855. key:'ChartVarietyNameEn',
  856. id:item.ChartVarietyId,
  857. placeholder:'请输入英文品种名称'
  858. }
  859. ])
  860. })
  861. }
  862. this.setEnName = true
  863. },
  864. // 更新英文信息
  865. async updateEnName(enNameData){
  866. let res=null
  867. if(this.chart_source === 1){
  868. res=await dataBaseInterface.chartInfoEditEn(enNameData)
  869. }else if([2,5].includes(this.chart_source)){
  870. res=await futuresInterface.editChartEn({
  871. ChartInfoId: enNameData.ChartInfoId,
  872. ChartNameEn: enNameData.ChartNameEn,
  873. UnitEn: enNameData.ChartEdbInfoList[0].UnitEn || '',
  874. EdbNameEn: enNameData.ChartEdbInfoList[0].EdbNameEn || '',
  875. FutureGoodNameEn: enNameData.FutureGoodNameEn || '',
  876. ProfitNameEn: enNameData.ProfitNameEn || ''
  877. })
  878. }else if(this.chart_source === 3){
  879. res=await chartRelevanceApi.editChartEn({
  880. ChartInfoId: enNameData.ChartInfoId,
  881. ChartNameEn: enNameData.ChartNameEn
  882. })
  883. }else if(this.chart_source===6){//拟合方程
  884. res=await fittingEquationInterface.editChartEn({
  885. ChartInfoId: enNameData.ChartInfoId,
  886. ChartNameEn: enNameData.ChartNameEn
  887. })
  888. }else if(this.chart_source===7){//统计特征
  889. res=await statisticFeatureInterface.editChartEn({
  890. ChartInfoId: enNameData.ChartInfoId,
  891. ChartNameEn: enNameData.ChartNameEn
  892. })
  893. }else if(this.chart_source===10) {//跨品种分析
  894. res=await crossVarietyInterface.editChartEn(enNameData)
  895. }
  896. if(res.Ret !==200) return
  897. this.$message({
  898. message:res.Msg,
  899. type:"success"
  900. })
  901. this.setEnName = false
  902. },
  903. /* 生成ppt时图表追加底部文字 来源/说明 */
  904. transChartBottomInfo(slide,{x,y,width,height},data) {
  905. let chartData = data;
  906. let yPercent = Number(Math.ceil(height.replace(/%/,''))+Math.ceil(y.replace(/%/,'')))+'%';
  907. // console.log(yPercent)
  908. if(chartData.SourcesFrom&&JSON.parse(chartData.SourcesFrom).isShow) {
  909. let sourceObj = JSON.parse(chartData.SourcesFrom);
  910. slide.addText(`来源:${sourceObj.text}`,{
  911. x:x,
  912. y: yPercent,
  913. w: width,
  914. margin:10,
  915. fontSize: sourceObj.fontSize*0.75,
  916. color: sourceObj.color.includes('rgb') ? rgbaToHex(sourceObj.color).color.substring(1) : sourceObj.color.indexOf('#')===0 ? sourceObj.color.substring(1): '666',
  917. })
  918. }
  919. if(chartData.Instructions&&JSON.parse(chartData.Instructions).isShow) {
  920. let instructObj = JSON.parse(chartData.Instructions);
  921. slide.addText(instructObj.text,{
  922. x:x,
  923. y: yPercent,
  924. w: width,
  925. align:'right',
  926. margin:10,
  927. fontSize: instructObj.fontSize*0.75,
  928. color: instructObj.color.includes('rgb') ? rgbaToHex(instructObj.color).color.substring(1) : instructObj.color.indexOf('#')===0 ? instructObj.color.substring(1): '666',
  929. })
  930. }
  931. }
  932. },
  933. mounted(){
  934. this.getpptConfig()
  935. }
  936. }