Commit 6b8d3df635c2287d3b7bb12e647f0a9ebe3e44c1
1 parent
6622cf87
电子站牌项目
1、重新定义一个线路模拟图滚动列表组件(bsth-line-chart-scrollList)代替原来的bsth-line-chart-list 2、定义了垂直向上滚动策略,每次滚动一条记录,可以无缝滚动,TODO:其他滚动策略再议 3、TODO:滚动的时候发现,滚动项的高度是不一致,导致每次滚动,可能会看到最后的还未显示的记录项的头部,以及滚动到最后然后衔接第一条记录时会抖动,这些问题后面再议
Showing
9 changed files
with
936 additions
and
0 deletions
front-end/h5/src/components/core/plugins/bsth/bsth-line-chart-scrollList-page.js
0 → 100644
| 1 | +/** | |
| 2 | + * 自定义线路模拟图滚动列表数据组件。 | |
| 3 | + */ | |
| 4 | + | |
| 5 | +import TestData from 'core/plugins/bsth/bsth-line-chart-list_testData' | |
| 6 | +import LineRouteDataOfApi from 'core/plugins/bsth/models/lineRouteDataOfApi' | |
| 7 | +import ScrollListInnerData from 'core/plugins/bsth/models/scrollListInnerData' | |
| 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_milliseconds: { type: Number, required: true }, | |
| 22 | + // gps数据刷新间隔(分钟) | |
| 23 | + gps_data_refresh_minute: { type: Number, required: true } | |
| 24 | + }, | |
| 25 | + data () { | |
| 26 | + return { | |
| 27 | + innerDataSet: [], // 数据对象 | |
| 28 | + | |
| 29 | + // --------------- 滚动翻页数据对象 --------------// | |
| 30 | + scrollListInnerData: null, | |
| 31 | + | |
| 32 | + // ---------------- 内部的定时timer --------------- // | |
| 33 | + scrollTimer: { // 滚动间隔timer | |
| 34 | + timer: null, | |
| 35 | + count: 0, | |
| 36 | + millisecond: 2000 | |
| 37 | + } | |
| 38 | + } | |
| 39 | + }, | |
| 40 | + mounted () { | |
| 41 | + // 1、创建滚动翻页对象 | |
| 42 | + this.scrollListInnerData = new ScrollListInnerData(this.page_size, this.list_width, this.list_height) | |
| 43 | + // 2、初始化数据 | |
| 44 | + // TODO:先使用测试数据,后面使用后台数据 | |
| 45 | + const lineRouteDataOfApiArray = [] | |
| 46 | + for (let obj of TestData.lineRouteList) { | |
| 47 | + lineRouteDataOfApiArray.push(new LineRouteDataOfApi(obj)) | |
| 48 | + } | |
| 49 | + this.scrollListInnerData.initRouteData(lineRouteDataOfApiArray) | |
| 50 | + this.scrollListInnerData.refreshGps(TestData.lineGpsList) | |
| 51 | + this.innerDataSet = this.scrollListInnerData.scrollDataItemList | |
| 52 | + | |
| 53 | + // 3、发送refreshData事件 | |
| 54 | + this.$emit('bindData', this.innerDataSet) | |
| 55 | + | |
| 56 | + // 4、preview模式下启动滚动分页 | |
| 57 | + if (this.editorMode === 'preview') { | |
| 58 | + this.scrollTimer.count++ | |
| 59 | + } | |
| 60 | + }, | |
| 61 | + destroyed () { | |
| 62 | + let scrollTimer = this.scrollTimer.timer | |
| 63 | + if (scrollTimer) { | |
| 64 | + try { | |
| 65 | + clearTimeout(scrollTimer) | |
| 66 | + } catch (err) {} | |
| 67 | + } | |
| 68 | + this.scrollTimer.timer = null | |
| 69 | + | |
| 70 | + if (this.scrollListInnerData) { | |
| 71 | + this.scrollListInnerData.resetData() | |
| 72 | + } | |
| 73 | + }, | |
| 74 | + watch: { | |
| 75 | + 'scrollTimer.count' () { | |
| 76 | + let timer = this.scrollTimer.timer | |
| 77 | + if (timer) { | |
| 78 | + try { | |
| 79 | + clearTimeout(timer) | |
| 80 | + } catch (err) {} | |
| 81 | + this.scrollTimer.timer = null | |
| 82 | + } | |
| 83 | + let self = this | |
| 84 | + this.scrollTimer.timer = setTimeout(function () { | |
| 85 | + self.startScroll() | |
| 86 | + self.scrollTimer.count++ | |
| 87 | + }, this.scroll_milliseconds) | |
| 88 | + }, | |
| 89 | + // -------------------- 监控父组件传递的属性 --------------- // | |
| 90 | + page_size (val) { | |
| 91 | + // 只在edit模式下监控,preview模式下不监控 | |
| 92 | + if (this.editorMode === 'edit') { // 使用测试数据 | |
| 93 | + this.scrollListInnerData.pageSize = val | |
| 94 | + } | |
| 95 | + }, | |
| 96 | + list_width (val) { | |
| 97 | + this.scrollListInnerData.listWidth = val | |
| 98 | + }, | |
| 99 | + list_height (val) { | |
| 100 | + this.scrollListInnerData.listHeight = val | |
| 101 | + } | |
| 102 | + }, | |
| 103 | + render () { | |
| 104 | + // TODO:暂时是没有内容显示的,只处理内部数据,后面再根据不同的错误显示内容 | |
| 105 | + return ( | |
| 106 | + <div></div> | |
| 107 | + ) | |
| 108 | + }, | |
| 109 | + methods: { | |
| 110 | + startScroll () { | |
| 111 | + this.scrollListInnerData.scrollUp(this) | |
| 112 | + } | |
| 113 | + } | |
| 114 | +} | ... | ... |
front-end/h5/src/components/core/plugins/bsth/bsth-line-chart-scrollList.js
0 → 100644
| 1 | +/** | |
| 2 | + * 自定义线路模拟图滚动列表组件。 | |
| 3 | + */ | |
| 4 | +import PropTypes from '@luban-h5/plugin-common-props' | |
| 5 | + | |
| 6 | +import ScrollPage from 'core/plugins/bsth/bsth-line-chart-scrollList-page' | |
| 7 | + | |
| 8 | +export default { | |
| 9 | + extra: { | |
| 10 | + defaultStyle: { // 默认属性 | |
| 11 | + top: 0, | |
| 12 | + left: 0, | |
| 13 | + width: 350, | |
| 14 | + height: 300 | |
| 15 | + } | |
| 16 | + }, | |
| 17 | + name: 'bsth-line-chart-scrollList', | |
| 18 | + data () { | |
| 19 | + // eslint-disable-next-line | |
| 20 | + this.private_jQuery = jQuery.noConflict() // jquery引用 | |
| 21 | + return { | |
| 22 | + /** | |
| 23 | + * 监控外层元素的宽度高度变化 | |
| 24 | + * 1、由于编辑器缩放,自定义组件无法监控,所以需要定义一个定时器监控最外层元素的大小变化 | |
| 25 | + * 2、建议所有自定义组件,最外层都定义一个div包在自定义组件最外层,不要关联任何自定义的属性,样式对应编辑器的通用样式 | |
| 26 | + */ | |
| 27 | + watchWidthHeightTimer: { | |
| 28 | + timer: null, | |
| 29 | + count: 0, | |
| 30 | + millisecond: 1000 | |
| 31 | + }, | |
| 32 | + list_width: 350, // 列表宽度 | |
| 33 | + list_height: 300, // 列表高度 | |
| 34 | + line_chart_outer_div_width: 0, // 线路图外层div宽度 | |
| 35 | + line_chart_outer_div_height: 0, // 线路图外层div高度 | |
| 36 | + internalDataSet: [], // 内部数据(由数据组件生成) | |
| 37 | + scrollTop: 0 // 控制垂直滚动 top | |
| 38 | + } | |
| 39 | + }, | |
| 40 | + props: { | |
| 41 | + editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview) | |
| 42 | + defaultValue: 'preview', | |
| 43 | + label: '模式', | |
| 44 | + visible: false | |
| 45 | + }), | |
| 46 | + // --------------- 数据属性 -------------- // | |
| 47 | + _flag_1_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='数据属性' class='bsth-line-item-divider'/>) } }), | |
| 48 | + page_size: PropTypes.number({ label: '每页显示线路图数量', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }), | |
| 49 | + scroll_mode: PropTypes.select({ label: '滚动模式', defaultValue: 'up', options: [{ label: '向上滚动', value: 'up' }, { label: '向下滚动', value: 'down' }], layout: { prefixCls: 'bsth-line' } }), | |
| 50 | + scroll_milliseconds: PropTypes.number({ label: '滚动时间间隔(毫秒)', defaultValue: 2000, layout: { prefixCls: 'bsth-line' } }), | |
| 51 | + gps_data_refresh_minute: PropTypes.number({ label: 'gps数据刷新间隔(分钟)', defaultValue: 1, layout: { prefixCls: 'bsth-line' } }), | |
| 52 | + // --------------- 外层css属性 --------------- // | |
| 53 | + _flag_2_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='外层css属性' class='bsth-line-item-divider'/>) } }), | |
| 54 | + margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }), | |
| 55 | + margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }), | |
| 56 | + margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }), | |
| 57 | + margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }), | |
| 58 | + border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 1, layout: { prefixCls: 'bsth-line' } }), | |
| 59 | + background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), | |
| 60 | + // --------------- 内部线路模拟图外层css属性 --------------- // | |
| 61 | + _flag_3_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='内部线路模拟图外层css属性' class='bsth-line-item-divider'></hr>) } }), | |
| 62 | + line_chart_name_font_size: PropTypes.number({ label: '线路名称字体大小', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }), | |
| 63 | + line_chart_name_font_color: PropTypes.color({ label: '线路名称字体颜色', defaultValue: '#babdbd', layout: { prefixCls: 'bsth-line' } }), | |
| 64 | + line_chart_margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 10, layout: { prefixCls: 'bsth-line' } }), | |
| 65 | + line_chart_margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 10, layout: { prefixCls: 'bsth-line' } }), | |
| 66 | + line_chart_margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }), | |
| 67 | + line_chart_margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }), | |
| 68 | + line_chart_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 1, layout: { prefixCls: 'bsth-line' } }), | |
| 69 | + line_chart_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), | |
| 70 | + // --------------- 内部线路模拟图内层css属性 --------------- // | |
| 71 | + _flag_4_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='内部线路模拟图内层css属性' class='bsth-line-item-divider'></hr>) } }), | |
| 72 | + chart_left_padding: PropTypes.number({ label: '内部线路图距离左边padding', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }), | |
| 73 | + chart_right_padding: PropTypes.number({ label: '内部线路图居中修正padding', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }), | |
| 74 | + chart_center_top_padding: PropTypes.number({ label: '内部线路图居中修正padding', defaultValue: 4, layout: { prefixCls: 'bsth-line' } }), | |
| 75 | + chart_station_name_max_size: PropTypes.number({ label: '站定名显示最大文字个数', defaultValue: 7, layout: { prefixCls: 'bsth-line' } }), | |
| 76 | + chart_up_line_path_s_color: PropTypes.color({ label: '上行线颜色', defaultValue: '#5E96D2', layout: { prefixCls: 'bsth-line' } }), | |
| 77 | + chart_down_line_path_s_color: PropTypes.color({ label: '下行线颜色', defaultValue: '#c92121', layout: { prefixCls: 'bsth-line' } }), | |
| 78 | + chart_up_line_circle_f_color: PropTypes.color({ label: '上行线站点圆圈填充色', defaultValue: '#5e96d2', layout: { prefixCls: 'bsth-line' } }), | |
| 79 | + chart_down_line_circle_f_color: PropTypes.color({ label: '下行线站点圆圈填充色', defaultValue: '#c92121', layout: { prefixCls: 'bsth-line' } }), | |
| 80 | + chart_station_text_font_size: PropTypes.number({ label: '站名字体大小', defaultValue: 14, layout: { prefixCls: 'bsth-line' } }), | |
| 81 | + chart_up_station_text_font_f_color: PropTypes.color({ label: '上行站名颜色', defaultValue: '#4556b6', layout: { prefixCls: 'bsth-line' } }), | |
| 82 | + chart_down_station_text_font_f_color: PropTypes.color({ label: '下行站名颜色', defaultValue: '#c94f21', layout: { prefixCls: 'bsth-line' } }), | |
| 83 | + chart_up_down_station_text_font_f_color: PropTypes.color({ label: '上行下行同名站名颜色', defaultValue: '#3e3e3e', layout: { prefixCls: 'bsth-line' } }), | |
| 84 | + chart_gps_up_rect_color: PropTypes.color({ label: '上行gps车辆rect背景色', defaultValue: '#3e50b3', layout: { prefixCls: 'bsth-line' } }), | |
| 85 | + chart_gps_up_text_f_color: PropTypes.color({ label: '上行gps车辆文本颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), | |
| 86 | + chart_gps_down_rect_color: PropTypes.color({ label: '下行gps车辆rect背景色', defaultValue: '#c94f21', layout: { prefixCls: 'bsth-line' } }), | |
| 87 | + chart_gps_down_text_f_color: PropTypes.color({ label: '下行gps车辆文本颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), | |
| 88 | + chart_gps_up_merge_rect_color: PropTypes.color({ label: '上行合并gps车辆rect背景色', defaultValue: '#19a53a', layout: { prefixCls: 'bsth-line' } }), | |
| 89 | + chart_gps_up_merge_text_f_color: PropTypes.color({ label: '上行合并gps车辆文本颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), | |
| 90 | + chart_gps_down_merge_rect_color: PropTypes.color({ label: '下行合并gps车辆rect背景色', defaultValue: '#19a53a', layout: { prefixCls: 'bsth-line' } }), | |
| 91 | + chart_gps_down_merge_text_f_color: PropTypes.color({ label: '下行合并gps车辆文本颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }) | |
| 92 | + }, | |
| 93 | + render () { | |
| 94 | + const innerDivStyle = { | |
| 95 | + 'width': this.list_width + 'px', | |
| 96 | + 'height': this.list_height + 'px', | |
| 97 | + 'border': this.border_size + 'px solid black', | |
| 98 | + 'margin-left': this.margin_left + 'px', | |
| 99 | + 'margin-right': this.margin_right + 'px', | |
| 100 | + 'margin-top': this.margin_top + 'px', | |
| 101 | + 'margin-bottom': this.margin_bottom + 'px', | |
| 102 | + 'background': this.background_color, | |
| 103 | + 'position': 'relative', | |
| 104 | + 'overflow': 'hidden' | |
| 105 | + } | |
| 106 | + | |
| 107 | + // TODO: | |
| 108 | + const wrapperDivStyle = { | |
| 109 | + 'top': this.scrollTop + 'px', | |
| 110 | + 'position': 'absolute', | |
| 111 | + 'width': this.list_width + 'px', | |
| 112 | + 'height': this.list_height * 4 + 'px' | |
| 113 | + } | |
| 114 | + | |
| 115 | + /* 最外层div对应编辑器的通用样式 */ | |
| 116 | + return ( | |
| 117 | + <div> | |
| 118 | + { | |
| 119 | + this.renderScrollDataComponent() | |
| 120 | + } | |
| 121 | + <div style={innerDivStyle}> | |
| 122 | + <div style={wrapperDivStyle}> | |
| 123 | + { | |
| 124 | + this.internalDataSet.map(dataItem => ( | |
| 125 | + this.renderBsthLinechartDataList(dataItem) | |
| 126 | + )) | |
| 127 | + } | |
| 128 | + </div> | |
| 129 | + </div> | |
| 130 | + </div> | |
| 131 | + ) | |
| 132 | + }, | |
| 133 | + mounted () { | |
| 134 | + // 使用外部元素的框架定义图的长宽 | |
| 135 | + let $jQuery = this.private_jQuery | |
| 136 | + this.list_width = $jQuery(this.$el).width() - this.margin_left - this.margin_right - this.border_size * 2 | |
| 137 | + this.list_height = $jQuery(this.$el).height() - this.margin_top - this.margin_bottom - this.border_size * 2 | |
| 138 | + // 线路图外层div长宽就是列表长宽,因为线路图作为子组件无法编辑通用样式,最外穿div的margin,border一律为0 | |
| 139 | + this.line_chart_outer_div_width = this.list_width | |
| 140 | + this.line_chart_outer_div_height = Math.floor(this.list_height / this.page_size) | |
| 141 | + // 开启外部元素长宽监控计数 | |
| 142 | + /** | |
| 143 | + * 开启外部元素长宽监控逻辑 | |
| 144 | + * 1、必须在编辑模式下启效果,否则无效 | |
| 145 | + */ | |
| 146 | + if (this.editorMode === 'edit') { | |
| 147 | + this.watchWidthHeightTimer.count++ | |
| 148 | + } | |
| 149 | + // TODO:使用数据组件获取数据 | |
| 150 | + }, | |
| 151 | + destroyed () { | |
| 152 | + // 消耗 watchWidthHeightTimer 定时器 | |
| 153 | + let timer1 = this.watchWidthHeightTimer.timer | |
| 154 | + if (timer1) { | |
| 155 | + try { | |
| 156 | + clearTimeout(timer1) | |
| 157 | + } catch (e) {} | |
| 158 | + this.watchWidthHeightTimer.timer = null | |
| 159 | + } | |
| 160 | + | |
| 161 | + // TODO:其他 | |
| 162 | + }, | |
| 163 | + watch: { | |
| 164 | + 'watchWidthHeightTimer.count' () { // 长宽定时器监控 | |
| 165 | + let timer = this.watchWidthHeightTimer.timer | |
| 166 | + if (timer) { | |
| 167 | + clearTimeout(timer) | |
| 168 | + this.watchWidthHeightTimer.timer = null | |
| 169 | + } | |
| 170 | + | |
| 171 | + let self = this | |
| 172 | + let $jQuery = this.private_jQuery | |
| 173 | + self.watchWidthHeightTimer.timer = setTimeout(function () { | |
| 174 | + // 处理逻辑 | |
| 175 | + let width = $jQuery(self.$el).width() | |
| 176 | + let height = $jQuery(self.$el).height() | |
| 177 | + | |
| 178 | + if (width !== self.list_width) { | |
| 179 | + self.list_width = width - self.margin_left - self.margin_right - self.border_size * 2 | |
| 180 | + self.line_chart_outer_div_width = self.list_width | |
| 181 | + } | |
| 182 | + if (height !== self.list_height) { | |
| 183 | + self.list_height = height - self.margin_top - self.margin_bottom - self.border_size * 2 | |
| 184 | + self.line_chart_outer_div_height = Math.floor(self.list_height / self.page_size) | |
| 185 | + } | |
| 186 | + | |
| 187 | + self.watchWidthHeightTimer.count++ | |
| 188 | + }, self.watchWidthHeightTimer.millisecond) | |
| 189 | + }, | |
| 190 | + // ----------------- 数据属性 ---------------- // | |
| 191 | + page_size (val) { | |
| 192 | + self.line_chart_outer_div_height = Math.floor(self.list_height / self.page_size) | |
| 193 | + }, | |
| 194 | + // ----------------- 本身宽高 监控 ---------------- // | |
| 195 | + list_width () { | |
| 196 | + let self = this | |
| 197 | + self.line_chart_outer_div_width = self.list_width | |
| 198 | + }, | |
| 199 | + list_height () { | |
| 200 | + let self = this | |
| 201 | + self.line_chart_outer_div_height = Math.floor(self.list_height / self.page_size) | |
| 202 | + }, | |
| 203 | + // ----------------- 外层css属性 监控 ----------------- // | |
| 204 | + margin_left () { | |
| 205 | + let self = this | |
| 206 | + self.list_width = self.list_width - self.margin_left - self.margin_right - self.border_size * 2 | |
| 207 | + }, | |
| 208 | + margin_right () { | |
| 209 | + let self = this | |
| 210 | + self.list_width = self.list_width - self.margin_left - self.margin_right - self.border_size * 2 | |
| 211 | + }, | |
| 212 | + margin_top () { | |
| 213 | + let self = this | |
| 214 | + self.list_height = self.list_height - self.margin_top - self.margin_bottom - self.border_size * 2 | |
| 215 | + }, | |
| 216 | + margin_bottom () { | |
| 217 | + let self = this | |
| 218 | + self.list_height = self.list_height - self.margin_top - self.margin_bottom - self.border_size * 2 | |
| 219 | + }, | |
| 220 | + border_size () { | |
| 221 | + let self = this | |
| 222 | + self.list_width = self.list_width - self.margin_left - self.margin_right - self.border_size * 2 | |
| 223 | + self.list_height = self.list_height - self.margin_top - self.margin_bottom - self.border_size * 2 | |
| 224 | + } | |
| 225 | + }, | |
| 226 | + methods: { | |
| 227 | + onScrollTop (val) { | |
| 228 | + this.scrollTop = val | |
| 229 | + }, | |
| 230 | + onBindData (dataSet) { | |
| 231 | + // 初始化的时候绑定一次数据,之后所有数据的变化都在ScrollPage内部变化 | |
| 232 | + this.internalDataSet = dataSet | |
| 233 | + }, | |
| 234 | + renderScrollDataComponent () { | |
| 235 | + return ( | |
| 236 | + <ScrollPage | |
| 237 | + editorMode={this.editorMode} | |
| 238 | + page_size={this.page_size} | |
| 239 | + list_width={this.list_width} | |
| 240 | + list_height={this.list_height} | |
| 241 | + scroll_milliseconds={this.scroll_milliseconds} | |
| 242 | + gps_data_refresh_minute={this.gps_data_refresh_minute} | |
| 243 | + onBindData={this.onBindData} | |
| 244 | + onScrollTop={this.onScrollTop} | |
| 245 | + ></ScrollPage> | |
| 246 | + ) | |
| 247 | + }, | |
| 248 | + renderBsthLinechartDataList (dataItem) { | |
| 249 | + return ( | |
| 250 | + <bsth-line-chart | |
| 251 | + useMode='child' | |
| 252 | + editorMode={this.editorMode} | |
| 253 | + line_chart_outer_div_width={this.line_chart_outer_div_width} | |
| 254 | + line_chart_outer_div_height={this.line_chart_outer_div_height} | |
| 255 | + line_route_data_child={dataItem.route} | |
| 256 | + line_gps_data_child={dataItem.gps} | |
| 257 | + line_name={dataItem.lineName} | |
| 258 | + line_code={dataItem.lineCode} | |
| 259 | + // 内部线路模拟图外层css属性 | |
| 260 | + line_name_font_size={this.line_chart_name_font_size} | |
| 261 | + line_name_font_color={this.line_chart_name_font_color} | |
| 262 | + margin_left={this.line_chart_margin_left} | |
| 263 | + margin_right={this.line_chart_margin_right} | |
| 264 | + margin_top={this.line_chart_margin_top} | |
| 265 | + margin_bottom={this.line_chart_margin_bottom} | |
| 266 | + border_size={this.line_chart_border_size} | |
| 267 | + background_color={this.line_chart_background_color} | |
| 268 | + // 内部线路模拟图内层css属性 | |
| 269 | + chart_left_padding={this.chart_left_padding} | |
| 270 | + chart_right_padding={this.chart_right_padding} | |
| 271 | + chart_center_top_padding={this.chart_center_top_padding} | |
| 272 | + chart_station_name_max_size={this.chart_station_name_max_size} | |
| 273 | + chart_up_line_path_s_color={this.chart_up_line_path_s_color} | |
| 274 | + chart_down_line_path_s_color={this.chart_down_line_path_s_color} | |
| 275 | + chart_up_line_circle_f_color={this.chart_up_line_circle_f_color} | |
| 276 | + chart_down_line_circle_f_color={this.chart_down_line_circle_f_color} | |
| 277 | + chart_station_text_font_size={this.chart_station_text_font_size} | |
| 278 | + chart_up_station_text_font_f_color={this.chart_up_station_text_font_f_color} | |
| 279 | + chart_down_station_text_font_f_color={this.chart_down_station_text_font_f_color} | |
| 280 | + chart_up_down_station_text_font_f_color={this.chart_up_down_station_text_font_f_color} | |
| 281 | + chart_gps_up_rect_color={this.chart_gps_up_rect_color} | |
| 282 | + chart_gps_up_text_f_color={this.chart_gps_up_text_f_color} | |
| 283 | + chart_gps_down_rect_color={this.chart_gps_down_rect_color} | |
| 284 | + chart_gps_down_text_f_color={this.chart_gps_down_text_f_color} | |
| 285 | + chart_gps_up_merge_rect_color={this.chart_gps_up_merge_rect_color} | |
| 286 | + chart_gps_up_merge_text_f_color={this.chart_gps_up_merge_text_f_color} | |
| 287 | + chart_gps_down_merge_rect_color={this.chart_gps_down_merge_rect_color} | |
| 288 | + chart_gps_down_merge_text_f_color={this.chart_gps_down_merge_text_f_color} | |
| 289 | + /> | |
| 290 | + ) | |
| 291 | + } | |
| 292 | + } | |
| 293 | +} | ... | ... |
front-end/h5/src/components/core/plugins/bsth/models/lineGpsDataOfApi.js
0 → 100644
| 1 | +/** | |
| 2 | + * Api接口传过来的线路gps数据格式类。 | |
| 3 | + * @param value 参数对象 | |
| 4 | + * 参数对象说明: | |
| 5 | + * { | |
| 6 | + * lineName: '测试线路1', | |
| 7 | + * lineCode: '线路编码1', | |
| 8 | + * stopNo: 'ACODE', // 站点编码 | |
| 9 | + * upDown: 1, // 上下行(0 上行 , 1 下行 , -1 无效) | |
| 10 | + * deviceId: '559L1045', // 设备编码 | |
| 11 | + * instation: 1, // 0: 站外 1:站内 2:场内 | |
| 12 | + * nbbm: 'W2B-046' // 车辆内部编码(自编号) | |
| 13 | + * } | |
| 14 | + */ | |
| 15 | +class LineGpsDataOfApi { | |
| 16 | + constructor (value = {}) { | |
| 17 | + this.lineName = value.lineName // 线路名字 | |
| 18 | + this.lineCode = value.lineCode // 线路编码 | |
| 19 | + this.stopNo = value.stopNo // 站定编码 | |
| 20 | + this.upDown = value.upDown // 上下行(0 上行 , 1 下行 , -1 无效) | |
| 21 | + this.deviceId = value.deviceId // 设备编码 | |
| 22 | + this.instation = value.instation // 0: 站外 1:站内 2:场内 | |
| 23 | + this.nbbm = value.nbbm // 车辆内部编码(自编号) | |
| 24 | + } | |
| 25 | +} | |
| 26 | + | |
| 27 | +export default LineGpsDataOfApi | ... | ... |
front-end/h5/src/components/core/plugins/bsth/models/lineGpsDataOfLineChart.js
0 → 100644
| 1 | +/** | |
| 2 | + * 线路模拟图组件(bsth-line-chart)用的线路Gps数据格式类。 | |
| 3 | + * @param value 参数对象 | |
| 4 | + * 参数对象说明: | |
| 5 | + * { | |
| 6 | + * stopNo: 'BCODE', // 站点编码 | |
| 7 | + * upDown: 0, // 上下行(0 上行 , 1 下行 , -1 无效) | |
| 8 | + * deviceId: '559L1014', // 设备编码 | |
| 9 | + * instation: 1, // 0: 站外 1:站内 2:场内 | |
| 10 | + * nbbm: 'W2B-064' // 车辆内部编码(自编号) | |
| 11 | + * } | |
| 12 | + */ | |
| 13 | +class LineGpsDataOfLineChart { | |
| 14 | + constructor (value = {}) { | |
| 15 | + this.stopNo = value.stopNo // 站点编码 | |
| 16 | + this.upDown = value.upDown // 上下行(0 上行 , 1 下行 , -1 无效) | |
| 17 | + this.deviceId = value.deviceId // 设备编码 | |
| 18 | + this.instation = value.instation // 0: 站外 1:站内 2:场内 | |
| 19 | + this.nbbm = value.nbbm // 车辆内部编码(自编号) | |
| 20 | + } | |
| 21 | +} | |
| 22 | + | |
| 23 | +export default LineGpsDataOfLineChart | ... | ... |
front-end/h5/src/components/core/plugins/bsth/models/lineRouteDataOfApi.js
0 → 100644
| 1 | +/** | |
| 2 | + * Api接口传过来的线路路由数据格式类。 | |
| 3 | + * @param value 参数对象 | |
| 4 | + * 参数对象说明: | |
| 5 | + * { | |
| 6 | + * lineName: '测试线路1', | |
| 7 | + * lineCode: '线路编码1', | |
| 8 | + * directions: 0, | |
| 9 | + * stationRouteCode: 10, | |
| 10 | + * stationCode: 'ACODE', | |
| 11 | + * stationName: 'A起点站', | |
| 12 | + * stationMark: 'B' | |
| 13 | + * } | |
| 14 | + */ | |
| 15 | +class LineRouteDataOfApi { | |
| 16 | + constructor (value = {}) { | |
| 17 | + this.lineName = value.lineName // 线路名字 | |
| 18 | + this.lineCode = value.lineCode // 线路编码 | |
| 19 | + this.directions = value.directions // 方向 0:上行,1:下行 | |
| 20 | + this.stationRouteCode = value.stationRouteCode // 站点路由代码(用于站点排序) | |
| 21 | + this.stationCode = value.stationCode // 站点编码 | |
| 22 | + this.stationName = value.stationName // 站点名字 | |
| 23 | + this.stationMark = value.stationMark // 站定标识 B:起点站,E:终点站,Z:中途站 | |
| 24 | + } | |
| 25 | + | |
| 26 | + toObject () { | |
| 27 | + return { | |
| 28 | + lineName: this.lineName, | |
| 29 | + lineCode: this.lineCode, | |
| 30 | + directions: this.directions, | |
| 31 | + stationRouteCode: this.stationRouteCode, | |
| 32 | + stationCode: this.stationCode, | |
| 33 | + stationName: this.stationName, | |
| 34 | + stationMark: this.stationMark | |
| 35 | + } | |
| 36 | + } | |
| 37 | +} | |
| 38 | + | |
| 39 | +export default LineRouteDataOfApi | ... | ... |
front-end/h5/src/components/core/plugins/bsth/models/lineRouteDataOfLineChart.js
0 → 100644
| 1 | +/** | |
| 2 | + * 线路模拟图组件(bsth-line-chart)用的线路路由数据格式类。 | |
| 3 | + * @param value 参数对象 | |
| 4 | + * { | |
| 5 | + * names: ["A起点站"], // 站点名字数组 | |
| 6 | + * ids: ["ACODE_0", "ACODE_1"], // 站点编码_上下行 | |
| 7 | + * type: 2, // 0:上行 1:下行 2:同名合并 3:异名合并 | |
| 8 | + * stationMark: "B" // 站点表识 | |
| 9 | + * } | |
| 10 | + */ | |
| 11 | + | |
| 12 | +import LineRouteDataOfApi from 'core/plugins/bsth/models/lineRouteDataOfApi' | |
| 13 | + | |
| 14 | +class LineRouteDataOfLineChart { | |
| 15 | + constructor (value = {}) { | |
| 16 | + this.names = value.names // 站定名字数组 | |
| 17 | + this.ids = value.ids // // 站点编码_上下行 数组 | |
| 18 | + this.type = value.type // 0:上行 1:下行 2:同名合并 3:异名合并 | |
| 19 | + this.stationMark = value.stationMark // 站点表识 B:起点站,E:终点站,Z:中途站 | |
| 20 | + } | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 构造内部数据 | |
| 24 | + * @param up 上行站点数据(LineRouteDataOfApi类型) | |
| 25 | + * @param down 下行站点数据(LineRouteDataOfApi类型) | |
| 26 | + */ | |
| 27 | + static fromLineRouteDataOfApi (up, down) { | |
| 28 | + if (up === null && down === null) { | |
| 29 | + return null | |
| 30 | + } | |
| 31 | + | |
| 32 | + if (up !== null && !(up instanceof LineRouteDataOfApi)) { | |
| 33 | + throw new Error('up不等于null,up参数不是LineRouteDataOfApi类型') | |
| 34 | + } | |
| 35 | + if (down !== null && !(down instanceof LineRouteDataOfApi)) { | |
| 36 | + throw new Error('down不等于null,down参数不是LineRouteDataOfApi类型') | |
| 37 | + } | |
| 38 | + | |
| 39 | + let [names, type, ids, stationMark] = [null, 2, null, null] | |
| 40 | + if (up === null) { | |
| 41 | + type = 1 | |
| 42 | + names = [down.stationName] | |
| 43 | + ids = [down.stationCode + '_' + down.directions] | |
| 44 | + stationMark = down.stationMark | |
| 45 | + } else if (down === null) { | |
| 46 | + type = 0 | |
| 47 | + names = [up.stationName] | |
| 48 | + ids = [up.stationCode + '_' + up.directions] | |
| 49 | + stationMark = up.stationMark | |
| 50 | + } else { | |
| 51 | + names = [up.stationName] | |
| 52 | + ids = [up.stationCode + '_' + up.directions, down.stationCode + '_' + down.directions] | |
| 53 | + stationMark = up.stationMark | |
| 54 | + if (up.stationName !== down.stationName) { | |
| 55 | + type = 3 | |
| 56 | + names.push(down.stationName) | |
| 57 | + } | |
| 58 | + } | |
| 59 | + return new LineRouteDataOfLineChart({ names, ids, type, stationMark }) | |
| 60 | + } | |
| 61 | +} | |
| 62 | + | |
| 63 | +export default LineRouteDataOfLineChart | ... | ... |
front-end/h5/src/components/core/plugins/bsth/models/scrollListInnerData.js
0 → 100644
| 1 | +/** | |
| 2 | + * 线路模拟图滚动列表组件(bsth-line-chart-scrollList)内部数据类。 | |
| 3 | + */ | |
| 4 | + | |
| 5 | +import Utils from 'core/plugins/bsth/bsth-utils' | |
| 6 | +import LineRouteDataOfLineChart from 'core/plugins/bsth/models/lineRouteDataOfLineChart' | |
| 7 | +import LineGpsDataOfLineChart from 'core/plugins/bsth/models/lineGpsDataOfLineChart' | |
| 8 | +import ScrollListInnerDataItem from 'core/plugins/bsth/models/scrollListInnerDataItem' | |
| 9 | + | |
| 10 | +class ScrollListInnerData { | |
| 11 | + constructor (pageSize, listWidth, listHeight) { | |
| 12 | + this._pageSize = pageSize // 每页大小 | |
| 13 | + this._listWidth = listWidth // 滚动列表宽度 | |
| 14 | + this._listHeight = listHeight // 滚动列表高度 | |
| 15 | + | |
| 16 | + // --------------- 内部数据对象 ---------------- // | |
| 17 | + this._innerDataItemList = [] // InnerDataItem类型数组 | |
| 18 | + this._pageCount = 0 // 一共多少页 | |
| 19 | + | |
| 20 | + // --------------- 内部滚动数据对象 --------------- // | |
| 21 | + this._scrollDataItemList = [] // 滚动用的InnerDataItem类型数组(根据不同的滚动策略会和_innerDataItemList不一致) | |
| 22 | + this._currentScrollIndex = 0 // 当前滚动项index | |
| 23 | + this._nextScrollIndex = 1 // 下一个滚动项index | |
| 24 | + this._scrollAnimateTimer = { // 滚动动画效果timer | |
| 25 | + timer: null, | |
| 26 | + count: 0, | |
| 27 | + millisecond: 1 | |
| 28 | + } | |
| 29 | + } | |
| 30 | + set pageSize (val) { // 设置每页大小 | |
| 31 | + this._pageSize = val | |
| 32 | + this._pageCount = Math.ceil(this._innerDataItemList.length / this._pageSize) | |
| 33 | + // 重新计算_scrollDataItemList | |
| 34 | + refreshScrollData.call(this) | |
| 35 | + } | |
| 36 | + get scrollDataItemList () { // 返回滚动数据集 | |
| 37 | + return this._scrollDataItemList | |
| 38 | + } | |
| 39 | + set listWidth (val) { | |
| 40 | + this._listWidth = val | |
| 41 | + // 刷新滚动数据中 宽,高,top | |
| 42 | + refreshScrollDataSizeProperty.call(this) | |
| 43 | + } | |
| 44 | + set listHeight (val) { | |
| 45 | + this._listHeight = val | |
| 46 | + // 刷新滚动数据中 宽,高,top | |
| 47 | + refreshScrollDataSizeProperty.call(this) | |
| 48 | + } | |
| 49 | + | |
| 50 | + // -------------------------------- 移动方法 ---------------------------- // | |
| 51 | + scrollUp (scrollListComponent) { // 向上滚动 | |
| 52 | + if (this._scrollDataItemList.length <= this._pageSize) { // 总数据小于页大小,不滚动 | |
| 53 | + return | |
| 54 | + } | |
| 55 | + | |
| 56 | + if (this._scrollAnimateTimer.timer) { | |
| 57 | + try { | |
| 58 | + clearInterval(this._scrollAnimateTimer.timer) | |
| 59 | + } catch (err) {} | |
| 60 | + this._scrollAnimateTimer.timer = null | |
| 61 | + } | |
| 62 | + | |
| 63 | + let topFrom = this._scrollDataItemList[this._currentScrollIndex].top | |
| 64 | + let topTo = this._scrollDataItemList[this._nextScrollIndex].top | |
| 65 | + let step = (topTo - topFrom) / 100 | |
| 66 | + let self = this | |
| 67 | + self._scrollAnimateTimer.timer = setInterval(function () { | |
| 68 | + self._scrollAnimateTimer.count++ | |
| 69 | + let currentTop = topFrom + self._scrollAnimateTimer.count * step | |
| 70 | + // console.log(currentTop) | |
| 71 | + scrollListComponent.$emit('scrollTop', currentTop) | |
| 72 | + if (Math.abs(topTo - currentTop) < Math.abs(step)) { | |
| 73 | + scrollListComponent.$emit('scrollTop', topTo) | |
| 74 | + self._scrollAnimateTimer.count = 0 | |
| 75 | + | |
| 76 | + // console.log(self._pageCount) | |
| 77 | + // console.log(self._scrollDataItemList[self._nextScrollIndex].pageIndex) | |
| 78 | + if (self._scrollDataItemList[self._nextScrollIndex].pageIndex === self._pageCount) { | |
| 79 | + scrollListComponent.$emit('scrollTop', self._scrollDataItemList[0].top) | |
| 80 | + self._currentScrollIndex = 0 | |
| 81 | + self._nextScrollIndex = 1 | |
| 82 | + } else { | |
| 83 | + self._currentScrollIndex = self._nextScrollIndex | |
| 84 | + self._nextScrollIndex++ | |
| 85 | + } | |
| 86 | + | |
| 87 | + if (self._scrollAnimateTimer.timer) { | |
| 88 | + try { | |
| 89 | + clearInterval(self._scrollAnimateTimer.timer) | |
| 90 | + } catch (err) {} | |
| 91 | + self._scrollAnimateTimer.timer = null | |
| 92 | + } | |
| 93 | + } | |
| 94 | + }, 1) | |
| 95 | + } | |
| 96 | + | |
| 97 | + // -------------------------------- 数据处理方法 -------------------------------// | |
| 98 | + /** | |
| 99 | + * 初始化路由数据。 | |
| 100 | + * @param routeDataArray LineRouteDataOfApi类型数组 | |
| 101 | + */ | |
| 102 | + initRouteData (routeDataArray) { | |
| 103 | + // 1、重置内部数据 | |
| 104 | + this.resetData() | |
| 105 | + | |
| 106 | + // 2、计算内部数据对象 | |
| 107 | + // 2.1、route数据 | |
| 108 | + this._innerDataItemList.splice(0, this._innerDataItemList.length) | |
| 109 | + for (let tempItem of initInnerDataSetWithRoute(routeDataArray)) { | |
| 110 | + this._innerDataItemList.push(tempItem) | |
| 111 | + } | |
| 112 | + // 2.2、一共有多少页 | |
| 113 | + this._pageCount = Math.ceil(this._innerDataItemList.length / this._pageSize) | |
| 114 | + | |
| 115 | + // 3、计算内部滚动数据对象 | |
| 116 | + refreshScrollData.call(this) | |
| 117 | + } | |
| 118 | + | |
| 119 | + /** | |
| 120 | + * 刷新gps数据(依赖于initRouteData,注意调用顺序) | |
| 121 | + * @param gpsDataArray LineGpsDataOfApi类型数组 | |
| 122 | + */ | |
| 123 | + refreshGps (gpsDataArray) { | |
| 124 | + // refreshInnerDataSetWithGps(gpsDataArray, this._innerDataItemList) | |
| 125 | + refreshInnerDataSetWithGps(gpsDataArray, this._scrollDataItemList) | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * 清除内部数据 | |
| 130 | + */ | |
| 131 | + resetData () { | |
| 132 | + // ------------ 重置内部数据对象 ------------ // | |
| 133 | + this._innerDataItemList.splice(0, this._innerDataItemList.length) // 直接删除数据内部数据,而不是 = [] | |
| 134 | + this._pageCount = 0 | |
| 135 | + | |
| 136 | + // ------------ 重置内部滚动数据对象 ---------- // | |
| 137 | + this._scrollDataItemList.splice(0, this._scrollDataItemList.length) | |
| 138 | + this._currentScrollIndex = 0 | |
| 139 | + this._nextScrollIndex = 1 | |
| 140 | + if (this._scrollAnimateTimer.timer) { | |
| 141 | + try { | |
| 142 | + clearInterval(this._scrollAnimateTimer.timer) | |
| 143 | + } catch (err) {} | |
| 144 | + } | |
| 145 | + this._scrollAnimateTimer.timer = null | |
| 146 | + this._scrollAnimateTimer.count = 0 | |
| 147 | + } | |
| 148 | +} | |
| 149 | + | |
| 150 | +/** | |
| 151 | + * 计算内部滚动数据。 | |
| 152 | + */ | |
| 153 | +function refreshScrollData () { | |
| 154 | + this._scrollDataItemList.splice(0, this._scrollDataItemList.length) | |
| 155 | + | |
| 156 | + // 3.1、拷贝属性赋值 | |
| 157 | + for (let dataItem of this._innerDataItemList) { | |
| 158 | + // 注意这里直接拷贝_innerDataItemList元素属性,然后new新的ScrollListInnerDataItem对象 | |
| 159 | + this._scrollDataItemList.push(new ScrollListInnerDataItem(dataItem)) | |
| 160 | + } | |
| 161 | + // 3.2、如果总数据小于页大小,不用计算其他滚动数据,返回 | |
| 162 | + if (this._innerDataItemList.length <= this._pageSize) { | |
| 163 | + return | |
| 164 | + } | |
| 165 | + // 3.3、计算每条数据的 itemIndex pageIndex 属性 | |
| 166 | + for (let i = 0; i < this._pageCount; i++) { // 计算itemIndex pageIndex | |
| 167 | + for (let j = 0; j < this._pageSize; j++) { | |
| 168 | + let index = i * this._pageSize + j | |
| 169 | + if (index === this._scrollDataItemList.length) { // 超出记录退出 | |
| 170 | + break | |
| 171 | + } | |
| 172 | + let innerDataItem = this._scrollDataItemList[i * this._pageSize + j] | |
| 173 | + innerDataItem.itemIndex = j | |
| 174 | + innerDataItem.pageIndex = i | |
| 175 | + } | |
| 176 | + } | |
| 177 | + // 3.4、在最后添加第一页的数据(为了无缝滚动需要),同时pageIndex要加1 | |
| 178 | + // 注意:添加的一页不计算进this.pageCount中 | |
| 179 | + for (let i = 0; i < this._pageSize; i++) { | |
| 180 | + let InnerDataItem = new ScrollListInnerDataItem(this._innerDataItemList[i]) | |
| 181 | + InnerDataItem.pageIndex = this._pageCount | |
| 182 | + this._scrollDataItemList.push(InnerDataItem) | |
| 183 | + } | |
| 184 | + // 3.5、计算每个元素的宽,高,top | |
| 185 | + refreshScrollDataSizeProperty.call(this) | |
| 186 | +} | |
| 187 | + | |
| 188 | +/** | |
| 189 | + * 刷新滚动数据中 宽,高,top | |
| 190 | + */ | |
| 191 | +function refreshScrollDataSizeProperty () { | |
| 192 | + let scrollHeight = Math.floor(this._listHeight / this._pageSize) // TODO:先直接除假设每个item高度相同,后面再改 | |
| 193 | + for (let i = 0; i < this._scrollDataItemList.length; i++) { | |
| 194 | + let innerDataItem = this._scrollDataItemList[i] | |
| 195 | + innerDataItem.width = this._listWidth | |
| 196 | + innerDataItem.height = scrollHeight | |
| 197 | + innerDataItem.top = -(i * scrollHeight) | |
| 198 | + } | |
| 199 | +} | |
| 200 | + | |
| 201 | +/** | |
| 202 | + * 使用原始gps数据刷新内部gps数据(依赖路由数据) | |
| 203 | + * @param gpsDataArray LineGpsDataOfApi类型数组 | |
| 204 | + * @param innerDataSet InnerDataItem类型数组 | |
| 205 | + */ | |
| 206 | +function refreshInnerDataSetWithGps (gpsDataArray, innerDataSet) { | |
| 207 | + // 1、按照线路名字_线路编码分组数据 | |
| 208 | + let gpsGroupByLineNameCode = Utils.listGroupBy(gpsDataArray, function (d) { | |
| 209 | + return d.lineName + '_' + d.lineCode | |
| 210 | + }) | |
| 211 | + // 2、处理数据,循环计算每条线路的数据 | |
| 212 | + for (let internalData of innerDataSet) { | |
| 213 | + let key = internalData.lineName + '_' + internalData.lineCode | |
| 214 | + internalData.gps.splice(0, internalData.gps.length) // 清除原来的gps数据 | |
| 215 | + if (gpsGroupByLineNameCode[key]) { | |
| 216 | + for (let gpsData of gpsGroupByLineNameCode[key]) { | |
| 217 | + internalData.gps.push(new LineGpsDataOfLineChart(gpsData)) | |
| 218 | + } | |
| 219 | + } | |
| 220 | + } | |
| 221 | +} | |
| 222 | + | |
| 223 | +/** | |
| 224 | + * 使用原始路由数据初始化内部路由数据 | |
| 225 | + * @param routeDataArray LineRouteDataOfApi类型数组 | |
| 226 | + * @return Array InnerDataItem类型数组 | |
| 227 | + */ | |
| 228 | +function initInnerDataSetWithRoute (routeDataArray) { | |
| 229 | + // 1、按照线路名字_线路编码分组数据 | |
| 230 | + let routeGroupByLineNameCode = Utils.listGroupBy(routeDataArray, function (d) { | |
| 231 | + return d.lineName + '_' + d.lineCode | |
| 232 | + }) | |
| 233 | + // 2、获取线路名字_线路编码列表(按照线路名字排序) | |
| 234 | + let lineNameCodeList = [] | |
| 235 | + let routeGroupByLineNameCodeKeys = Object.keys(routeGroupByLineNameCode) | |
| 236 | + for (let key of routeGroupByLineNameCodeKeys) { | |
| 237 | + lineNameCodeList.push(key) | |
| 238 | + } | |
| 239 | + lineNameCodeList.sort(function (a, b) { | |
| 240 | + return a.localeCompare(b) | |
| 241 | + }) | |
| 242 | + // 3、处理数据,循环计算每条线路的数据 | |
| 243 | + if (lineNameCodeList.length === 0) { | |
| 244 | + return [] | |
| 245 | + } | |
| 246 | + | |
| 247 | + let innerDataSet = [] | |
| 248 | + | |
| 249 | + for (let key of lineNameCodeList) { | |
| 250 | + let lineName = key.split('_')[0] | |
| 251 | + let lineCode = key.split('_')[1] | |
| 252 | + | |
| 253 | + // 3.1 定义内部数据 | |
| 254 | + let internalData = new ScrollListInnerDataItem({ | |
| 255 | + lineName: lineName, | |
| 256 | + lineCode: lineCode, | |
| 257 | + route: [], | |
| 258 | + gps: [], | |
| 259 | + | |
| 260 | + // ------------- 滚动列表用的数据 ------------ // | |
| 261 | + width: 0, // 对应的LineChart组件的宽度 | |
| 262 | + height: 0, // 对应的LineChart组件的高度 | |
| 263 | + top: 0, // 距离顶部 css top值 | |
| 264 | + itemIndex: 0, // 每页中的item下标(从0开始) | |
| 265 | + pageIndex: 0 // 第几页下标(从0开始) | |
| 266 | + }) | |
| 267 | + // 3.2 处理路由数据 | |
| 268 | + // 3.2.1 获取指定线路路由 | |
| 269 | + let lineRoute = routeGroupByLineNameCode[key] | |
| 270 | + // 3.2.2 按照directions方向分组 | |
| 271 | + let lineRouteGroupByDir = Utils.listGroupBy(lineRoute, function (d) { | |
| 272 | + return d.directions | |
| 273 | + }) | |
| 274 | + // 3.2.3 排序分组,上行升序,下行降序(下行降序为了后面进行站点名合并) | |
| 275 | + try { | |
| 276 | + lineRouteGroupByDir[0].sort(function (a, b) { | |
| 277 | + return a.stationRouteCode - b.stationRouteCode | |
| 278 | + }) | |
| 279 | + lineRouteGroupByDir[1].sort(function (a, b) { | |
| 280 | + return b.stationRouteCode - a.stationRouteCode | |
| 281 | + }) | |
| 282 | + } catch (e) { | |
| 283 | + console.log('站定路由数据异常!') | |
| 284 | + console.log(e) | |
| 285 | + } | |
| 286 | + | |
| 287 | + // TODO:如果是环线,lineRouteGroupByDir[1] = [] | |
| 288 | + /** | |
| 289 | + * 3.2.4 核心合并算法。 | |
| 290 | + */ | |
| 291 | + let mergeRouteData = [] | |
| 292 | + let dirUpData | |
| 293 | + let dirDownData | |
| 294 | + for (let i = 0; i < 888; i++) { | |
| 295 | + dirUpData = lineRouteGroupByDir[0][i] | |
| 296 | + dirDownData = lineRouteGroupByDir[1][i] | |
| 297 | + if (dirUpData != null && dirDownData != null && dirUpData.stationName !== dirDownData.stationName) { | |
| 298 | + // arr2 包含 a1 | |
| 299 | + let ii = Utils.listIndexOf(lineRouteGroupByDir[1], dirUpData, 'stationName') | |
| 300 | + if (ii > i) { | |
| 301 | + Utils.insertNullToList(lineRouteGroupByDir[0], i, ii - i) | |
| 302 | + i -= 1 | |
| 303 | + continue | |
| 304 | + } | |
| 305 | + // arr1 包含 a2 | |
| 306 | + ii = Utils.listIndexOf(lineRouteGroupByDir[0], dirDownData, 'stationName') | |
| 307 | + if (ii > i) { | |
| 308 | + Utils.insertNullToList(lineRouteGroupByDir[1], i, ii - i) | |
| 309 | + i -= 1 | |
| 310 | + continue | |
| 311 | + } | |
| 312 | + } | |
| 313 | + | |
| 314 | + if (dirUpData == null && dirDownData == null) { | |
| 315 | + break | |
| 316 | + } | |
| 317 | + mergeRouteData.splice(i, 1, LineRouteDataOfLineChart.fromLineRouteDataOfApi(dirUpData, dirDownData)) | |
| 318 | + } | |
| 319 | + internalData.route = mergeRouteData | |
| 320 | + | |
| 321 | + // 3.3 处理总数据集 | |
| 322 | + innerDataSet.push(internalData) | |
| 323 | + } | |
| 324 | + | |
| 325 | + return innerDataSet | |
| 326 | +} | |
| 327 | + | |
| 328 | +export default ScrollListInnerData | ... | ... |
front-end/h5/src/components/core/plugins/bsth/models/scrollListInnerDataItem.js
0 → 100644
| 1 | +/** | |
| 2 | + * 内部数据类(每个线路模拟图用数据) | |
| 3 | + * @param value 参数对象 | |
| 4 | + */ | |
| 5 | +class ScrollListInnerDataItem { | |
| 6 | + constructor (value = {}) { | |
| 7 | + this.lineName = value.lineName // 线路名称 | |
| 8 | + this.lineCode = value.lineCode // 线路代码 | |
| 9 | + this.route = value.route // LineRouteDataOfLineChart类型数组 | |
| 10 | + this.gps = value.gps // LineGpsDataOfLineChart类型数组 | |
| 11 | + | |
| 12 | + // ------------- 滚动列表用的数据 ------------ // | |
| 13 | + this.width = 0 // 对应的LineChart组件的宽度 | |
| 14 | + this.height = 0 // 对应的LineChart组件的高度 | |
| 15 | + this.top = value.top // 距离顶部 css top值 | |
| 16 | + this.itemIndex = value.itemIndex // 每页中的item下标(从0开始) | |
| 17 | + this.pageIndex = value.pageIndex // 第几页下标(从0开始) | |
| 18 | + } | |
| 19 | + | |
| 20 | + toObject () { | |
| 21 | + return { | |
| 22 | + lineName: this.lineName, | |
| 23 | + lineCode: this.lineCode, | |
| 24 | + route: this.route, | |
| 25 | + gps: this.gps, | |
| 26 | + width: this.width, | |
| 27 | + height: this.height, | |
| 28 | + top: this.top, | |
| 29 | + itemIndex: this.itemIndex, | |
| 30 | + pageIndex: this.pageIndex | |
| 31 | + } | |
| 32 | + } | |
| 33 | +} | |
| 34 | + | |
| 35 | +export default ScrollListInnerDataItem | ... | ... |
front-end/h5/src/components/core/plugins/index.js
| ... | ... | @@ -19,8 +19,10 @@ import LbpTable from 'core/plugins/lbp-table' |
| 19 | 19 | import LbpNewsList from 'core/plugins/lbp-news-list' |
| 20 | 20 | // import LbpTabs from 'core/components/plugins/lbp-tabs' |
| 21 | 21 | |
| 22 | +/** 自定义的组件 */ | |
| 22 | 23 | import BsthLineChart from 'core/plugins/bsth/bsth-line-chart' |
| 23 | 24 | import BsthLineChartList from 'core/plugins/bsth/bsth-line-chart-list' |
| 25 | +import BsthLineChartScrollList from 'core/plugins/bsth/bsth-line-chart-scrollList' | |
| 24 | 26 | import BsthSlide from 'core/plugins/bsth/bsth-slide' |
| 25 | 27 | |
| 26 | 28 | export const pluginsList = [ |
| ... | ... | @@ -335,6 +337,18 @@ export const pluginsList = [ |
| 335 | 337 | |
| 336 | 338 | { |
| 337 | 339 | i18nTitle: { |
| 340 | + 'en-US': 'LineChartScrollList', | |
| 341 | + 'zh-CN': '线路模拟图滚动列表' | |
| 342 | + }, | |
| 343 | + title: '线路模拟图滚动列表', | |
| 344 | + icon: 'list', | |
| 345 | + component: BsthLineChartScrollList, | |
| 346 | + visible: true, | |
| 347 | + name: BsthLineChartScrollList.name | |
| 348 | + }, | |
| 349 | + | |
| 350 | + { | |
| 351 | + i18nTitle: { | |
| 338 | 352 | 'en-US': 'Carousel2', |
| 339 | 353 | 'zh-CN': '轮播图2' |
| 340 | 354 | }, | ... | ... |