From abe942f4c6d49a6ad42acaf8e74f5f02b5ffc089 Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期五, 04 六月 2021 15:26:17 +0800 Subject: [PATCH] 2021-06-04 --- src/menu/components/chart/antv-pie/index.jsx | 246 +++++++++++ src/menu/components/chart/antv-bar/chartcompile/index.jsx | 18 src/menu/components/chart/antv-bar/index.jsx | 212 +++++++++ src/tabviews/custom/components/chart/antv-bar-line/index.jsx | 265 ++++++++++- src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx | 20 src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx | 4 src/menu/components/chart/antv-pie/chartcompile/index.jsx | 6 src/menu/components/table/normal-table/index.jsx | 5 src/tabviews/zshare/actionList/normalbutton/index.jsx | 24 src/tabviews/custom/components/chart/antv-pie/index.jsx | 404 +++++++++++++++++- src/utils/utils.js | 6 11 files changed, 1,091 insertions(+), 119 deletions(-) diff --git a/src/menu/components/chart/antv-bar/chartcompile/index.jsx b/src/menu/components/chart/antv-bar/chartcompile/index.jsx index 2a2d793..f1661fe 100644 --- a/src/menu/components/chart/antv-bar/chartcompile/index.jsx +++ b/src/menu/components/chart/antv-bar/chartcompile/index.jsx @@ -331,6 +331,13 @@ this.setState({plot: {...plot, enabled: val}}) } + mutilBarChange = (e) => { + const { plot } = this.state + let val = e.target.value + + this.setState({plot: {...plot, mutilBar: val}}) + } + onSubmit = () => { const { config } = this.props const { plot, view } = this.state @@ -530,6 +537,17 @@ </Form.Item> </Form> </Col> + <Col span={12}> + <Form {...formItemLayout}> + <Form.Item label="澶氭煴鎺掑垪" style={{marginBottom: 10}}> + <Radio.Group value={plot.mutilBar || 'dodge'} onChange={this.mutilBarChange}> + <Radio value="dodge">鍒嗙粍</Radio> + <Radio value="stack">鍫嗗彔</Radio> + <Radio value="overlap">閲嶅彔</Radio> + </Radio.Group> + </Form.Item> + </Form> + </Col> <Col style={{fontSize: '12px', color: '#757575', paddingLeft: '10px'}} span={24}>娉細浣跨敤鑷畾涔夎缃椂锛屾樉绀虹殑鍧愭爣杞寸涓�涓湪宸︿晶锛岀浜屼釜鍦ㄥ彸渚э紝澶氫綑鐨勪笉鐢熸晥锛涙煴褰㈠浘鍙彲浠ユ坊鍔犱竴涓紙璁剧疆澶氫釜鏃讹紝绗竴涓敓鏁堬級銆�</Col> <EditTable actions={['edit', 'move']} data={plot.customs || []} columns={cusColumns} onChange={this.changeCustom}/> </TabPane> : null} diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx index 63f0182..c2b5b41 100644 --- a/src/menu/components/chart/antv-bar/index.jsx +++ b/src/menu/components/chart/antv-bar/index.jsx @@ -357,6 +357,7 @@ let fields = [] let legends = [] let transfield = {} + let Bar_axis = [] card.columns.forEach(col => { if (col.field) { @@ -391,11 +392,9 @@ colorIndex++ } - if (item.chartType === 'bar' && !hasBar) { + if (item.chartType === 'bar') { + Bar_axis.push(item.type) hasBar = true - } else if (item.chartType === 'bar') { - item.chartType = 'line' - item.shape = 'smooth' } if (item.axis === 'true' && axisIndex < 2) { @@ -432,13 +431,24 @@ } }) + let padding = [10, 30, 30, 30] + if (plot.mutilBar === 'overlap') { + Bar_axis = [] + } + + if (!Bar_axis.length) { + if (axisIndex === 2) { + padding = [10, 50, 30, 50] + } else if (axisIndex === 1) { + padding = [10, 30, 30, 50] + } + } + const chart = new Chart({ container: card.uuid + 'canvas', autoFit: true, - height: plot.height || 400 + height: plot.height || 400, }) - - chart.data(dv.rows) // chart.axis(plot.Xaxis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) chart.axis(plot.Xaxis, { label: { style: { fill: color } } }) @@ -471,17 +481,182 @@ chart.scale({ nice: true }) + + if (Bar_axis.length) { + const view1 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + const dst = new DataSet() + const dvt = dst.createView().source(data) + + dvt.transform({ + type: 'fold', + fields: [...Bar_axis], + key: 'key', + value: 'value' + }) + + dvt.transform({ + type: 'map', + callback(row) { + row.key = transfield[row.key] || row.key + return row + }, + }) - fields.forEach(item => { - chart.axis(item.name, item.axis) - - chart.scale(item.name, { + view1.data(dvt.rows) + view1.interaction('other-visible') + view1.scale('value', { nice: true, range: [0, 0.9] }) + + view1.legend(false) - if (item.chartType === 'bar') { - let _chart = chart + let colors = new Map() + let colorIndex = 0 + + if (plot.colors && plot.colors.length > 0) { + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], item.color) + } + }) + } + + if (plot.mutilBar !== 'stack') { + let _chart = view1 + .interval() + .position(`${plot.Xaxis}*value`) + .adjust([ + { + type: 'dodge', + marginRatio: 0 + } + ]) + .shape(plot.shape || 'rect') + .tooltip(`${plot.Xaxis}*value*key`, (name, value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: key, + value: value + } + }) + + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (colors.get(key)) { + return colors.get(key) + } else { + colors.set(key, chartColors[colorIndex % limit]) + colorIndex++ + } + }) + } else { + _chart.color('key') + } + if (plot.label === 'true') { + _chart.label('value', (value) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + content: value, + style: { + fill: color + } + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } 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) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: type, + value: value + } + }) + + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (colors.get(key)) { + return colors.get(key) + } else { + colors.set(key, chartColors[colorIndex % limit]) + colorIndex++ + } + }) + } else { + _chart.color('key') + } + if (plot.label === 'true') { + _chart.label('value', (value) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + content: value, + style: { + fill: color + } + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } + } + + const view2 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + + view2.data(dv.rows) + view2.interaction('other-visible') + + view2.legend(false) + + fields.forEach(item => { + if (item.chartType === 'bar' && !Bar_axis.length) { + view2.axis(item.name, item.axis) + + view2.scale(item.name, { + nice: true, + range: [0, 0.9] + }) + + let _chart = view2 .interval() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) @@ -516,7 +691,16 @@ _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) } } else if (item.chartType === 'line') { - let _chart = chart + if (!Bar_axis.length) { + view2.axis(item.name, item.axis) + } else { + view2.axis(item.name, { grid: null, title: null, label: null }) + } + view2.scale(item.name, { + nice: true, + range: [0, 0.9] + }) + let _chart = view2 .line() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) diff --git a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx index 107b8b7..445f08d 100644 --- a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx +++ b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx @@ -144,13 +144,14 @@ options: [ { value: 'pie', text: '楗煎浘' }, { value: 'ring', text: '鐜浘' }, + { value: 'nest', text: '宓屽' }, { value: 'nightingale', text: '鍗椾竵鏍煎皵鍥�' } ] }, { type: 'select', key: 'Xaxis', - label: 'X-杞�', + label: '鍚嶇О', initVal: card.Xaxis || '', required: true, options: xfields @@ -158,10 +159,20 @@ { type: 'select', key: 'Yaxis', - label: 'Y-杞�', + label: '鍊�', initVal: card.Yaxis || '', required: true, options: yfields + }, + { + type: 'select', + key: 'type', + label: '绫诲瀷', + initVal: card.type || '', + tooltip: '鍐呯幆鐨勫垎绫诲瓧娈点��', + required: true, + options: xfields, + hidden: card.shape !== 'nest', }, { type: 'select', @@ -183,7 +194,8 @@ { field: 'left-top', label: '宸︿笂' }, { field: 'left-bottom', label: '宸︿笅' }, { field: 'hidden', label: '闅愯棌' } - ] + ], + hidden: card.shape === 'nest', }, { type: 'number', @@ -251,7 +263,7 @@ }, { value: 'outer', text: '澶栦晶' - }] + }], }, { type: 'radio', key: 'repeat', diff --git a/src/menu/components/chart/antv-pie/chartcompile/index.jsx b/src/menu/components/chart/antv-pie/chartcompile/index.jsx index 2152dde..5c5101e 100644 --- a/src/menu/components/chart/antv-pie/chartcompile/index.jsx +++ b/src/menu/components/chart/antv-pie/chartcompile/index.jsx @@ -70,6 +70,10 @@ formlist: formlist.map(item => { if (item.key === 'innerRadius') { item.hidden = val === 'pie' + } else if (item.key === 'type') { + item.hidden = val !== 'nest' + } else if (item.key === 'legend') { + item.hidden = val === 'nest' } return item }) @@ -184,7 +188,7 @@ } ] })( - <Radio.Group disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> + <Radio.Group style={{whiteSpace: 'nowrap'}} disabled={item.readonly} onChange={(e) => this.radioChange(e, item.key)}> {item.options.map(option => { return ( <Radio key={option.value} value={option.value}>{option.text}</Radio> diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx index ebd9179..8c6428b 100644 --- a/src/menu/components/chart/antv-pie/index.jsx +++ b/src/menu/components/chart/antv-pie/index.jsx @@ -3,7 +3,7 @@ import { is, fromJS } from 'immutable' import { Icon, Popover } from 'antd' import { Chart } from '@antv/g2' -import DataSet from '@antv/data-set' +import DataSet, { DataView } from '@antv/data-set' import MKEmitter from '@/utils/events.js' import asyncComponent from '@/utils/asyncComponent' @@ -54,6 +54,9 @@ if (card.subtype === 'ring') { _plot.innerRadius = 50 + } else if (card.subtype === 'nest') { + _plot.innerRadius = 30 + _plot.radius = 80 } let _card = { @@ -150,13 +153,6 @@ { label: '2003', value: 33.7 }, { label: '2004', value: 30.7 }, { label: '2005', value: 25.8 }, - { label: '2006', value: 31.7 }, - { label: '2007', value: 33 }, - { label: '2008', value: 46 }, - { label: '2009', value: 38.3 }, - { label: '2010', value: 28 }, - { label: '2011', value: 42.5 }, - { label: '2012', value: 30.3 } ] let data = xdata.map(item => { @@ -169,11 +165,243 @@ return data } + getnestdata = (X_axis, Y_axis, type) => { + const xdata = [ + { name: '鐙瓙', type: '鐏薄', value: 11 }, + { name: '鐧界緤', type: '鐏薄', value: 10 }, + { name: '姘寸摱', type: '椋庡悜', value: 14 }, + { name: '灏勬墜', type: '鐏薄', value: 10 }, + { name: '鍙屽瓙', type: '椋庡悜', value: 7 }, + { name: '澶╁钩', type: '椋庡悜', value: 7 }, + { name: '鎽╃警', type: '鍦熻薄', value: 14 }, + { name: '閲戠墰', type: '鍦熻薄', value: 3 }, + { name: '澶勫コ', type: '鍦熻薄', value: 3 }, + { name: '澶╄潕', type: '姘磋薄', value: 11 }, + { name: '宸ㄨ煿', type: '姘磋薄', value: 5 }, + { name: '鍙岄奔', type: '姘磋薄', value: 5 }, + ] + + let map = new Map() + let sort = 1 + let data = xdata.map(item => { + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + return { + [X_axis]: item.name, + [Y_axis]: item.value, + [type]: item.type, + $sort: _sort + } + }) + + return data + } + + nestrender = () => { + const { card } = this.state + const plot = card.plot + + let color = plot.color || 'rgba(0, 0, 0, 0.85)' + let X_axis = plot.Xaxis || 'x' + let Y_axis = plot.Yaxis || 'y' + let type = plot.type || 'type' + + const _data = this.getnestdata(X_axis, Y_axis, type) + const dvx = new DataView().source(_data) + + dvx.transform({ + type: 'sort-by', + fields: ['$sort'] + }) + + let data = dvx.rows + + // 閫氳繃 DataSet 璁$畻鐧惧垎姣� + const dv = new DataView() + dv.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: type, + as: '$percent' + }) + + const dv1 = new DataView() + dv1.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: X_axis, + as: '$percent', + }) + + const chart = new Chart({ + container: card.uuid + 'canvas', + autoFit: true, + height: card.plot.height ? (card.plot.height - 75) : 325, + padding: 0, + }) + + chart.data(dv.rows) + + if (plot.show !== 'value') { + chart.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + + Y_axis = '$percent' + } + let radius = plot.radius / 100 + let innerRadius = plot.innerRadius / 100 + + chart.coordinate('theta', { + innerRadius: innerRadius, + radius: innerRadius + (radius - innerRadius) / 2, + }) + chart.tooltip({ + showTitle: false, + showMarkers: false, + }) + chart.legend(false) + let chart1 = chart + .interval() + .adjust('stack') + .position(Y_axis) + .color(type) + .tooltip(`${type}*${Y_axis}`, (type, percent) => { + if (plot.show !== 'value') { + percent = (percent * 100).toFixed(2) + '%' + } + return { + name: type, + value: percent, + } + }) + .style({ + lineWidth: 1, + stroke: '#fff', + }) + + if (plot.label !== 'false') { + chart1.label(type, { + offset: -10, + }) + } + + const outterView = chart.createView() + + outterView.data(dv1.rows) + + if (plot.show !== 'value') { + outterView.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + } + outterView.coordinate('theta', { + innerRadius: (innerRadius + (radius - innerRadius) / 2) / radius, + radius: radius + }) + let chart2 = outterView + .interval() + .adjust('stack') + .position(Y_axis) + .color(X_axis) + .tooltip(`${X_axis}*${Y_axis}`, (name, value) => { + if (plot.show !== 'value') { + value = (value * 100).toFixed(2) + '%' + } + return { + name: name, + value: value + } + }) + .style({ + lineWidth: 1, + stroke: '#fff', + }) + + if (plot.label !== 'false') { + if (plot.label === 'inner') { + chart2.label(Y_axis, { + offset: -30, + content: (data) => { + let _label = '' + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + if (plot.label === 'inner') { + _label = _val + } else { + _label = `${data[X_axis]}: ${_val}` + } + return _label + }, + style: { + textAlign: 'center', + fontSize: 16, + shadowBlur: 2, + shadowColor: 'rgba(0, 0, 0, .45)', + fill: '#fff', + } + }) + } else { + chart2.label(Y_axis, { + layout: { type: 'pie-spider' }, + labelHeight: 20, + content: (data) => { + let _label = '' + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + if (plot.label === 'inner') { + _label = _val + } else { + _label = `${data[X_axis]}: ${_val}` + } + return _label + }, + labelLine: { + style: { + lineWidth: 0.5, + }, + }, + style: { + fill: color + } + }) + } + } + + chart.interaction('element-highlight') + + chart.render() + } + pierender = () => { const { card } = this.state const plot = card.plot - let color = plot.color || 'rgba(0, 0, 0, 0.85)' + if (plot.shape === 'nest') { + this.nestrender() + return + } + + let color = plot.color || 'rgba(0, 0, 0, 0.85)' let X_axis = plot.Xaxis || 'x' let Y_axis = plot.Yaxis || 'y' diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx index 83f0adb..4f47217 100644 --- a/src/menu/components/table/normal-table/index.jsx +++ b/src/menu/components/table/normal-table/index.jsx @@ -35,6 +35,7 @@ state = { dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + appType: sessionStorage.getItem('appType'), card: null, back: false } @@ -385,7 +386,7 @@ } render() { - const { card } = this.state + const { card, appType } = this.state let _style = resetStyle(card.style) return ( @@ -394,7 +395,7 @@ <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞鍒�" onClick={this.addColumns} type="plus" /> - <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> + {appType !== 'mob' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null} <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> <WrapComponent config={card} updateConfig={this.updateComponent} /> <CopyComponent type="normaltable" card={card}/> diff --git a/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx b/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx index 36b6bd9..f42f1a5 100644 --- a/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx +++ b/src/menu/components/table/normal-table/wrapsetting/settingform/index.jsx @@ -226,7 +226,7 @@ })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} </Form.Item> </Col> - <Col span={12}> + {appType !== 'mob' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��"> <Icon type="question-circle" /> @@ -237,7 +237,7 @@ initialValue: wrap.advanceWidth || 1000 })(<InputNumber min={10} max={3000} precision={0} onPressEnter={this.handleSubmit}/>)} </Form.Item> - </Col> + </Col> : null} {appType !== 'mob' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="鍙屽嚮琛ㄦ牸涓锛岃Е鍙戠殑鎸夐挳銆�"> diff --git a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx index b08062f..b1f524a 100644 --- a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx +++ b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx @@ -128,6 +128,7 @@ let axisIndex = 0 let hasBar = false + let Bar_axis = [] let fields = [] let legends = [] @@ -143,11 +144,9 @@ colorIndex++ } - if (item.chartType === 'bar' && !hasBar) { + if (item.chartType === 'bar') { hasBar = true - } else if (item.chartType === 'bar') { - item.chartType = 'line' - item.shape = 'smooth' + Bar_axis.push(item.type) } if (item.axis === 'true' && axisIndex < 2) { @@ -174,6 +173,13 @@ _config.plot.customs = fields _config.plot.legends = legends _config.plot.hasBar = hasBar + _config.plot.axisIndex = axisIndex + + if (_config.plot.mutilBar === 'overlap') { + _config.plot.Bar_axis = [] + } else { + _config.plot.Bar_axis = Bar_axis + } } else { _config.plot.enabled = 'false' } @@ -890,9 +896,23 @@ * @description 鑷畾涔夋覆鏌� */ customrender = (data) => { - const { plot } = this.state + const { plot, transfield } = this.state const ds = new DataSet() - const dv = ds.createView().source(data) + + let _copydata = data + // dodge is not support linear attribute, please use category attribute! 鏃堕棿鏍煎紡 + if (_copydata[0] && _copydata[0][plot.Xaxis] && /^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(_copydata[0][plot.Xaxis])) { + for (let i = 1; i < 12; i++) { + if (_copydata[i] && _copydata[i][plot.Xaxis] === _copydata[0][plot.Xaxis]) { + _copydata[i][plot.Xaxis] += ' ' + } else { + break; + } + } + _copydata[0][plot.Xaxis] += ' ' + } + + const dv = ds.createView().source(_copydata) dv.transform({ type: 'map', callback(row) { @@ -903,32 +923,21 @@ } }) + let padding = [10, 30, 30, 30] + + if (!plot.Bar_axis.length) { + if (plot.axisIndex === 2) { + padding = [10, 50, 30, 50] + } else if (plot.axisIndex === 1) { + padding = [10, 30, 30, 50] + } + } + const chart = new Chart({ container: this.state.chartId, autoFit: true, height: plot.height }) - - let _data = dv.rows - // dodge is not support linear attribute, please use category attribute! 鏃堕棿鏍煎紡 - if (_data[0] && _data[0][plot.Xaxis] && /^\d{4}-\d{2}-\d{2}(\s\d{2}:\d{2}:\d{2})?/.test(_data[0][plot.Xaxis])) { - for (let i = 1; i < 12; i++) { - if (_data[i] && _data[i][plot.Xaxis] === _data[0][plot.Xaxis]) { - _data[i][plot.Xaxis] += ' ' - } else { - break; - } - } - _data[0][plot.Xaxis] += ' ' - } - - chart.data(_data) - - if (!plot.hasBar) { - chart.scale(plot.Xaxis, { - range: [0, 1] - }) - } // 鍧愭爣杞存牸寮忓寲 chart.axis(plot.Xaxis, { @@ -942,6 +951,12 @@ style: { fill: plot.color } }, }) + + if (!plot.hasBar) { + chart.scale(plot.Xaxis, { + range: [0, 1] + }) + } if (!plot.legend || plot.legend === 'hidden') { chart.legend(false) @@ -962,16 +977,185 @@ }) } - plot.customs.forEach((item, i) => { - chart.axis(item.name, item.axis) - - chart.scale(item.name, { - nice: true, - range: [0, 0.93] + chart.scale({ + nice: true + }) + + if (plot.Bar_axis.length) { + const view1 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + const dst = new DataSet() + const dvt = dst.createView().source(_copydata) + + dvt.transform({ + type: 'fold', + fields: [...plot.Bar_axis], + key: 'key', + value: 'value' + }) + + dvt.transform({ + type: 'map', + callback(row) { + row.key = transfield[row.key] || row.key + return row + }, }) - if (item.chartType === 'bar') { - let _chart = chart + view1.data(dvt.rows) + view1.interaction('other-visible') + + view1.scale('value', { + nice: true, + range: [0, 0.9] + }) + + view1.legend(false) + + let colors = new Map() + let colorIndex = 0 + + if (plot.colors && plot.colors.length > 0) { + plot.colors.forEach(item => { + if (!colors.has(transfield[item.type])) { + colors.set(transfield[item.type], item.color) + } + }) + } + + if (plot.adjust !== 'stack') { + let _chart = view1 + .interval() + .position(`${plot.Xaxis}*value`) + .adjust([ + { + type: 'dodge', + marginRatio: 0 + } + ]) + .shape(plot.shape || 'rect') + .tooltip(`${plot.Xaxis}*value*key`, (name, value, key) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: key, + value: value + } + }) + + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (colors.get(key)) { + return colors.get(key) + } else { + colors.set(key, chartColors[colorIndex % limit]) + colorIndex++ + } + }) + } else { + _chart.color('key') + } + if (plot.label === 'true') { + _chart.label('value', (value) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + content: value, + style: { + fill: plot.color + } + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } else if (plot.adjust === 'stack') { + let _chart = view1 + .interval() + .position(`${plot.Xaxis}*value`) + .adjust('stack') + .shape(plot.shape || 'rect') + .tooltip(`${plot.Xaxis}*value*key`, (name, value, type) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + name: type, + value: value + } + }) + + if (plot.colors && plot.colors.length > 0) { + let limit = chartColors.length + _chart.color('key', (key) => { + if (colors.get(key)) { + return colors.get(key) + } else { + colors.set(key, chartColors[colorIndex % limit]) + colorIndex++ + } + }) + } else { + _chart.color('key') + } + if (plot.label === 'true') { + _chart.label('value', (value) => { + if (plot.show === 'percent') { + value = value + '%' + } + return { + content: value, + style: { + fill: plot.color + } + } + }) + } + + if (plot.barSize || plot.correction) { + _chart.size(plot.barSize || 35) + } + if (plot.barRadius) { + _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) + } + } + } + + const view2 = chart.createView({ + region: { + start: { x: 0, y: 0 }, + end: { x: 1, y: 1 } + }, + padding + }) + + view2.data(dv.rows) + view2.interaction('other-visible') + + view2.legend(false) + + plot.customs.forEach((item, i) => { + if (item.chartType === 'bar' && !plot.Bar_axis.length) { + view2.axis(item.name, item.axis) + + view2.scale(item.name, { + nice: true, + range: [0, 0.93] + }) + let _chart = view2 .interval() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) @@ -1003,7 +1187,16 @@ _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) } } else if (item.chartType === 'line') { - let _chart = chart + if (!plot.Bar_axis.length) { + view2.axis(item.name, item.axis) + } else { + view2.axis(item.name, { grid: null, title: null, label: null }) + } + view2.scale(item.name, { + nice: true, + range: [0, 0.9] + }) + let _chart = view2 .line() .position(`${plot.Xaxis}*${item.name}`) .color(item.color) diff --git a/src/tabviews/custom/components/chart/antv-pie/index.jsx b/src/tabviews/custom/components/chart/antv-pie/index.jsx index c398a77..717b6d7 100644 --- a/src/tabviews/custom/components/chart/antv-pie/index.jsx +++ b/src/tabviews/custom/components/chart/antv-pie/index.jsx @@ -3,7 +3,7 @@ import { is, fromJS } from 'immutable' import { Chart } from '@antv/g2' import { connect } from 'react-redux' -import DataSet from '@antv/data-set' +import DataSet, { DataView } from '@antv/data-set' import { Spin, Empty, notification } from 'antd' import moment from 'moment' @@ -63,6 +63,15 @@ } _config.style.height = height + + let decimal = 0 + _config.columns.forEach(col => { + if (_config.plot.Yaxis === col.field && /Decimal/ig.test(col.datatype)) { + decimal = +col.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '') + } + }) + + _config.plot.$decimal = decimal this.setState({ config: _config, @@ -273,19 +282,12 @@ * 3銆佹煴鐘跺浘鏁版嵁琛ラ綈 */ getdata = () => { - const { data, plot, config } = this.state + const { data, plot } = this.state if (!data) { this.setState({empty: true}) return [] } - - let decimal = 0 - config.columns.forEach(col => { - if (plot.Yaxis === col.field && /Decimal/ig.test(col.datatype)) { - decimal = +col.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '') - } - }) let _data = [] let _cdata = fromJS(data).toJS() @@ -296,14 +298,16 @@ if (typeof(item[plot.Yaxis]) !== 'number') { item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) if (isNaN(item[plot.Yaxis])) { - item[plot.Yaxis] = 0 + return } + } else if (!item[plot.Xaxis]) { + return } - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { + if (!_mdata.has(item[plot.Xaxis])) { item.$count = 1 _mdata.set(item[plot.Xaxis], item) - } else if (item[plot.Xaxis]) { + } else { let _item = _mdata.get(item[plot.Xaxis]) _item.$count++ _item[plot.Yaxis] += item[plot.Yaxis] @@ -314,8 +318,7 @@ _data = [..._mdata.values()] _data = _data.map(item => { item[plot.Yaxis] = item[plot.Yaxis] / item.$count - item[plot.Yaxis] = item[plot.Yaxis].toFixed(decimal) - item[plot.Yaxis] = +item[plot.Yaxis] + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) return item }) @@ -325,13 +328,15 @@ if (typeof(item[plot.Yaxis]) !== 'number') { item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) if (isNaN(item[plot.Yaxis])) { - item[plot.Yaxis] = 0 + return } + } else if (!item[plot.Xaxis]) { + return } - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { + if (!_mdata.has(item[plot.Xaxis])) { _mdata.set(item[plot.Xaxis], item) - } else if (item[plot.Xaxis]) { + } else { let _item = _mdata.get(item[plot.Xaxis]) _item[plot.Yaxis] += item[plot.Yaxis] _mdata.set(item[plot.Xaxis], _item) @@ -340,34 +345,355 @@ _data = [..._mdata.values()] _data = _data.map(item => { - item[plot.Yaxis] = item[plot.Yaxis].toFixed(decimal) - item[plot.Yaxis] = +item[plot.Yaxis] + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) return item }) } else { // plot.repeat === 'unrepeat' let _mdata = new Map() _cdata.forEach(item => { - if (item[plot.Xaxis] && !_mdata.has(item[plot.Xaxis])) { - - if (typeof(item[plot.Yaxis]) !== 'number') { - item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) - if (isNaN(item[plot.Yaxis])) { - item[plot.Yaxis] = 0 - } - } - - item[plot.Yaxis] = item[plot.Yaxis].toFixed(decimal) - item[plot.Yaxis] = +item[plot.Yaxis] - - _mdata.set(item[plot.Xaxis], item) + if (!item[plot.Xaxis] || _mdata.has(item[plot.Xaxis])) { + return } + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } + + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + + _mdata.set(item[plot.Xaxis], item) }) _data = [..._mdata.values()] } this.setState({empty: _data.length === 0}) + return _data + } + + getnestdata = () => { + const { data, plot } = this.state + + if (!data) { + this.setState({empty: true}) + return [] + } + + let _data = [] + let _cdata = fromJS(data).toJS() + + if (plot.repeat === 'average') { + let _mdata = new Map() + let map = new Map() + let sort = 1 + _cdata.forEach(item => { + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } else if (!item[plot.Xaxis] || !item[plot.type]) { + return + } + + let sign = item[plot.type] + item[plot.Xaxis] + + if (!_mdata.has(sign)) { + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + + item.$count = 1 + item.$sort = _sort + _mdata.set(sign, item) + } else { + let _item = _mdata.get(sign) + _item.$count++ + _item[plot.Yaxis] += item[plot.Yaxis] + _mdata.set(sign, _item) + } + }) + + _data = [..._mdata.values()] + _data = _data.map(item => { + item[plot.Yaxis] = item[plot.Yaxis] / item.$count + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + + return item + }) + } else if (plot.repeat === 'cumsum') { + let _mdata = new Map() + let map = new Map() + let sort = 1 + _cdata.forEach(item => { + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } else if (!item[plot.Xaxis] || !item[plot.type]) { + return + } + + let sign = item[plot.type] + item[plot.Xaxis] + + if (!_mdata.has(sign)) { + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + + item.$sort = _sort + _mdata.set(sign, item) + } else { + let _item = _mdata.get(sign) + _item[plot.Yaxis] += item[plot.Yaxis] + _mdata.set(sign, _item) + } + }) + + _data = [..._mdata.values()] + _data = _data.map(item => { + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + return item + }) + } else { // plot.repeat === 'unrepeat' + let _mdata = new Map() + let map = new Map() + let sort = 1 + _cdata.forEach(item => { + let sign = item[plot.type] + item[plot.Xaxis] + if (!item[plot.Xaxis] || !item[plot.type] || _mdata.has(sign)) { + return + } + + if (typeof(item[plot.Yaxis]) !== 'number') { + item[plot.Yaxis] = parseFloat(item[plot.Yaxis]) + if (isNaN(item[plot.Yaxis])) { + return + } + } + + let _sort = sort + if (map.has(item.type)) { + _sort = map.get(item.type) + } else { + map.set(item.type, _sort) + sort++ + } + + item.$sort = _sort + item[plot.Yaxis] = +item[plot.Yaxis].toFixed(plot.$decimal) + + _mdata.set(sign, item) + }) + + _data = [..._mdata.values()] + } + + this.setState({empty: _data.length === 0}) + + return _data + } + + nestrender = () => { + const { plot, chartId } = this.state + + let X_axis = plot.Xaxis + let Y_axis = plot.Yaxis + let type = plot.type + let color = plot.color + + let _data = this.getnestdata() + + const dvx = new DataView().source(_data) + + dvx.transform({ + type: 'sort-by', + fields: ['$sort'] + }) + + let data = dvx.rows + + // 閫氳繃 DataSet 璁$畻鐧惧垎姣� + const dv = new DataView() + dv.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: type, + as: '$percent' + }) + + const dv1 = new DataView() + dv1.source(data).transform({ + type: 'percent', + field: Y_axis, + dimension: X_axis, + as: '$percent', + }) + + const chart = new Chart({ + container: chartId, + autoFit: true, + height: plot.height, + padding: 0, + }) + + chart.data(dv.rows) + + if (plot.show !== 'value') { + chart.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + + Y_axis = '$percent' + } + let radius = plot.radius / 100 + let innerRadius = plot.innerRadius / 100 + + chart.coordinate('theta', { + innerRadius: innerRadius, + radius: innerRadius + (radius - innerRadius) / 2, + }) + chart.tooltip({ + showTitle: false, + showMarkers: false, + }) + chart.legend(false) + let chart1 = chart + .interval() + .adjust('stack') + .position(Y_axis) + .color(type) + .tooltip(`${type}*${Y_axis}`, (type, percent) => { + if (plot.show !== 'value') { + percent = (percent * 100).toFixed(2) + '%' + } + return { + name: type, + value: percent, + } + }) + .style({ + lineWidth: 1, + stroke: '#fff', + }) + + if (plot.label !== 'false') { + chart1.label(type, { + offset: -10, + }) + } + + const outterView = chart.createView() + + outterView.data(dv1.rows) + + if (plot.show !== 'value') { + outterView.scale('percent', { + formatter: (val) => { + val = val * 100 + '%' + return val + } + }) + } + outterView.coordinate('theta', { + innerRadius: (innerRadius + (radius - innerRadius) / 2) / radius, + radius: radius + }) + let chart2 = outterView + .interval() + .adjust('stack') + .position(Y_axis) + .color(X_axis) + .tooltip(`${X_axis}*${Y_axis}`, (name, value) => { + if (plot.show !== 'value') { + value = (value * 100).toFixed(2) + '%' + } + return { + name: name, + value: value + } + }) + .style({ + lineWidth: 1, + stroke: '#fff', + }) + + if (plot.label !== 'false') { + if (plot.label === 'inner') { + chart2.label(Y_axis, { + offset: -30, + content: (data) => { + let _label = '' + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + if (plot.label === 'inner') { + _label = _val + } else { + _label = `${data[X_axis]}: ${_val}` + } + return _label + }, + style: { + textAlign: 'center', + fontSize: 16, + shadowBlur: 2, + shadowColor: 'rgba(0, 0, 0, .45)', + fill: '#fff', + } + }) + } else { + chart2.label(Y_axis, { + layout: { type: 'pie-spider' }, + labelHeight: 20, + content: (data) => { + let _label = '' + let _val = '' + if (plot.show !== 'value') { + _val = `${(data[Y_axis] * 100).toFixed(2)}%` + } else { + _val = `${data[Y_axis]}` + } + if (plot.label === 'inner') { + _label = _val + } else { + _label = `${data[X_axis]}: ${_val}` + } + return _label + }, + labelLine: { + style: { + lineWidth: 0.5, + }, + }, + style: { + fill: color + } + }) + } + } + + chart.interaction('element-highlight') + + chart.render() } /** @@ -375,12 +701,18 @@ */ pierender = () => { const { plot, chartId } = this.state - let color = plot.color || 'rgba(0, 0, 0, 0.85)' - let X_axis = plot.Xaxis || 'x' - let Y_axis = plot.Yaxis || 'y' + if (plot.shape === 'nest') { + this.nestrender() + return + } - let data = this.getdata(X_axis, Y_axis) + let color = plot.color + + let X_axis = plot.Xaxis + let Y_axis = plot.Yaxis + + let data = this.getdata() const ds = new DataSet() const dv = ds.createView().source(data) diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx index b7ce5d0..34b102b 100644 --- a/src/tabviews/zshare/actionList/normalbutton/index.jsx +++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx @@ -272,11 +272,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, retmsg, this.moduleParams) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, false, this.moduleParams) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, '', param, data[0], columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -314,11 +314,11 @@ param.ID = primaryId || Utils.getguid() if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg, this.moduleParams) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, false, this.moduleParams) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -346,11 +346,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg, this.moduleParams) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, false, this.moduleParams) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, data[0], columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -408,11 +408,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, retmsg, this.moduleParams) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, false, this.moduleParams) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, '', param, cell, columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -441,11 +441,11 @@ param.ID = Utils.getguid() if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg, this.moduleParams) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, false, this.moduleParams) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 @@ -464,11 +464,11 @@ param.ID = primaryId if (retmsg) { - const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg, this.moduleParams) // 鏁版嵁婧� + const { sql, callbacksql } = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, retmsg, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� param.LText = sql param.$callbacksql = callbacksql } else { - param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, false, this.moduleParams) // 鏁版嵁婧� + param.LText = getSysDefaultSql(btn, setting, formdata, param, cell, columns, this.props.Tab, false, this.moduleParams, Utils.getAllSearchOptions) // 鏁版嵁婧� } if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺 diff --git a/src/utils/utils.js b/src/utils/utils.js index 1625ae6..c99abbb 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1057,7 +1057,7 @@ * @return {Object} tab 鏍囩淇℃伅 * @return {Boolean} retmsg 鏄惁闇�瑕佹暟鎹繑鍥� */ -export function getSysDefaultSql (btn, setting, formdata, param, data, columns, tab, retmsg = false, moduleParams) { +export function getSysDefaultSql (btn, setting, formdata, param, data, columns, tab, retmsg = false, moduleParams, getOptions) { let primaryId = param.ID let BID = param.BID let verify = btn.verify || {} @@ -1299,8 +1299,8 @@ datasource = '(' + datasource + ') tb' } - if (setting.queryType === 'statistics' || customScript) { - let allSearch = this.getAllSearchOptions(search) + if (getOptions && (setting.queryType === 'statistics' || customScript)) { + let allSearch = getOptions(search) let regoptions = allSearch.map(item => { return { -- Gitblit v1.8.0