| | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | ismob: sessionStorage.getItem('appType') === 'mob', |
| | | appType: sessionStorage.getItem('appType'), |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | const { ismob } = this.state |
| | | const { appType } = this.state |
| | | |
| | | if (card.isNew) { |
| | | let _card = { |
| | |
| | | btnlog: [], |
| | | subcards: [{ |
| | | uuid: Utils.getuuid(), |
| | | setting: { width: ismob ? 24 : 6, type: 'simple'}, |
| | | setting: { width: appType === 'mob' ? 24 : 6, type: 'simple'}, |
| | | style: { |
| | | borderWidth: '1px', borderColor: '#e8e8e8', |
| | | paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { card, ismob } = this.state |
| | | const { card, appType } = this.state |
| | | |
| | | let offset = 0 |
| | | if (card.wrap.cardFloat && card.wrap.cardFloat !== 'left') { |
| | |
| | | <NormalHeader defaultshow="hidden" config={card} updateComponent={this.updateComponent}/> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | {!ismob ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | {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="datacard" card={card}/> |
| | |
| | | <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/> |
| | | {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} offset={!index ? offset : 0} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} |
| | | <div style={{clear: 'both'}}></div> |
| | | {card.wrap.pagestyle !== 'switch' && card.setting.laypage === 'true' ? <Pagination total={85} size="small" showTotal={total => `共 ${total} 条`} pageSize={20} defaultCurrent={1}/> : null} |
| | | {card.wrap.pagestyle === 'page' && card.setting.laypage === 'true' ? <Pagination total={85} size="small" showTotal={total => `共 ${total} 条`} pageSize={20} defaultCurrent={1}/> : null} |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | |
| | | state = { |
| | | roleList: [], |
| | | appType: sessionStorage.getItem('appType'), |
| | | MenuType: '' |
| | | } |
| | | |
| | |
| | | render() { |
| | | const { wrap, config } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList, MenuType } = this.state |
| | | const { roleList, MenuType, appType } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {config.subtype === 'datacard' ? <Col span={12}> |
| | | {config.subtype === 'datacard' || (config.subtype === 'tablecard' && appType === 'mob') ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="数据源中选择分页时有效。"> |
| | | <Icon type="question-circle" /> |
| | |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="page">页码</Radio> |
| | | <Radio value="switch">左右切换</Radio> |
| | | {appType !== 'mob' ? <Radio value="switch">左右切换</Radio> : null} |
| | | {appType === 'mob' ? <Radio value="slide">滑动加载</Radio> : null} |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | |
| | | <div style={{minHeight: 'calc(100% - 90px)'}}> |
| | | {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} |
| | | </div> |
| | | {card.setting.laypage === 'true' ? <Pagination size="small" total={50} /> : null} |
| | | {card.setting.laypage === 'true' && card.wrap.pagestyle !== 'slide' ? <Pagination size="small" total={50} /> : null} |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | * @param {object} card // 图表对象 |
| | | */ |
| | | export function getBaseForm (card) { |
| | | let isApp = sessionStorage.getItem('appType') === 'pc' |
| | | let appType = sessionStorage.getItem('appType') |
| | | let menulist = null |
| | | |
| | | if (isApp) { |
| | | if (appType === 'pc' || appType === 'mob') { |
| | | menulist = sessionStorage.getItem('appMenus') |
| | | if (Array.isArray(card.linkmenu)) { |
| | | card.linkmenu = '' |
| | | } |
| | | } else { |
| | | menulist = sessionStorage.getItem('fstMenuList') |
| | | } |
| | |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | if (isApp) { |
| | | if (appType === 'pc' || appType === 'mob') { |
| | | menulist = menulist.map(item => { |
| | | item.value = item.MenuID |
| | | item.text = item.MenuName |
| | |
| | | initVal: card.linkmenu || [], |
| | | tooltip: '在使用柱形图且未启用自定义设置时有效。', |
| | | required: false, |
| | | forbid: isApp, |
| | | forbid: appType === 'pc' || appType === 'mob', |
| | | options: menulist |
| | | }, |
| | | { |
| | |
| | | initVal: card.linkmenu || '', |
| | | tooltip: '双击饼图,会打开关联的菜单。', |
| | | required: false, |
| | | forbid: !isApp, |
| | | forbid: !(appType === 'pc' || appType === 'mob'), |
| | | options: menulist |
| | | }, |
| | | { |
| | |
| | | label: '打开方式', |
| | | initVal: card.open || 'blank', |
| | | required: false, |
| | | forbid: !isApp, |
| | | forbid: !(appType === 'pc' || appType === 'mob'), |
| | | options: [ |
| | | { value: 'blank', text: '新窗口' }, |
| | | { value: 'self', text: '当前窗口' } |
| | |
| | | key: 'datatype', |
| | | label: '数据类型', |
| | | initVal: card.datatype || 'query', |
| | | tooltip: '统计图表适用于表格不分页,且数据需要转换', |
| | | tooltip: '统计图表适用于展示数据类型为动态值。', |
| | | required: false, |
| | | options: [ |
| | | { value: 'query', text: Formdict['header.form.query'] }, |
| | |
| | | value: 'polar', |
| | | text: '极坐标' |
| | | }] |
| | | }, { |
| | | type: 'number', |
| | | key: 'InfoDefNumber', |
| | | label: '展示数', |
| | | tooltip: '默认显示类型数量', |
| | | min: 1, |
| | | max: 50, |
| | | decimal: 0, |
| | | initVal: card.InfoDefNumber || 5, |
| | | hidden: card.datatype !== 'statistics', |
| | | required: true |
| | | }, { |
| | | type: 'number', |
| | | key: 'barSize', |
| | |
| | | formlist: formlist.map(item => { |
| | | if (['Yaxis'].includes(item.key)) { |
| | | item.hidden = val === 'statistics' |
| | | } else if (['InfoType', 'InfoValue', 'InfoDefNumber'].includes(item.key)) { |
| | | } else if (['InfoType', 'InfoValue'].includes(item.key)) { |
| | | item.hidden = val !== 'statistics' |
| | | } |
| | | return item |
| | |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | {config.type !== 'navbar' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'该组件如果受其他组件控制,请选项相应的组件,没有时选“无”。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | <Cascader options={modules} onChange={this.changeSupModule} expandTrigger="hover" placeholder="" /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | {config.pageable ? <Col span={8}> |
| | | <Form.Item label="分页"> |
| | | {getFieldDecorator('laypage', { |
| | |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {/* 1、不分页且不存在上级模块 */} |
| | | {(!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}> |
| | | {config.type !== 'navbar' && (!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'初始化加载时,是否与其他组件一同加载数据,注:仅在使用系统函数,且初始化加载数据时有效,分页请求时无效。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | {config.type !== 'navbar' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'优先使用同级的搜索条件组件,同级搜索不存在时,依次向上选取,与当前组件的搜索条件一同用作数据过滤(当前组件的搜索条件优先)。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {useMSearch === 'true' ? <Col span={8}> |
| | | </Col> : null} |
| | | {config.type !== 'navbar' && useMSearch === 'true' ? <Col span={8}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title={'外层搜索条件改变时,是否刷新当前组件数据。'}> |
| | | <Icon type="question-circle" /> |
| | |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | {config.type !== 'navbar' ? <Col span={8}> |
| | | <Form.Item label="初始化数据"> |
| | | {getFieldDecorator('onload', { |
| | | initialValue: setting.onload || 'true' |
| | |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | </Col> : null} |
| | | </Row> |
| | | </Form> |
| | | </div> |
| | |
| | | item.key = index |
| | | item.$$uuid = item[_config.setting.primaryKey] || '' |
| | | item.$$BID = BID || '' |
| | | item.$Index = index + 1 |
| | | return item |
| | | }) |
| | | } |
| | |
| | | item.key = index |
| | | item.$$uuid = item[config.setting.primaryKey] || '' |
| | | item.$$BID = BID || '' |
| | | item.$Index = index + 1 |
| | | return item |
| | | }) |
| | | |
| | |
| | | |
| | | let result = await Api.genericInterface(param) |
| | | if (result.status) { |
| | | let start = 1 |
| | | if (config.setting.laypage) { |
| | | start = config.setting.pageSize * (pageIndex - 1) + 1 |
| | | } |
| | | |
| | | this.setState({ |
| | | activeKey: '', |
| | | selectKeys: [], |
| | |
| | | item.key = index |
| | | item.$$uuid = item[config.setting.primaryKey] || '' |
| | | item.$$BID = BID || '' |
| | | item.$Index = index + start |
| | | return item |
| | | }), |
| | | total: result.total, |
| | |
| | | _data.key = item.key |
| | | _data.$$uuid = _data[config.setting.primaryKey] || '' |
| | | _data.$$BID = BID || '' |
| | | _data.$Index = item.$Index |
| | | return _data |
| | | } else { |
| | | return item |
| | |
| | | actions={config.action} |
| | | columns={config.columns} |
| | | selectedData={selectedData} |
| | | refreshdata={this.refreshbyaction} |
| | | /> : null |
| | | } |
| | | <div className={`data-zoom ${config.wrap.cardType || ''} ${config.wrap.scale || ''}`}> |
| | |
| | | import { Chart } from '@antv/g2' |
| | | import { connect } from 'react-redux' |
| | | import DataSet from '@antv/data-set' |
| | | import { Spin, Empty, Select, notification } from 'antd' |
| | | import { Spin, Empty, notification } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import asyncComponent from './asyncButtonComponent' |
| | |
| | | search: null, // 搜索条件 |
| | | vFields: [], // 数值字段 |
| | | vstFields: null, // 统计数据值字段信息 |
| | | chartData: [], // 图表数据 |
| | | chartFields: [], // 统计图表生成字段集 |
| | | selectFields: [], // 统计图表选择字段 |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | * @description 数据预处理,统计数据需要重置 |
| | | */ |
| | | handleData = () => { |
| | | const { data, plot } = this.state |
| | | |
| | | if (plot.datatype === 'statistics') { |
| | | let result = this.getStaticMsg(data) |
| | | |
| | | this.setState({ |
| | | chartData: result.data, |
| | | chartFields: result.chartFields, |
| | | selectFields: result.selectFields |
| | | }, () => { |
| | | let _element = document.getElementById(this.state.chartId) |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.viewrender() |
| | | }) |
| | | } else { |
| | | let _element = document.getElementById(this.state.chartId) |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.viewrender() |
| | | let _element = document.getElementById(this.state.chartId) |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.viewrender() |
| | | } |
| | | |
| | | /** |
| | |
| | | getdata = () => { |
| | | const { data, plot, vFields } = this.state |
| | | |
| | | if (!data) { |
| | | if (!data || data.length === 0) { |
| | | this.setState({empty: true}) |
| | | return [] |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description 统计数据预处理,动态生成统计字段并进行数据转换 |
| | | * @description 统计数据预处理 |
| | | */ |
| | | getStaticMsg = (data) => { |
| | | const { plot, vstFields } = this.state |
| | | getStaticMsg = () => { |
| | | const { plot, vstFields, data } = this.state |
| | | |
| | | let percent = false |
| | | let decimal = 0 |
| | | let decimal = vstFields ? vstFields.decimal : 0 |
| | | |
| | | if (plot.show === 'percent') { |
| | | percent = true |
| | | } |
| | | if (vstFields) { |
| | | decimal = vstFields.decimal |
| | | } |
| | | |
| | | if (!data) { |
| | | if (!data || data.length === 0) { |
| | | this.setState({empty: true}) |
| | | return {data: [], chartFields: [], selectFields: []} |
| | | return [] |
| | | } |
| | | |
| | | let _data = [] |
| | | let _cdata = fromJS(data).toJS() |
| | | let _chartFields = [] |
| | | let _selectFields = [] |
| | | |
| | | if (plot.repeat === 'average') { |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.InfoType] || !item[plot.Xaxis]) return |
| | | _chartFields.push(item[plot.InfoType]) |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | if (typeof(item[plot.InfoValue]) !== 'number') { |
| | |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.InfoType] || !item[plot.Xaxis]) return |
| | | _chartFields.push(item[plot.InfoType]) |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | |
| | |
| | | let _mdata = new Map() |
| | | _cdata.forEach(item => { |
| | | if (!item[plot.InfoType] || !item[plot.Xaxis]) return |
| | | _chartFields.push(item[plot.InfoType]) |
| | | |
| | | item.$uuid = item[plot.InfoType] + item[plot.Xaxis] |
| | | |
| | |
| | | _data = [..._mdata.values()] |
| | | } |
| | | |
| | | _chartFields = Array.from(new Set(_chartFields)) |
| | | |
| | | if (plot.InfoDefNumber >= _chartFields.length) { |
| | | _selectFields = _chartFields |
| | | } else { |
| | | _selectFields = _chartFields.slice(0, plot.InfoDefNumber) |
| | | } |
| | | |
| | | return {data: _data, chartFields: _chartFields, selectFields: _selectFields} |
| | | } |
| | | |
| | | /** |
| | | * @description 获取统计图表展示数据,通过选择类型筛选 |
| | | */ |
| | | getStaticData = () => { |
| | | const { plot, chartData, chartFields, selectFields } = this.state |
| | | |
| | | let _data = [] |
| | | if (selectFields.length === chartFields.length) { |
| | | _data = chartData |
| | | } else { |
| | | _data = chartData.filter(item => selectFields.includes(item[plot.InfoType])) |
| | | } |
| | | |
| | | this.setState({empty: _data.length === 0}) |
| | | |
| | | return _data |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | _data = this.getStaticData() |
| | | _data = this.getStaticMsg() |
| | | } else { |
| | | let data = this.getdata() |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | _data = this.getStaticData() |
| | | _data = this.getStaticMsg() |
| | | } else { |
| | | let data = this.getdata() |
| | | |
| | |
| | | chart.render() |
| | | } |
| | | |
| | | /** |
| | | * @description 统计图表,统计类型切换 |
| | | */ |
| | | handleChange = (val) => { |
| | | this.setState({selectFields: val}, () => { |
| | | let _element = document.getElementById(this.state.chartId) |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.viewrender() |
| | | }) |
| | | } |
| | | |
| | | refreshSearch = (list) => { |
| | | this.setState({search: list}, () => { |
| | | this.loadData() |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { config, loading, plot, empty, chartFields, selectFields, BID } = this.state |
| | | const { config, loading, empty, BID } = this.state |
| | | |
| | | return ( |
| | | <div className="custom-line-chart-plot-box" style={config.style}> |
| | |
| | | ) |
| | | } |
| | | })} |
| | | {plot.datatype === 'statistics' && chartFields.length > 0 ? <Select |
| | | mode="multiple" |
| | | showSearch |
| | | showArrow={true} |
| | | value={selectFields} |
| | | onChange={this.handleChange} |
| | | maxTagCount={0} |
| | | maxTagPlaceholder={(option) => <div className="type-label">{option.join('、')}</div>} |
| | | > |
| | | {chartFields.map((item, i) => <Select.Option key={i} value={item}>{item}</Select.Option>)} |
| | | </Select> : null} |
| | | </div> |
| | | <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div> |
| | | </div> |
| | |
| | | background: #ffffff; |
| | | } |
| | | } |
| | | > .ant-select { |
| | | width: 150px; |
| | | float: right; |
| | | position: relative; |
| | | z-index: 1; |
| | | .ant-select-selection { |
| | | min-height: 24px; |
| | | height: 28px; |
| | | li { |
| | | background: unset; |
| | | border: 0; |
| | | width: 99%; |
| | | padding: 0; |
| | | margin-right: 0; |
| | | cursor: pointer; |
| | | |
| | | .type-label { |
| | | overflow: hidden; |
| | | word-break: break-word; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | } |
| | | } |
| | | li + li { |
| | | margin-top: 0; |
| | | width: 1%; |
| | | opacity: 0; |
| | | } |
| | | } |
| | | } |
| | | > .ant-select.ant-select-focused { |
| | | .ant-select-selection { |
| | | li { |
| | | width: 50%; |
| | | } |
| | | li + li { |
| | | width: 49%; |
| | | opacity: 1; |
| | | } |
| | | } |
| | | } |
| | | .g2-tooltip-list{ |
| | | display: none; |
| | | } |
| | |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | | import asyncComponent from './asyncButtonComponent' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncBtnComponent from './asyncButtonComponent' |
| | | import UtilsDM from '@/utils/utils-datamanage.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | | |
| | | const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader')) |
| | | const ExcelOutButton = asyncComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton')) |
| | | const ExcelInButton = asyncComponent(() => import('@/tabviews/zshare/actionList/excelInbutton')) |
| | | const ExcelOutButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton')) |
| | | const ExcelInButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/excelInbutton')) |
| | | |
| | | class ScatterChart extends Component { |
| | | static propTpyes = { |