Commit 09b8a3f59ec2bfcd135d6cd7a5e9948c7a9d9b31

Authored by 徐烜
1 parent 7e7c73ce

闵行公交电子站牌页面组件化

1、新建mggj/list目录,添加mhgj-eBusStop-line-chart-list相关组件
front-end/h5/src/components/core/plugins/bsth/lggj/list/models/eBusStop-line-chart-list-scrollPage-innerData.js
@@ -34,6 +34,10 @@ class EBusStopLineChartListScrollPageInnerDataItem { @@ -34,6 +34,10 @@ class EBusStopLineChartListScrollPageInnerDataItem {
34 return this._height 34 return this._height
35 } 35 }
36 36
  37 + get top () {
  38 + return this._cssTop
  39 + }
  40 +
37 /** 41 /**
38 * 使用类本身对象创建。 42 * 使用类本身对象创建。
39 * @param dataItem EBusStopLineChartListScrollPageInnerDataItem 43 * @param dataItem EBusStopLineChartListScrollPageInnerDataItem
front-end/h5/src/components/core/plugins/bsth/mhgj/chart/css/mhgj-eBusStop-line-chart.css
@@ -68,7 +68,7 @@ svg.mhgj-eBusStop-line-chart g.part g.content1Bound text.content1 { @@ -68,7 +68,7 @@ svg.mhgj-eBusStop-line-chart g.part g.content1Bound text.content1 {
68 text-shadow: 0 0 2px #dadada; 68 text-shadow: 0 0 2px #dadada;
69 Pointer-events: none; 69 Pointer-events: none;
70 } 70 }
71 -svg.mhgj-eBusStop-line-chart g.part g.content1Bound { 71 +svg.mhgj-eBusStop-line-chart g.part g.content2Bound {
72 } 72 }
73 svg.mhgj-eBusStop-line-chart g.part g.content2Bound text.content2 { 73 svg.mhgj-eBusStop-line-chart g.part g.content2Bound text.content2 {
74 font-size: 28px; 74 font-size: 28px;
@@ -135,6 +135,39 @@ svg.mhgj-eBusStop-line-chart g.part g.content6Bound text.content6_right { @@ -135,6 +135,39 @@ svg.mhgj-eBusStop-line-chart g.part g.content6Bound text.content6_right {
135 Pointer-events: none; 135 Pointer-events: none;
136 } 136 }
137 137
  138 +svg.mhgj-eBusStop-line-chart g.part g.content7Bound1 {
  139 +}
  140 +svg.mhgj-eBusStop-line-chart g.part g.content7Bound1 text.content7_1_left {
  141 + font-size: 80px;
  142 + font-weight: bold;
  143 + fill: #cd2a40;
  144 + letter-spacing: -.2px;
  145 + text-shadow: 0 0 2px #dadada;
  146 + Pointer-events: none;
  147 +}
  148 +svg.mhgj-eBusStop-line-chart g.part g.content7Bound text.content7_1_right {
  149 + font-size: 20px;
  150 + letter-spacing: -.2px;
  151 + text-shadow: 0 0 2px #dadada;
  152 + Pointer-events: none;
  153 +}
  154 +svg.mhgj-eBusStop-line-chart g.part g.content7Bound2 {
  155 +}
  156 +svg.mhgj-eBusStop-line-chart g.part g.content7Bound2 text.content7_2_left {
  157 + font-size: 80px;
  158 + font-weight: bold;
  159 + fill: #cd2a40;
  160 + letter-spacing: -.2px;
  161 + text-shadow: 0 0 2px #dadada;
  162 + Pointer-events: none;
  163 +}
  164 +svg.mhgj-eBusStop-line-chart g.part g.content7Bound2 text.content7_2_right {
  165 + font-size: 20px;
  166 + letter-spacing: -.2px;
  167 + text-shadow: 0 0 2px #dadada;
  168 + Pointer-events: none;
  169 +}
  170 +
138 /** part3用 */ 171 /** part3用 */
139 svg.mhgj-eBusStop-line-chart g.part g.contentAllBound { 172 svg.mhgj-eBusStop-line-chart g.part g.contentAllBound {
140 } 173 }
front-end/h5/src/components/core/plugins/bsth/mhgj/chart/mhgj-eBusStop-line-chart.js
@@ -9,7 +9,7 @@ import './css/mhgj-eBusStop-line-chart.css' @@ -9,7 +9,7 @@ import './css/mhgj-eBusStop-line-chart.css'
9 import CarIcon from './svgicon/car.svg' 9 import CarIcon from './svgicon/car.svg'
10 10
11 import Utils from 'core/plugins/bsth/bsth-utils' 11 import Utils from 'core/plugins/bsth/bsth-utils'
12 -import { MhgjEBusStopLineChartData } from 'core/plugins/bsth/mhgj/chart/models/MhgjEBusStopLineChartData' 12 +import { MhgjEBusStopLineChartData } from 'core/plugins/bsth/mhgj/chart/models/mhgjEBusStopLineChartData'
13 13
14 export default { 14 export default {
15 extra: { 15 extra: {
@@ -105,21 +105,23 @@ export default { @@ -105,21 +105,23 @@ export default {
105 _flag_3_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层线路信息css属性" class="bsth-line-item-divider"></hr>) } }), 105 _flag_3_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层线路信息css属性" class="bsth-line-item-divider"></hr>) } }),
106 part1_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 106 part1_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
107 part1_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }), 107 part1_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  108 + part1_line_icon_width: PropTypes.number({ label: '线路图标宽度', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
  109 + part1_line_icon_height: PropTypes.number({ label: '线路图标高度', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
108 part1_line_name_font_size: PropTypes.number({ label: '线路名称字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }), 110 part1_line_name_font_size: PropTypes.number({ label: '线路名称字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
109 part1_line_name_font_color: PropTypes.color({ label: '线路名称字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }), 111 part1_line_name_font_color: PropTypes.color({ label: '线路名称字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
110 part1_terminal_stop_font_size: PropTypes.number({ label: '开往站点字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }), 112 part1_terminal_stop_font_size: PropTypes.number({ label: '开往站点字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
111 part1_terminal_stop_font_color: PropTypes.color({ label: '开往站点字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }), 113 part1_terminal_stop_font_color: PropTypes.color({ label: '开往站点字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
112 _flag_4_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层本班车信息css属性" class="bsth-line-item-divider"></hr>) } }), 114 _flag_4_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层本班车信息css属性" class="bsth-line-item-divider"></hr>) } }),
113 part2_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 115 part2_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
114 - part2_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }), 116 + part2_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 1, layout: { prefixCls: 'bsth-line' } }),
115 part2_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }), 117 part2_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
116 part2_title1_font_color: PropTypes.color({ label: '标题1字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }), 118 part2_title1_font_color: PropTypes.color({ label: '标题1字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
117 part2_title1_background_color: PropTypes.color({ label: '标题1背景颜色', defaultValue: '#acd48e', layout: { prefixCls: 'bsth-line' } }), 119 part2_title1_background_color: PropTypes.color({ label: '标题1背景颜色', defaultValue: '#acd48e', layout: { prefixCls: 'bsth-line' } }),
118 part2_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }), 120 part2_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
119 part2_title2_font_color: PropTypes.color({ label: '标题2字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }), 121 part2_title2_font_color: PropTypes.color({ label: '标题2字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
120 part2_title2_background_color: PropTypes.color({ label: '标题2背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 122 part2_title2_background_color: PropTypes.color({ label: '标题2背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
121 - part2_arrival_time_font_size: PropTypes.number({ label: '到达时间字体大小', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),  
122 - part2_arrival_time_font_color: PropTypes.color({ label: '到达时间字体颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 123 + part2_arrival_time_font_size: PropTypes.number({ label: '到达时间字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
  124 + part2_arrival_time_font_color: PropTypes.color({ label: '到达时间字体颜色', defaultValue: '#cd2a40', layout: { prefixCls: 'bsth-line' } }),
123 part2_arrival_time_minutes_left_font_size: PropTypes.number({ label: '到达时间(分钟)左边字体大小', defaultValue: 80, layout: { prefixCls: 'bsth-line' } }), 125 part2_arrival_time_minutes_left_font_size: PropTypes.number({ label: '到达时间(分钟)左边字体大小', defaultValue: 80, layout: { prefixCls: 'bsth-line' } }),
124 part2_arrival_time_minutes_left_font_color: PropTypes.color({ label: '到达时间(分钟)左边字体颜色', defaultValue: '#cd2a40', layout: { prefixCls: 'bsth-line' } }), 126 part2_arrival_time_minutes_left_font_color: PropTypes.color({ label: '到达时间(分钟)左边字体颜色', defaultValue: '#cd2a40', layout: { prefixCls: 'bsth-line' } }),
125 part2_arrival_time_minutes_right_font_size: PropTypes.number({ label: '到达时间(分钟)右边字体大小', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }), 127 part2_arrival_time_minutes_right_font_size: PropTypes.number({ label: '到达时间(分钟)右边字体大小', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),
@@ -130,14 +132,14 @@ export default { @@ -130,14 +132,14 @@ export default {
130 part2_from_stops_right_font_color: PropTypes.color({ label: '距离本站(几站)右边字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }), 132 part2_from_stops_right_font_color: PropTypes.color({ label: '距离本站(几站)右边字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
131 _flag_5_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层下一班车信息css属性" class="bsth-line-item-divider"></hr>) } }), 133 _flag_5_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层下一班车信息css属性" class="bsth-line-item-divider"></hr>) } }),
132 part3_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 134 part3_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
133 - part3_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }), 135 + part3_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 1, layout: { prefixCls: 'bsth-line' } }),
134 part3_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }), 136 part3_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
135 part3_title1_font_color: PropTypes.color({ label: '标题1字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }), 137 part3_title1_font_color: PropTypes.color({ label: '标题1字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
136 part3_title1_background_color: PropTypes.color({ label: '标题1背景颜色', defaultValue: '#7dc6fe', layout: { prefixCls: 'bsth-line' } }), 138 part3_title1_background_color: PropTypes.color({ label: '标题1背景颜色', defaultValue: '#7dc6fe', layout: { prefixCls: 'bsth-line' } }),
137 part3_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }), 139 part3_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
138 part3_title2_font_color: PropTypes.color({ label: '标题2字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }), 140 part3_title2_font_color: PropTypes.color({ label: '标题2字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
139 part3_title2_background_color: PropTypes.color({ label: '标题2背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 141 part3_title2_background_color: PropTypes.color({ label: '标题2背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
140 - part3_arrival_time_font_size: PropTypes.number({ label: '到达时间字体大小', defaultValue: 80, layout: { prefixCls: 'bsth-line' } }), 142 + part3_arrival_time_font_size: PropTypes.number({ label: '到达时间字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
141 part3_arrival_time_font_color: PropTypes.color({ label: '到达时间字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }) 143 part3_arrival_time_font_color: PropTypes.color({ label: '到达时间字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } })
142 144
143 }, 145 },
@@ -264,21 +266,21 @@ export default { @@ -264,21 +266,21 @@ export default {
264 self.component_height = val - self.margin_top - self.margin_bottom 266 self.component_height = val - self.margin_top - self.margin_bottom
265 } 267 }
266 }, 268 },
267 - eBusStopData_child: function (val) {  
268 - let self = this  
269 - if (self.useMode === 'child') {  
270 - self.eBusStopData_child = val  
271 - }  
272 - },  
273 269
274 //------------- data方法中绑定的数据监控 --------------------// 270 //------------- data方法中绑定的数据监控 --------------------//
275 // ----------- 数据属性 ----------- // 271 // ----------- 数据属性 ----------- //
276 - eBusStopData: function (currentVal, oldVal) {  
277 - let self = this  
278 - if (!Utils.objectEquals(currentVal, oldVal)) { 272 + eBusStopData: { // 使用deep检测所有属性变化
  273 + handler (currentVal, oldVal) {
  274 + let self = this
  275 + // TODO:这里objectEquals有点问题,暂时不用了
  276 + // if (!Utils.objectEquals(currentVal, oldVal)) {
  277 + // self.refreshSvg()
  278 + // }
279 self.refreshSvg() 279 self.refreshSvg()
280 - } 280 + },
  281 + deep: true
281 }, 282 },
  283 +
282 // ------------ 本身宽高 ----------- // 284 // ------------ 本身宽高 ----------- //
283 component_width () { 285 component_width () {
284 let self = this 286 let self = this
@@ -326,117 +328,223 @@ export default { @@ -326,117 +328,223 @@ export default {
326 328
327 //---------- 图内层css监控 --------// 329 //---------- 图内层css监控 --------//
328 // part1 线路信息,对应_flag_3_属性集合 330 // part1 线路信息,对应_flag_3_属性集合
329 - part1_background_color () {  
330 - let self = this;  
331 - // TODO: 331 + part1_background_color (val) {
  332 + let svg = this.private_svg
  333 + svg.selectAll('g.part:nth-child(1) rect.main')
  334 + .style('fill', val)
332 }, 335 },
333 - part1_border_size () {  
334 - let self = this;  
335 - // TODO: 336 + part1_border_size (val) {
  337 + let svg = this.private_svg
  338 + svg.selectAll('g.part:nth-child(1) rect.main')
  339 + .style('stroke-width', val)
336 }, 340 },
337 - part1_line_name_font_size () {  
338 - let self = this;  
339 - // TODO: 341 + part1_line_icon_width () {
  342 + let self = this
  343 + self.refreshSvg()
340 }, 344 },
341 - part1_line_name_font_color () {  
342 - let self = this;  
343 - // TODO: 345 + part1_line_icon_height () {
  346 + let self = this
  347 + self.refreshSvg()
344 }, 348 },
345 - part1_terminal_stop_font_size () {  
346 - let self = this;  
347 - // TODO: 349 + part1_line_name_font_size (val) {
  350 + let svg = this.private_svg
  351 + svg.selectAll('g.part:nth-child(1) g.titleBound text.title')
  352 + .style('font-size', val)
348 }, 353 },
349 - part1_terminal_stop_font_color () {  
350 - let self = this;  
351 - // TODO: 354 + part1_line_name_font_color (val) {
  355 + let svg = this.private_svg
  356 + svg.selectAll('g.part:nth-child(1) g.titleBound text.title')
  357 + .style('fill', val)
  358 + },
  359 + part1_terminal_stop_font_size (val) {
  360 + let svg = this.private_svg
  361 + svg.selectAll('g.part:nth-child(1) g.content1Bound text.content1')
  362 + .style('font-size', val)
  363 + svg.selectAll('g.part:nth-child(1) g.content2Bound text.content2')
  364 + .style('font-size', val)
  365 + },
  366 + part1_terminal_stop_font_color (val) {
  367 + let svg = this.private_svg
  368 + svg.selectAll('g.part:nth-child(1) g.content1Bound text.content1')
  369 + .style('fill', val)
  370 + svg.selectAll('g.part:nth-child(1) g.content2Bound text.content2')
  371 + .style('fill', val)
352 }, 372 },
353 373
354 // part2 本班车信息,对应_flag_4属性集合 374 // part2 本班车信息,对应_flag_4属性集合
355 - part2_background_color () {  
356 - // TODO: 375 + part2_background_color (val) {
  376 + let svg = this.private_svg
  377 + svg.selectAll('g.part:nth-child(2) rect.main')
  378 + .style('fill', val)
357 }, 379 },
358 - part2_border_size () {  
359 - // TODO: 380 + part2_border_size (val) {
  381 + let svg = this.private_svg
  382 + svg.selectAll('g.part:nth-child(2) rect.main')
  383 + .style('stroke-width', val)
360 }, 384 },
361 - part2_title1_font_size () {  
362 - // TODO: 385 + part2_title1_font_size (val) {
  386 + let svg = this.private_svg
  387 + svg.selectAll('g.part:nth-child(2) g.titleBound text.title')
  388 + .style('font-size', val)
363 }, 389 },
364 - part2_title1_font_color () {  
365 - // TODO: 390 + part2_title1_font_color (val) {
  391 + let svg = this.private_svg
  392 + svg.selectAll('g.part:nth-child(2) g.titleBound text.title')
  393 + .style('fill', val)
366 }, 394 },
367 - part2_title1_background_color () {  
368 - // TODO: 395 + part2_title1_background_color (val) {
  396 + let svg = this.private_svg
  397 + svg.selectAll('g.part:nth-child(2) rect.titleBackground')
  398 + .style('fill', val)
369 }, 399 },
370 - part2_title2_font_size () {  
371 - // TODO: 400 + part2_title2_font_size (val) {
  401 + let svg = this.private_svg
  402 + svg.selectAll('g.part:nth-child(2) g.content3Bound text.content3')
  403 + .style('font-size', val)
  404 + svg.selectAll('g.part:nth-child(2) g.content4Bound text.content4')
  405 + .style('font-size', val)
372 }, 406 },
373 - part2_title2_font_color () {  
374 - // TODO: 407 + part2_title2_font_color (val) {
  408 + let svg = this.private_svg
  409 + svg.selectAll('g.part:nth-child(2) g.content3Bound text.content3')
  410 + .style('fill', val)
  411 + svg.selectAll('g.part:nth-child(2) g.content4Bound text.content4')
  412 + .style('fill', val)
375 }, 413 },
376 part2_title2_background_color () { 414 part2_title2_background_color () {
377 // TODO: 415 // TODO:
378 }, 416 },
379 - part2_arrival_time_font_size () {  
380 - // TODO: 417 + part2_arrival_time_font_size (val) {
  418 + let showType = this.eBusStopData.showType
  419 + if (showType === 0 || showType === 2) {
  420 + let svg = this.private_svg
  421 + svg.selectAll('g.part:nth-child(2) g.content5Bound text.content5_left')
  422 + .style('font-size', val)
  423 + }
381 }, 424 },
382 - part2_arrival_time_font_color () {  
383 - // TODO: 425 + part2_arrival_time_font_color (val) {
  426 + let showType = this.eBusStopData.showType
  427 + if (showType === 0 || showType === 2) {
  428 + let svg = this.private_svg
  429 + svg.selectAll('g.part:nth-child(2) g.content5Bound text.content5_left')
  430 + .style('fill', val)
  431 + }
384 }, 432 },
385 - part2_arrival_time_minutes_left_font_size () {  
386 - // TODO: 433 + part2_arrival_time_minutes_left_font_size (val) {
  434 + let svg = this.private_svg
  435 + let showType = this.eBusStopData.showType
  436 + if (showType === 1 || showType === 3) {
  437 + svg.selectAll('g.part:nth-child(2) g.content5Bound text.content5_left')
  438 + .style('font-size', val)
  439 + }
  440 +
  441 + // part3不存在时添加
  442 + svg.selectAll('g.part:nth-child(2) g.content7Bound2 text.content7_2_left')
  443 + .style('font-size', val)
387 }, 444 },
388 - part2_arrival_time_minutes_left_font_color () {  
389 - // TODO: 445 + part2_arrival_time_minutes_left_font_color (val) {
  446 + let svg = this.private_svg
  447 + let showType = this.eBusStopData.showType
  448 + if (showType === 1 || showType === 3) {
  449 + svg.selectAll('g.part:nth-child(2) g.content5Bound text.content5_left')
  450 + .style('fill', val)
  451 + }
  452 +
  453 + // part3不存在时添加
  454 + svg.selectAll('g.part:nth-child(2) g.content7Bound2 text.content7_2_left')
  455 + .style('fill', val)
390 }, 456 },
391 - part2_arrival_time_minutes_right_font_size () {  
392 - // TODO: 457 + part2_arrival_time_minutes_right_font_size (val) {
  458 + let svg = this.private_svg
  459 + svg.selectAll('g.part:nth-child(2) g.content5Bound text.content5_right')
  460 + .style('font-size', val)
  461 + svg.selectAll('g.part:nth-child(2) g.content7Bound2 text.content7_2_right')
  462 + .style('font-size', val)
393 }, 463 },
394 - part2_arrival_time_minutes_right_font_color () {  
395 - // TODO: 464 + part2_arrival_time_minutes_right_font_color (val) {
  465 + let svg = this.private_svg
  466 + svg.selectAll('g.part:nth-child(2) g.content5Bound text.content5_right')
  467 + .style('fill', val)
  468 + svg.selectAll('g.part:nth-child(2) g.content7Bound2 text.content7_2_right')
  469 + .style('fill', val)
396 }, 470 },
397 - part2_from_stops_left_font_size () {  
398 - // TODO: 471 + part2_from_stops_left_font_size (val) {
  472 + let svg = this.private_svg
  473 + svg.selectAll('g.part:nth-child(2) g.content6Bound text.content6_left')
  474 + .style('font-size', val)
  475 + svg.selectAll('g.part:nth-child(2) g.content7Bound1 text.content7_1_left')
  476 + .style('font-size', val)
399 }, 477 },
400 - part2_from_stops_left_font_color () {  
401 - // TODO: 478 + part2_from_stops_left_font_color (val) {
  479 + let svg = this.private_svg
  480 + svg.selectAll('g.part:nth-child(2) g.content6Bound text.content6_left')
  481 + .style('fill', val)
  482 + svg.selectAll('g.part:nth-child(2) g.content7Bound1 text.content7_1_left')
  483 + .style('fill', val)
402 }, 484 },
403 - part2_from_stops_right_font_size () {  
404 - // TODO: 485 + part2_from_stops_right_font_size (val) {
  486 + let svg = this.private_svg
  487 + svg.selectAll('g.part:nth-child(2) g.content6Bound text.content6_right')
  488 + .style('font-size', val)
  489 + svg.selectAll('g.part:nth-child(2) g.content7Bound1 text.content7_1_right')
  490 + .style('font-size', val)
405 }, 491 },
406 - part2_from_stops_right_font_color () {  
407 - // TODO: 492 + part2_from_stops_right_font_color (val) {
  493 + let svg = this.private_svg
  494 + svg.selectAll('g.part:nth-child(2) g.content6Bound text.content6_right')
  495 + .style('fill', val)
  496 + svg.selectAll('g.part:nth-child(2) g.content7Bound1 text.content7_1_right')
  497 + .style('fill', val)
408 }, 498 },
409 499
410 // part3 下一班车信息,对应_flag_5_属性集合 500 // part3 下一班车信息,对应_flag_5_属性集合
411 - part3_background_color () {  
412 - // TODO: 501 + part3_background_color (val) {
  502 + let svg = this.private_svg
  503 + svg.selectAll('g.part:nth-child(3) rect.main')
  504 + .style('fill', val)
413 }, 505 },
414 - part3_border_size () {  
415 - // TODO: 506 + part3_border_size (val) {
  507 + let svg = this.private_svg
  508 + svg.selectAll('g.part:nth-child(3) rect.main')
  509 + .style('stroke-width', val)
416 }, 510 },
417 - part3_title1_font_size () {  
418 - // TODO: 511 + part3_title1_font_size (val) {
  512 + let svg = this.private_svg
  513 + svg.selectAll('g.part:nth-child(3) g.titleBound text.title')
  514 + .style('font-size', val)
419 }, 515 },
420 - part3_title1_font_color () {  
421 - // TODO: 516 + part3_title1_font_color (val) {
  517 + let svg = this.private_svg
  518 + svg.selectAll('g.part:nth-child(3) g.titleBound text.title')
  519 + .style('fill', val)
422 }, 520 },
423 - part3_title1_background_color () {  
424 - // TODO: 521 + part3_title1_background_color (val) {
  522 + let svg = this.private_svg
  523 + svg.selectAll('g.part:nth-child(3) rect.titleBackground')
  524 + .style('fill', val)
425 }, 525 },
426 - part3_title2_font_size () {  
427 - // TODO: 526 + part3_title2_font_size (val) {
  527 + let svg = this.private_svg
  528 + svg.selectAll('g.part:nth-child(3) g.contentAllBound text.content')
  529 + .style('font-size', val)
428 }, 530 },
429 - part3_title2_font_color () {  
430 - // TODO: 531 + part3_title2_font_color (val) {
  532 + let svg = this.private_svg
  533 + svg.selectAll('g.part:nth-child(3) g.contentAllBound text.content')
  534 + .style('fill', val)
431 }, 535 },
432 part3_title2_background_color () { 536 part3_title2_background_color () {
433 // TODO: 537 // TODO:
434 }, 538 },
435 - part3_arrival_time_font_size () {  
436 - // TODO: 539 + part3_arrival_time_font_size (val) {
  540 + let svg = this.private_svg
  541 + svg.selectAll('g.part:nth-child(3) g.contentAllBound text.arrivalTime')
  542 + .style('font-size', val)
437 }, 543 },
438 - part3_arrival_time_font_color () {  
439 - // TODO: 544 + part3_arrival_time_font_color (val) {
  545 + let svg = this.private_svg
  546 + svg.selectAll('g.part:nth-child(3) g.contentAllBound text.arrivalTime')
  547 + .style('fill', val)
440 } 548 }
441 549
442 }, 550 },
@@ -450,22 +558,35 @@ export default { @@ -450,22 +558,35 @@ export default {
450 558
451 // 刷新svg数据,对应_flag_3_,_flag_4_,_flag_5_属性集合 559 // 刷新svg数据,对应_flag_3_,_flag_4_,_flag_5_属性集合
452 refreshSvg () { 560 refreshSvg () {
  561 + // console.log('refreshsvg')
  562 +
453 let self = this 563 let self = this
454 564
455 let d3 = self.private_d3 565 let d3 = self.private_d3
456 let svg = self.private_svg 566 let svg = self.private_svg
457 let width = self.svg_width 567 let width = self.svg_width
458 let height = self.svg_height 568 let height = self.svg_height
  569 +
  570 + let svgData = self.eBusStopData.generateSvgData()
  571 + let showType = self.eBusStopData.showType
  572 +
  573 + // console.log(svgData)
  574 +
  575 + // ------------ 0、前置计算准备 --------------//
  576 + // part上下左右,之间的间隔
459 let partUpPadding = 10 577 let partUpPadding = 10
460 let partDownPadding = 10 578 let partDownPadding = 10
461 let partLeftPadding = 10 579 let partLeftPadding = 10
462 let partRightPadding = 10 580 let partRightPadding = 10
463 let partBetweenPadding = 5 581 let partBetweenPadding = 5
464 582
465 - let svgData = self.eBusStopData.generateSvgData()  
466 - let showType = self.eBusStopData.showType 583 + // part上部放置title的rect的高度
  584 + let partTitleRectHeight = 48
  585 +
  586 + // 计算三个part的宽度(宽度相同)
  587 + let partWidth = Math.floor((width - partLeftPadding - partRightPadding - partBetweenPadding * 2) / 3)
  588 + let partHeight = height - partUpPadding - partDownPadding
467 589
468 - // ------------ 0、前置计算准备 --------------//  
469 // 创建x轴比例尺 590 // 创建x轴比例尺
470 let xScale = d3.scaleLinear() 591 let xScale = d3.scaleLinear()
471 .domain([0, 3]) // 定义域 592 .domain([0, 3]) // 定义域
@@ -473,9 +594,6 @@ export default { @@ -473,9 +594,6 @@ export default {
473 let yScale = d3.scaleLinear() 594 let yScale = d3.scaleLinear()
474 .domain([0, 1]) // 定义域 595 .domain([0, 1]) // 定义域
475 .range([partUpPadding, height - partDownPadding]) // 值域 596 .range([partUpPadding, height - partDownPadding]) // 值域
476 - // 计算三个part的宽度(宽度相同)  
477 - let partWidth = Math.floor((width - partLeftPadding - partRightPadding - partBetweenPadding * 2) / 3)  
478 - let partHeight = height - partUpPadding - partDownPadding  
479 597
480 // ------------ 1、添加g元素 ----------------// 598 // ------------ 1、添加g元素 ----------------//
481 let itemsUpdate = svg.selectAll('g.part') 599 let itemsUpdate = svg.selectAll('g.part')
@@ -514,17 +632,42 @@ export default { @@ -514,17 +632,42 @@ export default {
514 return `translate(${x}, ${y})` 632 return `translate(${x}, ${y})`
515 }) 633 })
516 634
517 - // ------------ 2、添加part的上半部分 ----------------// 635 + // ------------ 2、添加各个part的上半部分 ----------------//
  636 + // ------------- 2-1、添加每个part最外部的rect(以下)------------//
518 itemsEnter.append('rect') 637 itemsEnter.append('rect')
519 .classed('main', true) 638 .classed('main', true)
520 - .attr('stroke-dasharray', function (d, i) { 639 + .style('fill', function (d, i) {
521 if (i === 0) { 640 if (i === 0) {
522 - return null 641 + return self.part1_background_color
  642 + } else if (i === 1) {
  643 + return self.part2_background_color
  644 + } else if (i === 2) {
  645 + return self.part3_background_color
  646 + } else {
  647 + return '#FFFFFF'
  648 + }
  649 + })
  650 + .style('stroke-width', function (d, i) {
  651 + if (i === 0) { // part1没有边框
  652 + return self.part1_border_size
  653 + } else if (i === 1) {
  654 + return self.part2_border_size
  655 + } else if (i === 2) {
  656 + return self.part3_border_size
523 } else { 657 } else {
  658 + return 0
  659 + }
  660 + })
  661 + .attr('stroke-dasharray', function (d, i) {
  662 + if (i === 0) { // part1没有边框
  663 + return null
  664 + } else { // part2、part3的边框样式为虚线
524 return "4,2" 665 return "4,2"
525 } 666 }
526 }) 667 })
527 .attr('width', function (d, i) { 668 .attr('width', function (d, i) {
  669 + // 三个part都存在,同宽度,part3不存在时,part2占用2个宽度
  670 + // 宽度计算参考 0、前置计算准备
528 if (i === 1 ) { // part2 671 if (i === 1 ) { // part2
529 if (showType === 0 || showType === 1) { 672 if (showType === 0 || showType === 1) {
530 return partWidth 673 return partWidth
@@ -539,13 +682,6 @@ export default { @@ -539,13 +682,6 @@ export default {
539 }) 682 })
540 .attr('height', partHeight + 'px') 683 .attr('height', partHeight + 'px')
541 itemsUpdate.select('rect.main') 684 itemsUpdate.select('rect.main')
542 - .attr('stroke-dasharray', function (d, i) {  
543 - if (i === 0) {  
544 - return null  
545 - } else {  
546 - return "4,2"  
547 - }  
548 - })  
549 .attr('width', function (d, i) { 685 .attr('width', function (d, i) {
550 if (i === 1 ) { // part2 686 if (i === 1 ) { // part2
551 if (showType === 0 || showType === 1) { 687 if (showType === 0 || showType === 1) {
@@ -560,7 +696,9 @@ export default { @@ -560,7 +696,9 @@ export default {
560 } 696 }
561 }) 697 })
562 .attr('height', partHeight + 'px') 698 .attr('height', partHeight + 'px')
  699 + // ------------- 2-1、添加每个part最外部的rect(以上)------------//
563 700
  701 + // ------------- 2-1、添加每个part上部放置title的外部rect(以下)------------//
564 itemsEnter.append('rect') 702 itemsEnter.append('rect')
565 .classed('titleBackground', true) 703 .classed('titleBackground', true)
566 .attr('width', function (d, i) { 704 .attr('width', function (d, i) {
@@ -577,10 +715,10 @@ export default { @@ -577,10 +715,10 @@ export default {
577 } 715 }
578 }) 716 })
579 .attr('height', function (d, i) { 717 .attr('height', function (d, i) {
580 - if (i === 0) { 718 + if (i === 0) { // part1的title外部不需要rect
581 return 0 719 return 0
582 } else { 720 } else {
583 - return 48 721 + return partTitleRectHeight
584 } 722 }
585 }) 723 })
586 .style('fill', function (d, i) { 724 .style('fill', function (d, i) {
@@ -608,24 +746,22 @@ export default { @@ -608,24 +746,22 @@ export default {
608 return partWidth - 2 746 return partWidth - 2
609 } 747 }
610 }) 748 })
  749 + // ------------- 2-1、添加每个part上部放置title的外部rect(以上)------------//
611 750
  751 + // ------------- 2-2、添加每个part上部title(以下)------------//
612 itemsEnter.append('g') 752 itemsEnter.append('g')
613 .classed('titleBound', true) 753 .classed('titleBound', true)
614 .attr('transform', 'translate(10, 10)') 754 .attr('transform', 'translate(10, 10)')
615 - itemsUpdate.select('g.titleBound')  
616 - .attr('transform', function (d, i) {  
617 -  
618 - })  
619 - itemsEnter.select('g.titleBound') 755 + itemsEnter.select('g.titleBound') // 添加part1上部分title中的图标
620 .select(function (d, i) {return i === 0 ? this : null}) 756 .select(function (d, i) {return i === 0 ? this : null})
621 .append('image') 757 .append('image')
622 .classed('carIcon', true) 758 .classed('carIcon', true)
623 - .attr('x', 0) // 指定x位置,TODO:之后这个属性可能需要可编辑  
624 - .attr('y', 15) // 指定y位置,TODO:之后这个属性可能需要可编辑 759 + .attr('x', 0)
  760 + .attr('y', 0)
625 .attr('href', CarIcon) 761 .attr('href', CarIcon)
626 - .attr('width', 50) // 指定宽度,TODO:之后这个属性可能需要可编辑  
627 - .attr('height', 50) // 指定高度,TODO:之后这个属性可能需要可编辑  
628 - itemsEnter.select('g.titleBound') 762 + .attr('width', self.part1_line_icon_width) // 指定宽度
  763 + .attr('height', self.part1_line_icon_height) // 指定高度
  764 + itemsEnter.select('g.titleBound') // 添加所有part上部分title中的text
629 .append('text') 765 .append('text')
630 .classed('title', true) 766 .classed('title', true)
631 .text(function (d, i) { 767 .text(function (d, i) {
@@ -659,27 +795,65 @@ export default { @@ -659,27 +795,65 @@ export default {
659 }) 795 })
660 .attr('x', function (d, i) { 796 .attr('x', function (d, i) {
661 if (i === 0) { 797 if (i === 0) {
662 - return 60 798 + return self.part1_line_icon_width + 10
663 } else { 799 } else {
664 return 0 800 return 0
665 } 801 }
666 }) 802 })
667 .attr('y', function (d, i) { 803 .attr('y', function (d, i) {
668 - return this.getBBox().height - 10 804 + if (i === 0) {
  805 + let icon_bounds = svg.select('image.carIcon').node().getBBox();
  806 + let text_bounds = this.getBBox();
  807 + let temp = (text_bounds.height - icon_bounds.height) / 2
  808 + if (temp > 0) {
  809 + return icon_bounds.height - temp + 5
  810 + } else {
  811 + return text_bounds.height
  812 + }
  813 +
  814 + } else {
  815 + return 0
  816 + }
  817 + })
  818 + itemsUpdate.select('g.titleBound image.carIcon')
  819 + .attr('width', self.part1_line_icon_width) // 指定宽度
  820 + .attr('height', self.part1_line_icon_height) // 指定高度
  821 + itemsUpdate.select('g.titleBound text.title')
  822 + .attr('x', function (d, i) {
  823 + if (i === 0) {
  824 + return self.part1_line_icon_width + 10
  825 + } else {
  826 + return 0
  827 + }
  828 + })
  829 + .attr('y', function (d, i) {
  830 + if (i === 0) {
  831 + let icon_bounds = svg.select('image.carIcon').node().getBBox();
  832 + let text_bounds = this.getBBox();
  833 + let temp = (text_bounds.height - icon_bounds.height) / 2
  834 + if (temp > 0) {
  835 + return icon_bounds.height - temp + 5
  836 + } else {
  837 + return text_bounds.height
  838 + }
  839 +
  840 + } else {
  841 + return 0
  842 + }
669 }) 843 })
670 itemsUpdate.select('g.titleBound') 844 itemsUpdate.select('g.titleBound')
671 .attr('transform', function (d, i) { 845 .attr('transform', function (d, i) {
672 - let g_part_bounds = svg.select('g.part:nth-child(' + (i + 1) +')').node().getBBox() 846 + let rect_bounds = svg.select('g.part:nth-child(' + (i + 1) +') rect.main').node().getBBox()
673 let title_bounds = this.getBBox() 847 let title_bounds = this.getBBox()
674 let dx = 1 848 let dx = 1
675 let dy = 1 849 let dy = 1
676 850
677 - if (i === 0) {  
678 - dx = (g_part_bounds.width - title_bounds.width) / 2 - title_bounds.x  
679 - dy = (g_part_bounds.height / 2 - title_bounds.height) / 2 - title_bounds.y  
680 - } else {  
681 - dx = (g_part_bounds.width - title_bounds.width) / 2 - title_bounds.x  
682 - dy = (48 - title_bounds.height) / 2 - title_bounds.y 851 + if (i === 0) { // part1标题部分相对于rect.main的上半部分居中
  852 + dx = (rect_bounds.width - title_bounds.width) / 2 - title_bounds.x
  853 + dy = (rect_bounds.height / 2 - title_bounds.height) / 2 - title_bounds.y
  854 + } else { // part2,part3标题部分相对于rect.main的partTitleRectHeight高度居中
  855 + dx = (rect_bounds.width - title_bounds.width) / 2 - title_bounds.x
  856 + dy = (partTitleRectHeight - title_bounds.height) / 2 - title_bounds.y
683 } 857 }
684 if (dx < 0) { 858 if (dx < 0) {
685 dx = 1 859 dx = 1
@@ -689,6 +863,7 @@ export default { @@ -689,6 +863,7 @@ export default {
689 } 863 }
690 return `translate(${dx}, ${dy})` 864 return `translate(${dx}, ${dy})`
691 }) 865 })
  866 + // ------------- 2-2、添加每个part上部title(以上)------------//
692 867
693 // ------------ 3、添加part的下半部分 ----------------// 868 // ------------ 3、添加part的下半部分 ----------------//
694 // ------------ 3-1、part1部分 -------------// 869 // ------------ 3-1、part1部分 -------------//
@@ -711,12 +886,12 @@ export default { @@ -711,12 +886,12 @@ export default {
711 .style('fill', self.part1_terminal_stop_font_color) 886 .style('fill', self.part1_terminal_stop_font_color)
712 itemsUpdate.select('g.content1Bound') 887 itemsUpdate.select('g.content1Bound')
713 .attr('transform', function (d, i) { 888 .attr('transform', function (d, i) {
714 - if (i === 0) { 889 + if (i === 0) { // 相对于rect.main的下半部分的上二分之一居中(其中-5表示向上偏离5)
715 let rect_part1_bounds = svg.select('rect.main:nth-child(1)').node().getBBox() 890 let rect_part1_bounds = svg.select('rect.main:nth-child(1)').node().getBBox()
716 let g_content1_bounds = this.getBBox() 891 let g_content1_bounds = this.getBBox()
717 let dx = (rect_part1_bounds.width - g_content1_bounds.width) / 2 - g_content1_bounds.x 892 let dx = (rect_part1_bounds.width - g_content1_bounds.width) / 2 - g_content1_bounds.x
718 let dy = (rect_part1_bounds.height / 4 - g_content1_bounds.height) - g_content1_bounds.y 893 let dy = (rect_part1_bounds.height / 4 - g_content1_bounds.height) - g_content1_bounds.y
719 - + rect_part1_bounds.height / 2 894 + + rect_part1_bounds.height / 2 - 5
720 if (dx < 0) { 895 if (dx < 0) {
721 dx = 1 896 dx = 1
722 } 897 }
@@ -746,7 +921,7 @@ export default { @@ -746,7 +921,7 @@ export default {
746 .style('fill', self.part1_terminal_stop_font_color) 921 .style('fill', self.part1_terminal_stop_font_color)
747 itemsUpdate.select('g.content2Bound') 922 itemsUpdate.select('g.content2Bound')
748 .attr('transform', function (d, i) { 923 .attr('transform', function (d, i) {
749 - if (i === 0) { 924 + if (i === 0) { // 相对于rect.main的下半部分的下二分之一居中
750 let rect_part1_bounds = svg.select('rect.main:nth-child(1)').node().getBBox() 925 let rect_part1_bounds = svg.select('rect.main:nth-child(1)').node().getBBox()
751 let g_content1_bounds = this.getBBox() 926 let g_content1_bounds = this.getBBox()
752 let dx = (rect_part1_bounds.width - g_content1_bounds.width) / 2 - g_content1_bounds.x 927 let dx = (rect_part1_bounds.width - g_content1_bounds.width) / 2 - g_content1_bounds.x
@@ -762,27 +937,29 @@ export default { @@ -762,27 +937,29 @@ export default {
762 } 937 }
763 }) 938 })
764 939
765 -  
766 // ------------ 3-2、part2部分 -------------// 940 // ------------ 3-2、part2部分 -------------//
  941 + // ------------ 3-2-1、当part3存在时,part2中间纵向添加一条虚线(以下)---------- //
767 let boundLineFun = d3.line() 942 let boundLineFun = d3.line()
768 itemsEnter.select(function (d, i) { 943 itemsEnter.select(function (d, i) {
769 - return i === 1 ? this : null 944 + return i === 1 && (showType === 0 || showType === 1) ? this : null
770 }).append('path') 945 }).append('path')
771 .classed('bound', true) 946 .classed('bound', true)
772 - .attr('d', function (d) { 947 + .attr('d', function () {
773 return boundLineFun([ 948 return boundLineFun([
774 - [partWidth / 2, 48], 949 + [partWidth / 2, partTitleRectHeight],
775 [partWidth / 2, partHeight] 950 [partWidth / 2, partHeight]
776 ]) 951 ])
777 }) 952 })
778 itemsUpdate.select('path.bound') 953 itemsUpdate.select('path.bound')
779 - .attr('d', function (d) { 954 + .attr('d', function () {
780 return boundLineFun([ 955 return boundLineFun([
781 - [partWidth / 2, 48], 956 + [partWidth / 2, partTitleRectHeight],
782 [partWidth / 2, partHeight] 957 [partWidth / 2, partHeight]
783 ]) 958 ])
784 }) 959 })
  960 + // ------------ 3-2-1、当part3存在时,part2中间纵向添加一条虚线(以上)---------- //
785 961
  962 + // ------------ 3-2-2、当part3存在时,part2纵向中间左侧添加内容标题(以下)----------- //
786 itemsEnter.select(function (d, i) { 963 itemsEnter.select(function (d, i) {
787 return i === 1 ? this : null 964 return i === 1 ? this : null
788 }).append('g') 965 }).append('g')
@@ -801,11 +978,11 @@ export default { @@ -801,11 +978,11 @@ export default {
801 .style('fill', self.part2_title2_font_color) 978 .style('fill', self.part2_title2_font_color)
802 itemsUpdate.select('g.content3Bound') 979 itemsUpdate.select('g.content3Bound')
803 .attr('transform', function (d, i) { 980 .attr('transform', function (d, i) {
804 - if (i === 1) { 981 + if (i === 1) { // x方向居中对齐,y方向顶部对齐
805 let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox() 982 let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
806 let g_bounds = this.getBBox() 983 let g_bounds = this.getBBox()
807 let dx = (rect_part2_bounds.width / 2 - g_bounds.width) / 2 - g_bounds.x 984 let dx = (rect_part2_bounds.width / 2 - g_bounds.width) / 2 - g_bounds.x
808 - let dy = 48 - g_bounds.y 985 + let dy = partTitleRectHeight - g_bounds.y
809 if (dx < 0) { 986 if (dx < 0) {
810 dx = 1 987 dx = 1
811 } 988 }
@@ -815,7 +992,9 @@ export default { @@ -815,7 +992,9 @@ export default {
815 return `translate(${dx}, ${dy})` 992 return `translate(${dx}, ${dy})`
816 } 993 }
817 }) 994 })
  995 + // ------------ 3-2-2、当part3存在时,part2纵向中间左侧添加内容标题(以上)----------- //
818 996
  997 + // ------------ 3-2-3、当part3存在时,part2纵向中间右侧添加内容标题(以下)----------- //
819 itemsEnter.select(function (d, i) { 998 itemsEnter.select(function (d, i) {
820 return i === 1 ? this : null 999 return i === 1 ? this : null
821 }).append('g') 1000 }).append('g')
@@ -834,7 +1013,7 @@ export default { @@ -834,7 +1013,7 @@ export default {
834 .style('fill', self.part2_title2_font_color) 1013 .style('fill', self.part2_title2_font_color)
835 itemsUpdate.select('g.content4Bound') 1014 itemsUpdate.select('g.content4Bound')
836 .attr('transform', function (d, i) { 1015 .attr('transform', function (d, i) {
837 - if (i === 1) { 1016 + if (i === 1) { // x方向居中对齐,y方向顶部对齐
838 let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox() 1017 let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
839 let g_bounds = this.getBBox() 1018 let g_bounds = this.getBBox()
840 let dx = (rect_part2_bounds.width / 2 - g_bounds.width) / 2 - g_bounds.x 1019 let dx = (rect_part2_bounds.width / 2 - g_bounds.width) / 2 - g_bounds.x
@@ -849,7 +1028,9 @@ export default { @@ -849,7 +1028,9 @@ export default {
849 return `translate(${dx},${dy})` 1028 return `translate(${dx},${dy})`
850 } 1029 }
851 }) 1030 })
  1031 + // ------------ 3-2-3、当part3存在时,part2纵向中间右侧添加内容标题(以上)----------- //
852 1032
  1033 + // ------------ 3-2-3、当part3存在时,part2纵向中间左侧添加内容(以下)----------- //
853 itemsEnter.select(function (d, i) { 1034 itemsEnter.select(function (d, i) {
854 return i === 1 ? this : null 1035 return i === 1 ? this : null
855 }).append('g') 1036 }).append('g')
@@ -859,21 +1040,86 @@ export default { @@ -859,21 +1040,86 @@ export default {
859 .append('text') 1040 .append('text')
860 .classed('content5_left', true) 1041 .classed('content5_left', true)
861 .text(function (d) { 1042 .text(function (d) {
862 - return d.currentArrivalMinutes_left 1043 + if (showType === 0) {
  1044 + return d.currentArrivalTime
  1045 + } else if (showType === 1) {
  1046 + return d.currentArrivalMinutes_left
  1047 + } else if (showType === 2) {
  1048 + return d.currentArrivalTime
  1049 + } else if (showType === 3) {
  1050 + return d.currentFromMinutes_left
  1051 + } else {
  1052 + return "todo"
  1053 + }
  1054 +
863 }) 1055 })
864 .attr('title', function (d) { 1056 .attr('title', function (d) {
865 - return d.currentArrivalMinutes_left 1057 + if (showType === 0) {
  1058 + return d.currentArrivalTime
  1059 + } else if (showType === 1) {
  1060 + return d.currentArrivalMinutes_left
  1061 + } else if (showType === 2) {
  1062 + return d.currentArrivalTime
  1063 + } else if (showType === 3) {
  1064 + return d.currentFromMinutes_left
  1065 + } else {
  1066 + return "todo"
  1067 + }
  1068 + })
  1069 + .style('font-size', function () {
  1070 + if (showType === 0) {
  1071 + return self.part2_arrival_time_font_size
  1072 + } else if (showType === 1) {
  1073 + return self.part2_arrival_time_minutes_left_font_size
  1074 + } else if (showType === 2) {
  1075 + return self.part2_arrival_time_font_size
  1076 + } else if (showType === 3) {
  1077 + return self.part2_arrival_time_minutes_left_font_size
  1078 + } else {
  1079 + return self.part2_arrival_time_font_size
  1080 + }
  1081 + })
  1082 + .style('fill', function () {
  1083 + if (showType === 0) {
  1084 + return self.part2_arrival_time_font_color
  1085 + } else if (showType === 1) {
  1086 + return self.part2_arrival_time_minutes_left_font_color
  1087 + } else if (showType === 2) {
  1088 + return self.part2_arrival_time_font_color
  1089 + } else if (showType === 3) {
  1090 + return self.part2_arrival_time_minutes_left_font_color
  1091 + } else {
  1092 + return self.part2_arrival_time_font_color
  1093 + }
866 }) 1094 })
867 - .style('font-size', self.part2_arrival_time_minutes_left_font_size)  
868 - .style('fill', self.part2_arrival_time_minutes_left_font_color)  
869 itemsEnter.select('g.content5Bound') 1095 itemsEnter.select('g.content5Bound')
870 .append('text') 1096 .append('text')
871 .classed('content5_right', true) 1097 .classed('content5_right', true)
872 .text(function (d) { 1098 .text(function (d) {
873 - return d.currentArrivalMinutes_right 1099 + if (showType === 0) {
  1100 + return ""
  1101 + } else if (showType === 1) {
  1102 + return d.currentArrivalMinutes_right
  1103 + } else if (showType === 2) {
  1104 + return ""
  1105 + } else if (showType === 3) {
  1106 + return d.currentFromMinutes_right
  1107 + } else {
  1108 + return "todo"
  1109 + }
874 }) 1110 })
875 .attr('title', function (d) { 1111 .attr('title', function (d) {
876 - return d.currentArrivalMinutes_right 1112 + if (showType === 0) {
  1113 + return ""
  1114 + } else if (showType === 1) {
  1115 + return d.currentArrivalMinutes_right
  1116 + } else if (showType === 2) {
  1117 + return ""
  1118 + } else if (showType === 3) {
  1119 + return d.currentFromMinutes_right
  1120 + } else {
  1121 + return "todo"
  1122 + }
877 }) 1123 })
878 .style('font-size', self.part2_arrival_time_minutes_right_font_size) 1124 .style('font-size', self.part2_arrival_time_minutes_right_font_size)
879 .style('fill', self.part2_arrival_time_minutes_right_font_color) 1125 .style('fill', self.part2_arrival_time_minutes_right_font_color)
@@ -881,6 +1127,70 @@ export default { @@ -881,6 +1127,70 @@ export default {
881 let left_bound = svg.select('text.content5_left').node().getBBox() 1127 let left_bound = svg.select('text.content5_left').node().getBBox()
882 return left_bound.width + 2 1128 return left_bound.width + 2
883 }) 1129 })
  1130 +
  1131 + itemsUpdate.select(function (d, i) {
  1132 + return i === 1 ? this : null
  1133 + }).select('g.content5Bound text.content5_left')
  1134 + .text(function (d) {
  1135 + if (showType === 0) {
  1136 + return d.currentArrivalTime
  1137 + } else if (showType === 1) {
  1138 + return d.currentArrivalMinutes_left
  1139 + } else if (showType === 2) {
  1140 + return d.currentArrivalTime
  1141 + } else if (showType === 3) {
  1142 + return d.currentFromMinutes_left
  1143 + } else {
  1144 + return "todo"
  1145 + }
  1146 +
  1147 + })
  1148 + .attr('title', function (d) {
  1149 + if (showType === 0) {
  1150 + return d.currentArrivalTime
  1151 + } else if (showType === 1) {
  1152 + return d.currentArrivalMinutes_left
  1153 + } else if (showType === 2) {
  1154 + return d.currentArrivalTime
  1155 + } else if (showType === 3) {
  1156 + return d.currentFromMinutes_left
  1157 + } else {
  1158 + return "todo"
  1159 + }
  1160 + })
  1161 + itemsUpdate.select(function (d, i) {
  1162 + return i === 1 ? this : null
  1163 + }).select('g.content5Bound text.content5_right')
  1164 + .text(function (d) {
  1165 + if (showType === 0) {
  1166 + return ""
  1167 + } else if (showType === 1) {
  1168 + return d.currentArrivalMinutes_right
  1169 + } else if (showType === 2) {
  1170 + return ""
  1171 + } else if (showType === 3) {
  1172 + return d.currentFromMinutes_right
  1173 + } else {
  1174 + return "todo"
  1175 + }
  1176 + })
  1177 + .attr('title', function (d) {
  1178 + if (showType === 0) {
  1179 + return ""
  1180 + } else if (showType === 1) {
  1181 + return d.currentArrivalMinutes_right
  1182 + } else if (showType === 2) {
  1183 + return ""
  1184 + } else if (showType === 3) {
  1185 + return d.currentFromMinutes_right
  1186 + } else {
  1187 + return "todo"
  1188 + }
  1189 + })
  1190 + .attr('x', function () {
  1191 + let left_bound = svg.select('text.content5_left').node().getBBox()
  1192 + return left_bound.width + 2
  1193 + })
884 itemsUpdate.select('g.content5Bound') 1194 itemsUpdate.select('g.content5Bound')
885 .attr('transform', function (d, i) { 1195 .attr('transform', function (d, i) {
886 if (i === 1) { 1196 if (i === 1) {
@@ -898,9 +1208,11 @@ export default { @@ -898,9 +1208,11 @@ export default {
898 return `translate(${dx}, ${dy})` 1208 return `translate(${dx}, ${dy})`
899 } 1209 }
900 }) 1210 })
  1211 + // ------------ 3-2-3、当part3存在时,part2纵向中间左侧添加内容(以上)----------- //
901 1212
  1213 + // ------------ 3-2-4、当part3存在时,part2纵向中间右侧添加内容(以下)----------- //
902 itemsEnter.select(function (d, i) { 1214 itemsEnter.select(function (d, i) {
903 - return i === 1 ? this : null 1215 + return i === 1 && (showType === 0 || showType === 1 || showType === 3) ? this : null
904 }).append('g') 1216 }).append('g')
905 .classed('content6Bound', true) 1217 .classed('content6Bound', true)
906 .attr('transform', 'translate(10, 10)') 1218 .attr('transform', 'translate(10, 10)')
@@ -908,10 +1220,18 @@ export default { @@ -908,10 +1220,18 @@ export default {
908 .append('text') 1220 .append('text')
909 .classed('content6_left', true) 1221 .classed('content6_left', true)
910 .text(function (d) { 1222 .text(function (d) {
911 - return d.currentFromStations_left 1223 + if (showType === 3) {
  1224 + return d.currentFromStations
  1225 + } else {
  1226 + return d.currentFromStations_left
  1227 + }
912 }) 1228 })
913 .attr('title', function (d) { 1229 .attr('title', function (d) {
914 - return d.currentFromStations_left 1230 + if (showType === 3) {
  1231 + return d.currentFromStations
  1232 + } else {
  1233 + return d.currentFromStations_left
  1234 + }
915 }) 1235 })
916 .style('font-size', self.part2_from_stops_left_font_size) 1236 .style('font-size', self.part2_from_stops_left_font_size)
917 .style('fill', self.part2_from_stops_left_font_color) 1237 .style('fill', self.part2_from_stops_left_font_color)
@@ -919,10 +1239,18 @@ export default { @@ -919,10 +1239,18 @@ export default {
919 .append('text') 1239 .append('text')
920 .classed('content6_right', true) 1240 .classed('content6_right', true)
921 .text(function (d) { 1241 .text(function (d) {
922 - return d.currentFromStations_right 1242 + if (showType === 3) {
  1243 + return ""
  1244 + } else {
  1245 + return d.currentFromStations_right
  1246 + }
923 }) 1247 })
924 .attr('title', function (d) { 1248 .attr('title', function (d) {
925 - return d.currentFromStations_right 1249 + if (showType === 3) {
  1250 + return ""
  1251 + } else {
  1252 + return d.currentFromStations_right
  1253 + }
926 }) 1254 })
927 .style('font-size', self.part2_from_stops_right_font_size) 1255 .style('font-size', self.part2_from_stops_right_font_size)
928 .style('fill', self.part2_from_stops_right_font_color) 1256 .style('fill', self.part2_from_stops_right_font_color)
@@ -930,6 +1258,45 @@ export default { @@ -930,6 +1258,45 @@ export default {
930 let left_bound = svg.select('text.content6_left').node().getBBox() 1258 let left_bound = svg.select('text.content6_left').node().getBBox()
931 return left_bound.width + 2 1259 return left_bound.width + 2
932 }) 1260 })
  1261 +
  1262 + itemsUpdate.select(function (d, i) {
  1263 + return i === 1 && (showType === 0 || showType === 1 || showType === 3) ? this : null
  1264 + }).select('g.content6Bound text.content6_left')
  1265 + .text(function (d) {
  1266 + if (showType === 3) {
  1267 + return d.currentFromStations
  1268 + } else {
  1269 + return d.currentFromStations_left
  1270 + }
  1271 + })
  1272 + .attr('title', function (d) {
  1273 + if (showType === 3) {
  1274 + return d.currentFromStations
  1275 + } else {
  1276 + return d.currentFromStations_left
  1277 + }
  1278 + })
  1279 + itemsUpdate.select(function (d, i) {
  1280 + return i === 1 && (showType === 0 || showType === 1 || showType === 3) ? this : null
  1281 + }).select('g.content6Bound text.content6_right')
  1282 + .text(function (d) {
  1283 + if (showType === 3) {
  1284 + return ""
  1285 + } else {
  1286 + return d.currentFromStations_right
  1287 + }
  1288 + })
  1289 + .attr('title', function (d) {
  1290 + if (showType === 3) {
  1291 + return ""
  1292 + } else {
  1293 + return d.currentFromStations_right
  1294 + }
  1295 + })
  1296 + .attr('x', function () {
  1297 + let left_bound = svg.select('text.content6_left').node().getBBox()
  1298 + return left_bound.width + 2
  1299 + })
933 itemsUpdate.select('g.content6Bound') 1300 itemsUpdate.select('g.content6Bound')
934 .attr('transform', function (d, i) { 1301 .attr('transform', function (d, i) {
935 if (i === 1) { 1302 if (i === 1) {
@@ -948,6 +1315,155 @@ export default { @@ -948,6 +1315,155 @@ export default {
948 return `translate(${dx}, ${dy})` 1315 return `translate(${dx}, ${dy})`
949 } 1316 }
950 }) 1317 })
  1318 + // ------------ 3-2-4、当part3存在时,part2纵向中间右侧添加内容(以上)----------- //
  1319 +
  1320 + // ------------ 3-2-5、当part3不存在时,part2添加内容(以下)----------- //
  1321 + itemsEnter.select(function (d, i) {
  1322 + return i === 1 && showType === 2 ? this : null
  1323 + }).append('g')
  1324 + .classed('content7Bound1', true)
  1325 + .attr('transform', 'translate(10, 10)')
  1326 + itemsEnter.select('g.content7Bound1')
  1327 + .append('text')
  1328 + .classed('content7_1_left', true)
  1329 + .text(function (d) {
  1330 + return d.currentFromStations_left
  1331 + })
  1332 + .attr('title', function (d) {
  1333 + return d.currentFromStations_left
  1334 + })
  1335 + .style('font-size', self.part2_from_stops_left_font_size)
  1336 + .style('fill', self.part2_from_stops_left_font_color)
  1337 + itemsEnter.select('g.content7Bound1')
  1338 + .append('text')
  1339 + .classed('content7_1_right', true)
  1340 + .text(function (d) {
  1341 + return d.currentFromStations_right
  1342 + })
  1343 + .attr('title', function (d) {
  1344 + return d.currentFromStations_right
  1345 + })
  1346 + .style('font-size', self.part2_from_stops_right_font_size)
  1347 + .style('fill', self.part2_from_stops_right_font_color)
  1348 + .attr('x', function () {
  1349 + let left_bound = svg.select('text.content7_1_left').node().getBBox()
  1350 + return left_bound.width + 2
  1351 + })
  1352 +
  1353 + itemsUpdate.select(function (d, i) {
  1354 + return i === 1 && showType === 2 ? this : null
  1355 + }).select('g.content7Bound1 text.content7_1_left')
  1356 + .text(function (d) {
  1357 + return d.currentFromStations_left
  1358 + })
  1359 + .attr('title', function (d) {
  1360 + return d.currentFromStations_left
  1361 + })
  1362 + itemsUpdate.select(function (d, i) {
  1363 + return i === 1 && showType === 2 ? this : null
  1364 + }).select('g.content7Bound1 text.content7_1_right')
  1365 + .text(function (d) {
  1366 + return d.currentFromStations_right
  1367 + })
  1368 + .attr('title', function (d) {
  1369 + return d.currentFromStations_right
  1370 + })
  1371 + .attr('x', function () {
  1372 + let left_bound = svg.select('text.content7_1_left').node().getBBox()
  1373 + return left_bound.width + 2
  1374 + })
  1375 + itemsUpdate.select('g.content7Bound1')
  1376 + .attr('transform', function (d, i) {
  1377 + if (i === 1) {
  1378 + let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
  1379 + let g_bounds = this.getBBox()
  1380 + let dx = (rect_part2_bounds.width / 4 - g_bounds.width) / 2 - g_bounds.x
  1381 + + rect_part2_bounds.width / 2
  1382 + let dy = (rect_part2_bounds.height / 2 - g_bounds.height) / 2 - g_bounds.y
  1383 + + rect_part2_bounds.height / 2
  1384 + if (dx < 0) {
  1385 + dx = 1
  1386 + }
  1387 + if (dy < 0) {
  1388 + dy = 1
  1389 + }
  1390 + return `translate(${dx}, ${dy})`
  1391 + }
  1392 + })
  1393 +
  1394 + itemsEnter.select(function (d, i) {
  1395 + return i === 1 && showType === 2 ? this : null
  1396 + }).append('g')
  1397 + .classed('content7Bound2', true)
  1398 + .attr('transform', 'translate(10, 10)')
  1399 + itemsEnter.select('g.content7Bound2')
  1400 + .append('text')
  1401 + .classed('content7_2_left', true)
  1402 + .text(function (d) {
  1403 + return d.currentFromMinutes_left
  1404 + })
  1405 + .attr('title', function (d) {
  1406 + return d.currentFromMinutes_left
  1407 + })
  1408 + .style('font-size', self.part2_arrival_time_minutes_left_font_size)
  1409 + .style('fill', self.part2_arrival_time_minutes_left_font_color)
  1410 + itemsEnter.select('g.content7Bound2')
  1411 + .append('text')
  1412 + .classed('content7_2_right', true)
  1413 + .text(function (d) {
  1414 + return d.currentFromMinutes_right
  1415 + })
  1416 + .attr('title', function (d) {
  1417 + return d.currentFromMinutes_right
  1418 + })
  1419 + .style('font-size', self.part2_arrival_time_minutes_right_font_size)
  1420 + .style('fill', self.part2_arrival_time_minutes_right_font_color)
  1421 + .attr('x', function () {
  1422 + let left_bound = svg.select('text.content7_2_left').node().getBBox()
  1423 + return left_bound.width + 2
  1424 + })
  1425 +
  1426 + itemsUpdate.select(function (d, i) {
  1427 + return i === 1 && showType === 2 ? this : null
  1428 + }).select('g.content7Bound2 text.content7_2_left')
  1429 + .text(function (d) {
  1430 + return d.currentFromMinutes_left
  1431 + })
  1432 + .attr('title', function (d) {
  1433 + return d.currentFromMinutes_left
  1434 + })
  1435 + itemsUpdate.select(function (d, i) {
  1436 + return i === 1 && showType === 2 ? this : null
  1437 + }).select('g.content7Bound2 text.content7_2_right')
  1438 + .text(function (d) {
  1439 + return d.currentFromMinutes_right
  1440 + })
  1441 + .attr('title', function (d) {
  1442 + return d.currentFromMinutes_right
  1443 + })
  1444 + .attr('x', function () {
  1445 + let left_bound = svg.select('text.content7_2_left').node().getBBox()
  1446 + return left_bound.width + 2
  1447 + })
  1448 + itemsUpdate.select('g.content7Bound2')
  1449 + .attr('transform', function (d, i) {
  1450 + if (i === 1) {
  1451 + let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
  1452 + let g_bounds = this.getBBox()
  1453 + let dx = (rect_part2_bounds.width / 4 - g_bounds.width) / 2 - g_bounds.x
  1454 + + rect_part2_bounds.width * 0.75
  1455 + let dy = (rect_part2_bounds.height / 2 - g_bounds.height) / 2 - g_bounds.y
  1456 + + rect_part2_bounds.height / 2
  1457 + if (dx < 0) {
  1458 + dx = 1
  1459 + }
  1460 + if (dy < 0) {
  1461 + dy = 1
  1462 + }
  1463 + return `translate(${dx}, ${dy})`
  1464 + }
  1465 + })
  1466 + // ------------ 3-2-5、当part3不存在时,part2添加内容(以上)----------- //
951 1467
952 // ------------ 3-3、part3部分 -------------// 1468 // ------------ 3-3、part3部分 -------------//
953 itemsEnter.select(function (d, i) { 1469 itemsEnter.select(function (d, i) {
@@ -972,9 +1488,34 @@ export default { @@ -972,9 +1488,34 @@ export default {
972 .text(function (d) { 1488 .text(function (d) {
973 return d.nextArrivalTime 1489 return d.nextArrivalTime
974 }) 1490 })
  1491 + .attr('title', function (d) {
  1492 + return d.nextArrivalTime
  1493 + })
975 .style('font-size', self.part3_arrival_time_font_size) 1494 .style('font-size', self.part3_arrival_time_font_size)
976 .style('fill', self.part3_arrival_time_font_color) 1495 .style('fill', self.part3_arrival_time_font_color)
977 - .attr('x', 100) 1496 + .attr('x', function () {
  1497 + let left_bounds = svg.select('g.contentAllBound text.content').node().getBBox()
  1498 + return left_bounds.width + 10
  1499 + })
  1500 +
  1501 + itemsUpdate.select(function (d, i) {
  1502 + return i === 2 ? this : null
  1503 + }).select('g.contentAllBound text.content')
  1504 + .text(function (d) {
  1505 + return d.text2
  1506 + })
  1507 + .attr('title', function (d) {
  1508 + return d.text2
  1509 + })
  1510 + itemsUpdate.select(function (d, i) {
  1511 + return i === 2 ? this : null
  1512 + }).select('g.contentAllBound text.arrivalTime')
  1513 + .text(function (d) {
  1514 + return d.nextArrivalTime
  1515 + })
  1516 + .attr('title', function (d) {
  1517 + return d.nextArrivalTime
  1518 + })
978 itemsUpdate.select('g.contentAllBound') 1519 itemsUpdate.select('g.contentAllBound')
979 .attr('transform', function (d, i) { 1520 .attr('transform', function (d, i) {
980 if (i === 2) { 1521 if (i === 2) {
front-end/h5/src/components/core/plugins/bsth/mhgj/chart/models/MhgjEBusStopLineChartData.js renamed to front-end/h5/src/components/core/plugins/bsth/mhgj/chart/models/mhgjEBusStopLineChartData.js
1 // 电子站牌数据信息 1 // 电子站牌数据信息
  2 +import { ScrollPageInnerDataItem } from '../../list/models/mhgj-eBusStop-line-chart-list-scrollPage-innerData'
  3 +
  4 +import moment from 'moment'
  5 +
2 class MhgjEBusStopLineChartData { 6 class MhgjEBusStopLineChartData {
3 /** 7 /**
4 * 构造函数。 8 * 构造函数。
@@ -29,6 +33,72 @@ class MhgjEBusStopLineChartData { @@ -29,6 +33,72 @@ class MhgjEBusStopLineChartData {
29 this._showType = null; 33 this._showType = null;
30 } 34 }
31 35
  36 + // 使用远程数据设置属性,对应 mhgj-eBusStop-line-chart-list-scrollPage-innerData.js中的ScrollPageInnerDataItem类
  37 + // 远程数据格式参考 http://27.115.69.123:19102/General_Interface/getArriveVO?deviceId=66MH0001
  38 + setFromRemoteLineInfo (info) {
  39 + this._lineName = info['lineName'] || '' // 线路名称
  40 + this._terminalStationName = (info['direction'] === 0 ? info['endStop'] : info['startStop']) || '' // 当前线路方向终点站名称
  41 +
  42 + // 构造当前日期
  43 + let _currentMoment = null
  44 + if (info['currDate'] && info['currTime']) {
  45 + _currentMoment = moment(info['currDate'] + " " + info['currTime'], moment.ISO_8601)
  46 + } else {
  47 + _currentMoment = moment(moment().format('YYYY-MM-dd HH:mm'), moment.ISO_8601)
  48 + }
  49 + if (!_currentMoment.isValid()) {
  50 + console.log('当前时间[%s]格式错误,正确格式[yyyy-MM-dd HH:mm]', _currentMoment)
  51 + this._showType = 3
  52 + return this
  53 + }
  54 +
  55 + if (info['arrive'] && info['arrive'].length >= 2) { // 判定是否显示part3
  56 + let firstArrive = info['arrive'][0]
  57 + let arrive_moment = moment(_currentMoment).add(firstArrive['time'], 'seconds')
  58 + if (!arrive_moment.isValid()) {
  59 + console.log('arrive.time异常,不是数字[%s]', firstArrive['time'])
  60 + this._showType = 3
  61 + return this
  62 + }
  63 + let _diffMinutes = arrive_moment.diff(_currentMoment, 'minutes')
  64 + if (_diffMinutes <= 1) {
  65 + this._showType = 0
  66 + this._currentArrivalTime = arrive_moment.format('HH:mm')
  67 + this._currentFromStations = firstArrive['stopdis']
  68 + // console.log(this._showType)
  69 + } else {
  70 + this._showType = 1
  71 + this._currentArrivalMinutes = Math.ceil(firstArrive['time'] / 60)
  72 + this._currentFromStations = firstArrive['stopdis']
  73 + // console.log(this._showType)
  74 + }
  75 +
  76 + let nextArrive = info['arrive'][1]
  77 + let next_arrive_moment = moment(_currentMoment).add(nextArrive['time'], 's')
  78 + if (next_arrive_moment.isValid()) {
  79 + this._nextArrivalTime = next_arrive_moment.format("HH:mm")
  80 + }
  81 + } else {
  82 + if (info['arrive'] && info['arrive'].length === 1) {
  83 + let arrive = info['arrive'][0]
  84 + let arrive_moment = moment(_currentMoment).add(arrive['time'], 's')
  85 + if (!arrive_moment.isValid()) {
  86 + console.log('arrive.time异常,不是数字[%s]', arrive['time'])
  87 + this._showType = 3
  88 + return this
  89 + }
  90 + this._showType = 2
  91 + this._currentArrivalTime = arrive_moment.format('HH:mm')
  92 + this._currentFromStations = arrive['stopdis']
  93 + this._currentFromMinutes = Math.ceil(arrive['time'] / 60)
  94 + } else {
  95 + this._showType = 3
  96 + }
  97 + }
  98 +
  99 + return this
  100 + }
  101 +
32 setLineName (lineName) { 102 setLineName (lineName) {
33 this._lineName = lineName 103 this._lineName = lineName
34 return this 104 return this
@@ -87,6 +157,32 @@ class MhgjEBusStopLineChartData { @@ -87,6 +157,32 @@ class MhgjEBusStopLineChartData {
87 return this._showType 157 return this._showType
88 } 158 }
89 159
  160 +
  161 + set lineName (val) {
  162 + this._lineName = val
  163 + }
  164 + set terminalStationName (val) {
  165 + this._terminalStationName = val
  166 + }
  167 + set currentArrivalTime (val) {
  168 + this._currentArrivalTime = val
  169 + }
  170 + set currentArrivalMinutes (val) {
  171 + this._currentArrivalMinutes = val
  172 + }
  173 + set currentFromStations (val) {
  174 + this._currentFromStations = val
  175 + }
  176 + set currentFromMinutes (val) {
  177 + this._currentFromMinutes = val
  178 + }
  179 + set nextArrivalTime (val) {
  180 + this._nextArrivalTime = val
  181 + }
  182 + set showType (val) {
  183 + this._showType = val
  184 + }
  185 +
90 generateSvgData () { 186 generateSvgData () {
91 // 根据内部数据产生svg用数据 187 // 根据内部数据产生svg用数据
92 let showData = []; 188 let showData = [];
@@ -178,6 +274,20 @@ class MhgjEBusStopLineChartData { @@ -178,6 +274,20 @@ class MhgjEBusStopLineChartData {
178 /** 274 /**
179 * 产生测试数据1,包含三个完整部分的显示,part1,part2,part3 275 * 产生测试数据1,包含三个完整部分的显示,part1,part2,part3
180 */ 276 */
  277 + static generateTestData_type0 () {
  278 + let testData = new MhgjEBusStopLineChartData()
  279 + return testData
  280 + .setShowType(0)
  281 + .setLineName("浦江12路")
  282 + .setTerminalStationName("漕河泾综合保税区")
  283 + .setCurrentArrivalTime("11:30")
  284 + .setCurrentFromStations("1")
  285 + .setNextArrivalTime("11:47")
  286 + }
  287 +
  288 + /**
  289 + * 产生测试数据1,包含三个完整部分的显示,part1,part2,part3
  290 + */
181 static generateTestData_type1 () { 291 static generateTestData_type1 () {
182 let testData = new MhgjEBusStopLineChartData() 292 let testData = new MhgjEBusStopLineChartData()
183 return testData 293 return testData
front-end/h5/src/components/core/plugins/bsth/mhgj/list/css/mhgj-eBusStop-line-chart-list.css 0 → 100644
  1 +/*
  2 + 内部使用的是border-box
  3 + 注意:
  4 + 1、这个设置很重要,因为内部计算width是减去两侧border的
  5 + 2、在编辑器模式下,外层的.ant-layout会给内层所有元素设置border-box,此时你不设置无所谓
  6 + 3、但是在打包预览模式下,是没有外层.ant-layout定义的,此时如果组件内部不定义,则会使用content-box,会和内部计算宽度产生偏差
  7 +*/
  8 +.mhgj-eBusStop-line-chart-list-outer-div, .mhgj-eBusStop-line-chart-list-outer-div * {
  9 + box-sizing: border-box;
  10 +}
  11 +
  12 +/**
  13 + 这里使用float布局,当多个线路模拟图排列的时候
  14 + 1、如果最外层div使用position: relative或不指定position,
  15 + 最外层的div位置会有偏差,滚动列表是会造成距离偏差
  16 + 2、如果使用position:absolute,需要指定top,可以算出的,但是麻烦
  17 + 3、直接使用float:left,不会有问题,因为宽度是死的,高度是活的,排列时没有偏差
  18 + */
  19 +.mhgj-eBusStop-line-chart-list-outer-div .mhgj-eBusStop-line-chart-outer-div {
  20 + float: left;
  21 +}
front-end/h5/src/components/core/plugins/bsth/mhgj/list/mhgj-eBusStop-line-chart-list-scrollPage.js 0 → 100644
  1 +/**
  2 + * 自定义线路模拟图组件列表滚动Page
  3 + * 注意:此组件不单独使用,只用在 mhgj-eBusStop-line-chart-list 组件内部)
  4 + */
  5 +
  6 +import { jsonp } from 'vue-jsonp'
  7 +import { ScrollPageInnerData } from 'core/plugins/bsth/mhgj/list/models/mhgj-eBusStop-line-chart-list-scrollPage-innerData'
  8 +
  9 +export default {
  10 + props: {
  11 + // ---------------- 父组件传递的属性 ---------------- //
  12 + // 编辑模式
  13 + editorMode: { type: String, required: true },
  14 + // 每页大小
  15 + page_size: { type: Number, required: true },
  16 + // 列表宽度
  17 + list_width: { type: Number, required: true },
  18 + // 列表高度
  19 + list_height: { type: Number, required: true },
  20 + // 滚动时间间隔(秒)
  21 + scroll_seconds: { type: Number, required: true },
  22 + // 滚动速度(像素/秒)
  23 + scroll_speed: { type: Number, required: true },
  24 +
  25 + // 获取远端数据url
  26 + remote_data_url: { type: String, required: true },
  27 + // 获取远端数据url参数:站牌设备id
  28 + remote_data_url_param_device_id: { type: String, required: true },
  29 + // 获取远端数据间隔(秒)
  30 + remote_data_refresh_seconds: { type: Number, required: true }
  31 + },
  32 + computed: {
  33 + remoteUrl () {
  34 + return this.remote_data_url + '?deviceId=' + this.remote_data_url_param_device_id
  35 + }
  36 + },
  37 +
  38 + data () {
  39 + return {
  40 + // --------------- lazy加载slot --------------- //
  41 + lazySlot: true,
  42 +
  43 + // --------------- 滚动翻页数据对象 --------------//
  44 + scrollPageInnerData: null,
  45 + initLoading: true,
  46 + initLoadingText: '',
  47 +
  48 + // ---------------- 内部的定时timer --------------- //
  49 + scrollTimer: { // 滚动间隔timer
  50 + timer: undefined,
  51 + count: 0
  52 + },
  53 + remoteDataTimer: { // 远程数据刷新间隔timer
  54 + timer: undefined,
  55 + count: 0
  56 + }
  57 + }
  58 + },
  59 + mounted () {
  60 + // 1、初始化数据
  61 + // 1.1、edit模式下,使用测试数据
  62 + if (this.editorMode === 'edit') {
  63 + this.initLoading = true
  64 + this.initLoadingText = '初始化数据...'
  65 + this.scrollPageInnerData = ScrollPageInnerData.generateDataListByTest(
  66 + this.page_size, this.list_width, this.list_height)
  67 + // 发送bindData事件,父组件绑定该事件
  68 + this.$emit('bindData', this.scrollPageInnerData.scrollDataItemList)
  69 + this.initLoading = false
  70 + this.lazySlot = false
  71 +
  72 + }
  73 + // 1.2、preview模式下,使用远程数据
  74 + if (this.editorMode === 'preview') {
  75 + this.initDataByRemoteApi()
  76 + }
  77 + },
  78 + destroyed () {
  79 + // 重置滚动间隔timer
  80 + let scrollTimer = this.scrollTimer.timer
  81 + if (scrollTimer) {
  82 + try {
  83 + clearTimeout(scrollTimer)
  84 + } catch (err) {}
  85 + }
  86 + this.scrollTimer.timer = undefined
  87 +
  88 + // 重置远程数据刷新间隔timer
  89 + let remoteDataTimer = this.remoteDataTimer.timer
  90 + if (remoteDataTimer) {
  91 + try {
  92 + clearTimeout(remoteDataTimer)
  93 + } catch (err) {}
  94 + }
  95 + this.remoteDataTimer.timer = undefined
  96 +
  97 + // 重置滚动翻页数据对象
  98 + if (this.scrollPageInnerData) {
  99 + this.scrollPageInnerData.resetData()
  100 + }
  101 + },
  102 + watch: {
  103 + 'scrollTimer.count' () {
  104 + let timer = this.scrollTimer.timer
  105 + if (timer) {
  106 + try {
  107 + clearTimeout(timer)
  108 + } catch (err) {}
  109 + this.scrollTimer.timer = undefined
  110 + }
  111 + let self = this
  112 + this.scrollTimer.timer = setTimeout(function () {
  113 + self.startScroll()
  114 + // self.scrollTimer.count++ // 滚动完成再触发,this.scrollListInnerData.scrollUp触发
  115 + }, this.scroll_seconds * 1000)
  116 + },
  117 + 'remoteDataTimer.count' () {
  118 + let timer = this.remoteDataTimer.timer
  119 + if (timer) {
  120 + try {
  121 + clearTimeout(timer)
  122 + } catch (err) {}
  123 + }
  124 + let self = this
  125 + this.remoteDataTimer.timer = setTimeout(function () {
  126 + self.refreshDataByRemoteApi()
  127 + }, this.remote_data_refresh_seconds * 1000)
  128 + },
  129 + // -------------------- 监控父组件传递的属性 --------------- //
  130 + page_size (val) {
  131 + // 只在edit模式下监控,preview模式下不监控
  132 + if (this.editorMode === 'edit') { // 使用测试数据
  133 + this.scrollPageInnerData.pageSize = val
  134 + }
  135 + },
  136 + list_width (val) {
  137 + if (this.editorMode === 'edit') {
  138 + this.scrollPageInnerData.width = val
  139 + } else {
  140 + // TODO:
  141 + }
  142 + },
  143 + list_height (val) {
  144 + if (this.editorMode === 'edit') {
  145 + this.scrollPageInnerData.height = val
  146 + } else {
  147 + // TODO:
  148 + }
  149 + }
  150 + },
  151 + render () {
  152 + // TODO:暂时是没有内容显示的,只处理内部数据,后面再根据不同的错误显示内容
  153 + return (
  154 + <a-spin tip={this.initLoadingText} spinning={this.initLoading} size="large">
  155 + {
  156 + !this.lazySlot ? this.$slots.default : ''
  157 + }
  158 + </a-spin>
  159 + )
  160 + },
  161 + methods: {
  162 + startScroll () {
  163 + this.scrollPageInnerData.scrollUp(this)
  164 + },
  165 + initDataByRemoteApi () { // 使用后台api初始化数据
  166 + this.initLoading = true
  167 + this.initLoadingText = '初始化数据...'
  168 + jsonp(this.remoteUrl).then(remoteDataList => {
  169 + if (!remoteDataList || !remoteDataList.length) {
  170 + this.initLoadingText = `远端数据为空,等待${this.remote_data_refresh_seconds}秒后重新获取,请稍后...`
  171 + this.remoteDataTimer.count++
  172 + } else {
  173 + this.scrollPageInnerData = ScrollPageInnerData.generateDataListByRemoteData(
  174 + this.page_size, this.list_width, this.list_height, remoteDataList)
  175 + // 发送bindData事件,父组件绑定该事件
  176 + this.$emit('bindData', this.scrollPageInnerData.scrollDataItemList)
  177 + this.initLoading = false
  178 + this.lazySlot = false
  179 + // 启动滚动分页,后台数据刷新
  180 + this.scrollTimer.count++
  181 + this.remoteDataTimer.count++
  182 + }
  183 + }).catch(err => {
  184 + console.log(err)
  185 + this.$message.error(`获取远端数据失败,状态:${err.status},错误:${err.statusText}`, 1)
  186 + this.initLoadingText = `获取远端数据失败,等待${this.remote_data_refresh_seconds}秒后重新获取,请稍后...`
  187 + this.remoteDataTimer.count++
  188 + })
  189 + },
  190 + refreshDataByRemoteApi () { // 使用后台api刷新数据
  191 + // console.log('refreshDataByRemoteApi')
  192 + // length===0说明初始化失败,或者后台无数据,重新刷新
  193 + if (!this.scrollPageInnerData || !this.scrollPageInnerData.scrollDataItemList.length) {
  194 + this.initDataByRemoteApi()
  195 + } else {
  196 + jsonp(this.remoteUrl).then(remoteDataList => {
  197 + this.scrollPageInnerData.refreshDataWithRemoteData(remoteDataList)
  198 + }).catch(err => {
  199 + console.log(err)
  200 + this.$message.error(` 获取数据失败,状态:${err.status},错误:${err.statusText}`, 1)
  201 + })
  202 + this.remoteDataTimer.count++
  203 + }
  204 + }
  205 + }
  206 +}
  207 +
  208 +
  209 +
front-end/h5/src/components/core/plugins/bsth/mhgj/list/mhgj-eBusStop-line-chart-list.js 0 → 100644
  1 +/**
  2 + * 自定义线路模拟图组件列表(内部使用 mhgj-eBusStop-line-chart 组件)
  3 + */
  4 +
  5 +import PropTypes from '@luban-h5/plugin-common-props'
  6 +
  7 +import scrollPage from 'core/plugins/bsth/mhgj/list/mhgj-eBusStop-line-chart-list-scrollPage'
  8 +
  9 +import './css/mhgj-eBusStop-line-chart-list.css'
  10 +
  11 +export default {
  12 + extra: {
  13 + defaultStyle: { // 默认属性
  14 + top: 0,
  15 + left: 0,
  16 + width: 1000,
  17 + height: 800
  18 + }
  19 + },
  20 + name: 'mhgj-eBusStop-line-chart-list',
  21 + data () {
  22 + // eslint-disable-next-line
  23 + this.private_jQuery = jQuery.noConflict() // jquery引用
  24 + return {
  25 + /**
  26 + * 监控外层元素的宽度高度变化
  27 + * 1、由于编辑器缩放,自定义组件无法监控,所以需要定义一个定时器监控最外层元素的大小变化
  28 + * 2、建议所有自定义组件,最外层都定义一个div包在自定义组件最外层,不要关联任何自定义的属性,样式对应编辑器的通用样式
  29 + */
  30 + watchWidthHeightTimer: {
  31 + timer: undefined,
  32 + count: 0,
  33 + millisecond: 1000
  34 + },
  35 + list_width: 350, // 列表组件宽度
  36 + list_height: 300, // 列表组件高度
  37 + line_chart_outer_div_width: 0, // 线路图外层div宽度
  38 + line_chart_outer_div_height: 0, // 线路图外层div高度
  39 + internalDataSet: [], // 内部数据(ScrollPageInnerDataItem类型数组,由数据组件生成)
  40 + scrollTop: 0 // 控制垂直滚动 top
  41 + }
  42 + },
  43 + props: {
  44 + editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview)
  45 + defaultValue: 'preview',
  46 + label: '模式',
  47 + visible: false
  48 + }),
  49 + // --------------- 数据属性 -------------- //
  50 + _flag_1_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='数据属性' class='bsth-line-item-divider'/>) } }),
  51 + page_size: PropTypes.number({ label: '每页显示线路图数量', defaultValue: 4, layout: { prefixCls: 'bsth-line' } }),
  52 + scroll_seconds: PropTypes.number({ label: '滚动时间间隔(秒)', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }),
  53 + scroll_speed: PropTypes.number({ label: '滚动速度(像素/秒)', defaultValue: 1000000, layout: { prefixCls: 'bsth-line' } }),
  54 + remote_data_refresh_seconds: PropTypes.number({ label: '数据刷新间隔(秒)', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
  55 + remote_data_url: PropTypes.string({ label: '远端数据url', component: 'a-textarea', defaultValue: 'http://27.115.69.123:19102/General_Interface/getArriveVO', layout: { prefixCls: 'bsth-line' } }),
  56 + device_id: PropTypes.string({ label: '站牌设备Id', defaultValue: '66MH0001', layout: { prefixCls: 'bsth-line' } }),
  57 + // --------------- 外层css属性 --------------- //
  58 + _flag_2_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='外层css属性' class='bsth-line-item-divider'/>) } }),
  59 + margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  60 + margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  61 + margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  62 + margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  63 + border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  64 + background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#9EE0DF', layout: { prefixCls: 'bsth-line' } }),
  65 + // --------------- 内部线路模拟图外层css属性 --------------- //
  66 + _flag_3_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='内部线路模拟图外层css属性' class='bsth-line-item-divider'></hr>) } }),
  67 + line_chart_margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  68 + line_chart_margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  69 + line_chart_margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  70 + line_chart_margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  71 + line_chart_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  72 + line_chart_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  73 + _flag_3_1_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层线路信息css属性" class="bsth-line-item-divider"></hr>) } }),
  74 + part1_line_icon_width: PropTypes.number({ label: '线路图标宽度', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
  75 + part1_line_icon_height: PropTypes.number({ label: '线路图标高度', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
  76 + part1_line_name_font_size: PropTypes.number({ label: '线路名称字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
  77 + part1_terminal_stop_font_size: PropTypes.number({ label: '开往站点字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
  78 + _flag_3_2_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层本班车信息css属性" class="bsth-line-item-divider"></hr>) } }),
  79 + part2_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
  80 + part2_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
  81 + part2_arrival_time_font_size: PropTypes.number({ label: '到达时间字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
  82 + part2_arrival_time_minutes_left_font_size: PropTypes.number({ label: '到达时间(分钟)左边字体大小', defaultValue: 80, layout: { prefixCls: 'bsth-line' } }),
  83 + part2_arrival_time_minutes_right_font_size: PropTypes.number({ label: '到达时间(分钟)右边字体大小', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),
  84 + part2_from_stops_left_font_size: PropTypes.number({ label: '距离本站(几站)左边字体大小', defaultValue: 80, layout: { prefixCls: 'bsth-line' } }),
  85 + part2_from_stops_right_font_size: PropTypes.number({ label: '距离本站(几站)右边字体大小', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),
  86 + _flag_3_3_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层下一班车信息css属性" class="bsth-line-item-divider"></hr>) } }),
  87 + part3_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
  88 + part3_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
  89 + part3_arrival_time_font_size: PropTypes.number({ label: '到达时间字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
  90 +
  91 + },
  92 + render () {
  93 + /* 最外层div对应编辑器的通用样式 */
  94 + return (
  95 + <div class="mhgj-eBusStop-line-chart-list-outer-div">
  96 + {
  97 + this.renderScrollPage()
  98 + }
  99 + </div>
  100 + )
  101 + },
  102 + mounted () {
  103 + // 使用外部元素的框架定义图的长宽
  104 + let $jQuery = this.private_jQuery
  105 + this.list_width = $jQuery(this.$el).width() - this.margin_left - this.margin_right
  106 + this.list_height = $jQuery(this.$el).height() - this.margin_top - this.margin_bottom
  107 + // 开启外部元素长宽监控计数
  108 + /**
  109 + * 开启外部元素长宽监控逻辑
  110 + * 1、必须在编辑模式下启效果,否则无效
  111 + */
  112 + if (this.editorMode === 'edit') {
  113 + this.watchWidthHeightTimer.count++
  114 + }
  115 + },
  116 + destroyed () {
  117 + // 消耗 watchWidthHeightTimer 定时器
  118 + let timer1 = this.watchWidthHeightTimer.timer
  119 + if (timer1) {
  120 + try {
  121 + clearTimeout(timer1)
  122 + } catch (e) {}
  123 + this.watchWidthHeightTimer.timer = undefined
  124 + }
  125 + },
  126 + watch: {
  127 + 'watchWidthHeightTimer.count' () { // 长宽定时器监控
  128 + let timer = this.watchWidthHeightTimer.timer
  129 + if (timer) {
  130 + clearTimeout(timer)
  131 + this.watchWidthHeightTimer.timer = null
  132 + }
  133 +
  134 + let self = this
  135 + let $jQuery = this.private_jQuery
  136 + self.watchWidthHeightTimer.timer = setTimeout(function () {
  137 + // 处理逻辑
  138 + let width = $jQuery(self.$el).width()
  139 + let height = $jQuery(self.$el).height()
  140 +
  141 + if (width !== self.list_width) {
  142 + self.list_width = width - self.margin_left - self.margin_right
  143 + }
  144 + if (height !== self.list_height) {
  145 + self.list_height = height - self.margin_top - self.margin_bottom
  146 + }
  147 +
  148 + self.watchWidthHeightTimer.count++
  149 + }, self.watchWidthHeightTimer.millisecond)
  150 + },
  151 + // ----------------- 数据属性 ---------------- //
  152 + page_size () {
  153 + this.line_chart_outer_div_height = Math.floor(this.list_height / this.page_size)
  154 + },
  155 + // ----------------- 本身宽高 监控 ---------------- //
  156 + list_width () {
  157 + this.line_chart_outer_div_width = this.list_width - this.border_size * 2
  158 + },
  159 + list_height () {
  160 + this.line_chart_outer_div_height = Math.floor((this.list_height - this.border_size * 2) / this.page_size)
  161 + },
  162 + // ----------------- 外层css属性 监控 ----------------- //
  163 + margin_left () {
  164 + this.list_width = this.list_width - this.margin_left - this.margin_right
  165 + },
  166 + margin_right () {
  167 + this.list_width = this.list_width - this.margin_left - this.margin_right
  168 + },
  169 + margin_top () {
  170 + this.list_height = this.list_height - this.margin_top - this.margin_bottom
  171 + },
  172 + margin_bottom () {
  173 + this.list_height = this.list_height - this.margin_top - this.margin_bottom
  174 + },
  175 + border_size () {
  176 + this.line_chart_outer_div_width = this.list_width - this.border_size * 2
  177 + this.line_chart_outer_div_height = Math.floor((this.list_height - this.border_size * 2) / this.page_size)
  178 + }
  179 + },
  180 + methods: {
  181 + /**
  182 + * scrollPage组件的scrollTop事件处理函数。
  183 + * @param val 视口距离内部page的距离
  184 + */
  185 + onScrollTop (val) {
  186 +
  187 + // 注意:默认向上滚动,scrollPage组件内部的view视口是向下移动的,top是大于等于0的
  188 + // 但是,使用scrollPage的组件外部view视口div是固定的,只能移动内部的div,所以top要变成负值
  189 + if (val === 0) {
  190 + this.scrollTop = 0
  191 + } else {
  192 + this.scrollTop = -val
  193 + }
  194 + },
  195 + /**
  196 + * scrollPage组件的bindData事件处理函数。
  197 + * @param dataSet
  198 + */
  199 + onBindData (dataSet) {
  200 + // 初始化的时候绑定一次数据,之后所有数据的变化都在ScrollPage内部变化
  201 + this.internalDataSet = dataSet
  202 + },
  203 +
  204 + /**
  205 + * 绘制scrollPage组件(内部组件,只能在本组件中使用,index.js中未注册)。
  206 + * @return {*}
  207 + */
  208 + renderScrollPage () {
  209 + const innerDivStyle = {
  210 + 'width': this.list_width + 'px',
  211 + 'height': this.list_height + 'px',
  212 + 'border': this.border_size + 'px solid black',
  213 + 'margin-left': this.margin_left + 'px',
  214 + 'margin-right': this.margin_right + 'px',
  215 + 'margin-top': this.margin_top + 'px',
  216 + 'margin-bottom': this.margin_bottom + 'px',
  217 + 'background': this.background_color,
  218 + 'position': 'relative',
  219 + 'overflow': 'hidden' // 隐藏超出的模拟图
  220 + }
  221 +
  222 + // 包含所有的线路模拟图,滚动时设置top值,总高度等于所有图高度和
  223 + const wrapperDivStyle = {
  224 + 'top': this.scrollTop + 'px',
  225 + 'position': 'absolute',
  226 + 'width': this.list_width + 'px',
  227 + 'height': this.line_chart_outer_div_height * this.internalDataSet.length + 'px'
  228 + }
  229 +
  230 + return (
  231 + <scrollPage
  232 + editorMode={this.editorMode}
  233 + page_size={this.page_size}
  234 + list_width={this.list_width}
  235 + list_height={this.list_height}
  236 + scroll_seconds={this.scroll_seconds}
  237 + scroll_speed={this.scroll_speed}
  238 + remote_data_url={this.remote_data_url}
  239 + remote_data_url_param_device_id={this.device_id}
  240 + remote_data_refresh_seconds={this.remote_data_refresh_seconds}
  241 + onBindData={this.onBindData}
  242 + onScrollTop={this.onScrollTop}>
  243 + <div style={innerDivStyle}>
  244 + <div style={wrapperDivStyle}>
  245 + {
  246 + this.internalDataSet.map(dataItem => (
  247 + this.renderLineChart(dataItem._eBusStopData)
  248 + ))
  249 + }
  250 + </div>
  251 + </div>
  252 + </scrollPage>
  253 + )
  254 + },
  255 + /**
  256 + * 绘制eBusStop-line-chart组件(index.js中已经注册过,不需要import)。
  257 + * @param eBusStopData EBusStopData类型
  258 + * @return {*}
  259 + */
  260 + renderLineChart (eBusStopData) {
  261 + return (
  262 + <mhgj-eBusStop-line-chart
  263 + useMode='child'
  264 + editorMode={this.editorMode}
  265 + line_chart_outer_div_width={this.line_chart_outer_div_width}
  266 + line_chart_outer_div_height={this.line_chart_outer_div_height}
  267 + eBusStopData_child={eBusStopData}
  268 + // 内部线路模拟图外层css属性
  269 + margin_left={this.line_chart_margin_left}
  270 + margin_right={this.line_chart_margin_right}
  271 + margin_top={this.line_chart_margin_top}
  272 + margin_bottom={this.line_chart_margin_bottom}
  273 + border_size={this.line_chart_border_size}
  274 + background_color={this.line_chart_background_color}
  275 + // 内部线路模拟图内层css属性
  276 + part1_line_icon_width={this.part1_line_icon_width}
  277 + part1_line_icon_height={this.part1_line_icon_height}
  278 + part1_line_name_font_size={this.part1_line_name_font_size}
  279 + part1_terminal_stop_font_size={this.part1_terminal_stop_font_size}
  280 + part2_title1_font_size={this.part2_title1_font_size}
  281 + part2_title2_font_size={this.part2_title2_font_size}
  282 + part2_arrival_time_font_size={this.part2_arrival_time_font_size}
  283 + part2_arrival_time_minutes_left_font_size={this.part2_arrival_time_minutes_left_font_size}
  284 + part2_arrival_time_minutes_right_font_size={this.part2_arrival_time_minutes_right_font_size}
  285 + part2_from_stops_left_font_size={this.part2_from_stops_left_font_size}
  286 + part2_from_stops_right_font_size={this.part2_from_stops_right_font_size}
  287 + part3_title1_font_size={this.part3_title1_font_size}
  288 + part3_title2_font_size={this.part3_title2_font_size}
  289 + part3_arrival_time_font_size={this.part3_arrival_time_font_size}
  290 +
  291 + />
  292 + )
  293 + }
  294 +
  295 + }
  296 +
  297 +}
front-end/h5/src/components/core/plugins/bsth/mhgj/list/models/mhgj-eBusStop-line-chart-list-scrollPage-innerData.js 0 → 100644
  1 +
  2 +/**
  3 + * mhgj-eBusStop-line-chart-list-scrollPage.js 内部使用数据对象
  4 + */
  5 +
  6 +import Utils from 'core/plugins/bsth/bsth-utils'
  7 +import { MhgjEBusStopLineChartData } from 'core/plugins/bsth/mhgj/chart/models/mhgjEBusStopLineChartData'
  8 +
  9 +class ScrollPageInnerDataItem {
  10 + /**
  11 + * 构造函数。
  12 + * @param width int 对应chart组件宽度
  13 + * @param height int 对应chart组件高度
  14 + * @param cssTop int 对应chart组件距离顶部css top值
  15 + * @param itemIndex int 每页中的item下标(从0开始)
  16 + * @param pageIndex int 第几页下标(从0开始)
  17 + * @param eBusStopData MhgjEBusStopLineChartData 对应mhgj-eBusStop-line-chart组件使用的数据对象
  18 + */
  19 + constructor (width = 0, height = 0, cssTop, itemIndex, pageIndex, eBusStopData) {
  20 + // 数据对象
  21 + this._eBusStopData = eBusStopData
  22 +
  23 + // ------------- 滚动列表用的数据 ------------ //
  24 + this._width = width
  25 + this._height = height
  26 + this._cssTop = cssTop
  27 + this._itemIndex = itemIndex
  28 + this._pageIndex = pageIndex
  29 + }
  30 +
  31 + get width () {
  32 + return this._width
  33 + }
  34 + get height () {
  35 + return this._height
  36 + }
  37 +
  38 + get top () {
  39 + return this._cssTop
  40 + }
  41 +
  42 + /**
  43 + * 使用类本身对象创建。
  44 + * @param dataItem ScrollPageInnerDataItem
  45 + * @return ScrollPageInnerDataItem
  46 + */
  47 + static createByDataItem (dataItem) {
  48 + return new ScrollPageInnerDataItem(
  49 + 0, 0,
  50 + dataItem._cssTop,
  51 + dataItem._itemIndex,
  52 + dataItem._pageIndex,
  53 + dataItem._eBusStopData
  54 + )
  55 + }
  56 +
  57 + // TODO:
  58 +}
  59 +
  60 +class ScrollPageInnerData {
  61 + /**
  62 + * 构造函数。
  63 + * @param pageSize 每页大小
  64 + * @param width 列表宽度
  65 + * @param height 列表高度
  66 + */
  67 + constructor (pageSize, width, height) {
  68 + this._pageSize = pageSize
  69 + this._width = width
  70 + this._height = height
  71 +
  72 + // --------------- 内部数据对象 ---------------- //
  73 + // ScrollPageInnerDataItem 类型数组
  74 + this._innerDataItemList = []
  75 + this._pageCount = 0 // 一共多少页
  76 +
  77 + // --------------- 内部滚动数据对象 --------------- //
  78 + // 滚动用的 ScrollPageInnerDataItem 类型数组(根据不同的滚动策略会和_innerDataItemList不一致)
  79 + this._scrollDataItemList = []
  80 + this._currentScrollIndex = 0 // 当前滚动项index
  81 + this._nextScrollIndex = 1 // 下一个滚动项index
  82 + this._scrollAnimateTimer = { // 滚动动画效果timer
  83 + timer: undefined,
  84 + count: 0,
  85 + millisecond: 1
  86 + }
  87 + }
  88 +
  89 + // ---------------- get/set方法 -------------- //
  90 + set pageSize (val) { // 设置每页大小
  91 + this._pageSize = val
  92 + this._pageCount = Math.ceil(this._innerDataItemList.length / this._pageSize)
  93 + // 重新计算_scrollDataItemList
  94 + _private_refreshScrollData.call(this)
  95 + }
  96 +
  97 + get scrollDataItemList () { // 返回滚动数据集
  98 + return this._scrollDataItemList
  99 + }
  100 +
  101 + set width (val) {
  102 + this._width = val
  103 + // 刷新滚动数据中 宽,高,top
  104 + _private_refreshScrollDataSizeProperty.call(this)
  105 + }
  106 +
  107 + set height (val) {
  108 + this._height = val
  109 + // 刷新滚动数据中 宽,高,top
  110 + _private_refreshScrollDataSizeProperty.call(this)
  111 + }
  112 +
  113 + // --------------------- 分页移动方法 --------------------- //
  114 + /**
  115 + * mhgj-eBusStop-line-chart-list-scrollPage组件联动,向上滚动翻页
  116 + * 主要分页逻辑:每次向上移动一个chart,第一个chart接到最后一个chart组成一个环滚动翻
  117 + * @param scrollListComponent mhgj-eBusStop-line-chart-list-scrollPage组件
  118 + */
  119 + scrollUp (scrollListComponent) {
  120 + if (this._scrollDataItemList.length <= this._pageSize) { // 小于一页,不滚动
  121 + return
  122 + }
  123 +
  124 + if (this._scrollAnimateTimer.timer) {
  125 + try {
  126 + clearInterval(this._scrollAnimateTimer.timer)
  127 + } catch (err) {
  128 + }
  129 + this._scrollAnimateTimer.timer = undefined
  130 + }
  131 +
  132 + // 往上滚动,相当于视口view向下移动
  133 + let viewTopFrom = this._scrollDataItemList[this._currentScrollIndex].top
  134 + let viewTopTo = this._scrollDataItemList[this._nextScrollIndex].top
  135 + let speed = scrollListComponent.scroll_speed // 每秒移动像素数
  136 + let step = speed / 1000 // 每毫秒移动像素数
  137 + // let step = (topTo - topFrom) / 20 // 每毫秒移动距离差的5分之一
  138 + let self = this
  139 + self._scrollAnimateTimer.timer = setInterval(function () {
  140 + self._scrollAnimateTimer.count++
  141 + let currentViewTop = viewTopFrom + self._scrollAnimateTimer.count * step
  142 + // console.log(currentViewTop)
  143 + if (currentViewTop > viewTopTo || (viewTopTo - currentViewTop) < step) {
  144 + scrollListComponent.$emit('scrollTop', viewTopTo)
  145 + self._scrollAnimateTimer.count = 0
  146 +
  147 + // console.log(self._pageCount)
  148 + // console.log(self._scrollDataItemList[self._nextScrollIndex].pageIndex)
  149 + if (self._scrollDataItemList[self._nextScrollIndex].pageIndex === self._pageCount) {
  150 + scrollListComponent.$emit('scrollTop', self._scrollDataItemList[0].top)
  151 + self._currentScrollIndex = 0
  152 + self._nextScrollIndex = 1
  153 + } else {
  154 + self._currentScrollIndex = self._nextScrollIndex
  155 + self._nextScrollIndex++
  156 + }
  157 +
  158 + if (self._scrollAnimateTimer.timer) {
  159 + try {
  160 + clearInterval(self._scrollAnimateTimer.timer)
  161 + } catch (err) {
  162 + }
  163 + self._scrollAnimateTimer.timer = null
  164 + }
  165 +
  166 + scrollListComponent.scrollTimer.count++
  167 + } else {
  168 + scrollListComponent.$emit('scrollTop', currentViewTop)
  169 + }
  170 +
  171 + }, 1)
  172 + }
  173 +
  174 + // ----------------------- 数据方法 --------------------- //
  175 + /**
  176 + * 重置内部数据
  177 + */
  178 + resetData () {
  179 + // ------------ 重置内部数据对象 ------------ //
  180 + this._innerDataItemList.splice(0, this._innerDataItemList.length) // 直接删除数据内部数据,而不是 = []
  181 + this._pageCount = 0
  182 +
  183 + // ------------ 重置内部滚动数据对象 ---------- //
  184 + this._scrollDataItemList.splice(0, this._scrollDataItemList.length)
  185 + this._currentScrollIndex = 0
  186 + this._nextScrollIndex = 1
  187 + if (this._scrollAnimateTimer.timer) {
  188 + try {
  189 + clearInterval(this._scrollAnimateTimer.timer)
  190 + } catch (err) {}
  191 + }
  192 + this._scrollAnimateTimer.timer = undefined
  193 + this._scrollAnimateTimer.count = 0
  194 + }
  195 +
  196 + /**
  197 + * 使用远程数据刷新内部数据。
  198 + * @param remoteDataList Object
  199 + */
  200 + refreshDataWithRemoteData (remoteDataList) {
  201 + // 远程数据格式参考 http://27.115.69.123:19102/General_Interface/getArriveVO?deviceId=66MH0001
  202 + if (!remoteDataList || !remoteDataList.length) {
  203 + return
  204 + }
  205 +
  206 + // 1、按照线路名字分组数据
  207 + let dataGroupByLineName = Utils.listGroupBy(remoteDataList, function (d) {
  208 + return d['lineName']
  209 + })
  210 + // 2、设置数据
  211 + for (let internalData of this._innerDataItemList) {
  212 + let key = internalData._eBusStopData.lineName
  213 + if (dataGroupByLineName[key]) {
  214 + let remoteInfo = dataGroupByLineName[key][0]
  215 + internalData._eBusStopData.setFromRemoteLineInfo(remoteInfo)
  216 +
  217 + // console.log(`${key}刷新remote数据`)
  218 + }
  219 + }
  220 + // this._innerDataItemList[0]._eBusStopData.currentFromStations = 20
  221 + // console.log(this._innerDataItemList[0]._eBusStopData)
  222 +
  223 + }
  224 +
  225 + // --------------------------- static构建方法 ------------------------- //
  226 + /**
  227 + * 使用远程数据生成对象。
  228 + * @param pageSize 每页大小
  229 + * @param width 列表宽度
  230 + * @param height 列表高度
  231 + * @param remoteDataList Object
  232 + * @return ScrollPageInnerData
  233 + */
  234 + static generateDataListByRemoteData (pageSize, width, height, remoteDataList) {
  235 + let rtnData = new ScrollPageInnerData(
  236 + pageSize, width, height
  237 + )
  238 +
  239 + // 1、重置内部数据
  240 + rtnData.resetData()
  241 + // 1-1、如果远端数据为空,直接返回
  242 + if (!remoteDataList || !remoteDataList.length) {
  243 + return rtnData
  244 + }
  245 +
  246 + // 2、计算内部数据对象
  247 + rtnData._innerDataItemList.splice(0, rtnData._innerDataItemList.length)
  248 +
  249 + // 2-1、使用远端数据构造内部数据
  250 + // 远程数据格式参考 http://27.115.69.123:19102/General_Interface/getArriveVO?deviceId=66MH0001
  251 + for (const info of remoteDataList) {
  252 + if (info) {
  253 + let eBusStopData = new MhgjEBusStopLineChartData()
  254 + .setFromRemoteLineInfo(info)
  255 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(0, 0, 0, 0, 0, eBusStopData))
  256 + }
  257 + }
  258 +
  259 + // 2.2、一共有多少页
  260 + rtnData._pageCount = Math.ceil(rtnData._innerDataItemList.length / rtnData._pageSize)
  261 +
  262 + // 3、计算内部滚动数据对象
  263 + _private_refreshScrollData.call(rtnData)
  264 +
  265 + return rtnData
  266 + }
  267 +
  268 + /**
  269 + * static方法,使用测试数据生成对象。
  270 + * @param pageSize 每页大小
  271 + * @param width 列表宽度
  272 + * @param height 列表高度
  273 + * @return ScrollPageInnerData
  274 + */
  275 + static generateDataListByTest (pageSize, width, height) {
  276 + let rtnData = new ScrollPageInnerData(
  277 + pageSize, width, height
  278 + )
  279 +
  280 + // 1、重置内部数据
  281 + rtnData.resetData()
  282 +
  283 + // 2、计算内部数据对象
  284 + rtnData._innerDataItemList.splice(0, rtnData._innerDataItemList.length)
  285 + // 2-1、测试数据
  286 + let type1_data0 = MhgjEBusStopLineChartData.generateTestData_type0()
  287 + let type1_data1 = MhgjEBusStopLineChartData.generateTestData_type1().setLineName('test1路')
  288 + let type1_data2 = MhgjEBusStopLineChartData.generateTestData_type2().setLineName('test2路')
  289 + let type1_data3 = MhgjEBusStopLineChartData.generateTestData_type3().setLineName('test3路')
  290 +
  291 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(0, 0, 0, 0, 0, type1_data0))
  292 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(0, 0, 0, 0, 0, type1_data1))
  293 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(0, 0, 0, 0, 0, type1_data2))
  294 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(0, 0, 0, 0, 0, type1_data3))
  295 +
  296 + // 2.2、一共有多少页
  297 + rtnData._pageCount = Math.ceil(rtnData._innerDataItemList.length / rtnData._pageSize)
  298 +
  299 + // 3、计算内部滚动数据对象
  300 + _private_refreshScrollData.call(rtnData)
  301 +
  302 + // console.log(rtnData)
  303 +
  304 + return rtnData
  305 + }
  306 +
  307 +}
  308 +
  309 +// ---------------- private私有方法 -----------------//
  310 +/**
  311 + * 计算内部滚动数据。
  312 + */
  313 +function _private_refreshScrollData () {
  314 + this._scrollDataItemList.splice(0, this._scrollDataItemList.length)
  315 +
  316 + // 3.1、拷贝属性赋值
  317 + for (let dataItem of this._innerDataItemList) {
  318 + // 注意这里直接拷贝_innerDataItemList元素属性,然后new新的ScrollListInnerDataItem对象
  319 + this._scrollDataItemList.push(
  320 + ScrollPageInnerDataItem.createByDataItem(dataItem)
  321 + )
  322 + }
  323 + // 3.2、如果总数据小于等于1页,不用计算其他滚动数据,返回
  324 + if (this._innerDataItemList.length <= this._pageSize) {
  325 + return
  326 + }
  327 + // 3.3、计算每条数据的 itemIndex pageIndex 属性
  328 + for (let i = 0; i < this._pageCount; i++) { // 计算itemIndex pageIndex
  329 + for (let j = 0; j < this._pageSize; j++) {
  330 + let index = i * this._pageSize + j
  331 + if (index === this._scrollDataItemList.length) { // 超出记录退出
  332 + break
  333 + }
  334 + let innerDataItem = this._scrollDataItemList[i * this._pageSize + j]
  335 + innerDataItem.itemIndex = j
  336 + innerDataItem.pageIndex = i
  337 + }
  338 + }
  339 + // 3.4、在最后添加第一页的数据(为了无缝滚动需要),同时pageIndex要加1
  340 + // 注意:添加的一页不计算进this.pageCount中
  341 + for (let i = 0; i < this._pageSize; i++) {
  342 + let InnerDataItem = ScrollPageInnerDataItem.createByDataItem(this._innerDataItemList[i])
  343 + InnerDataItem.pageIndex = this._pageCount
  344 + this._scrollDataItemList.push(InnerDataItem)
  345 + }
  346 + // 3.5、计算每个元素的宽,高,top
  347 + _private_refreshScrollDataSizeProperty.call(this)
  348 +}
  349 +
  350 +/**
  351 + * 刷新滚动数据中 宽,高,top
  352 + */
  353 +function _private_refreshScrollDataSizeProperty () {
  354 + // TODO:先直接除假设每个item高度相同,后面再改
  355 + let scrollHeight = Math.floor(this._height / this._pageSize)
  356 + for (let i = 0; i < this._scrollDataItemList.length; i++) {
  357 + let innerDataItem = this._scrollDataItemList[i]
  358 + innerDataItem._width = this._width
  359 + innerDataItem._height = scrollHeight
  360 + innerDataItem._cssTop = i * scrollHeight
  361 + }
  362 +}
  363 +
  364 +export {
  365 + ScrollPageInnerDataItem,
  366 + ScrollPageInnerData
  367 +}
front-end/h5/src/components/core/plugins/index.js
@@ -31,6 +31,7 @@ import EBusStopLineChart from &#39;core/plugins/bsth/lggj/chart/eBusStop-line-chart&#39; @@ -31,6 +31,7 @@ import EBusStopLineChart from &#39;core/plugins/bsth/lggj/chart/eBusStop-line-chart&#39;
31 import EBusStopLineChartList from 'core/plugins/bsth/lggj/list/eBusStop-line-chart-list' 31 import EBusStopLineChartList from 'core/plugins/bsth/lggj/list/eBusStop-line-chart-list'
32 32
33 import MhgjEBusStopLineChart from 'core/plugins/bsth/mhgj/chart/mhgj-eBusStop-line-chart' 33 import MhgjEBusStopLineChart from 'core/plugins/bsth/mhgj/chart/mhgj-eBusStop-line-chart'
  34 +import MhgjEBusStopLineChartList from 'core/plugins/bsth/mhgj/list/mhgj-eBusStop-line-chart-list'
34 35
35 export const pluginsList = [ 36 export const pluginsList = [
36 // { 37 // {
@@ -354,6 +355,18 @@ export const pluginsList = [ @@ -354,6 +355,18 @@ export const pluginsList = [
354 name: MhgjEBusStopLineChart.name 355 name: MhgjEBusStopLineChart.name
355 }, 356 },
356 357
  358 + {
  359 + i18nTitle: {
  360 + 'en-US': 'MhgjEBusStopLineChartList',
  361 + 'zh-CN': '电子站牌单线路模拟图2list'
  362 + },
  363 + title: '电子站牌单线路模拟图2list',
  364 + icon: 'list',
  365 + component: MhgjEBusStopLineChartList,
  366 + visible: true,
  367 + name: MhgjEBusStopLineChartList.name
  368 + },
  369 +
357 // { 370 // {
358 // i18nTitle: { 371 // i18nTitle: {
359 // 'en-US': 'LineChart', 372 // 'en-US': 'LineChart',