Commit f31399f27a7fda81a4f086853dcb7de13d33a9b7

Authored by 徐烜
1 parent 2818a609

添加新的日期控件

front-end/h5/src/components/core/plugins/bsth/weather/css/weather-chart.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 +.weather-chart-outer-div, .weather-chart-outer-div * {
  9 + box-sizing: border-box;
  10 +}
  11 +
  12 +/**
  13 + 天气图使用的css
  14 + */
  15 +svg.weather-chart {
  16 + width: 100%;
  17 + height: 100%;
  18 + position: absolute;
  19 + left: 0;
  20 +
  21 + /* 文本css */
  22 + font-style: normal;
  23 + font-variant-ligatures: normal;
  24 + font-variant-caps: normal;
  25 + font-variant-numeric: normal;
  26 + font-variant-east-asian: normal;
  27 + font-weight: 400;
  28 + font-stretch: normal;
  29 + font-size: 14px;
  30 + line-height: 20px;
  31 + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
  32 +}
  33 +
front-end/h5/src/components/core/plugins/bsth/weather/models/WeatherData.js 0 → 100644
  1 +// 天气图表数据信息
  2 +
  3 +class WeatherData {
  4 + /**
  5 + * 构造函数。
  6 + */
  7 + constructor () {
  8 + /** 城市信息(如:上海) */
  9 + this._cityInfo = null;
  10 + /** 天气信息(如:阵雨) */
  11 + this._weatherInfo = null;
  12 + /** 温度信息(如:31°C)*/
  13 + this._temperatureInfo = null;
  14 + }
  15 +
  16 + setCityInfo (cityInfo) {
  17 + this._cityInfo = cityInfo
  18 + return this
  19 + }
  20 + setWeatherInfo (weatherInfo) {
  21 + this._weatherInfo = weatherInfo
  22 + return this
  23 + }
  24 + setTemperatureInfo (temperatureInfo) {
  25 + this._temperatureInfo = temperatureInfo
  26 + return this
  27 + }
  28 +
  29 + get cityInfo () {
  30 + return this._cityInfo
  31 + }
  32 + get weatherInfo () {
  33 + return this._weatherInfo
  34 + }
  35 + get temperatureInfo () {
  36 + return this._temperatureInfo
  37 + }
  38 +
  39 + generateSvgData () {
  40 + let showData = []
  41 + showData.push({
  42 + svgD3PartKey: 'cityInfo',
  43 + text: this._cityInfo,
  44 + bgProp: 'city_info_background',
  45 + fsProp: 'city_info_font_size',
  46 + fcProp: 'city_info_font_color'
  47 + })
  48 + showData.push({
  49 + svgD3PartKey: 'weatherInfo',
  50 + text: this._weatherInfo,
  51 + bgProp: 'weather_info_background',
  52 + fsProp: 'weather_info_font_size',
  53 + fcProp: 'weather_info_font_color'
  54 + })
  55 + showData.push({
  56 + svgD3PartKey: 'temperatureInfo',
  57 + text: this._temperatureInfo,
  58 + bgProp: 'temperature_info_background',
  59 + fsProp: 'temperature_info_font_size',
  60 + fcProp: 'temperature_info_font_color'
  61 + })
  62 +
  63 + return showData
  64 + }
  65 +
  66 + // 远程数据格式参考 http://36.138.68.10:19102/General_Interface/queryWeatherByCity
  67 + setFromRemoteWeatherInfo (data) {
  68 + console.log(data)
  69 + this._cityInfo = data.city || ''
  70 + this._weatherInfo = data.info || ''
  71 + this._temperatureInfo = data['temperature'] + '°C'
  72 + }
  73 +
  74 + /**
  75 + * 产生测试数据。
  76 + */
  77 + static generateTestData1 () {
  78 + let wd = new WeatherData()
  79 + wd.setCityInfo('上海').setWeatherInfo('晴').setTemperatureInfo('37°C')
  80 + return wd
  81 + }
  82 +
  83 +}
  84 +
  85 +export {
  86 + WeatherData
  87 +}
