king
2021-12-15 d76045be1cd5a030ed68269246d7ae1956a5ff06
2021-12-15
25个文件已修改
487 ■■■■ 已修改文件
public/options.json 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/chartcompile/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-dashboard/chartcompile/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-pie/chartcompile/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-scatter/chartcompile/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/chart-custom/chartcompile/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pc/components/login/normal-login/options.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.jsx 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.scss 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-dashboard/index.jsx 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-dashboard/index.scss 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-pie/index.jsx 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-pie/index.scss 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-scatter/index.jsx 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-scatter/index.scss 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/appmanage/submutilform/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/config.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pcdesign/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/rolemanage/index.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/options.json
@@ -1,17 +1,17 @@
{
  "appId": "202108312122504607B107A83F55B40C98CCF",
  "appkey": "20210831212235413F287EC3BF489424496C8",
  "appId": "201912040924165801464FF1788654BC5AC73",
  "appkey": "20191106103859640976D6E924E464D029CF0",
  "mainSystemApi": "http://sso.mk9h.cn/cloud/webapi/dostars",
  "systemType": "",
  "externalDatabase": "",
  "externalDatabase": "false",
  "lineColor": "",
  "filter": "false",
  "defaultApp": "",
  "defaultLang": "zh-CN",
  "WXAppID": "",
  "debugger": false,
  "licenseKey": "7EFE13KIKKILIJ7C8CFC",
  "licenseKey": "",
  "probation": "",
  "host": "http://demo.mk9h.cn",
  "service": "erp_new/"
  "host": "http://qingqiumarket.cn",
  "service": "MKWMS/"
}
src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -405,6 +405,20 @@
        text: '隐藏'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
      }]
    }, {
      type: 'number',
      key: 'barSize',
      label: '柱形宽度',
src/menu/components/chart/antv-bar/chartcompile/index.jsx
@@ -601,6 +601,7 @@
  }
  render() {
    const { config } = this.props
    const { view, visible, datatype, plot, ramp, colorColumns, rampColorColumns, statColorColumns, rampStatColorColumns, cusColumns, baseFormlist } = this.state
    const formItemLayout = {
      labelCol: {
@@ -618,7 +619,7 @@
        <EditOutlined title="编辑" onClick={this.showDrawer}/>
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
          title={config.type === 'bar' ? '柱状图编辑' : '折线图编辑'}
          visible={visible}
          width={950}
          maskClosable={false}
src/menu/components/chart/antv-bar/index.jsx
@@ -1350,6 +1350,7 @@
        </Popover>
        <NormalHeader config={card} updateComponent={this.updateComponent}/>
        <div className="canvas" id={card.uuid + 'canvas'} ref={ref => this.wrap = ref}></div>
        {card.plot.download === 'enable' ? <Icon type="download"/> : null}
        {appType !== 'mob' ? <ActionComponent
          type="chart"
          config={card}
src/menu/components/chart/antv-dashboard/chartcompile/formconfig.jsx
@@ -75,6 +75,7 @@
 * @param {Array}  columns    // 显示列
 */
export function getOptionForm (card, columns) {
  let appType = sessionStorage.getItem('appType')
  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
  return [
@@ -128,6 +129,20 @@
        value: 'false',
        text: '不使用'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
      }]
    },
    {
      type: 'color',
@@ -152,6 +167,7 @@
 * @param {Array}  columns    // 显示列
 */
export function getRadioOptionForm (card, columns) {
  let appType = sessionStorage.getItem('appType')
  let xfields = columns.filter(item => /^Nvarchar/ig.test(item.datatype))
  let yfields = columns.filter(item => /^(Int|Decimal)/ig.test(item.datatype))
@@ -216,6 +232,20 @@
        value: 'false',
        text: '不使用'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
      }]
    },
    {
      type: 'color',
src/menu/components/chart/antv-dashboard/chartcompile/index.jsx
@@ -283,6 +283,7 @@
  }
  render() {
    const { config } = this.props
    const { visible, plot, colorColumns, view, baseFormlist } = this.state
    const formItemLayout = {
      labelCol: {
@@ -300,7 +301,7 @@
        <EditOutlined title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
          title={config.subtype === 'ratioboard' ? '占比图编辑' : '仪表盘编辑'}
          visible={visible}
          width={850}
          maskClosable={false}
src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
@@ -282,6 +282,20 @@
        text: '累加'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
      }]
    }, {
      type: 'number',
      key: 'splitLine',
      label: '分隔线',
src/menu/components/chart/antv-pie/chartcompile/index.jsx
@@ -326,7 +326,7 @@
        <EditOutlined title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
          title="饼图编辑"
          visible={visible}
          width={850}
          maskClosable={false}
src/menu/components/chart/antv-scatter/chartcompile/formconfig.jsx
@@ -127,6 +127,20 @@
        value: 'false',
        text: '隐藏'
      }]
    }, {
      type: 'radio',
      key: 'download',
      label: '导出图片',
      initVal: card.download || 'forbid',
      required: false,
      forbid: appType === 'mob',
      options: [{
        value: 'forbid',
        text: '禁用'
      }, {
        value: 'enable',
        text: '启用'
      }]
    },
    {
      type: 'text',
src/menu/components/chart/antv-scatter/chartcompile/index.jsx
@@ -245,7 +245,7 @@
        <EditOutlined title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal menu-chart-edit-modal"
          title="图表编辑"
          title="散点图编辑"
          visible={visible}
          width={850}
          maskClosable={false}
src/menu/components/chart/chart-custom/chartcompile/index.jsx
@@ -93,7 +93,7 @@
        <Icon type="edit" style={{color: '#1890ff'}} title="编辑" onClick={this.showDrawer} />
        <Modal
          wrapClassName="popview-modal custom-chart-edit-modal"
          title="图表编辑"
          title="自定义图表编辑"
          visible={visible}
          width={950}
          maskClosable={false}
src/pc/components/login/normal-login/options.jsx
@@ -114,7 +114,7 @@
      field: 'tempId',
      label: '短信模板',
      initval: wrap.tempId || '',
      tooltip: '短信模板可在管理系统 HS-奇云短信模板 处添加。',
      tooltip: '短信模板可在 云系统->应用服务->开发者中心->短信模板 处添加。',
      required: true,
      options: msgTemps
    },
