| | |
| | | _config.style.height = 'auto' |
| | | _config.style.minHeight = _config.plot.height + 30 |
| | | |
| | | if (_config.plot.correction) { |
| | | delete _config.plot.correction // 数据修正(已弃用) |
| | | _config.plot.barSize = 35 |
| | | } |
| | | |
| | | if (!_config.plot.legend || _config.plot.legend === 'hidden') { |
| | | _config.plot.legend = false |
| | | } |
| | | |
| | | if (_config.plot.title) { |
| | | _config.style.minHeight = _config.style.minHeight + 45 |
| | | } |
| | |
| | | |
| | | if (_config.plot.mutilBar !== 'overlap' && Bar_axis.length > 1) { |
| | | _config.plot.Bar_axis = Bar_axis |
| | | } |
| | | |
| | | if (_config.plot.Bar_axis && _config.plot.Bar_axis.length) { |
| | | let label = _config.plot.label |
| | | |
| | | if (label === 'false') { |
| | | _config.plot.customs.forEach(item => { |
| | | if (!Bar_axis.includes(item.type)) return |
| | | if (item.label === 'true') { |
| | | label = 'true' |
| | | } |
| | | }) |
| | | } else { |
| | | let reset = true |
| | | _config.plot.customs.forEach(item => { |
| | | if (!Bar_axis.includes(item.type)) return |
| | | if (item.label === 'true') { |
| | | reset = false |
| | | } |
| | | }) |
| | | if (reset) { |
| | | label = 'false' |
| | | } |
| | | } |
| | | |
| | | _config.plot.$label = label |
| | | } |
| | | |
| | | if (_config.plot.zoomYaxis === 'adjust' && _config.plot.mutilBar === 'stack') { |
| | | if (_config.plot.Bar_axis) { |
| | | _config.plot.zoomFields = _config.plot.Yaxis.filter(cell => !_config.plot.Bar_axis.includes(cell)) |
| | | } |
| | | } |
| | | } else { |
| | | _config.plot.enabled = 'false' |
| | |
| | | |
| | | let xc = {label: { |
| | | formatter: (val) => { |
| | | if (!val || /^\s*$/.test(val)) return val |
| | | if (!val || /^\s+$/.test(val)) return val |
| | | let _val = `${val}` |
| | | if (_val.length <= limit) return val |
| | | return _val.substring(0, limit) + '...' |
| | |
| | | this.data = window.GLOB.SyncData.get(_config.dataName) || [] |
| | | |
| | | if (_config.$cache) { |
| | | Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS()) |
| | | Api.writeCacheConfig(_config.uuid, fromJS(this.data).toJS(), BID) |
| | | } |
| | | |
| | | _config.setting.sync = 'false' |
| | |
| | | BID: BID || '', |
| | | vFields: vFields, |
| | | vstFields: vstFields, |
| | | arr_field: _config.columns.map(col => col.field).join(','), |
| | | plot: _config.plot, |
| | | search: _config.$searches, |
| | | transfield |
| | |
| | | if (config.timer) { |
| | | this.timer = new TimerTask() |
| | | this.timer.init(config.uuid, config.timer, config.timerRepeats, () => { |
| | | this.loadData(true) |
| | | this.loadData('timer') |
| | | }) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | initExec = () => { |
| | | const { config } = this.state |
| | | const { config, BID } = this.state |
| | | |
| | | if (config.$cache) { |
| | | if (config.$time) { |
| | | if (!this.loaded) { |
| | | Api.getLCacheConfig(config.uuid, config.$time).then(res => { |
| | | Api.getLCacheConfig(config.uuid, config.$time, BID).then(res => { |
| | | if (!res.valid && config.setting.onload === 'true') { |
| | | setTimeout(() => { |
| | | this.loadData() |
| | | this.loadData('init') |
| | | }, config.setting.delay || 0) |
| | | } |
| | | |
| | |
| | | } |
| | | } else { |
| | | if (!this.loaded) { |
| | | Api.getLCacheConfig(config.uuid, 0).then(res => { |
| | | Api.getLCacheConfig(config.uuid, 0, BID).then(res => { |
| | | if (!res.data || this.loaded) return |
| | | |
| | | this.data = res.data |
| | |
| | | |
| | | if (config.setting.onload === 'true') { |
| | | setTimeout(() => { |
| | | this.loadData() |
| | | this.loadData('init') |
| | | }, config.setting.delay || 0) |
| | | } else if (this.loaded) { |
| | | this.handleData() |
| | |
| | | } |
| | | |
| | | transferSyncData = (syncId) => { |
| | | const { config } = this.state |
| | | const { config, BID } = this.state |
| | | |
| | | if (config.$syncId !== syncId) return |
| | | |
| | | let _data = window.GLOB.SyncData.get(config.dataName) || [] |
| | | |
| | | if (config.$cache) { |
| | | Api.writeCacheConfig(config.uuid, fromJS(_data).toJS()) |
| | | Api.writeCacheConfig(config.uuid, fromJS(_data).toJS(), BID) |
| | | } |
| | | |
| | | this.data = _data |
| | |
| | | * @description 导出Excel时,获取页面搜索排序等参数 |
| | | */ |
| | | queryModuleParam = (menuId, callback) => { |
| | | const { arr_field, config, search } = this.state |
| | | const { config, search } = this.state |
| | | |
| | | if (config.uuid !== menuId) return |
| | | |
| | |
| | | } |
| | | |
| | | callback({ |
| | | arr_field: arr_field, |
| | | orderBy: config.setting.order || '', |
| | | search: searches, |
| | | menuName: config.name |
| | |
| | | /** |
| | | * @description 数据加载 |
| | | */ |
| | | async loadData (hastimer) { |
| | | const { config, arr_field, BID, search } = this.state |
| | | async loadData (type) { |
| | | const { config, BID, search } = this.state |
| | | |
| | | if (config.setting.supModule && !BID) { // BID 不存在时,不做查询 |
| | | if (!is(fromJS(this.data), fromJS([]))) { |
| | |
| | | return |
| | | } |
| | | |
| | | if (!hastimer) { |
| | | if (type !== 'timer') { |
| | | this.setState({ |
| | | loading: true |
| | | }) |
| | | } |
| | | |
| | | let _orderBy = config.setting.order || '' |
| | | let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, '', '', BID) |
| | | let param = UtilsDM.getQueryDataParams(config.setting, searches, _orderBy, '', '', BID) |
| | | |
| | | let result = await Api.genericInterface(param) |
| | | if (result.status) { |
| | | if (config.$cache && config.setting.onload !== 'false') { |
| | | Api.writeCacheConfig(config.uuid, result.data || []) |
| | | if (config.$cache && type === 'init') { |
| | | Api.writeCacheConfig(config.uuid, result.data || [], BID) |
| | | } |
| | | |
| | | this.loaded = true |
| | |
| | | chart.axis(plot.Xaxis, plot.$xc) |
| | | chart.axis(_valfield, plot.$yc) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | if (!plot.legend) { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | |
| | | .position(`${plot.Xaxis}*${_valfield}`) |
| | | .shape(plot.shape || 'smooth') |
| | | .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | return { |
| | | name: type, |
| | | value: plot.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | return null |
| | | } |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | style: { |
| | | fill: plot.color |
| | | } |
| | |
| | | */ |
| | | customrender = (data) => { |
| | | const { plot, transfield } = this.state |
| | | |
| | | let max = 0 |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | data.forEach(item => { |
| | | if (plot.zoomFields) { |
| | | plot.zoomFields.forEach(f => { |
| | | if (item[f] > max) { |
| | | max = item[f] |
| | | } |
| | | }) |
| | | let sum = 0 |
| | | plot.Bar_axis.forEach(f => { |
| | | sum += item[f] |
| | | }) |
| | | if (sum > max) { |
| | | max = sum |
| | | } |
| | | } else { |
| | | plot.Yaxis.forEach(f => { |
| | | if (item[f] > max) { |
| | | max = item[f] |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | if (!isNaN(max)) { |
| | | max = Math.ceil(max) |
| | | let s = max > 10 ? Math.pow(10, (max + '').length - 2) : 1 |
| | | max = Math.ceil(max / s) * s |
| | | } else { |
| | | max = 0 |
| | | } |
| | | } |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | if (!plot.legend) { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | |
| | | range: [0, 0.9] |
| | | } |
| | | |
| | | if (plot.min || plot.min === 0) { |
| | | c.min = plot.min |
| | | } |
| | | if (plot.max || plot.max === 0) { |
| | | c.max = plot.max |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | if (max) { |
| | | c.min = 0 |
| | | c.max = max |
| | | } |
| | | } else { |
| | | if (plot.min || plot.min === 0) { |
| | | c.min = plot.min |
| | | } |
| | | if (plot.max || plot.max === 0) { |
| | | c.max = plot.max |
| | | c.min = c.min || 0 |
| | | } |
| | | } |
| | | view1.scale('value', c) |
| | | view1.axis('value', plot.$yc) |
| | | |
| | | // view1.legend(false) |
| | | if (plot.legend) { |
| | | view1.legend(false) |
| | | } |
| | | |
| | | let colorIndex = 0 |
| | | |
| | | if (plot.adjust !== 'stack') { |
| | | if (plot.mutilBar !== 'stack') { |
| | | let _chart = view1 |
| | | .interval() |
| | | .position(`${plot.Xaxis}*value`) |
| | |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*value*key`, (name, value, key) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: key, |
| | | value: value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | if (plot.$label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | if (plot.$label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | lablecfg.style.fill = plot.$colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } else if (plot.adjust === 'stack') { |
| | | } else if (plot.mutilBar === 'stack') { |
| | | let _chart = view1 |
| | | .interval() |
| | | .position(`${plot.Xaxis}*value`) |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*value*key`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: type, |
| | | value: value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | if (plot.$label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.labelValue === 'zero' && value === 0) { |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | if (plot.$label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | | lablecfg.style.fill = plot.$colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.barRadius) { |
| | |
| | | } |
| | | |
| | | view2.data(dv.rows) |
| | | // view2.legend(false) |
| | | |
| | | if (plot.legend && plot.Bar_axis) { |
| | | view2.legend(false) |
| | | } |
| | | |
| | | plot.customs.forEach(item => { |
| | | if (item.chartType === 'bar' && !plot.Bar_axis) { |
| | |
| | | range: [0, 0.9] |
| | | } |
| | | |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | if (max) { |
| | | c.min = 0 |
| | | c.max = max |
| | | } |
| | | } else { |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | } |
| | | } |
| | | |
| | | view2.scale(item.name, c) |
| | |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | .tooltip(`${item.name}`, (value) => { |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: item.name, |
| | | value: item.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && item.color) { |
| | | lablecfg.style.fill = item.color |
| | | } |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | |
| | | range: [0, 0.9] |
| | | } |
| | | |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | if (plot.zoomYaxis === 'adjust') { |
| | | if (max) { |
| | | c.min = 0 |
| | | c.max = max |
| | | } |
| | | } else { |
| | | if (item.min || item.min === 0) { |
| | | c.min = item.min |
| | | } |
| | | if (item.max || item.max === 0) { |
| | | c.max = item.max |
| | | } |
| | | } |
| | | |
| | | view2.scale(item.name, c) |
| | |
| | | .color(item.color) |
| | | .shape(item.shape) |
| | | .tooltip(`${item.name}`, (value) => { |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | return { |
| | | name: item.name, |
| | | value: item.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (item.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (item.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | style: { |
| | | fill: plot.color |
| | | } |
| | |
| | | } |
| | | if (plot.max || plot.max === 0) { |
| | | c.max = plot.max |
| | | c.min = c.min || 0 |
| | | } |
| | | chart.scale(_valfield, c) |
| | | |
| | | chart.axis(plot.Xaxis, plot.$xc) |
| | | chart.axis(_valfield, plot.$yc) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | if (!plot.legend) { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: type, |
| | | value: plot.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${plot.Xaxis}*${_valfield}*${_typefield}`, (name, value, type) => { |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | return { |
| | | name: type, |
| | | value: plot.show === 'percent' ? value + '%' : value |
| | | value: val |
| | | } |
| | | }) |
| | | |
| | |
| | | return null |
| | | } |
| | | |
| | | let val = value |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | val = value + '%' |
| | | } else if (plot.show === 'thdSeparator') { |
| | | val = val + '' |
| | | val = val.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && plot.$colors && plot.$colors.has(key)) { |
| | |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | content: val, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | |
| | | MKEmitter.emit('modifyTabs', newtab, true) |
| | | } else if (plot.click === 'menu') { |
| | | let menuId = plot.menu.slice(-1)[0] |
| | | let newtab = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0] |
| | | let menu = null |
| | | |
| | | if (!newtab && plot.MenuID) { |
| | | newtab = { |
| | | if (window.GLOB.mkThdMenus.has(menuId)) { |
| | | menu = {...window.GLOB.mkThdMenus.get(menuId)} |
| | | } else if (plot.MenuID) { |
| | | menu = { |
| | | MenuID: plot.MenuID, |
| | | MenuName: plot.MenuName, |
| | | MenuNo: plot.MenuNo, |
| | | type: plot.tabType |
| | | } |
| | | } else if (!newtab) { |
| | | return |
| | | } |
| | | |
| | | if (!menu) return |
| | | |
| | | newtab = { |
| | | ...newtab, |
| | | param: {} |
| | | } |
| | | menu.param = {} |
| | | |
| | | if (plot.joint === 'true') { |
| | | newtab.param.$BID = data.$$uuid || '' |
| | | menu.param.$BID = data.$$uuid || '' |
| | | |
| | | Object.keys(data).forEach(key => { |
| | | if (/^\$/.test(key)) return |
| | | newtab.param[key] = data[key] |
| | | menu.param[key] = data[key] |
| | | }) |
| | | } |
| | | |
| | | MKEmitter.emit('modifyTabs', newtab, true) |
| | | MKEmitter.emit('modifyTabs', menu, true) |
| | | } else { |
| | | MKEmitter.emit('resetSelectLine', config.uuid, (data ? data.$$uuid : ''), data) |
| | | } |