front-end/h5/src/components/core/plugins/bsth/weather/weather-chart.js 0 → 100644
  1 +
  2 +import PropTypes from '@luban-h5/plugin-common-props'
  3 +
  4 +import './css/weather-chart.css'
  5 +import { WeatherData } from 'core/plugins/bsth/weather/models/WeatherData'
  6 +import { jsonp } from 'vue-jsonp'
  7 +
  8 +import axios from 'axios'
  9 +
  10 +export default {
  11 + extra: {
  12 + defaultStyle: { // 默认属性
  13 + top: 0,
  14 + left: 0,
  15 + width: 200,
  16 + height: 50
  17 + }
  18 + },
  19 + name: 'weather-chart',
  20 + data () {
  21 + this.private_svgns = 'http://www.w3.org/2000/svg' // svg元素名字空间
  22 + this.private_svg = null // 创建的根svg元素,由mounted钩子函数创建
  23 + // eslint-disable-next-line
  24 + this.private_jQuery = jQuery.noConflict() // jquery引用
  25 + // eslint-disable-next-line
  26 + this.private_d3 = d3 // d3引用
  27 +
  28 + return {
  29 + /**
  30 + * 监控外层元素的宽度高度变化
  31 + * 1、由于编辑器缩放,自定义组件无法监控,所以需要定义一个定时器监控最外层元素的大小变化
  32 + * 2、建议所有自定义组件,最外层都定义一个div包在自定义组件最外层,不要关联任何自定义的属性,样式对应编辑器的通用样式
  33 + */
  34 + watchWidthHeightTimer: {
  35 + timer: null,
  36 + count: 0,
  37 + millisecond: 1000
  38 + },
  39 +
  40 + // 注意:css里设定了box-sizing: border-box;,所以组件本身的宽高包括了margin,padding,border
  41 + // 所以计算内部其他组件宽高需要减去margin,padding,border
  42 + component_width: 350, // 组件宽度
  43 + component_height: 400, // 组件高度
  44 +
  45 + svg_width: 350, // svg根元素的宽度
  46 + svg_height: 400, // svg根元素的高度
  47 +
  48 + initLoading: true, // 数据是否正在初始化
  49 + initLoadingText: '', // 初始化期间的文本显示
  50 + weatherData: null, // 天气图表数据(WeatherChartData类型)
  51 + weatherDataTimer: { // 天气数据刷新间隔timer
  52 + timer: undefined,
  53 + count: 0
  54 + }
  55 + }
  56 + },
  57 + computed: {
  58 + weatherDataAxios () {
  59 + return axios.create({ baseURL: this.remote_data_url, timeout: 50000 })
  60 + }
  61 + },
  62 + props: {
  63 + //------------------- 内部不可编辑属性 -----------------------//
  64 + useMode: PropTypes.string({ // 自定义使用模式,alone:(单独使用),child:(子组件)
  65 + defaultValue: 'alone',
  66 + label: '使用模式',
  67 + visible: false
  68 + }),
  69 + editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview)
  70 + defaultValue: 'preview',
  71 + label: '模式',
  72 + visible: false
  73 + }),
  74 + weather_chart_outer_div_width: PropTypes.number({
  75 + defaultValue: 350,
  76 + label: 'weather-chart-outer-div样式的div宽度',
  77 + visible: false
  78 + }),
  79 + weather_chart_outer_div_height: PropTypes.number({
  80 + defaultValue: 300,
  81 + label: 'weather-chart-outer-div样式的div高度',
  82 + visible: false
  83 + }),
  84 + weatherData_child: { // 作为子组件,父对象传值
  85 + type: WeatherData,
  86 + default: function () {
  87 + return null
  88 + }
  89 + },
  90 +
  91 + //---------------------- 外部编辑器可编辑属性 -----------------------//
  92 + // 数据属性
  93 + _flag_1_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="数据属性" class="bsth-line-item-divider"></hr>) } }),
  94 + remote_data_url: PropTypes.string({ label: '远端数据url', component: 'a-textarea', defaultValue: 'http://36.138.68.10:19102/General_Interface/queryWeatherByCity', layout: { prefixCls: 'bsth-line' } }),
  95 + remote_data_refresh_seconds: PropTypes.number({ label: '数据刷新间隔(秒)', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
  96 + // 图外层css
  97 + _flag_2_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图外层css属性" class="bsth-line-item-divider"></hr>) } }),
  98 + margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  99 + margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  100 + margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  101 + margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  102 + border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  103 + background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  104 + // 图内层css
  105 + _flat_2_1_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层svg css属性" class="bsth-line-item-divider"></hr>) } }),
  106 + svg_background: PropTypes.color({ label: '整体svg背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  107 + city_info_font_size: PropTypes.number({ label: '城市信息字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
  108 + city_info_font_color: PropTypes.color({ label: '城市信息字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
  109 + city_info_background: PropTypes.color({ label: '城市信息背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  110 + weather_info_font_size: PropTypes.number({ label: '天气信息字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
  111 + weather_info_font_color: PropTypes.color({ label: '天气信息字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
  112 + weather_info_background: PropTypes.color({ label: '天气信息背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  113 + temperature_info_font_size: PropTypes.number({ label: '温度信息字体大小', defaultValue: 28, layout: { prefixCls: 'bsth-line' } }),
  114 + temperature_info_font_color: PropTypes.color({ label: '温度信息字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
  115 + temperature_info_background: PropTypes.color({ label: '温度信息背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } })
  116 +
  117 + },
  118 + render () {
  119 + const innerDivStyle = {
  120 + 'width': this.component_width + 'px',
  121 + 'height': this.component_height + 'px',
  122 + 'border': this.border_size + 'px solid black',
  123 + 'margin-left': this.margin_left + 'px',
  124 + 'margin-right': this.margin_right + 'px',
  125 + 'margin-top': this.margin_top + 'px',
  126 + 'margin-bottom': this.margin_bottom + 'px',
  127 + 'background': this.background_color,
  128 + 'position': 'relative'
  129 + }
  130 + const svgStyle = {
  131 + 'width': this.svg_width + 'px',
  132 + 'height': this.svg_height + 'px',
  133 + 'background-color': this.svg_background
  134 + }
  135 +
  136 + /* 最外层div对应编辑器的通用样式 */
  137 + return (
  138 + <a-spin tip={this.initLoadingText} spinning={this.initLoading} size="large">
  139 + <div class="weather-chart-outer-div">
  140 + <div style={innerDivStyle}>
  141 + <svg class="weather-chart"
  142 + style={svgStyle}>
  143 + </svg>
  144 + </div>
  145 + </div>
  146 + </a-spin>
  147 + )
  148 + },
  149 + beforeMount () {
  150 + // 设置数据
  151 + if (this.useMode === 'alone' && this.editorMode === 'edit') { // 单独使用,使用测试数据
  152 + this.weatherData = WeatherData.generateTestData1()
  153 + } else { // 自组件使用,使用父组件传值
  154 + this.weatherData = this.weatherData_child
  155 + }
  156 + },
  157 + mounted () {
  158 + // svg元素
  159 + this.private_svg = this.findD3SvgDom()
  160 +
  161 + // 使用外部元素的框架定义图的长宽
  162 + let $jQuery = this.private_jQuery
  163 + this.component_width = $jQuery(this.$el).width() - this.margin_left - this.margin_right
  164 + this.component_height = $jQuery(this.$el).height() - this.margin_top - this.margin_bottom
  165 +
  166 + if (this.useMode === 'child') {
  167 + this.component_width = this.line_chart_outer_div_width - this.margin_left - this.margin_right
  168 + this.component_height = this.line_chart_outer_div_height - this.margin_top - this.margin_bottom
  169 + }
  170 +
  171 + // 开启外部元素长宽监控计数
  172 + /**
  173 + * 开启外部元素长宽监控逻辑(class='line-chart-outer-div')
  174 + * 1、使用模式是alone,并且是编辑模式edit
  175 + * 2、preview预览模式下有条件监控
  176 + */
  177 + if (this.useMode === 'alone' && this.editorMode === 'edit') {
  178 + this.watchWidthHeightTimer.count++
  179 + }
  180 +
  181 + // 1、初始化数据
  182 + // 1.1、edit模式下,使用测试数据
  183 + if (this.editorMode === 'edit') {
  184 + this.initLoading = false
  185 + }
  186 + // 1.2、preview模式下,使用远程数据
  187 + if (this.editorMode === 'preview') {
  188 + console.log('initDataByRemoteApi')
  189 + this.initDataByRemoteApi()
  190 + }
  191 + },
  192 + destroyed () {
  193 + // 组件删除的时候,删除监控定时器
  194 + let timer = this.watchWidthHeightTimer.timer
  195 + if (timer) {
  196 + clearTimeout(timer)
  197 + this.watchWidthHeightTimer.timer = null
  198 + }
  199 + timer = this.weatherDataTimer.timer
  200 + if (timer) {
  201 + clearTimeout(timer)
  202 + this.weatherDataTimer.timer = null
  203 + }
  204 + },
  205 + watch: {
  206 + //------------ 定时器监控 -----------//
  207 + 'watchWidthHeightTimer.count' () { // 定时器监控
  208 + let timer = this.watchWidthHeightTimer.timer
  209 + if (timer) {
  210 + clearTimeout(timer)
  211 + this.watchWidthHeightTimer.timer = null
  212 + }
  213 +
  214 + let self = this
  215 + let $jQuery = this.private_jQuery
  216 + self.watchWidthHeightTimer.timer = setTimeout(function () {
  217 + // 处理逻辑
  218 + let width = $jQuery(self.$el).width()
  219 + let height = $jQuery(self.$el).height()
  220 +
  221 + if (width !== self.component_width) {
  222 + self.component_width = width - self.margin_left - self.margin_right
  223 + }
  224 + if (height !== self.component_height) {
  225 + self.component_height = height - self.margin_top - self.margin_bottom
  226 + }
  227 + self.watchWidthHeightTimer.count++
  228 + }, self.watchWidthHeightTimer.millisecond)
  229 + },
  230 + 'weatherDataTimer.count' () {
  231 + let timer = this.weatherDataTimer.timer
  232 + if (timer) {
  233 + try {
  234 + clearTimeout(timer)
  235 + } catch (err) {}
  236 + }
  237 + let self = this
  238 + this.weatherDataTimer.timer = setTimeout(function () {
  239 + self.refreshDataByRemoteApi()
  240 + }, this.remote_data_refresh_seconds * 1000)
  241 + },
  242 + //-------------- 不可编辑属性监控 ---------------//
  243 + /**
  244 + * 当组件作为子组件使用时(useMode=child),line-chart-outer-div样式的div尺寸无法通过编辑器改变(通用样式)
  245 + * 必须由父组件设定,自组件需要监控改变
  246 + */
  247 + weather_chart_outer_div_width: function (val) {
  248 + let self = this
  249 + if (self.useMode === 'child') {
  250 + self.component_width = val - self.margin_left - self.margin_right
  251 + }
  252 + },
  253 + weather_chart_outer_div_height: function (val) {
  254 + let self = this
  255 + if (self.useMode === 'child') {
  256 + self.component_height = val - self.margin_top - self.margin_bottom
  257 + }
  258 + },
  259 +
  260 + //------------- data方法中绑定的数据监控 --------------------//
  261 + // ----------- 数据属性 ----------- //
  262 + weatherData: { // 使用deep检测所有属性变化
  263 + handler (currentVal, oldVal) {
  264 + let self = this
  265 + // TODO:这里objectEquals有点问题,暂时不用了
  266 + // if (!Utils.objectEquals(currentVal, oldVal)) {
  267 + // self.refreshSvg()
  268 + // }
  269 + console.log('refreshSvg()')
  270 + self.refreshSvg()
  271 + },
  272 + deep: true
  273 + },
  274 +
  275 + // ------------ 本身宽高 ----------- //
  276 + component_width () {
  277 + let self = this
  278 + self.svg_width = self.component_width - self.border_size * 2
  279 + },
  280 + component_height () {
  281 + let self = this
  282 + self.svg_height = self.component_height - self.border_size * 2
  283 + },
  284 +
  285 + svg_width () {
  286 + let self = this
  287 + self.refreshSvg()
  288 + },
  289 + svg_height () {
  290 + let self = this
  291 + self.refreshSvg()
  292 + },
  293 +
  294 + //--------------- 外部编辑器可编辑属性监控 -----------------//
  295 + //--------- 图外层css监控 -------//
  296 + margin_left () {
  297 + let self = this
  298 + self.component_width = self.component_width - self.margin_left - self.margin_right
  299 + },
  300 + margin_right () {
  301 + let self = this
  302 + self.component_width = self.component_width - self.margin_left - self.margin_right
  303 + },
  304 + margin_top () {
  305 + let self = this
  306 + self.component_height = self.component_height - self.margin_top - self.margin_bottom
  307 + },
  308 + margin_bottom () {
  309 + let self = this
  310 + self.component_height = self.component_height - self.margin_top - self.margin_bottom
  311 + },
  312 + border_size () {
  313 + let self = this
  314 + self.svg_width = self.component_width - self.border_size * 2
  315 + self.svg_height = self.component_height - self.border_size * 2
  316 + },
  317 +
  318 + //---------- 图内层css监控 --------//
  319 + // 对应 _flat_2_1_ 属性集合
  320 + city_info_font_size () {
  321 + let self = this
  322 + self.refreshSvg()
  323 + },
  324 + city_info_font_color () {
  325 + let self = this
  326 + self.refreshSvg()
  327 + },
  328 + city_info_background () {
  329 + let self = this
  330 + self.refreshSvg()
  331 + },
  332 + weather_info_font_size () {
  333 + let self = this
  334 + self.refreshSvg()
  335 + },
  336 + weather_info_font_color () {
  337 + let self = this
  338 + self.refreshSvg()
  339 + },
  340 + weather_info_background () {
  341 + let self = this
  342 + self.refreshSvg()
  343 + },
  344 + temperature_info_font_size () {
  345 + let self = this
  346 + self.refreshSvg()
  347 + },
  348 + temperature_info_font_color () {
  349 + let self = this
  350 + self.refreshSvg()
  351 + },
  352 + temperature_info_background () {
  353 + let self = this
  354 + self.refreshSvg()
  355 + }
  356 +
  357 + },
  358 + methods: {
  359 + findD3SvgDom () {
  360 + let $jQuery = this.private_jQuery
  361 + let d3 = this.private_d3
  362 + let svgDom = $jQuery(this.$el).find('svg')[0]
  363 + return d3.select(svgDom)
  364 + },
  365 +
  366 + refreshSvg () {
  367 + // console.log('refreshsvg')
  368 +
  369 + let self = this
  370 +
  371 + let d3 = self.private_d3
  372 + let svg = self.private_svg
  373 + let width = self.svg_width
  374 + let height = self.svg_height
  375 +
  376 + let svgData = self.weatherData == null ? [] : self.weatherData.generateSvgData()
  377 +
  378 + // console.log(svgData)
  379 +
  380 + // ------------ 0、前置计算准备 --------------//
  381 + // part上下左右,之间的间隔
  382 + let partUpPadding = 10
  383 + let partDownPadding = 10
  384 + let partLeftPadding = 10
  385 + let partRightPadding = 10
  386 + let partBetweenPadding = 5
  387 +
  388 + // 计算三个part的宽度(宽度相同)
  389 + let partWidth = Math.floor((width - partLeftPadding - partRightPadding - partBetweenPadding * 2) / 3)
  390 + let partHeight = height - partUpPadding - partDownPadding
  391 +
  392 + // 创建x轴比例尺
  393 + let xScale = d3.scaleLinear()
  394 + .domain([0, 3]) // 定义域
  395 + .range([partLeftPadding, width - partRightPadding]) // 值域
  396 + let yScale = d3.scaleLinear()
  397 + .domain([0, 1]) // 定义域
  398 + .range([partUpPadding, height - partDownPadding]) // 值域
  399 +
  400 + // ------------ 1、添加g元素 ---------------- //
  401 + let itemsUpdate = svg.selectAll('g.part')
  402 + .data(svgData, function (d) {
  403 + return d.svgD3PartKey
  404 + })
  405 + let itemsEnter = itemsUpdate
  406 + let itemsExit = itemsUpdate.exit()
  407 +
  408 + itemsExit.remove()
  409 + itemsEnter = itemsEnter.enter().append('g')
  410 + .classed('part', true)
  411 + .attr('transform', function (d, index) {
  412 + let x, y
  413 + x = xScale(0) + partWidth * index + partBetweenPadding * index
  414 + y = yScale(0)
  415 + return `translate(${x}, ${y})`
  416 + })
  417 + itemsUpdate
  418 + .attr('transform', function (d, index) {
  419 + let x, y
  420 + x = xScale(0) + partWidth * index + partBetweenPadding * index
  421 + y = yScale(0)
  422 + return `translate(${x}, ${y})`
  423 + })
  424 +
  425 + // ------------ 1-1、添加 rect.main 元素 ---------------- //
  426 + itemsEnter.append('rect')
  427 + .classed('main', true)
  428 + .style('fill', function (d) {
  429 + return self[d.bgProp]
  430 + })
  431 + .style('stroke-width', function (d) {
  432 + return 0
  433 + })
  434 + .attr('stroke-dasharray', function (d) {
  435 + return null
  436 + })
  437 + .attr('width', function (d) {
  438 + return partWidth
  439 + })
  440 + .attr('height', partHeight + 'px')
  441 + itemsUpdate.select('rect.main')
  442 + .style('fill', function (d) {
  443 + return self[d.bgProp]
  444 + })
  445 + .attr('width', function (d) {
  446 + return partWidth
  447 + })
  448 + .attr('height', partHeight + 'px')
  449 +
  450 + // ------------ 1-2、添加 g text 元素 ---------------- //
  451 + itemsEnter.append('g')
  452 + .classed('contentBound', true)
  453 + .attr('transform', 'translate(10, 10)')
  454 + itemsEnter.select('g.contentBound')
  455 + .append('text')
  456 + .classed('content', true)
  457 + .text(function (d) {
  458 + return d.text
  459 + })
  460 + .attr('title', function (d) {
  461 + return d.text
  462 + })
  463 + .style('font-size', function (d) {
  464 + return self[d.fsProp]
  465 + })
  466 + .style('fill', function (d) {
  467 + return self[d.fcProp]
  468 + })
  469 + itemsEnter.select('g.contentBound')
  470 + .attr('transform', function (d) {
  471 + // x方向居中对齐,y方向居中对齐
  472 + let rect_main_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
  473 + let g_bounds = this.getBBox()
  474 + let dx = (rect_main_bounds.width - g_bounds.width) / 2 - g_bounds.x
  475 + let dy = (rect_main_bounds.height - g_bounds.height) / 2 - g_bounds.y
  476 + if (dx < 0) {
  477 + dx = 1
  478 + }
  479 + if (dy < 0) {
  480 + dy = 1
  481 + }
  482 + return `translate(${dx}, ${dy})`
  483 + })
  484 + itemsUpdate.select('text.content')
  485 + .text(function (d) {
  486 + return d.text
  487 + })
  488 + .attr('title', function (d) {
  489 + return d.text
  490 + })
  491 + .style('font-size', function (d) {
  492 + return self[d.fsProp]
  493 + })
  494 + .style('fill', function (d) {
  495 + return self[d.fcProp]
  496 + })
  497 + itemsUpdate.select('g.contentBound')
  498 + .attr('transform', function (d) {
  499 + // x方向居中对齐,y方向居中对齐
  500 + let rect_main_bounds = d3.select(this.parentNode).select('rect.main').node().getBBox()
  501 + let g_bounds = this.getBBox()
  502 + let dx = (rect_main_bounds.width - g_bounds.width) / 2 - g_bounds.x
  503 + let dy = (rect_main_bounds.height - g_bounds.height) / 2 - g_bounds.y
  504 + if (dx < 0) {
  505 + dx = 1
  506 + }
  507 + if (dy < 0) {
  508 + dy = 1
  509 + }
  510 + return `translate(${dx}, ${dy})`
  511 + })
  512 +
  513 + },
  514 +
  515 + initDataByRemoteApi () { // 使用后台api初始化数据
  516 + this.initLoading = true
  517 + this.initLoadingText = '初始化数据...'
  518 + this.weatherDataAxios.post().then(remoteData => {
  519 + if (!remoteData) {
  520 + this.initLoadingText = `远端数据为空,等待${this.remote_data_refresh_seconds}秒后重新获取,请稍后...`
  521 + this.count++
  522 + } else {
  523 + this.weatherData = new WeatherData()
  524 + this.weatherData.setFromRemoteWeatherInfo(remoteData.data)
  525 + this.initLoading = false
  526 + this.refreshSvg()
  527 + // 启动滚动分页,后台数据刷新
  528 + this.weatherDataTimer.count++
  529 + }
  530 + }).catch(err => {
  531 + console.log(err)
  532 + this.$message.error(`获取远端数据失败,状态:${err.status},错误:${err.statusText}`, 1)
  533 + this.initLoadingText = `获取远端数据失败,等待${this.remote_data_refresh_seconds}秒后重新获取,请稍后...`
  534 + this.weatherDataTimer.count++
  535 + })
  536 + },
  537 + refreshDataByRemoteApi () { // 使用后台api刷新数据
  538 + if (!this.weatherData) {
  539 + this.initDataByRemoteApi()
  540 + } else {
  541 + this.weatherDataAxios.post().then(remoteData => {
  542 + this.weatherData.setFromRemoteWeatherInfo(remoteData.data)
  543 + this.refreshSvg()
  544 + }).catch(err => {
  545 + console.log(err)
  546 + this.$message.error(` 获取数据失败,状态:${err.status},错误:${err.statusText}`, 1)
  547 + })
  548 + this.weatherDataTimer.count++
  549 + }
  550 + }
  551 + }
  552 +
  553 +}
front-end/h5/src/components/core/plugins/index.js
@@ -36,6 +36,8 @@ import MhgjEBusStopLineChartList from &#39;core/plugins/bsth/mhgj/list/mhgj-eBusStop @@ -36,6 +36,8 @@ import MhgjEBusStopLineChartList from &#39;core/plugins/bsth/mhgj/list/mhgj-eBusStop
36 import OthergjEBusStopLineChart from 'core/plugins/bsth/othergj/linechart/chart/othergj-eBusStop-line-chart' 36 import OthergjEBusStopLineChart from 'core/plugins/bsth/othergj/linechart/chart/othergj-eBusStop-line-chart'
37 import OthergjEBusStopLineChartList from 'core/plugins/bsth/othergj/linechart/list/othergj-eBusStop-line-chart-list' 37 import OthergjEBusStopLineChartList from 'core/plugins/bsth/othergj/linechart/list/othergj-eBusStop-line-chart-list'
38 38
  39 +import WeatherChart from 'core/plugins/bsth/weather/weather-chart'
  40 +
39 export const pluginsList = [ 41 export const pluginsList = [
40 // { 42 // {
41 // i18nTitle: { 43 // i18nTitle: {
@@ -458,6 +460,19 @@ export const pluginsList = [ @@ -458,6 +460,19 @@ export const pluginsList = [
458 460
459 { 461 {
460 i18nTitle: { 462 i18nTitle: {
  463 + 'en-US': 'Weather',
  464 + 'zh-CN': '实时天气'
  465 + },
  466 + title: '实时天气',
  467 + icon: 'photo',
  468 + component: WeatherChart,
  469 + visible: true,
  470 + name: WeatherChart.name
  471 + // disabled: true
  472 + },
  473 +
  474 + {
  475 + i18nTitle: {
461 'en-US': 'Datetime', 476 'en-US': 'Datetime',
462 'zh-CN': '日期时间' 477 'zh-CN': '日期时间'
463 }, 478 },