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 34 return this._height
35 35 }
36 36  
  37 + get top () {
  38 + return this._cssTop
  39 + }
  40 +
37 41 /**
38 42 * 使用类本身对象创建。
39 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 68 text-shadow: 0 0 2px #dadada;
69 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 73 svg.mhgj-eBusStop-line-chart g.part g.content2Bound text.content2 {
74 74 font-size: 28px;
... ... @@ -135,6 +135,39 @@ svg.mhgj-eBusStop-line-chart g.part g.content6Bound text.content6_right {
135 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 171 /** part3用 */
139 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 9 import CarIcon from './svgicon/car.svg'
10 10  
11 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 14 export default {
15 15 extra: {
... ... @@ -105,21 +105,23 @@ export default {
105 105 _flag_3_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层线路信息css属性" class="bsth-line-item-divider"></hr>) } }),
106 106 part1_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
107 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 110 part1_line_name_font_size: PropTypes.number({ label: '线路名称字体大小', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
109 111 part1_line_name_font_color: PropTypes.color({ label: '线路名称字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
110 112 part1_terminal_stop_font_size: PropTypes.number({ label: '开往站点字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
111 113 part1_terminal_stop_font_color: PropTypes.color({ label: '开往站点字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
112 114 _flag_4_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层本班车信息css属性" class="bsth-line-item-divider"></hr>) } }),
113 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 117 part2_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
116 118 part2_title1_font_color: PropTypes.color({ label: '标题1字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
117 119 part2_title1_background_color: PropTypes.color({ label: '标题1背景颜色', defaultValue: '#acd48e', layout: { prefixCls: 'bsth-line' } }),
118 120 part2_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
119 121 part2_title2_font_color: PropTypes.color({ label: '标题2字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
120 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 125 part2_arrival_time_minutes_left_font_size: PropTypes.number({ label: '到达时间(分钟)左边字体大小', defaultValue: 80, layout: { prefixCls: 'bsth-line' } }),
124 126 part2_arrival_time_minutes_left_font_color: PropTypes.color({ label: '到达时间(分钟)左边字体颜色', defaultValue: '#cd2a40', layout: { prefixCls: 'bsth-line' } }),
125 127 part2_arrival_time_minutes_right_font_size: PropTypes.number({ label: '到达时间(分钟)右边字体大小', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),
... ... @@ -130,14 +132,14 @@ export default {
130 132 part2_from_stops_right_font_color: PropTypes.color({ label: '距离本站(几站)右边字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
131 133 _flag_5_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层下一班车信息css属性" class="bsth-line-item-divider"></hr>) } }),
132 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 136 part3_title1_font_size: PropTypes.number({ label: '标题1字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
135 137 part3_title1_font_color: PropTypes.color({ label: '标题1字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
136 138 part3_title1_background_color: PropTypes.color({ label: '标题1背景颜色', defaultValue: '#7dc6fe', layout: { prefixCls: 'bsth-line' } }),
137 139 part3_title2_font_size: PropTypes.number({ label: '标题2字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
138 140 part3_title2_font_color: PropTypes.color({ label: '标题2字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
139 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 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 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 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 279 self.refreshSvg()
280   - }
  280 + },
  281 + deep: true
281 282 },
  283 +
282 284 // ------------ 本身宽高 ----------- //
283 285 component_width () {
284 286 let self = this
... ... @@ -326,117 +328,223 @@ export default {
326 328  
327 329 //---------- 图内层css监控 --------//
328 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 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 414 part2_title2_background_color () {
377 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 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 536 part3_title2_background_color () {
433 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 558  
451 559 // 刷新svg数据,对应_flag_3_,_flag_4_,_flag_5_属性集合
452 560 refreshSvg () {
  561 + // console.log('refreshsvg')
  562 +
453 563 let self = this
454 564  
455 565 let d3 = self.private_d3
456 566 let svg = self.private_svg
457 567 let width = self.svg_width
458 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 577 let partUpPadding = 10
460 578 let partDownPadding = 10
461 579 let partLeftPadding = 10
462 580 let partRightPadding = 10
463 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 590 // 创建x轴比例尺
470 591 let xScale = d3.scaleLinear()
471 592 .domain([0, 3]) // 定义域
... ... @@ -473,9 +594,6 @@ export default {
473 594 let yScale = d3.scaleLinear()
474 595 .domain([0, 1]) // 定义域
475 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 598 // ------------ 1、添加g元素 ----------------//
481 599 let itemsUpdate = svg.selectAll('g.part')
... ... @@ -514,17 +632,42 @@ export default {
514 632 return `translate(${x}, ${y})`
515 633 })
516 634  
517   - // ------------ 2、添加part的上半部分 ----------------//
  635 + // ------------ 2、添加各个part的上半部分 ----------------//
  636 + // ------------- 2-1、添加每个part最外部的rect(以下)------------//
518 637 itemsEnter.append('rect')
519 638 .classed('main', true)
520   - .attr('stroke-dasharray', function (d, i) {
  639 + .style('fill', function (d, i) {
521 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 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 665 return "4,2"
525 666 }
526 667 })
527 668 .attr('width', function (d, i) {
  669 + // 三个part都存在,同宽度,part3不存在时,part2占用2个宽度
  670 + // 宽度计算参考 0、前置计算准备
528 671 if (i === 1 ) { // part2
529 672 if (showType === 0 || showType === 1) {
530 673 return partWidth
... ... @@ -539,13 +682,6 @@ export default {
539 682 })
540 683 .attr('height', partHeight + 'px')
541 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 685 .attr('width', function (d, i) {
550 686 if (i === 1 ) { // part2
551 687 if (showType === 0 || showType === 1) {
... ... @@ -560,7 +696,9 @@ export default {
560 696 }
561 697 })
562 698 .attr('height', partHeight + 'px')
  699 + // ------------- 2-1、添加每个part最外部的rect(以上)------------//
563 700  
  701 + // ------------- 2-1、添加每个part上部放置title的外部rect(以下)------------//
564 702 itemsEnter.append('rect')
565 703 .classed('titleBackground', true)
566 704 .attr('width', function (d, i) {
... ... @@ -577,10 +715,10 @@ export default {
577 715 }
578 716 })
579 717 .attr('height', function (d, i) {
580   - if (i === 0) {
  718 + if (i === 0) { // part1的title外部不需要rect
581 719 return 0
582 720 } else {
583   - return 48
  721 + return partTitleRectHeight
584 722 }
585 723 })
586 724 .style('fill', function (d, i) {
... ... @@ -608,24 +746,22 @@ export default {
608 746 return partWidth - 2
609 747 }
610 748 })
  749 + // ------------- 2-1、添加每个part上部放置title的外部rect(以上)------------//
611 750  
  751 + // ------------- 2-2、添加每个part上部title(以下)------------//
612 752 itemsEnter.append('g')
613 753 .classed('titleBound', true)
614 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 756 .select(function (d, i) {return i === 0 ? this : null})
621 757 .append('image')
622 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 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 765 .append('text')
630 766 .classed('title', true)
631 767 .text(function (d, i) {
... ... @@ -659,27 +795,65 @@ export default {
659 795 })
660 796 .attr('x', function (d, i) {
661 797 if (i === 0) {
662   - return 60
  798 + return self.part1_line_icon_width + 10
663 799 } else {
664 800 return 0
665 801 }
666 802 })
667 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 844 itemsUpdate.select('g.titleBound')
671 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 847 let title_bounds = this.getBBox()
674 848 let dx = 1
675 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 858 if (dx < 0) {
685 859 dx = 1
... ... @@ -689,6 +863,7 @@ export default {
689 863 }
690 864 return `translate(${dx}, ${dy})`
691 865 })
  866 + // ------------- 2-2、添加每个part上部title(以上)------------//
692 867  
693 868 // ------------ 3、添加part的下半部分 ----------------//
694 869 // ------------ 3-1、part1部分 -------------//
... ... @@ -711,12 +886,12 @@ export default {
711 886 .style('fill', self.part1_terminal_stop_font_color)
712 887 itemsUpdate.select('g.content1Bound')
713 888 .attr('transform', function (d, i) {
714   - if (i === 0) {
  889 + if (i === 0) { // 相对于rect.main的下半部分的上二分之一居中(其中-5表示向上偏离5)
715 890 let rect_part1_bounds = svg.select('rect.main:nth-child(1)').node().getBBox()
716 891 let g_content1_bounds = this.getBBox()
717 892 let dx = (rect_part1_bounds.width - g_content1_bounds.width) / 2 - g_content1_bounds.x
718 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 895 if (dx < 0) {
721 896 dx = 1
722 897 }
... ... @@ -746,7 +921,7 @@ export default {
746 921 .style('fill', self.part1_terminal_stop_font_color)
747 922 itemsUpdate.select('g.content2Bound')
748 923 .attr('transform', function (d, i) {
749   - if (i === 0) {
  924 + if (i === 0) { // 相对于rect.main的下半部分的下二分之一居中
750 925 let rect_part1_bounds = svg.select('rect.main:nth-child(1)').node().getBBox()
751 926 let g_content1_bounds = this.getBBox()
752 927 let dx = (rect_part1_bounds.width - g_content1_bounds.width) / 2 - g_content1_bounds.x
... ... @@ -762,27 +937,29 @@ export default {
762 937 }
763 938 })
764 939  
765   -
766 940 // ------------ 3-2、part2部分 -------------//
  941 + // ------------ 3-2-1、当part3存在时,part2中间纵向添加一条虚线(以下)---------- //
767 942 let boundLineFun = d3.line()
768 943 itemsEnter.select(function (d, i) {
769   - return i === 1 ? this : null
  944 + return i === 1 && (showType === 0 || showType === 1) ? this : null
770 945 }).append('path')
771 946 .classed('bound', true)
772   - .attr('d', function (d) {
  947 + .attr('d', function () {
773 948 return boundLineFun([
774   - [partWidth / 2, 48],
  949 + [partWidth / 2, partTitleRectHeight],
775 950 [partWidth / 2, partHeight]
776 951 ])
777 952 })
778 953 itemsUpdate.select('path.bound')
779   - .attr('d', function (d) {
  954 + .attr('d', function () {
780 955 return boundLineFun([
781   - [partWidth / 2, 48],
  956 + [partWidth / 2, partTitleRectHeight],
782 957 [partWidth / 2, partHeight]
783 958 ])
784 959 })
  960 + // ------------ 3-2-1、当part3存在时,part2中间纵向添加一条虚线(以上)---------- //
785 961  
  962 + // ------------ 3-2-2、当part3存在时,part2纵向中间左侧添加内容标题(以下)----------- //
786 963 itemsEnter.select(function (d, i) {
787 964 return i === 1 ? this : null
788 965 }).append('g')
... ... @@ -801,11 +978,11 @@ export default {
801 978 .style('fill', self.part2_title2_font_color)
802 979 itemsUpdate.select('g.content3Bound')
803 980 .attr('transform', function (d, i) {
804   - if (i === 1) {
  981 + if (i === 1) { // x方向居中对齐,y方向顶部对齐
805 982 let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
806 983 let g_bounds = this.getBBox()
807 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 986 if (dx < 0) {
810 987 dx = 1
811 988 }
... ... @@ -815,7 +992,9 @@ export default {
815 992 return `translate(${dx}, ${dy})`
816 993 }
817 994 })
  995 + // ------------ 3-2-2、当part3存在时,part2纵向中间左侧添加内容标题(以上)----------- //
818 996  
  997 + // ------------ 3-2-3、当part3存在时,part2纵向中间右侧添加内容标题(以下)----------- //
819 998 itemsEnter.select(function (d, i) {
820 999 return i === 1 ? this : null
821 1000 }).append('g')
... ... @@ -834,7 +1013,7 @@ export default {
834 1013 .style('fill', self.part2_title2_font_color)
835 1014 itemsUpdate.select('g.content4Bound')
836 1015 .attr('transform', function (d, i) {
837   - if (i === 1) {
  1016 + if (i === 1) { // x方向居中对齐,y方向顶部对齐
838 1017 let rect_part2_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
839 1018 let g_bounds = this.getBBox()
840 1019 let dx = (rect_part2_bounds.width / 2 - g_bounds.width) / 2 - g_bounds.x
... ... @@ -849,7 +1028,9 @@ export default {
849 1028 return `translate(${dx},${dy})`
850 1029 }
851 1030 })
  1031 + // ------------ 3-2-3、当part3存在时,part2纵向中间右侧添加内容标题(以上)----------- //
852 1032  
  1033 + // ------------ 3-2-3、当part3存在时,part2纵向中间左侧添加内容(以下)----------- //
853 1034 itemsEnter.select(function (d, i) {
854 1035 return i === 1 ? this : null
855 1036 }).append('g')
... ... @@ -859,21 +1040,86 @@ export default {
859 1040 .append('text')
860 1041 .classed('content5_left', true)
861 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 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 1095 itemsEnter.select('g.content5Bound')
870 1096 .append('text')
871 1097 .classed('content5_right', true)
872 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 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 1124 .style('font-size', self.part2_arrival_time_minutes_right_font_size)
879 1125 .style('fill', self.part2_arrival_time_minutes_right_font_color)
... ... @@ -881,6 +1127,70 @@ export default {
881 1127 let left_bound = svg.select('text.content5_left').node().getBBox()
882 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 1194 itemsUpdate.select('g.content5Bound')
885 1195 .attr('transform', function (d, i) {
886 1196 if (i === 1) {
... ... @@ -898,9 +1208,11 @@ export default {
898 1208 return `translate(${dx}, ${dy})`
899 1209 }
900 1210 })
  1211 + // ------------ 3-2-3、当part3存在时,part2纵向中间左侧添加内容(以上)----------- //
901 1212  
  1213 + // ------------ 3-2-4、当part3存在时,part2纵向中间右侧添加内容(以下)----------- //
902 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 1216 }).append('g')
905 1217 .classed('content6Bound', true)
906 1218 .attr('transform', 'translate(10, 10)')
... ... @@ -908,10 +1220,18 @@ export default {
908 1220 .append('text')
909 1221 .classed('content6_left', true)
910 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 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 1236 .style('font-size', self.part2_from_stops_left_font_size)
917 1237 .style('fill', self.part2_from_stops_left_font_color)
... ... @@ -919,10 +1239,18 @@ export default {
919 1239 .append('text')
920 1240 .classed('content6_right', true)
921 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 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 1255 .style('font-size', self.part2_from_stops_right_font_size)
928 1256 .style('fill', self.part2_from_stops_right_font_color)
... ... @@ -930,6 +1258,45 @@ export default {
930 1258 let left_bound = svg.select('text.content6_left').node().getBBox()
931 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 1300 itemsUpdate.select('g.content6Bound')
934 1301 .attr('transform', function (d, i) {
935 1302 if (i === 1) {
... ... @@ -948,6 +1315,155 @@ export default {
948 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 1468 // ------------ 3-3、part3部分 -------------//
953 1469 itemsEnter.select(function (d, i) {
... ... @@ -972,9 +1488,34 @@ export default {
972 1488 .text(function (d) {
973 1489 return d.nextArrivalTime
974 1490 })
  1491 + .attr('title', function (d) {
  1492 + return d.nextArrivalTime
  1493 + })
975 1494 .style('font-size', self.part3_arrival_time_font_size)
976 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 1519 itemsUpdate.select('g.contentAllBound')
979 1520 .attr('transform', function (d, i) {
980 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 6 class MhgjEBusStopLineChartData {
3 7 /**
4 8 * 构造函数。
... ... @@ -29,6 +33,72 @@ class MhgjEBusStopLineChartData {
29 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 102 setLineName (lineName) {
33 103 this._lineName = lineName
34 104 return this
... ... @@ -87,6 +157,32 @@ class MhgjEBusStopLineChartData {
87 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 186 generateSvgData () {
91 187 // 根据内部数据产生svg用数据
92 188 let showData = [];
... ... @@ -178,6 +274,20 @@ class MhgjEBusStopLineChartData {
178 274 /**
179 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 291 static generateTestData_type1 () {
182 292 let testData = new MhgjEBusStopLineChartData()
183 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 31 import EBusStopLineChartList from 'core/plugins/bsth/lggj/list/eBusStop-line-chart-list'
32 32  
33 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 36 export const pluginsList = [
36 37 // {
... ... @@ -354,6 +355,18 @@ export const pluginsList = [
354 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 371 // i18nTitle: {
359 372 // 'en-US': 'LineChart',
... ...