src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -4,6 +4,7 @@
import { Chart } from '@antv/g2'
import DataSet from '@antv/data-set'
import { Spin, Empty, notification } from 'antd'
import { DownloadOutlined } from '@ant-design/icons'
import moment from 'moment'
import asyncComponent from './asyncButtonComponent'
@@ -41,6 +42,7 @@
    search: null,              // 搜索条件
    vFields: [],               // 数值字段
    vstFields: null,           // 统计数据值字段信息
    chart: null
  }
  UNSAFE_componentWillMount () {
@@ -1053,6 +1055,8 @@
    }
    
    chart.render()
    this.setState({chart})
  }
  /**
@@ -1418,6 +1422,8 @@
    }
    chart.render()
    this.setState({chart})
  }
  /**
@@ -1691,12 +1697,51 @@
    }
    chart.render()
    this.setState({chart})
  }
  refreshSearch = (list) => {
    this.setState({search: list}, () => {
      this.loadData()
    })
  }
  downloadImage = () => {
    const { chart, config } = this.state
    const link = document.createElement('a');
    const filename = `${config.name}${moment().format('YYYY-MM-DD HH_mm_ss')}.png`;
    const canvas = chart.getCanvas();
    canvas.get('timeline').stopAllAnimations();
    setTimeout(() => {
      const canvas = chart.getCanvas();
      const canvasDom = canvas.get('el');
      const dataURL = canvasDom.toDataURL('image/png');
      if (window.Blob && window.URL) {
        const arr = dataURL.split(',');
        const mime = arr[0].match(/:(.*?);/)[1];
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        const blobObj = new Blob([u8arr], { type: mime });
        if (window.navigator.msSaveBlob) {
          window.navigator.msSaveBlob(blobObj, filename);
        } else {
          link.addEventListener('click', () => {
            link.download = filename;
            link.href = window.URL.createObjectURL(blobObj);
          });
        }
      }
      const e = document.createEvent('MouseEvents');
      e.initEvent('click', false, false);
      link.dispatchEvent(e);
    }, 16);
  }
  render() {
@@ -1712,7 +1757,8 @@
        }
        <NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} />
        <div className="canvas-wrap" ref={ref => this.wrap = ref}>
          <div className="chart-action">
          {config.plot.download === 'enable' && this.state.chart && !empty ? <DownloadOutlined onClick={this.downloadImage} className="system-color download"/> : null}
          <div className={'chart-action' + (config.plot.download === 'enable' ? ' downable' : '')}>
            {config.action.map(item => {
              if (item.OpenType === 'excelOut') {
                return (
src/tabviews/custom/components/chart/antv-bar-line/index.scss
@@ -21,12 +21,31 @@
        float: right;
      }
    }
    .download {
      position: absolute;
      z-index: 1;
      right: 10px;
      top: 8px;
      opacity: 0;
      transition: opacity 0.3s;
      cursor: pointer;
      font-size: 16px;
    }
    .chart-action.downable {
      right: 35px;
    }
  }
  .canvas-wrap:hover {
    .download {
      opacity: 1;
    }
  }
  .canvas {
    margin: 0;
    padding: 15px 10px 10px;
    letter-spacing: 0px;
    height: 100%;
  }
  .canvas.empty {
    div {
src/tabviews/custom/components/chart/antv-dashboard/index.jsx
@@ -3,17 +3,15 @@
import { is, fromJS } from 'immutable'
import { Chart, registerShape } from '@antv/g2'
import { Spin, notification } from 'antd'
import { DownloadOutlined } from '@ant-design/icons'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
// import asyncComponent from '@/utils/asyncComponent'
import UtilsDM from '@/utils/utils-datamanage.js'
import MKEmitter from '@/utils/events.js'
import NormalHeader from '@/tabviews/custom/components/share/normalheader'
import './index.scss'
// const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
registerShape('point', 'pointer', {
  draw(cfg, container) {
@@ -70,6 +68,7 @@
    sync: false,               // 是否统一请求数据
    plot: null,                // 图表设置
    data: {},                  // 数据
    chart: null
  }
  UNSAFE_componentWillMount () {
@@ -436,6 +435,8 @@
      }
    })
    chart.render()
    this.setState({chart})
  }
  /**
@@ -594,10 +595,49 @@
    }
    chart.render()
    this.setState({chart})
  }
  downloadImage = () => {
    const { chart, config } = this.state
    const link = document.createElement('a');
    const filename = `${config.name}${moment().format('YYYY-MM-DD HH_mm_ss')}.png`;
    const canvas = chart.getCanvas();
    canvas.get('timeline').stopAllAnimations();
    setTimeout(() => {
      const canvas = chart.getCanvas();
      const canvasDom = canvas.get('el');
      const dataURL = canvasDom.toDataURL('image/png');
      if (window.Blob && window.URL) {
        const arr = dataURL.split(',');
        const mime = arr[0].match(/:(.*?);/)[1];
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        const blobObj = new Blob([u8arr], { type: mime });
        if (window.navigator.msSaveBlob) {
          window.navigator.msSaveBlob(blobObj, filename);
        } else {
          link.addEventListener('click', () => {
            link.download = filename;
            link.href = window.URL.createObjectURL(blobObj);
          });
        }
      }
      const e = document.createEvent('MouseEvents');
      e.initEvent('click', false, false);
      link.dispatchEvent(e);
    }, 16);
  }
  render() {
    const { config, loading, empty } = this.state
    const { config, loading } = this.state
    return (
      <div className="custom-dashboard-plot-box" style={config.style}>
@@ -609,7 +649,8 @@
        }
        <NormalHeader config={config} />
        <div className="canvas-wrap" ref={ref => this.wrap = ref}>
          <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div>
          {config.plot.download === 'enable' && this.state.chart ? <DownloadOutlined onClick={this.downloadImage} className="system-color download"/> : null}
          <div className="canvas" id={this.state.chartId}></div>
        </div>
      </div>
    )
src/tabviews/custom/components/chart/antv-dashboard/index.scss
@@ -12,14 +12,21 @@
    margin: 0 0px;
    position: relative;
    flex: 1;
    .chart-action {
    .download {
      position: absolute;
      top: 2px;
      right: 5px;
      z-index: 1;
      right: 10px;
      top: 10px;
      opacity: 0;
      transition: opacity 0.3s;
      cursor: pointer;
      font-size: 16px;
    }
    .chart-action.with-title {
      top: 35px;
  }
  .canvas-wrap:hover {
    .download {
      opacity: 1;
    }
  }
@@ -27,21 +34,9 @@
    margin: 0;
    padding: 15px;
    letter-spacing: 0px;
    height: 100%;
  }
  .canvas.empty {
    div {
      opacity: 0;
    }
  }
  .ant-empty {
    position: absolute;
    top: calc(50% - 34px);
    left: calc(50% - 92px);
    .ant-empty-image {
      height: 60px;
    }
  }
  .loading-mask {
    position: absolute;
    left: 0px;
@@ -60,47 +55,6 @@
      height: 100%;
      opacity: 0.5;
      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{
src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -5,6 +5,7 @@
import { connect } from 'react-redux'
import DataSet, { DataView } from '@antv/data-set'
import { Spin, Empty, notification } from 'antd'
import { DownloadOutlined } from '@ant-design/icons'
import moment from 'moment'
import Api from '@/api'
@@ -35,6 +36,7 @@
    plot: null,                // 图表设置
    data: null,                // 数据
    search: null,              // 搜索条件
    chart: null
  }
  UNSAFE_componentWillMount () {
@@ -728,6 +730,8 @@
      })
    }
    chart.render()
    this.setState({chart})
  }
  /**
@@ -989,12 +993,51 @@
      })
    }
    chart.render()
    this.setState({chart})
  }
  refreshSearch = (list) => {
    this.setState({search: list}, () => {
      this.loadData()
    })
  }
  downloadImage = () => {
    const { chart, config } = this.state
    const link = document.createElement('a');
    const filename = `${config.name}${moment().format('YYYY-MM-DD HH_mm_ss')}.png`;
    const canvas = chart.getCanvas();
    canvas.get('timeline').stopAllAnimations();
    setTimeout(() => {
      const canvas = chart.getCanvas();
      const canvasDom = canvas.get('el');
      const dataURL = canvasDom.toDataURL('image/png');
      if (window.Blob && window.URL) {
        const arr = dataURL.split(',');
        const mime = arr[0].match(/:(.*?);/)[1];
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        const blobObj = new Blob([u8arr], { type: mime });
        if (window.navigator.msSaveBlob) {
          window.navigator.msSaveBlob(blobObj, filename);
        } else {
          link.addEventListener('click', () => {
            link.download = filename;
            link.href = window.URL.createObjectURL(blobObj);
          });
        }
      }
      const e = document.createEvent('MouseEvents');
      e.initEvent('click', false, false);
      link.dispatchEvent(e);
    }, 16);
  }
  render() {
@@ -1010,6 +1053,7 @@
        }
        <NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} />
        <div className="canvas-wrap" ref={ref => this.wrap = ref}>
          {config.plot.download === 'enable' && this.state.chart && !empty ? <DownloadOutlined onClick={this.downloadImage} className="system-color download"/> : null}
          <div className={'canvas' + (empty ? ' empty' : '')} id={this.state.chartId}></div>
        </div>
        {empty ? <Empty description={false}/> : null}
src/tabviews/custom/components/chart/antv-pie/index.scss
@@ -12,14 +12,20 @@
    margin: 0 0px;
    position: relative;
    flex: 1;
    .chart-action {
    .download {
      position: absolute;
      top: 2px;
      right: 5px;
      z-index: 1;
      right: 10px;
      top: 10px;
      opacity: 0;
      transition: opacity 0.3s;
      cursor: pointer;
      font-size: 16px;
    }
    .chart-action.with-title {
      top: 35px;
  }
  .canvas-wrap:hover {
    .download {
      opacity: 1;
    }
  }
@@ -27,6 +33,7 @@
    margin: 0;
    padding: 15px;
    letter-spacing: 0px;
    height: 100%;
  }
  .canvas.empty {
    div {
@@ -60,47 +67,6 @@
      height: 100%;
      opacity: 0.5;
      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{
src/tabviews/custom/components/chart/antv-scatter/index.jsx
@@ -3,18 +3,17 @@
import { is, fromJS } from 'immutable'
import { Chart } from '@antv/g2'
import { Spin, Empty, notification } from 'antd'
import { DownloadOutlined } from '@ant-design/icons'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
// import asyncComponent from '@/utils/asyncComponent'
import asyncBtnComponent from './asyncButtonComponent'
import UtilsDM from '@/utils/utils-datamanage.js'
import MKEmitter from '@/utils/events.js'
import NormalHeader from '@/tabviews/custom/components/share/normalheader'
import './index.scss'
// const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
const ExcelOutButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton'))
const ExcelInButton = asyncBtnComponent(() => import('@/tabviews/zshare/actionList/excelInbutton'))
@@ -37,6 +36,7 @@
    plot: null,                // 图表设置
    data: null,                // 数据
    search: null,              // 搜索条件
    chart: null
  }
  UNSAFE_componentWillMount () {
@@ -376,12 +376,51 @@
      })
    }
    chart.render()
    this.setState({chart})
  }
  refreshSearch = (list) => {
    this.setState({search: list}, () => {
      this.loadData()
    })
  }
  downloadImage = () => {
    const { chart, config } = this.state
    const link = document.createElement('a');
    const filename = `${config.name}${moment().format('YYYY-MM-DD HH_mm_ss')}.png`;
    const canvas = chart.getCanvas();
    canvas.get('timeline').stopAllAnimations();
    setTimeout(() => {
      const canvas = chart.getCanvas();
      const canvasDom = canvas.get('el');
      const dataURL = canvasDom.toDataURL('image/png');
      if (window.Blob && window.URL) {
        const arr = dataURL.split(',');
        const mime = arr[0].match(/:(.*?);/)[1];
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        const blobObj = new Blob([u8arr], { type: mime });
        if (window.navigator.msSaveBlob) {
          window.navigator.msSaveBlob(blobObj, filename);
        } else {
          link.addEventListener('click', () => {
            link.download = filename;
            link.href = window.URL.createObjectURL(blobObj);
          });
        }
      }
      const e = document.createEvent('MouseEvents');
      e.initEvent('click', false, false);
      link.dispatchEvent(e);
    }, 16);
  }
  render() {
@@ -397,7 +436,8 @@
        }
        <NormalHeader config={config} BID={BID} menuType={this.props.menuType} refresh={this.refreshSearch} />
        <div className="canvas-wrap" ref={ref => this.wrap = ref}>
          <div className="chart-action">
          {config.plot.download === 'enable' && this.state.chart && !empty ? <DownloadOutlined onClick={this.downloadImage} className="system-color download"/> : null}
          <div className={'chart-action' + (config.plot.download === 'enable' ? ' downable' : '')}>
            {config.action.map(item => {
              if (item.OpenType === 'excelOut') {
                return (
src/tabviews/custom/components/chart/antv-scatter/index.scss
@@ -21,12 +21,32 @@
        float: right;
      }
    }
    .download {
      position: absolute;
      z-index: 1;
      right: 10px;
      top: 8px;
      opacity: 0;
      transition: opacity 0.3s;
      cursor: pointer;
      font-size: 16px;
    }
    .chart-action.downable {
      right: 35px;
    }
  }
  .canvas-wrap:hover {
    .download {
      opacity: 1;
    }
  }
  .canvas {
    margin: 0;
    padding: 15px 10px 10px;
    letter-spacing: 0px;
    height: 100%;
  }
  .canvas.empty {
    div {
src/views/appmanage/submutilform/index.jsx
@@ -185,7 +185,7 @@
          </Col> : null}
          {typename !== 'pc' && user_binding.includes('sms_vcode') ? <Col span={12}>
            <Form.Item label={
              <Tooltip placement="topLeft" title="短信模板可在管理系统 HS-奇云短信模板 处添加。">
              <Tooltip placement="topLeft" title="短信模板可在 云系统->应用服务->开发者中心->短信模板 处添加。">
                <QuestionCircleOutlined className="mk-form-tip" />
                短信模板
              </Tooltip>
src/views/design/sidemenu/config.jsx
@@ -185,13 +185,13 @@
  //   MenuID: '15900310928174dro07ihfckghpb5h13',
  //   MenuNo: 'bd_msn_sms_tempM',
  //   MenuName: '大于短信模板',
  }, {
    src: '',
    PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
    type: 'ManageTable',
    MenuID: '1599613340050c8nu6rbst9d4emnnbsq',
    MenuNo: 's_sms_qxM',
    MenuName: '奇云短信模板',
  // }, {
  //   src: '',
  //   PageParam: {OpenType: 'newtab', Template: 'ManageTable'},
  //   type: 'ManageTable',
  //   MenuID: '1599613340050c8nu6rbst9d4emnnbsq',
  //   MenuNo: 's_sms_qxM',
  //   MenuName: '奇云短信模板',
  }]
}, {
  MenuID: 'systemPayManage',
src/views/menudesign/index.scss
@@ -1,3 +1,6 @@
body {
  overflow-x: hidden;
}
.pc-menu-view {
  background: #000;
  min-height: 100vh;
src/views/pcdesign/index.scss
@@ -1,3 +1,6 @@
body {
  overflow-x: hidden;
}
.mk-pc-view {
  background: #000;
  min-height: 100vh;
src/views/rolemanage/index.jsx
@@ -809,6 +809,14 @@
    if (app.typename === 'pc') {
      route = 'pcdesign'
    }
    if (item.type === 'navbar') {
      notification.warning({
        top: 92,
        message: '导航栏不可单独编辑,请在含有导航栏的页面中修改。',
        duration: 5
      })
      return
    }
    window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...app, MenuID: item.MenuID, type: 'app'})))}`))
  }