| | |
| | | confirmLoading: false, |
| | | userName: sessionStorage.getItem('User_Name'), |
| | | logourl: window.GLOB.mainlogo, |
| | | appVersion: window.GLOB.appVersion, |
| | | loginVisible: false, |
| | | loginLoading: false, |
| | | avatar: Utils.getrealurl(sessionStorage.getItem('avatar')), |
| | |
| | | |
| | | verup = () => { |
| | | confirm({ |
| | | title: '版本升级', |
| | | title: '页面更新', |
| | | content: '重新加载应用信息', |
| | | onOk() { |
| | | return new Promise(resolve => { |
| | |
| | | }) |
| | | } |
| | | |
| | | about = () => { |
| | | Modal.success({ |
| | | title: '系统版本v' + this.state.appVersion |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { mainMenu, collapse } = this.props |
| | | const { thdMenuList, searchkey, debug, menulist, navBar, menuType } = this.state |
| | | const { thdMenuList, searchkey, debug, menulist, navBar, menuType, appVersion } = this.state |
| | | |
| | | const menu = ( |
| | | <Menu className="header-dropdown"> |
| | |
| | | </Menu.SubMenu> : null} |
| | | <Menu.Item key="doc" onClick={this.gotoDoc}>{this.state.dict['main.doc']}</Menu.Item> |
| | | <Menu.Item key="verup" onClick={this.verup}> |
| | | 版本升级 |
| | | 页面更新 |
| | | </Menu.Item> |
| | | {appVersion ? <Menu.Item key="version" onClick={this.about}> |
| | | 关于 |
| | | </Menu.Item> : null} |
| | | <Menu.Item key="logout" onClick={this.logout}>{this.state.dict['main.logout']}</Menu.Item> |
| | | </Menu> |
| | | ) |
| | |
| | | GLOB.style = _systemMsg.style |
| | | GLOB.showline = _systemMsg.showline || '' |
| | | GLOB.navBar = _systemMsg.navBar || '' |
| | | GLOB.appVersion = _systemMsg.app_version || '' |
| | | |
| | | if (GLOB.favicon) { |
| | | let link = document.querySelector("link[rel*='icon']") || document.createElement('link') |
New file |
| | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | |
| | | const Formdict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | |
| | | /** |
| | | * @description 获取图表视图配置表单 |
| | | * @param {object} card // 图表对象 |
| | | */ |
| | | export function getBaseForm (card) { |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | | roleList = JSON.parse(roleList) |
| | | } catch (e) { |
| | | roleList = [] |
| | | } |
| | | } else { |
| | | roleList = [] |
| | | } |
| | | |
| | | return [ |
| | | { |
| | | type: 'text', |
| | | key: 'title', |
| | | label: '标题', |
| | | initVal: card.title, |
| | | required: false |
| | | }, |
| | | { |
| | | type: 'text', |
| | | key: 'name', |
| | | label: '组件名称', |
| | | initVal: card.name, |
| | | tooltip: '用于组件间的区分。', |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'width', |
| | | label: '宽度', |
| | | initVal: card.width, |
| | | tooltip: '栅格布局,每行等分为24列。', |
| | | min: 1, |
| | | max: 24, |
| | | decimal: 0, |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'height', |
| | | label: '高度', |
| | | initVal: card.height, |
| | | min: 100, |
| | | max: 1000, |
| | | decimal: 0, |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'blacklist', |
| | | label: '黑名单', |
| | | initVal: card.blacklist || [], |
| | | multi: true, |
| | | required: false, |
| | | options: roleList |
| | | }, |
| | | // { |
| | | // type: 'cascader', |
| | | // key: 'linkmenu', |
| | | // label: '关联菜单', |
| | | // initVal: card.linkmenu || [], |
| | | // tooltip: '在使用柱形图且未启用自定义设置时有效。', |
| | | // required: false, |
| | | // forbid: appType === 'pc' || appType === 'mob', |
| | | // options: menulist |
| | | // }, |
| | | // { |
| | | // type: 'select', |
| | | // key: 'linkmenu', |
| | | // label: '关联菜单', |
| | | // initVal: card.linkmenu || '', |
| | | // tooltip: '双击柱状图,会打开关联的菜单。', |
| | | // required: false, |
| | | // forbid: appType !== 'pc', |
| | | // options: menulist |
| | | // }, |
| | | // { |
| | | // type: 'radio', |
| | | // key: 'open', |
| | | // label: '打开方式', |
| | | // initVal: card.open || 'blank', |
| | | // required: false, |
| | | // forbid: appType !== 'pc', |
| | | // options: [ |
| | | // { value: 'blank', text: '新窗口' }, |
| | | // { value: 'self', text: '当前窗口' } |
| | | // ] |
| | | // } |
| | | ] |
| | | } |
| | | |
| | | /** |
| | | * @description 获取图表视图配置表单 |
| | | * @param {object} card // 图表对象 |
| | | * @param {Array} columns // 显示列 |
| | | */ |
| | | export function getOptionForm (card, columns) { |
| | | let appType = sessionStorage.getItem('appType') |
| | | let shapes = [] |
| | | |
| | | if (card.chartType === 'line') { |
| | | shapes = [ |
| | | { field: 'smooth', label: 'smooth' }, |
| | | { field: 'line', label: 'line' }, |
| | | { field: 'dot', label: 'dot' }, |
| | | { field: 'dash', label: 'dash' }, |
| | | { field: 'hv', label: 'hv' }, |
| | | { field: 'vh', label: 'vh' }, |
| | | { field: 'hvh', label: 'hvh' }, |
| | | { field: 'vhv', label: 'vhv' } |
| | | ] |
| | | } else if (card.chartType === 'bar') { |
| | | shapes = [ |
| | | { field: 'rect', label: 'rect' }, |
| | | { field: 'hollow-rect', label: 'hollow-rect' }, |
| | | { field: 'line', label: 'line' }, |
| | | { field: 'tick', label: 'tick' }, |
| | | { field: 'funnel', label: 'funnel' }, |
| | | { field: 'pyramid', label: 'pyramid' } |
| | | ] |
| | | } |
| | | |
| | | let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype)) |
| | | let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype)) |
| | | |
| | | let labelOptions = [{ |
| | | value: 'false', |
| | | text: '隐藏' |
| | | }, { |
| | | value: 'true', |
| | | text: '显示' |
| | | }] |
| | | |
| | | if (card.chartType === 'bar') { |
| | | labelOptions[1].text = '外部' |
| | | labelOptions.push(...[{ |
| | | value: 'top', |
| | | text: '顶部' |
| | | }, { |
| | | value: 'middle', |
| | | text: '中间' |
| | | }, { |
| | | value: 'bottom', |
| | | text: '底部' |
| | | }]) |
| | | } |
| | | |
| | | return [ |
| | | { |
| | | type: 'radio', |
| | | key: 'datatype', |
| | | label: '数据类型', |
| | | initVal: card.datatype || 'query', |
| | | tooltip: '统计图表适用于展示数据类型为动态值。', |
| | | required: false, |
| | | options: [ |
| | | { value: 'query', text: Formdict['header.form.query'] }, |
| | | { value: 'statistics', text: Formdict['header.form.statistics'] } |
| | | ] |
| | | }, { |
| | | type: 'select', |
| | | key: 'Xaxis', |
| | | label: 'X-轴', |
| | | initVal: card.Xaxis || '', |
| | | required: true, |
| | | options: xfields |
| | | }, { |
| | | type: 'select', |
| | | key: 'InfoType', |
| | | label: '类型', |
| | | initVal: card.InfoType || '', |
| | | hidden: card.datatype !== 'statistics', |
| | | required: true, |
| | | options: xfields |
| | | }, { |
| | | type: 'select', |
| | | key: 'InfoValue', |
| | | label: '值', |
| | | initVal: card.InfoValue || '', |
| | | hidden: card.datatype !== 'statistics', |
| | | required: true, |
| | | options: yfields |
| | | }, { |
| | | type: 'select', |
| | | key: 'legend', |
| | | label: '图例位置', |
| | | initVal: card.legend || 'bottom', |
| | | required: false, |
| | | options: [ |
| | | { field: 'bottom', label: '下' }, |
| | | { field: 'bottom-left', label: '下左' }, |
| | | { field: 'bottom-right', label: '下右' }, |
| | | { field: 'top', label: '上' }, |
| | | { field: 'top-left', label: '上左' }, |
| | | { field: 'top-right', label: '上右' }, |
| | | { field: 'right', label: '右' }, |
| | | { field: 'right-top', label: '右上' }, |
| | | { field: 'right-bottom', label: '右下' }, |
| | | { field: 'left', label: '左' }, |
| | | { field: 'left-top', label: '左上' }, |
| | | { field: 'left-bottom', label: '左下' }, |
| | | { field: 'hidden', label: '隐藏' } |
| | | ] |
| | | }, { |
| | | type: 'select', |
| | | key: 'Yaxis', |
| | | label: 'Y-轴', |
| | | initVal: card.Yaxis || [], |
| | | multi: true, // 多选 |
| | | hidden: card.datatype === 'statistics', |
| | | required: true, |
| | | options: yfields |
| | | }, { |
| | | type: 'select', |
| | | key: 'shape', |
| | | label: '形状', |
| | | initVal: card.shape || (shapes[0] && shapes[0].field), |
| | | required: false, |
| | | options: shapes |
| | | }, { |
| | | type: 'radio', |
| | | key: 'tooltip', |
| | | label: '悬浮提示', |
| | | initVal: card.tooltip || 'true', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | | text: '显示' |
| | | }, { |
| | | value: 'false', |
| | | text: '隐藏' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'point', |
| | | label: '点图', |
| | | initVal: card.point || 'false', |
| | | required: false, |
| | | forbid: !['line'].includes(card.chartType), |
| | | options: [{ |
| | | value: 'true', |
| | | text: '显示' |
| | | }, { |
| | | value: 'false', |
| | | text: '隐藏' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'transpose', |
| | | label: '变换', |
| | | initVal: card.transpose || 'false', |
| | | tooltip: '横纵坐标轴交换', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | | text: Formdict['model.true'] |
| | | }, { |
| | | value: 'false', |
| | | text: Formdict['model.false'] |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'show', |
| | | label: '格式化', |
| | | initVal: card.show || 'value', |
| | | required: false, |
| | | options: [{ |
| | | value: 'value', |
| | | text: '无' |
| | | }, { |
| | | value: 'percent', |
| | | text: '百分比' |
| | | }] |
| | | }, { |
| | | type: labelOptions.length > 20 ? 'select' : 'radio', |
| | | key: 'label', |
| | | label: '标签', |
| | | initVal: card.label || 'false', |
| | | required: false, |
| | | options: labelOptions |
| | | }, { |
| | | type: 'radio', |
| | | key: 'labelColor', |
| | | label: '标签颜色', |
| | | initVal: card.labelColor || 'system', |
| | | tooltip: '使用系统色时,使用色系选项设置的系统颜色,使用自定义为颜色设置中定义的图形颜色。', |
| | | required: false, |
| | | options: [{ |
| | | value: 'system', |
| | | text: '系统' |
| | | }, { |
| | | value: 'custom', |
| | | text: '自定义' |
| | | }] |
| | | // }, { |
| | | // type: 'radio', |
| | | // key: 'offset', |
| | | // label: '标注位置', |
| | | // initVal: card.offset || 'outer', |
| | | // required: false, |
| | | // options: [{ |
| | | // value: 'outer', |
| | | // text: '外部' |
| | | // }, { |
| | | // value: 'inner', |
| | | // text: '内部' |
| | | // }], |
| | | // forbid: card.chartType !== 'bar' |
| | | }, { |
| | | type: 'radio', |
| | | key: 'adjust', |
| | | label: '多柱排列', |
| | | initVal: card.adjust || 'dodge', |
| | | required: false, |
| | | forbid: !['bar'].includes(card.chartType), |
| | | options: [{ |
| | | value: 'dodge', |
| | | text: '分组' |
| | | }, { |
| | | value: 'stack', |
| | | text: '堆叠' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'area', |
| | | label: '面积图', |
| | | initVal: card.area || 'false', |
| | | // tooltip: '仅在形状为smooth时有效。', |
| | | required: false, |
| | | forbid: ['bar'].includes(card.chartType), |
| | | options: [{ |
| | | value: 'true', |
| | | text: '显示' |
| | | }, { |
| | | value: 'false', |
| | | text: '不显示' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'repeat', |
| | | label: '重复数据', |
| | | initVal: card.repeat || 'unrepeat', |
| | | required: false, |
| | | options: [{ |
| | | value: 'unrepeat', |
| | | text: '去重' |
| | | }, { |
| | | value: 'average', |
| | | text: '平均' |
| | | }, { |
| | | value: 'cumsum', |
| | | text: '累加' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'coordinate', |
| | | label: '坐标', |
| | | initVal: card.coordinate || 'angle', |
| | | required: false, |
| | | options: [{ |
| | | value: 'angle', |
| | | text: '二维坐标' |
| | | }, { |
| | | value: 'polar', |
| | | text: '极坐标' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'grid', |
| | | label: '网格线', |
| | | initVal: card.grid || 'show', |
| | | required: false, |
| | | options: [{ |
| | | value: 'show', |
| | | text: '显示' |
| | | }, { |
| | | value: 'hidden', |
| | | text: '隐藏' |
| | | }] |
| | | }, { |
| | | type: 'radio', |
| | | key: 'y_line', |
| | | label: 'y轴边线', |
| | | initVal: card.y_line || 'hidden', |
| | | tooltip: '图形左侧或右侧的边线。', |
| | | required: false, |
| | | options: [{ |
| | | value: 'show', |
| | | text: '显示' |
| | | }, { |
| | | value: 'hidden', |
| | | text: '隐藏' |
| | | }] |
| | | }, { |
| | | type: 'number', |
| | | key: 'barSize', |
| | | label: '柱形宽度', |
| | | tooltip: '空值时,宽度自适应。', |
| | | min: 5, |
| | | max: 100, |
| | | decimal: 0, |
| | | initVal: card.barSize, |
| | | forbid: !['bar'].includes(card.chartType), |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'barRadius', |
| | | label: '柱形圆角', |
| | | tooltip: '柱形图上端圆角。', |
| | | min: 0, |
| | | max: 200, |
| | | decimal: 0, |
| | | initVal: card.barRadius || 0, |
| | | forbid: !['bar'].includes(card.chartType), |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'min', |
| | | label: '最小值', |
| | | tooltip: 'y轴最小值,为空时自适应。', |
| | | initVal: card.min, |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'max', |
| | | label: '最大值', |
| | | tooltip: 'y轴最大值,为空时自适应。', |
| | | initVal: card.max, |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'color', |
| | | label: '色系', |
| | | initVal: card.color || 'rgba(0, 0, 0, 0.65)', |
| | | tooltip: '坐标轴提示文字及示例的颜色。', |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'lineColor', |
| | | label: '轴线颜色', |
| | | initVal: card.lineColor, |
| | | tooltip: '坐标轴线的颜色,包括x轴、y轴及网格线。', |
| | | allowClear: true, |
| | | required: false |
| | | }, { |
| | | type: 'color', |
| | | key: 'selectColor', |
| | | label: '选中颜色', |
| | | initVal: card.selectColor || '', |
| | | tooltip: '选中柱形图的颜色,在交互效果《元素选中(多选)》和《元素选中(单选)》中有效,自定义设置中无效。', |
| | | forbid: !['bar'].includes(card.chartType), |
| | | allowClear: true, |
| | | required: false |
| | | }, { |
| | | type: 'number', |
| | | key: 'rotate', |
| | | label: '旋转', |
| | | tooltip: '坐标轴标注文本的旋转角度。', |
| | | min: 0, |
| | | max: 360, |
| | | decimal: 0, |
| | | initVal: card.rotate, |
| | | forbid: appType !== 'mob', |
| | | required: false |
| | | }, { |
| | | type: 'select', |
| | | key: 'interaction', |
| | | label: '交互效果', |
| | | initVal: card.interaction || [], |
| | | multi: true, |
| | | required: false, |
| | | forbid: appType === 'mob', |
| | | options: [ |
| | | { value: 'element-active', label: '元素聚焦' }, |
| | | { value: 'element-selected', label: '元素选中(多选)' }, |
| | | { value: 'element-single-selected', label: '元素选中(单选)' }, |
| | | { value: 'active-region', label: '背景框' }, |
| | | { value: 'view-zoom', label: '视图缩放' }, |
| | | { value: 'element-highlight', label: '元素高亮' }, |
| | | { value: 'element-highlight-by-color', label: '同色元素高亮' }, |
| | | { value: 'element-highlight-by-x', label: '同X轴元素高亮' }, |
| | | { value: 'legend-filter', label: '图例过滤' }, |
| | | { value: 'legend-active', label: '图例聚焦' }, |
| | | { value: 'legend-highlight', label: '图例高亮' }, |
| | | { value: 'brush', label: '选框过滤' }, |
| | | ] |
| | | } |
| | | ] |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Modal, Form, Row, Col, Select, Icon, Radio, Tooltip, Input, InputNumber, Tabs, Button } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import { chartColors } from '@/utils/option.js' |
| | | import { getBaseForm, getOptionForm } from './formconfig' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import ColorSketch from '@/mob/colorsketch' |
| | | import './index.scss' |
| | | |
| | | const { TabPane } = Tabs |
| | | const EditTable = asyncComponent(() => import('@/templates/zshare/editTable')) |
| | | const NormalForm = asyncComponent(() => import('@/menu/components/share/normalform')) |
| | | |
| | | class LineChartDrawerForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, |
| | | plot: PropTypes.object, |
| | | config: PropTypes.object, |
| | | plotchange: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | view: 'normal', |
| | | ramp: 'false', |
| | | visible: false, |
| | | datatype: '', |
| | | plot: null, |
| | | formlist: null, |
| | | baseFormlist: null, |
| | | fieldName: null, |
| | | colorColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'label', |
| | | editable: false, |
| | | width: '40%' |
| | | }, |
| | | { |
| | | title: '颜色', |
| | | dataIndex: 'color', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '40%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | ], |
| | | rampColorColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'label', |
| | | editable: false, |
| | | width: '20%' |
| | | }, |
| | | { |
| | | title: '颜色1', |
| | | dataIndex: 'color', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | { |
| | | title: '颜色2', |
| | | dataIndex: 'color1', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | ], |
| | | statColorColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'type', |
| | | inputType: 'input', |
| | | editable: true, |
| | | width: '40%' |
| | | }, |
| | | { |
| | | title: '颜色', |
| | | dataIndex: 'color', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '40%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | ], |
| | | rampStatColorColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'type', |
| | | inputType: 'input', |
| | | editable: true, |
| | | width: '20%' |
| | | }, |
| | | { |
| | | title: '颜色1', |
| | | dataIndex: 'color', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | { |
| | | title: '颜色2', |
| | | dataIndex: 'color1', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '30%', |
| | | render: (text, record) => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | ], |
| | | cusColumns: [ |
| | | { |
| | | title: '指标', |
| | | dataIndex: 'name', |
| | | editable: false, |
| | | width: '14%' |
| | | }, |
| | | { |
| | | title: '形状', |
| | | dataIndex: 'shape', |
| | | inputType: 'cascader', |
| | | editable: true, |
| | | width: '12%', |
| | | render: (text, record) => { |
| | | return text.join(' / ').replace('line', '折线').replace('bar', '柱形') |
| | | }, |
| | | options: [ |
| | | { |
| | | value: 'line', |
| | | label: '折线', |
| | | children: [ |
| | | { value: 'smooth', label: 'smooth' }, |
| | | { value: 'line', label: 'line' }, |
| | | { value: 'dot', label: 'dot' }, |
| | | { value: 'dash', label: 'dash' }, |
| | | { value: 'hv', label: 'hv' }, |
| | | { value: 'vh', label: 'vh' }, |
| | | { value: 'hvh', label: 'hvh' }, |
| | | { value: 'vhv', label: 'vhv' } |
| | | ] |
| | | }, |
| | | { |
| | | value: 'bar', |
| | | label: '柱形', |
| | | children: [ |
| | | { value: 'rect', label: 'rect' }, |
| | | { value: 'hollow-rect', label: 'hollow-rect' }, |
| | | { value: 'line', label: 'line' }, |
| | | { value: 'tick', label: 'tick' }, |
| | | { value: 'funnel', label: 'funnel' }, |
| | | { value: 'pyramid', label: 'pyramid' } |
| | | ], |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | title: '坐标轴', |
| | | dataIndex: 'axis', |
| | | inputType: 'select', |
| | | editable: true, |
| | | width: '12%', |
| | | options: [ |
| | | { value: 'true', text: '显示'}, |
| | | { value: 'false', text: '隐藏'} |
| | | ], |
| | | render: (text, record) => { |
| | | let trans = {'true': '显示', 'false': '隐藏'} |
| | | return trans[text] || '隐藏' |
| | | } |
| | | }, |
| | | { |
| | | title: '标注', |
| | | dataIndex: 'label', |
| | | inputType: 'select', |
| | | editable: true, |
| | | width: '12%', |
| | | options: [ |
| | | { value: 'true', text: '显示'}, |
| | | { value: 'false', text: '隐藏'} |
| | | ], |
| | | render: (text, record) => { |
| | | let trans = {'true': '显示', 'false': '隐藏'} |
| | | return trans[text] || '隐藏' |
| | | } |
| | | }, |
| | | { |
| | | title: '标题', |
| | | dataIndex: 'title', |
| | | inputType: 'select', |
| | | editable: true, |
| | | width: '12%', |
| | | options: [ |
| | | { value: 'true', text: '显示'}, |
| | | { value: 'false', text: '隐藏'} |
| | | ], |
| | | render: (text, record) => { |
| | | let trans = {'true': '显示', 'false': '隐藏'} |
| | | return trans[text] || '显示' |
| | | } |
| | | }, |
| | | { |
| | | title: '最小值', |
| | | dataIndex: 'min', |
| | | inputType: 'number', |
| | | editable: true, |
| | | required: false, |
| | | width: '12%' |
| | | }, |
| | | { |
| | | title: '最大值', |
| | | dataIndex: 'max', |
| | | inputType: 'number', |
| | | editable: true, |
| | | required: false, |
| | | width: '12%' |
| | | }, |
| | | ] |
| | | } |
| | | |
| | | showDrawer = () => { |
| | | const { config } = this.props |
| | | |
| | | let fieldName = {} |
| | | config.columns.forEach(col => { |
| | | if (col.field) { |
| | | fieldName[col.field] = col.label |
| | | } |
| | | }) |
| | | |
| | | if (config.plot.correction) { |
| | | delete config.plot.correction // 数据修正(已弃用) |
| | | config.plot.barSize = 35 |
| | | } |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | view: 'normal', |
| | | ramp: config.plot.ramp || 'false', |
| | | datatype: config.plot.datatype || 'query', |
| | | fieldName: fieldName, |
| | | plot: fromJS(config.plot).toJS(), |
| | | baseFormlist: getBaseForm(config.plot), |
| | | formlist: getOptionForm(config.plot, config.columns) |
| | | }) |
| | | } |
| | | |
| | | radioChange = (e, key) => { |
| | | const { formlist } = this.state |
| | | let val = e.target.value |
| | | |
| | | if (key === 'datatype') { |
| | | this.setState({ |
| | | datatype: val, |
| | | formlist: formlist.map(item => { |
| | | if (['Yaxis'].includes(item.key)) { |
| | | item.hidden = val === 'statistics' |
| | | } else if (['InfoType', 'InfoValue'].includes(item.key)) { |
| | | item.hidden = val !== 'statistics' |
| | | } |
| | | return item |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | getFields() { |
| | | const { formlist } = this.state |
| | | const { getFieldDecorator } = this.props.form |
| | | const fields = [] |
| | | |
| | | if (!formlist) { |
| | | return fields |
| | | } |
| | | |
| | | formlist.forEach((item, index) => { |
| | | if (item.hidden || item.forbid) return |
| | | |
| | | if (item.type === 'text') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | } |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.onSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'number') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.onSubmit}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'select') { // 下拉 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select mode={item.multi ? 'multiple' : ''}> |
| | | {item.options.map((option, index) => |
| | | <Select.Option key={index} value={option.field || option.value}> |
| | | {option.label || option.text} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'radio') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <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> |
| | | ) |
| | | })} |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'color') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal |
| | | })( |
| | | <ColorSketch allowClear={item.allowClear} /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } |
| | | }) |
| | | return fields |
| | | } |
| | | |
| | | enabledChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | |
| | | this.setState({plot: {...plot, enabled: val}}) |
| | | } |
| | | |
| | | mutilBarChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | |
| | | this.setState({plot: {...plot, mutilBar: val}}) |
| | | } |
| | | |
| | | rampChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | let colors = plot.colors || [] |
| | | |
| | | if (val === 'true') { |
| | | colors = colors.map(item => { |
| | | item.color1 = item.color1 || item.color |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | this.setState({plot: {...plot, colors, ramp: val}, ramp: val}) |
| | | } |
| | | |
| | | rampDirectionChange = (e) => { |
| | | const { plot } = this.state |
| | | let val = e.target.value |
| | | |
| | | this.setState({plot: {...plot, rampDirection: val}}) |
| | | } |
| | | |
| | | onSubmit = () => { |
| | | const { config } = this.props |
| | | const { plot, view } = this.state |
| | | |
| | | if (view === 'normal') { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | let _plot = {...plot, ...values} |
| | | |
| | | if (values.datatype === 'statistics' || values.datatype !== plot.datatype) { |
| | | _plot.enabled = 'false' |
| | | _plot.customs = [] |
| | | } else if (!values.Yaxis || !plot.Yaxis || !is(fromJS(values.Yaxis), fromJS(plot.Yaxis))) { |
| | | _plot.enabled = 'false' |
| | | _plot.customs = [] |
| | | _plot.colors = null |
| | | } |
| | | |
| | | if (values.datatype !== plot.datatype) { |
| | | _plot.colors = null |
| | | } |
| | | |
| | | this.setState({ |
| | | plot: _plot, |
| | | visible: false |
| | | }) |
| | | |
| | | this.props.plotchange({...config, plot: _plot}) |
| | | } |
| | | }) |
| | | } else if (view === 'base') { |
| | | this.baseRef.handleConfirm().then(res => { |
| | | let _plot = {...plot, ...res} |
| | | |
| | | this.setState({ |
| | | plot: _plot, |
| | | visible: false |
| | | }) |
| | | |
| | | this.props.plotchange({...config, plot: _plot}) |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | this.props.plotchange({...config, plot}) |
| | | } |
| | | } |
| | | |
| | | changeTab = (tab) => { |
| | | const { config } = this.props |
| | | const { plot, view } = this.state |
| | | |
| | | if (view === 'normal') { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | let _plot = {...plot, ...values} |
| | | |
| | | if (values.datatype === 'statistics' || values.datatype !== plot.datatype) { |
| | | _plot.enabled = 'false' |
| | | _plot.customs = [] |
| | | } else if (!values.Yaxis || !plot.Yaxis || !is(fromJS(values.Yaxis), fromJS(plot.Yaxis))) { |
| | | _plot.enabled = 'false' |
| | | _plot.customs = [] |
| | | _plot.colors = null |
| | | } |
| | | |
| | | let labels = {} |
| | | config.columns.forEach(col => { |
| | | labels[col.field] = col.label |
| | | }) |
| | | |
| | | if (values.datatype !== 'statistics' && (!_plot.customs || _plot.customs.length === 0)) { |
| | | _plot.customs = _plot.Yaxis.map((item, i) => { |
| | | return { |
| | | uuid: Utils.getuuid(), |
| | | type: item, |
| | | name: labels[item] || item, |
| | | axis: i === 0 ? 'true' : 'false', |
| | | label: 'false', |
| | | title: 'true', |
| | | shape: _plot.chartType === 'bar' && i === 0 ? ['bar', 'rect'] : ['line', 'smooth'] |
| | | } |
| | | }) |
| | | } |
| | | if (values.datatype !== plot.datatype || !_plot.colors) { |
| | | _plot.colors = [] |
| | | if (_plot.datatype === 'query') { |
| | | let limit = chartColors.length |
| | | |
| | | _plot.colors = _plot.Yaxis.map((item, i) => { |
| | | return { |
| | | uuid: Utils.getuuid(), |
| | | type: item, |
| | | label: labels[item] || item, |
| | | color: chartColors[i % limit], |
| | | color1: chartColors[i % limit] |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | datatype: _plot.datatype, |
| | | plot: _plot, |
| | | view: tab |
| | | }) |
| | | } |
| | | }) |
| | | } else if (view === 'base') { |
| | | this.baseRef.handleConfirm().then(res => { |
| | | this.setState({ |
| | | plot: {...plot, ...res}, |
| | | view: tab |
| | | }) |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | view: tab |
| | | }) |
| | | } |
| | | } |
| | | |
| | | addColor = () => { |
| | | let plot = fromJS(this.state.plot).toJS() |
| | | plot.colors = plot.colors || [] |
| | | |
| | | plot.colors.push({ |
| | | uuid: Utils.getuuid(), |
| | | type: `指标${plot.colors.length}`, |
| | | color: 'rgb(91, 143, 249)', |
| | | color1: 'rgb(91, 143, 249)' |
| | | }) |
| | | |
| | | this.setState({plot}) |
| | | } |
| | | |
| | | changeColor = (colors) => { |
| | | const { plot } = this.state |
| | | |
| | | this.setState({plot: {...plot, colors}}) |
| | | } |
| | | |
| | | changeCustom = (customs) => { |
| | | const { plot } = this.state |
| | | |
| | | this.setState({plot: {...plot, customs}}) |
| | | } |
| | | |
| | | render() { |
| | | const { view, visible, datatype, plot, ramp, colorColumns, rampColorColumns, statColorColumns, rampStatColorColumns, cusColumns, baseFormlist } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 6 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 18 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="line-chart-drawer-form"> |
| | | <Icon type="edit" title="编辑" onClick={this.showDrawer} /> |
| | | <Modal |
| | | wrapClassName="popview-modal menu-chart-edit-modal" |
| | | title="图表编辑" |
| | | visible={visible} |
| | | width={950} |
| | | maskClosable={false} |
| | | onOk={this.onSubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <Tabs activeKey={view} className="menu-chart-edit-box" onChange={this.changeTab}> |
| | | <TabPane tab="组件设置" key="base"> |
| | | <NormalForm dict={this.props.dict} formlist={baseFormlist} inputSubmit={this.onSubmit} wrappedComponentRef={(inst) => this.baseRef = inst}/> |
| | | </TabPane> |
| | | <TabPane tab="图表设置" key="normal"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={16}>{this.getFields()}</Row> |
| | | </Form> |
| | | </TabPane> |
| | | {plot ? <TabPane tab="颜色设置" key="color"> |
| | | <div> |
| | | <Col span={8} style={{height: '40px', top: '-5px', zIndex: 1}}> |
| | | <Form {...formItemLayout}> |
| | | <Form.Item label="渐变色" style={{marginBottom: 10}}> |
| | | <Radio.Group value={plot.ramp || 'false'} onChange={this.rampChange}> |
| | | <Radio value="false">不使用</Radio> |
| | | <Radio value="true">使用</Radio> |
| | | </Radio.Group> |
| | | </Form.Item> |
| | | </Form> |
| | | </Col> |
| | | {plot.chartType === 'line' ? <Col span={8} style={{height: '40px', top: '-5px', zIndex: 1}}> |
| | | <Form {...formItemLayout}> |
| | | <Form.Item label="渐变方向" style={{marginBottom: 10}}> |
| | | <Radio.Group value={plot.rampDirection || 'horizontal'} onChange={this.rampDirectionChange}> |
| | | <Radio value="horizontal">水平</Radio> |
| | | <Radio value="vertical">垂直</Radio> |
| | | </Radio.Group> |
| | | </Form.Item> |
| | | </Form> |
| | | </Col> : null} |
| | | {datatype === 'statistics' ? <Button className="color-add mk-green" onClick={this.addColor}>{this.props.dict['model.add']}</Button> : null} |
| | | {datatype === 'statistics' ? <EditTable actions={['edit', 'move', 'del']} data={plot.colors || []} columns={ramp ==='true' ? rampStatColorColumns : statColorColumns} onChange={this.changeColor}/> : null} |
| | | {datatype !== 'statistics' ? <EditTable actions={['edit']} data={plot.colors || []} columns={ramp ==='true' ? rampColorColumns : colorColumns} onChange={this.changeColor}/> : null} |
| | | </div> |
| | | </TabPane> : null} |
| | | {plot ? <TabPane tab="自定义设置" disabled={datatype === 'statistics'} key="custom"> |
| | | <Col span={12}> |
| | | <Form {...formItemLayout}> |
| | | <Form.Item label="是否启用" style={{marginBottom: 10}}> |
| | | <Radio.Group value={plot.enabled || 'false'} onChange={this.enabledChange}> |
| | | <Radio value="true">是</Radio> |
| | | <Radio value="false">否</Radio> |
| | | </Radio.Group> |
| | | </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} |
| | | </Tabs> |
| | | </Modal> |
| | | </div> |
| | | ); |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(LineChartDrawerForm) |
New file |
| | |
| | | .line-chart-drawer-form { |
| | | display: inline-block; |
| | | > .anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
| | | .menu-chart-edit-modal { |
| | | .ant-modal { |
| | | top: 50px; |
| | | .ant-modal-body { |
| | | max-height: calc(100vh - 190px); |
| | | min-height: 50vh; |
| | | padding-top: 10px; |
| | | .menu-chart-edit-box { |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | position: relative; |
| | | left: -3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .ant-radio-wrapper { |
| | | margin-right: 5px; |
| | | } |
| | | .ant-tabs-nav-wrap { |
| | | text-align: center; |
| | | } |
| | | .color-sketch-block { |
| | | position: relative; |
| | | top: 5px; |
| | | width: 240px; |
| | | } |
| | | .color-add { |
| | | float: right; |
| | | margin-bottom: 10px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover } from 'antd' |
| | | import { Chart } from '@antv/g2' |
| | | import DataSet from '@antv/data-set' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import { chartColors } from '@/utils/option.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import './index.scss' |
| | | |
| | | const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) |
| | | const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) |
| | | const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) |
| | | const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent')) |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | | const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) |
| | | |
| | | class ChartCustom extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | updateConfig: PropTypes.func, |
| | | deletecomponent: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | appType: sessionStorage.getItem('appType'), |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _plot = { |
| | | chartType: card.type, // 图表类型 |
| | | enabled: 'false', // 是否使用自定义设置 |
| | | datatype: 'query', // 数据类型查询或统计 |
| | | customs: [], |
| | | width: card.width || 24, |
| | | height: 400, |
| | | barSize: 35, |
| | | color: 'rgba(0, 0, 0, 0.65)', |
| | | name: card.name |
| | | } |
| | | |
| | | |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | tabId: card.tabId || '', |
| | | parentId: card.parentId || '', |
| | | format: 'array', // 组件属性 - 数据格式 |
| | | pageable: false, // 组件属性 - 是否可分页 |
| | | switchable: false, // 组件属性 - 数据是否可切换 |
| | | dataName: card.dataName || '', |
| | | width: _plot.width, |
| | | name: _plot.name, |
| | | subtype: card.subtype, |
| | | setting: { interType: 'system' }, |
| | | style: { |
| | | borderWidth: '1px', borderColor: 'rgb(217, 217, 217)', |
| | | marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' |
| | | }, |
| | | headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, |
| | | columns: [], |
| | | scripts: [], |
| | | search: [], |
| | | action: [], |
| | | plot: _plot, |
| | | btnlog: [], |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.plot = config.plot |
| | | _card.plot.name = card.name |
| | | _card.style = config.style |
| | | _card.headerStyle = config.headerStyle |
| | | |
| | | _card.action = config.action.map(col => { |
| | | col.uuid = Utils.getuuid() |
| | | return col |
| | | }) |
| | | _card.search = config.search.map(col => { |
| | | col.uuid = Utils.getuuid() |
| | | return col |
| | | }) |
| | | } |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('tabsChange', this.handleTabsChange) |
| | | setTimeout(() => { |
| | | this.viewrender() |
| | | }, 1000) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | MKEmitter.removeListener('tabsChange', this.handleTabsChange) |
| | | } |
| | | |
| | | handleTabsChange = (parentId) => { |
| | | const { card } = this.state |
| | | |
| | | if (parentId === card.parentId) { |
| | | let _element = document.getElementById(card.uuid + 'canvas') |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(this.viewrender, 100) |
| | | } |
| | | } |
| | | |
| | | getdata = (X_axis, Y_axis) => { |
| | | let data = [] |
| | | let xdata = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] |
| | | let point = 7 |
| | | |
| | | for (let i = 0; i < point; i++) { |
| | | let item = {} |
| | | |
| | | item[X_axis] = xdata[i] |
| | | |
| | | if (typeof(Y_axis) === 'string') { |
| | | item[Y_axis] = Math.floor(Math.random() * 5 * (i + 1)) + i |
| | | } else { |
| | | Y_axis.forEach(y => { |
| | | item[y] = Math.floor(Math.random() * 5 * (i + 1)) + i |
| | | }) |
| | | } |
| | | |
| | | data.push(item) |
| | | } |
| | | |
| | | return data |
| | | } |
| | | |
| | | viewrender = () => { |
| | | const { card } = this.state |
| | | |
| | | if (card.plot.chartType === 'line') { |
| | | this.linerender() |
| | | } else if (card.plot.chartType === 'bar') { |
| | | this.barrender() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 折线图 |
| | | */ |
| | | linerender = () => { |
| | | const { card } = this.state |
| | | const plot = card.plot |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.65)' |
| | | let X_axis = plot.Xaxis || 'x' |
| | | let Y_axis = plot.Yaxis || ['y'] |
| | | |
| | | let data = this.getdata(X_axis, Y_axis) |
| | | |
| | | if (plot.enabled !== 'true') { |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | let transfield = {} |
| | | card.columns.forEach(col => { |
| | | if (col.field) { |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', |
| | | value: 'value' |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] || row.key |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'canvas', |
| | | autoFit: true, |
| | | height: this.wrap.offsetHeight - 25 |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | // chart.axis(X_axis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) |
| | | // chart.axis('value', { grid: { line: { style: { stroke: color } }}, label: { style: { fill: color } } }) |
| | | |
| | | let xc = {label: { style: { fill: color } }} |
| | | let yc = {label: { style: { fill: color } }} |
| | | if (plot.grid === 'hidden') { |
| | | yc.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | yc.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | xc.tickLine = {style: { stroke: plot.lineColor }} |
| | | xc.line = { style: { stroke: plot.lineColor } } |
| | | if (yc.grid !== null) { |
| | | yc.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (yc.line) { |
| | | yc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | chart.axis(X_axis, xc) |
| | | chart.axis('value', yc) |
| | | |
| | | if (plot.coordinate !== 'polar') { |
| | | chart.scale(X_axis, { |
| | | range: [0, 1] |
| | | }) |
| | | } |
| | | chart.scale('value', { |
| | | nice: true, |
| | | range: [0, 0.9] |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend, |
| | | itemName: { style: { fill: color } } |
| | | }) |
| | | } |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | shared: true |
| | | }) |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | } |
| | | |
| | | if (plot.coordinate === 'polar') { |
| | | chart.coordinate('polar', { |
| | | innerRadius: 0.1, |
| | | radius: 0.8 |
| | | }) |
| | | } |
| | | |
| | | let colors = new Map() |
| | | let colorIndex = 0 |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | if (plot.ramp === 'true') { |
| | | let _s = 'l(0) ' |
| | | if (plot.rampDirection === 'vertical') { |
| | | _s = 'l(90) ' |
| | | } |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], `${_s}0:${item.color} 1:${item.color1}` ) |
| | | } |
| | | }) |
| | | } else { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | let _chart = chart |
| | | .line() |
| | | .position(`${X_axis}*value`) |
| | | .shape(plot.shape || 'smooth') |
| | | .tooltip(`${X_axis}*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.has(key)) { |
| | | if (plot.area === 'true' && plot.rampDirection === 'vertical') { |
| | | return colors.get(key).replace(/l\(9?0\) 0:|\s1:.*/ig, '') |
| | | } |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | let _color = color |
| | | |
| | | if (plot.labelColor === 'custom' && colors.has(key)) { |
| | | _color = colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | style: { |
| | | fill: _color |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.point === 'true') { |
| | | chart |
| | | .point() |
| | | .position(`${X_axis}*value`) |
| | | .color('key') |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | | |
| | | if (plot.area === 'true') { |
| | | let area = chart.area().position(`${X_axis}*value`).tooltip(false) |
| | | if (plot.shape === 'smooth') { |
| | | area.shape('smooth') |
| | | } |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | let limit = chartColors.length |
| | | area.color('key', (key) => { |
| | | if (colors.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | area.color('key') |
| | | } |
| | | } |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | chart.interaction(t) |
| | | }) |
| | | } |
| | | chart.render() |
| | | } else { |
| | | this.customrender(data) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 自定义图 |
| | | */ |
| | | customrender = (data) => { |
| | | let card = fromJS(this.state.card).toJS() |
| | | let plot = card.plot |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.65)' |
| | | let fields = [] |
| | | let legends = [] |
| | | let transfield = {} |
| | | let Bar_axis = [] |
| | | |
| | | card.columns.forEach(col => { |
| | | if (col.field) { |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | |
| | | let colors = new Map() |
| | | let colorIndex = 0 |
| | | let limit = chartColors.length |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | if (plot.ramp === 'true') { |
| | | let bars = {} |
| | | plot.customs.forEach(item => { |
| | | if (!item.shape || !item.shape[0] || item.shape[0] === 'bar') { |
| | | bars[item.type] = true |
| | | } |
| | | }) |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | if (bars[item.type]) { |
| | | colors.set(transfield[item.type], `l(90) 0:${item.color} 1:${item.color1}` ) |
| | | } else { |
| | | colors.set(transfield[item.type], `l(0) 0:${item.color} 1:${item.color1}` ) |
| | | } |
| | | } |
| | | }) |
| | | } else { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | let axisIndex = 0 |
| | | let hasBar = false |
| | | |
| | | plot.$paddingLeft = 30 |
| | | plot.$paddingRight = 30 |
| | | |
| | | plot.customs.forEach(item => { |
| | | item.name = transfield[item.type] || item.type |
| | | item.chartType = item.shape ? (item.shape[0] || 'bar') : 'bar' |
| | | item.shape = item.shape ? (item.shape[1] || '') : '' |
| | | |
| | | if (colors.has(item.name)) { |
| | | item.color = colors.get(item.name) |
| | | } else { |
| | | item.color = chartColors[colorIndex % limit] |
| | | colorIndex++ |
| | | } |
| | | |
| | | if (item.chartType === 'bar') { |
| | | Bar_axis.push(item.type) |
| | | hasBar = true |
| | | } |
| | | |
| | | if (item.axis === 'true' && axisIndex < 2) { |
| | | if (axisIndex === 0) { |
| | | // item.axis = { grid: {line: { style: { stroke: color } }}, title: { style: { fill: color } }, label: {style: { fill: color }} } |
| | | item.axis = { label: {style: { fill: color }} } |
| | | if (item.title !== 'false') { |
| | | item.axis.title = { style: { fill: color } } |
| | | plot.$paddingLeft = 50 |
| | | } |
| | | if (plot.grid === 'hidden') { |
| | | item.axis.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | item.axis.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | if (item.axis.grid !== null) { |
| | | item.axis.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (item.axis.line) { |
| | | item.axis.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | |
| | | fields.unshift(item) |
| | | } else { |
| | | item.axis = { grid: null, label: {style: { fill: color }} } |
| | | if (item.title !== 'false') { |
| | | item.axis.title = { style: { fill: color } } |
| | | plot.$paddingRight = 60 |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | item.axis.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor && item.axis.line) { |
| | | item.axis.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | fields.splice(1, 0, item) |
| | | } |
| | | axisIndex++ |
| | | } else { |
| | | item.axis = { grid: null, title: null, label: null } |
| | | fields.push(item) |
| | | } |
| | | |
| | | legends.push({ |
| | | value: item.name, |
| | | name: item.name, |
| | | marker: { symbol: item.chartType === 'bar' ? 'square' : 'hyphen', style: { stroke: item.color,fill: item.color, r: 5, lineWidth: 2 } } |
| | | }) |
| | | }) |
| | | |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | fields.forEach(line => { |
| | | row[line.name] = row[line.type] |
| | | }) |
| | | return row |
| | | } |
| | | }) |
| | | |
| | | let padding = [10, 30, 30, 30] |
| | | if (plot.mutilBar === 'overlap') { |
| | | Bar_axis = [] |
| | | } |
| | | |
| | | if (!Bar_axis.length) { |
| | | padding = [10, plot.$paddingRight, 30, plot.$paddingLeft] |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'canvas', |
| | | autoFit: true, |
| | | height: this.wrap.offsetHeight - 25, |
| | | }) |
| | | |
| | | // chart.axis(plot.Xaxis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) |
| | | |
| | | let xc = {label: { style: { fill: color } }} |
| | | if (plot.lineColor) { |
| | | xc.tickLine = {style: { stroke: plot.lineColor }} |
| | | xc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | chart.axis(plot.Xaxis, xc) |
| | | |
| | | if (!hasBar) { |
| | | chart.scale(plot.Xaxis, { |
| | | range: [0, 1] |
| | | }) |
| | | } |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | custom: true, |
| | | position: plot.legend, |
| | | items: legends, |
| | | itemName: { style: { fill: color } } |
| | | }) |
| | | } |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | shared: true, |
| | | }) |
| | | } |
| | | |
| | | chart.scale({ |
| | | nice: true |
| | | }) |
| | | |
| | | let lablecfg = { |
| | | position: 'top', |
| | | offset: 2, |
| | | style: { |
| | | fill: '#fff' |
| | | } |
| | | } |
| | | |
| | | if (plot.label === 'top') { |
| | | lablecfg.offset = -5 |
| | | lablecfg.style.textBaseline = 'top' |
| | | } else if (plot.label === 'middle') { |
| | | lablecfg.position = 'middle' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'bottom') { |
| | | lablecfg.position = 'bottom' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'true') { |
| | | lablecfg.style.fill = color |
| | | } |
| | | |
| | | 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 |
| | | }, |
| | | }) |
| | | |
| | | view1.data(dvt.rows) |
| | | view1.scale('value', { |
| | | nice: true, |
| | | range: [0, 0.9] |
| | | }) |
| | | |
| | | let yc = {label: { style: { fill: color } }} |
| | | if (plot.grid === 'hidden') { |
| | | yc.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | yc.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | if (yc.grid !== null) { |
| | | yc.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (yc.line) { |
| | | yc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | view1.axis('value', yc) |
| | | |
| | | view1.legend(false) |
| | | |
| | | 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.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | 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.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | 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.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) |
| | | .shape(item.shape) |
| | | .tooltip(`${item.name}`, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | return { |
| | | name: item.name, |
| | | value: value |
| | | } |
| | | }) |
| | | |
| | | if (plot.barSize) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (item.label !== 'false') { |
| | | _chart.label(item.name, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom') { |
| | | lablecfg.style.fill = item.color |
| | | } |
| | | return { |
| | | content: value, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } else if (item.chartType === 'line') { |
| | | 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) |
| | | .shape(item.shape) |
| | | .tooltip(`${item.name}`, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | return { |
| | | name: item.name, |
| | | value: value |
| | | } |
| | | }) |
| | | |
| | | if (item.label !== 'false') { |
| | | _chart.label(item.name, (value) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | let _color = color |
| | | |
| | | if (plot.labelColor === 'custom') { |
| | | _color = item.color |
| | | } |
| | | return { |
| | | content: value, |
| | | style: { |
| | | fill: _color |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.point === 'true') { |
| | | chart |
| | | .point() |
| | | .position(`${plot.Xaxis}*${item.name}`) |
| | | .color(item.color) |
| | | .size(3) |
| | | .shape('circle') |
| | | } |
| | | } |
| | | }) |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | if (t === 'element-active' || t === 'element-highlight') { |
| | | chart.interaction(t) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | | /** |
| | | * @description 柱形图 |
| | | */ |
| | | barrender = () => { |
| | | const { card } = this.state |
| | | const plot = card.plot |
| | | let color = plot.color || 'rgba(0, 0, 0, 0.65)' |
| | | let X_axis = plot.Xaxis || 'x' |
| | | let Y_axis = plot.Yaxis || ['y'] |
| | | |
| | | let data = this.getdata(X_axis, Y_axis) |
| | | |
| | | if (plot.enabled !== 'true') { |
| | | const ds = new DataSet() |
| | | const dv = ds.createView().source(data) |
| | | let transfield = {} |
| | | |
| | | card.columns.forEach(col => { |
| | | if (col.field) { |
| | | transfield[col.field] = col.label |
| | | } |
| | | }) |
| | | |
| | | dv.transform({ |
| | | type: 'fold', |
| | | fields: [...Y_axis], |
| | | key: 'key', |
| | | value: 'value' |
| | | }) |
| | | |
| | | if (plot.Xaxis) { |
| | | dv.transform({ |
| | | type: 'map', |
| | | callback(row) { |
| | | row.key = transfield[row.key] || row.key |
| | | return row |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | const chart = new Chart({ |
| | | container: card.uuid + 'canvas', |
| | | autoFit: true, |
| | | height: this.wrap.offsetHeight - 25 |
| | | }) |
| | | |
| | | chart.data(dv.rows) |
| | | |
| | | // chart.axis(X_axis, { label: { style: { fill: color } }, tickLine: {style: { stroke: color }}, line: { style: { stroke: color } } }) |
| | | // chart.axis('value', { grid: { line: { style: { stroke: color } }}, label: { style: { fill: color } } }) |
| | | |
| | | let xc = {label: { style: { fill: color } }} |
| | | let yc = {label: { style: { fill: color } }} |
| | | if (plot.grid === 'hidden') { |
| | | yc.grid = null |
| | | } |
| | | if (plot.y_line === 'show') { |
| | | yc.line = {style: { stroke: '#D1D2CE' }} |
| | | } |
| | | if (plot.lineColor) { |
| | | xc.tickLine = {style: { stroke: plot.lineColor }} |
| | | xc.line = { style: { stroke: plot.lineColor } } |
| | | if (yc.grid !== null) { |
| | | yc.grid = { line: { style: { stroke: plot.lineColor } }} |
| | | } |
| | | if (yc.line) { |
| | | yc.line = { style: { stroke: plot.lineColor } } |
| | | } |
| | | } |
| | | chart.axis(X_axis, xc) |
| | | chart.axis('value', yc) |
| | | |
| | | chart.scale('value', { |
| | | nice: true, |
| | | range: [0, 0.9] |
| | | }) |
| | | |
| | | if (!plot.legend || plot.legend === 'hidden') { |
| | | chart.legend(false) |
| | | } else { |
| | | chart.legend({ |
| | | position: plot.legend, |
| | | itemName: { style: { fill: color } } |
| | | }) |
| | | } |
| | | |
| | | if (plot.tooltip !== 'true') { |
| | | chart.tooltip(false) |
| | | } else { |
| | | chart.tooltip({ |
| | | shared: true |
| | | }) |
| | | } |
| | | |
| | | if (plot.coordinate === 'polar') { |
| | | chart.coordinate('polar', { |
| | | innerRadius: 0.1, |
| | | radius: 0.8 |
| | | }) |
| | | } |
| | | |
| | | let colors = new Map() |
| | | let colorIndex = 0 |
| | | let lablecfg = { |
| | | position: 'top', |
| | | offset: 2, |
| | | style: { |
| | | fill: '#fff' |
| | | } |
| | | } |
| | | |
| | | if (plot.label === 'top') { |
| | | lablecfg.offset = -5 |
| | | lablecfg.style.textBaseline = 'top' |
| | | } else if (plot.label === 'middle') { |
| | | lablecfg.position = 'middle' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'bottom') { |
| | | lablecfg.position = 'bottom' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'true') { |
| | | lablecfg.style.fill = color |
| | | } |
| | | |
| | | if (plot.transpose === 'true') { |
| | | chart.coordinate().transpose() |
| | | if (plot.label === 'top') { |
| | | delete lablecfg.style.textBaseline |
| | | lablecfg.position = 'right' |
| | | lablecfg.offset = -3 |
| | | lablecfg.style.textAlign = 'end' |
| | | } else if (plot.label === 'middle') { |
| | | lablecfg.position = 'middle' |
| | | lablecfg.offset = 0 |
| | | } else if (plot.label === 'bottom') { |
| | | lablecfg.position = 'left' |
| | | lablecfg.offset = 2 |
| | | } else if (plot.label === 'true') { |
| | | lablecfg.position = 'right' |
| | | lablecfg.offset = 2 |
| | | } |
| | | } |
| | | |
| | | if (plot.colors && plot.colors.length > 0) { |
| | | if (plot.ramp === 'true') { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], `l(90) 0:${item.color} 1:${item.color1}` ) |
| | | } |
| | | }) |
| | | } else { |
| | | plot.colors.forEach(item => { |
| | | if (!colors.has(transfield[item.type])) { |
| | | colors.set(transfield[item.type], item.color) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | if (plot.adjust !== 'stack') { |
| | | let _chart = chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .adjust([ |
| | | { |
| | | type: 'dodge', |
| | | marginRatio: 0 |
| | | } |
| | | ]) |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${X_axis}*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.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | |
| | | return { |
| | | content: value, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | | _chart.state({ |
| | | selected: { |
| | | style: { |
| | | fill: plot.selectColor, |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } else if (plot.adjust === 'stack') { |
| | | let _chart = chart |
| | | .interval() |
| | | .position(`${X_axis}*value`) |
| | | .adjust('stack') |
| | | .shape(plot.shape || 'rect') |
| | | .tooltip(`${X_axis}*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.has(key)) { |
| | | return colors.get(key) |
| | | } else { |
| | | colorIndex++ |
| | | return chartColors[(colorIndex - 1) % limit] |
| | | } |
| | | }) |
| | | } else { |
| | | _chart.color('key') |
| | | } |
| | | if (plot.label !== 'false') { |
| | | _chart.label('value*key', (value, key) => { |
| | | if (plot.show === 'percent') { |
| | | value = value + '%' |
| | | } |
| | | |
| | | if (plot.label === 'true' && plot.labelColor === 'custom' && colors.has(key)) { |
| | | lablecfg.style.fill = colors.get(key) |
| | | } |
| | | return { |
| | | content: value, |
| | | ...lablecfg |
| | | } |
| | | }) |
| | | } |
| | | |
| | | if (plot.barSize || plot.correction) { |
| | | _chart.size(plot.barSize || 35) |
| | | } |
| | | if (plot.selectColor) { |
| | | _chart.state({ |
| | | selected: { |
| | | style: { |
| | | fill: plot.selectColor, |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | if (plot.barRadius) { |
| | | _chart.style({ radius: [plot.barRadius, plot.barRadius, 0, 0] }) |
| | | } |
| | | } |
| | | |
| | | if (plot.interaction && plot.interaction.length) { |
| | | plot.interaction.forEach(t => { |
| | | chart.interaction(t) |
| | | }) |
| | | } |
| | | |
| | | chart.render() |
| | | } else { |
| | | this.customrender(data) |
| | | } |
| | | } |
| | | |
| | | updateComponent = (component) => { |
| | | const card = fromJS(this.state.card).toJS() |
| | | if (!is(fromJS(component.plot), fromJS(card.plot)) || !is(fromJS(component.style), fromJS(card.style))) { |
| | | let _element = document.getElementById(card.uuid + 'canvas') |
| | | if (_element) { |
| | | _element.innerHTML = '' |
| | | } |
| | | this.$timer && clearTimeout(this.$timer) |
| | | this.$timer = setTimeout(() => { |
| | | this.viewrender() |
| | | }, 150) |
| | | } |
| | | |
| | | component.width = component.plot.width |
| | | component.name = component.plot.name |
| | | |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | addSearch = () => { |
| | | const { card } = this.state |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.label = 'label' |
| | | newcard.initval = '' |
| | | newcard.type = 'select' |
| | | newcard.resourceType = '0' |
| | | newcard.options = [] |
| | | newcard.setAll = 'false' |
| | | newcard.orderType = 'asc' |
| | | newcard.display = 'dropdown' |
| | | newcard.match = '=' |
| | | |
| | | // 注册事件-添加搜索 |
| | | MKEmitter.emit('addSearch', card.uuid, newcard) |
| | | } |
| | | |
| | | addButton = () => { |
| | | const { card } = this.state |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.label = '导出Excel' |
| | | newcard.sqlType = '' |
| | | newcard.Ot = 'requiredSgl' |
| | | newcard.OpenType = 'excelOut' |
| | | newcard.icon = 'download' |
| | | newcard.class = 'dgreen' |
| | | newcard.intertype = card.setting.interType |
| | | newcard.innerFunc = card.setting.innerFunc || '' |
| | | newcard.sysInterface = card.setting.sysInterface || '' |
| | | newcard.outerFunc = card.setting.outerFunc || '' |
| | | newcard.interface = card.setting.interface || '' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
| | | newcard.verify = null |
| | | newcard.show = 'icon' |
| | | |
| | | // 注册事件-添加按钮 |
| | | MKEmitter.emit('addButton', card.uuid, newcard) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { card } = this.state |
| | | |
| | | if (comIds[0] !== card.uuid || comIds.length > 1) return |
| | | |
| | | let _card = {...card, style} |
| | | |
| | | this.updateComponent(_card) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | | MKEmitter.emit('clickComponent', this.state.card) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { card, appType } = this.state |
| | | let _style = resetStyle(card.style) |
| | | |
| | | return ( |
| | | <div className="menu-line-chart-edit-box" style={{..._style, height: card.plot.height || 400}} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | {appType !== 'mob' ? <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> : null} |
| | | <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> |
| | | <CopyComponent type="line" card={card}/> |
| | | <PasteComponent config={card} options={['action']} updateConfig={this.updateComponent} /> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <ClockComponent config={card} updateConfig={this.updateComponent}/> |
| | | <UserComponent config={card}/> |
| | | <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | <SettingComponent config={card} updateConfig={this.updateComponent}/> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | {card.plot.title || card.search.length > 0 ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} |
| | | <div className="canvas" id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div> |
| | | {appType !== 'mob' ? <ActionComponent |
| | | type="chart" |
| | | config={card} |
| | | updateaction={this.updateComponent} |
| | | /> : null} |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default ChartCustom |
New file |
| | |
| | | .menu-line-chart-edit-box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | display: flex; |
| | | flex-flow: column; |
| | | |
| | | .canvas { |
| | | margin: 0px; |
| | | padding: 15px 10px 10px; |
| | | letter-spacing: 0px; |
| | | flex: 1; |
| | | } |
| | | |
| | | .chart-header { |
| | | position: relative; |
| | | height: 45px; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | overflow: hidden; |
| | | padding-right: 35px; |
| | | |
| | | .chart-title { |
| | | text-decoration: inherit; |
| | | font-weight: inherit; |
| | | font-style: inherit; |
| | | float: left; |
| | | line-height: 45px; |
| | | margin-left: 10px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | } |
| | | |
| | | >.anticon-tool { |
| | | position: absolute; |
| | | right: 1px; |
| | | top: 1px; |
| | | z-index: 2; |
| | | font-size: 16px; |
| | | padding: 5px; |
| | | cursor: pointer; |
| | | color: rgba(0, 0, 0, 0.85); |
| | | background: rgba(255, 255, 255, 0.55); |
| | | } |
| | | |
| | | .model-menu-action-list { |
| | | position: absolute; |
| | | right: 0px; |
| | | top: 30px; |
| | | z-index: 4; |
| | | font-size: 16px; |
| | | |
| | | .ant-row .anticon-plus { |
| | | float: right; |
| | | } |
| | | |
| | | .page-card { |
| | | float: right; |
| | | } |
| | | } |
| | | .normal-header + .canvas + .model-menu-action-list { |
| | | top: 45px; |
| | | } |
| | | } |
| | | .menu-line-chart-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
| | |
| | | item.options = this.state.interTypeOptions.filter(op => (iscustom || op.value !== 'custom')) |
| | | } else if (item.key === 'Ot') { |
| | | if (type === 'card') { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) |
| | | if (card.sqlType === 'insert') { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired'].includes(op.value)) |
| | | } else { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) |
| | | } |
| | | } else if (_pageTemplate === 'pay') { // 行级按钮、支付按钮,只能选单行 |
| | | item.options = this.state.requireOptions.filter(op => ['requiredSgl'].includes(op.value)) |
| | | } else if (['innerpage', 'tab', 'popview', 'excelIn'].includes(_opentype)) { |
| | |
| | | this.setState({ |
| | | formlist: this.state.formlist.map(item => { |
| | | if (item.key === 'Ot' && type === 'card') { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) |
| | | if (value === 'insert') { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired'].includes(op.value)) |
| | | } else { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value)) |
| | | } |
| | | } else if (item.key === 'Ot' && value === 'insert') { |
| | | item.options = this.state.requireOptions.filter(op => ['notRequired'].includes(op.value)) |
| | | } else if (item.key === 'Ot') { |
| | |
| | | import dashboard from '@/assets/mobimg/dashboard.png' |
| | | import ratioboard from '@/assets/mobimg/ratioboard.png' |
| | | import scatter from '@/assets/mobimg/scatter.png' |
| | | // import chart from '@/assets/mobimg/chart.png' |
| | | import tree from '@/assets/mobimg/tree.png' |
| | | |
| | | // 组件配置信息 |
| | |
| | | { type: 'menu', url: dashboard, component: 'dashboard', subtype: 'dashboard', title: '仪表盘', width: 12 }, |
| | | { type: 'menu', url: ratioboard, component: 'dashboard', subtype: 'ratioboard', title: '占比图', width: 12 }, |
| | | { type: 'menu', url: scatter, component: 'scatter', subtype: 'scatter', title: '散点图', width: 24 }, |
| | | // { type: 'menu', url: chart, component: 'chart', subtype: 'custom', title: '自定义图表', width: 24 }, |
| | | { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '富文本', width: 24 }, |
| | | { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '自定义', width: 24 }, |
| | | { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24, forbid: ['billPrint'] }, |
| | |
| | | <div className="common-modal-edit-card"> |
| | | <Row className="search-row"> |
| | | <Col span={8}> |
| | | <Search placeholder="请输入字段" onSearch={value => {this.setState({searchKey: value})}} enterButton /> |
| | | <Search placeholder="请输入字段" autoFocus onSearch={value => {this.setState({searchKey: value})}} enterButton /> |
| | | </Col> |
| | | <Col span={8}> |
| | | <Button onClick={this.reset}>重置</Button> |
| | |
| | | |
| | | return ( |
| | | <> |
| | | <div style={{padding: '5px 25px'}} onClick={this.verup}>版本升级</div> |
| | | <div style={{padding: '5px 25px'}} onClick={this.verup}>应用升级</div> |
| | | <Modal |
| | | wrapClassName="version-up-modal" |
| | | title="应用升级" |
| | |
| | | style: res.CSS || '', |
| | | showline: res.split_line_show || 'true', |
| | | webSite: res.WebSite || '', |
| | | navBar: res.menu_type |
| | | navBar: res.menu_type, |
| | | app_version: res.app_version |
| | | } |
| | | |
| | | sessionStorage.setItem('home_background', res.index_background_color || '') |
| | |
| | | window.GLOB.mainlogo = systemMsg.mainlogo |
| | | window.GLOB.style = systemMsg.style |
| | | window.GLOB.navBar = systemMsg.navBar |
| | | window.GLOB.appVersion = systemMsg.app_version |
| | | |
| | | if (window.GLOB.style && styles[window.GLOB.style]) { |
| | | document.body.className = styles[window.GLOB.style] + ' ' + (res.split_line_show === 'false' ? 'hidden-split-line' : '') |