king
2020-05-22 523cec6c87d88b43954a4409a8dfde6aade095a1
2020-05-22
20个文件已修改
3个文件已删除
7个文件已添加
1630 ■■■■■ 已修改文件
src/assets/img/card1.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card2.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card2.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card3.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card3.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card4.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card5.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tabview/index.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.scss 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtabtable/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/index.jsx 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/cardcomponent/index.jsx 547 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/cardcomponent/index.scss 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/index.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/cardcomponent/carddetailform/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/cardcomponent/index.jsx 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/cardcomponent/index.scss 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartcomponent/chartcompile/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/chartform/index.jsx 81 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/chartform/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/index.jsx 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/markcolumn/markform/index.jsx 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/index.jsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/option.js 281 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/card1.jpg
Binary files differ
src/assets/img/card1.png
src/assets/img/card2.jpg
Binary files differ
src/assets/img/card2.png
src/assets/img/card3.jpg
Binary files differ
src/assets/img/card3.png
src/assets/img/card4.png
src/assets/img/card5.png
src/components/tabview/index.scss
@@ -20,6 +20,7 @@
            margin: 0px;
            padding: 5px;
            cursor: pointer;
            display: none;
          }
          span.tab-control i.anticon-redo {
            position: absolute;
@@ -41,6 +42,11 @@
            cursor: default;
          }
        }
        .ant-tabs-tab:hover {
          span.tab-control i.anticon-close {
            display: inline-block;
          }
        }
        .ant-tabs-tab-active.ant-tabs-tab:hover {
          span.tab-control i.anticon-redo {
            display: inline-block;
src/tabviews/commontable/index.jsx
@@ -9,20 +9,22 @@
import zhCN from '@/locales/zh-CN/main.js'
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
import asyncLoadComponent from '@/utils/asyncLoadComponent'
import {refreshTabView, modifyTabview} from '@/store/action'
import ChartComponent from '@/tabviews/zshare/chartcomponent'
import MainTable from '@/tabviews/zshare/normalTable'
import MainSearch from '@/tabviews/zshare/topSearch'
import NotFount from '@/components/404'
import './index.scss'
const VerifyCard = asyncLoadComponent(() => import('@/tabviews/zshare/verifycard'))
const MainAction = asyncLoadComponent(() => import('@/tabviews/zshare/actionList'))
const SubTable = asyncLoadComponent(() => import('@/tabviews/subtable'))
const SubTabTable = asyncLoadComponent(() => import('@/tabviews/subtabtable'))
const FormTab = asyncLoadComponent(() => import('@/tabviews/formtab'))
const VerifyCard = asyncComponent(() => import('@/tabviews/zshare/verifycard'))
const SubTable = asyncComponent(() => import('@/tabviews/subtable'))
const SubTabTable = asyncComponent(() => import('@/tabviews/subtabtable'))
const FormTab = asyncComponent(() => import('@/tabviews/formtab'))
const CardComponent = asyncComponent(() => import('@/tabviews/zshare/cardcomponent'))
const ChartComponent = asyncComponent(() => import('@/tabviews/zshare/chartcomponent'))
const { TabPane } = Tabs
const { TreeNode } = Tree
@@ -62,7 +64,7 @@
    BIDs: {},             // 上级表id
    pickup: false,        // 主表数据隐藏显示切换
    popAction: false,     // 弹框页面,按钮信息
    popData: false,       // 弹框页面,所选的表格数据
    popData: null,        // 弹框页面,所选的表格数据
    visible: false,       // 弹框显示隐藏控制
    treevisible: false,   // 菜单结构树弹框显示隐藏控制
    tabBtn: null,         // 表单标签按钮
@@ -1332,7 +1334,6 @@
                    {config.charts.length > 1 && item.title ? <p className="chart-table chart-title">{item.title}</p> : null}
                    <div style={{minHeight: '25px'}}>
                      <MainAction
                        BID=""
                        type="main"
                        menuType="main"
                        setting={setting}
@@ -1381,11 +1382,34 @@
              } else if (item.chartType === 'card') {
                return (
                  <Col span={item.width} key={item.uuid}>
                    <ChartComponent
                    <CardComponent
                      plot={item}
                      data={this.state.data}
                      config={config}
                      tableId="mainTable"
                      loading={this.state.loading}
                      data={this.state.data}
                      buttonTrigger={this.buttonTrigger}
                      handleTableId={this.handleTableId}
                    />
                    <div style={{display: 'none'}}>
                      <MainAction
                        type="main"
                        menuType="main"
                        setting={setting}
                        actions={actions}
                        triggerBtn={triggerBtn}
                        dict={this.state.dict}
                        MenuID={this.props.MenuID}
                        permRoles={this.props.permRoles}
                        dataManager={this.props.dataManager}
                        logcolumns={this.state.logcolumns}
                        ContainerId={this.state.ContainerId}
                        refreshdata={this.refreshbyaction}
                        triggerPopview={this.triggerPopview}
                        getexceloutparam={this.getexceloutparam}
                        gettableselected={this.gettableselected}
                      />
                    </div>
                  </Col>
                )
              } else {
@@ -1393,8 +1417,8 @@
                  <Col span={item.width} key={item.uuid}>
                    <ChartComponent
                      plot={item}
                      data={this.state.data}
                      config={config}
                      data={this.state.data}
                    />
                  </Col>
                )
@@ -1457,13 +1481,12 @@
            destroyOnClose
          >
            {<SubTabTable 
              BID={''}
              BID={this.state.popData ? this.state.popData[setting.primaryKey] : ''}
              menuType="main"
              SupMenuID={this.props.MenuID}
              MenuID={this.state.popAction.linkTab}
              BData={this.state.BIDs['mainTabledata'] || ''}
              BData={this.state.popData || ''}
              ContainerId={this.state.ContainerId}
              ID={this.state.popData ? this.state.popData[setting.primaryKey] : ''}
              refreshSupView={this.reloadtable}
            />}
          </Modal>
src/tabviews/commontable/index.scss
@@ -90,20 +90,22 @@
  }
  .chart-view {
    position: relative;
    .ant-tabs-bar {
      position: relative;
      z-index: 1;
      margin: 0;
      border: 0;
      .ant-tabs-nav-scroll {
        text-align: right;
        padding-right: 20px;
        .ant-tabs-ink-bar {
          display: none!important;
        }
        .ant-tabs-tab {
          padding: 5px 5px;
          margin-right: 5px;
    >.ant-tabs {
      .ant-tabs-bar {
        position: relative;
        z-index: 1;
        margin: 0;
        border: 0;
        .ant-tabs-nav-scroll {
          text-align: right;
          padding-right: 20px;
          .ant-tabs-ink-bar {
            display: none!important;
          }
          .ant-tabs-tab {
            padding: 5px 5px;
            margin-right: 5px;
          }
        }
      }
    }
src/tabviews/subtable/index.jsx
@@ -62,7 +62,7 @@
    orderBy: '',          // 排序
    search: '',           // 搜索条件数组,使用时需分场景处理
    popAction: false,     // 弹框页面,按钮信息
    popData: false,       // 弹框页面,所选的表格数据
    popData: null,        // 弹框页面,所选的表格数据
    visible: false,       // 弹框显示隐藏控制
    pickup: false,        // 子表数据隐藏显示切换
    triggerBtn: null,     // 按钮触发
@@ -935,7 +935,7 @@
              <TabPane tab={<Icon type={item.icon} />} key={item.uuid}></TabPane>
            ))}
          </Tabs> : null}
          {config.expand && config.charts.map(item => {
          {config.charts.map(item => {
            if (!config.expand && chartId !== item.uuid) return null
            if (item.chartType === 'table') {
              return (
@@ -1017,13 +1017,12 @@
          destroyOnClose
        >
          {<SubTabTable
            BID={this.props.BID}
            BID={this.state.popData ? this.state.popData[setting.primaryKey] : this.props.BID}
            menuType={this.props.menuType}
            BData={this.props.BData}
            BData={this.state.popData || this.props.BData}
            SupMenuID={this.props.MenuID}
            ContainerId={this.props.ContainerId}
            MenuID={this.state.popAction.linkTab}
            ID={this.state.popData ? this.state.popData[setting.primaryKey] : ''}
            refreshSupView={this.reloadtable}
          />}
        </Modal>
src/tabviews/subtabtable/index.jsx
@@ -25,9 +25,8 @@
class SubTabModalTable extends Component {
  static propTpyes = {
    menuType: PropTypes.any,         // 菜单类型,普通菜单或HS
    ID: PropTypes.string,            // 上级数据ID
    BID: PropTypes.string,           // 上上级数据ID
    BData: PropTypes.any,            // 上上级数据
    BID: PropTypes.string,           // 上级数据ID
    BData: PropTypes.any,            // 上级数据
    MenuID: PropTypes.string,        // 菜单Id
    SupMenuID: PropTypes.string,     // 上级菜单Id
    ContainerId: PropTypes.any,      // 三级菜单Container(html) ID
@@ -716,7 +715,7 @@
              <TabPane tab={<Icon type={item.icon} />} key={item.uuid}></TabPane>
            ))}
          </Tabs> : null}
          {config.expand && config.charts.map(item => {
          {config.charts.map(item => {
            if (!config.expand && chartId !== item.uuid) return null
            if (item.chartType === 'table') {
src/tabviews/zshare/actionList/index.jsx
@@ -192,7 +192,8 @@
        })
      }
    } else if (item.OpenType === 'popview' && this.props.type !== 'subtab') {
      this.props.triggerPopview(item, data)
      // 弹窗标签设置为不选则行时,不传递数据
      this.props.triggerPopview(item, item.Ot === 'notRequired' ? [] : data)
    } else if (item.OpenType === 'popview' && this.props.type === 'subtab') {
      notification.warning({
        top: 92,
@@ -447,8 +448,10 @@
    let _list = []
    return new Promise(resolve => {
      let params = []
      let param = {
        BID: this.props.BID
      let param = {}
      if (this.props.BID) {
        param.BID = this.props.BID
      }
      if (btn.Ot === 'notRequired') {
@@ -545,7 +548,7 @@
            // 使用处理后的数据调用外部接口
            let keys = Object.keys(res) // 提交外部接口前,添加BID
            if (keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
            if (this.props.BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
              res.BID = this.props.BID
            }
            
@@ -1027,8 +1030,11 @@
    let _this = this
    let param = {
      BID: this.props.BID,
      func: 'webapi_ChangeUser'
    }
    if (this.props.BID) {
      param.BID = this.props.BID
    }
    if (window.GLOB.mainSystemApi) {
@@ -1114,8 +1120,11 @@
        }
        let param = { // 系统存储过程
          func: 'sPC_TableData_InUpDe',
          BID: this.props.BID
          func: 'sPC_TableData_InUpDe'
        }
        if (this.props.BID) {
          param.BID = this.props.BID
        }
        
        let primaryId = ''
@@ -1191,9 +1200,13 @@
        let _params = data.map((cell, index) => {
          let param = {
            func: 'sPC_TableData_InUpDe',
            BID: this.props.BID
            func: 'sPC_TableData_InUpDe'
          }
          if (this.props.BID) {
            param.BID = this.props.BID
          }
          let primaryId = setting.primaryKey ? cell[setting.primaryKey] : ''
          if (btn.OpenType === 'prompt' || btn.OpenType === 'exec') { // 是否弹框或直接执行
@@ -1210,15 +1223,20 @@
              param.secretkey = Utils.encrypt(param.LText, param.timestamp)
            }
          } else if (btn.OpenType === 'pop') { // 表单
            if (index !== 0) {
              formdata = formdata.map(_data => {
                if (_data.readin && cell.hasOwnProperty(_data.key)) {
                  _data.value = cell[_data.key]
                }
                return _data
              })
            }
            if (btn.innerFunc) {
              param.func = btn.innerFunc
              formdata.forEach(_data => {
                if (index !== 0 && _data.readin && cell.hasOwnProperty(_data.key)) {
                  param[_data.key] = cell[_data.key]
                } else {
                  param[_data.key] = _data.value
                }
                param[_data.key] = _data.value
              })
              if (setting.primaryKey) {
@@ -1230,15 +1248,6 @@
              param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
              param.secretkey = Utils.encrypt(param.LText, param.timestamp)
            } else if (btn.sql) {
              if (index !== 0) {
                formdata = formdata.map(_data => {
                  if (_data.readin && cell.hasOwnProperty(_data.key)) {
                    _data.value = cell[_data.key]
                  }
                  return _data
                })
              }
              param.ID = primaryId
              param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param, cell, logcolumns, this.props.Tab)) // 数据源
              param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
@@ -1294,8 +1303,10 @@
      let _params = [] // 请求参数数组
      if (btn.Ot === 'notRequired' || btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
        let param = {
          BID: this.props.BID
        let param = {}
        if (this.props.BID) {
          param.BID = this.props.BID
        }
        if (btn.OpenType === 'pop' && formdata) { // 表单
@@ -1318,8 +1329,10 @@
      } else if (btn.Ot === 'required') {
        // 选择多行,循环调用
        _params = data.map((cell, index) => {
          let _cell = {
            BID: this.props.BID,
          let _cell = {}
          if (this.props.BID) {
            _cell.BID = this.props.BID
          }
          let _formparam = {}
@@ -1413,7 +1426,7 @@
            // 使用处理后的数据调用外部接口
            let keys = Object.keys(res) // 提交外部接口前,添加BID
            if (keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
            if (this.props.BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
              res.BID = this.props.BID
            }
            
@@ -1848,8 +1861,11 @@
    }
    let param = {
      BID: this.props.BID,
      ID: primaryId
    }
    if (this.props.BID) {
      param.BID = this.props.BID
    }
    param.LText = Utils.formatOptions(result.sql)
@@ -1895,7 +1911,7 @@
              // 使用处理后的数据调用外部接口
              let keys = Object.keys(res) // 提交外部接口前,添加BID
              if (keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
              if (this.props.BID && keys.filter(key => key.toLowerCase() === 'bid').length === 0) {
                res.BID = this.props.BID
              }
              resolve(res)
src/tabviews/zshare/cardcomponent/index.jsx
New file
@@ -0,0 +1,547 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Icon, Card, Dropdown, Menu, Spin, Empty, Tabs } from 'antd'
import './index.scss'
const { TabPane } = Tabs
class CardCell extends Component {
  static propTpyes = {
    card: PropTypes.object,
    data: PropTypes.object,
    selectKey: PropTypes.string,
    colMap: PropTypes.any,
    triggerBtn: PropTypes.func,
    switchCard: PropTypes.func
  }
  state = {
    card: null,
    extra: null,
    actions: null
  }
  UNSAFE_componentWillMount () {
    const { card } = this.props
    let extra = null
    if (card.header && card.header.actions) {
      let actions = card.header.actions.map(item => {
        let _action = null
        if (card.header.show === 'icon') {
          _action = <span className="action-cell" onClick={() => this.triggerAction(item)} key={item.uuid}><Icon type={item.icon || 'dash'} /></span>
        } else if (card.bottom.show === 'text') {
          _action = <span className="action-cell" onClick={() => this.triggerAction(item)} key={item.uuid}>{item.label}</span>
        } else {
          _action = <span className="action-cell" onClick={() => this.triggerAction(item)} key={item.uuid}><Icon type={item.icon || 'dash'} /> {item.label}</span>
        }
        return _action
      })
      if (actions.length === 1) {
        extra = actions[0]
      } else {
        extra = <Dropdown overlay={
          <Menu>{actions.map((item, i) => <Menu.Item key={i}> {item} </Menu.Item>)}</Menu>
        } placement="bottomRight">
          Action
        </Dropdown>
      }
    }
    let _actions = null
    if (card.bottom && card.bottom.actions) {
      _actions = card.bottom.actions.map(item => {
        let _action = null
        if (card.bottom.show === 'icon') {
          _action = <span className="action-cell" onClick={() => this.triggerAction(item)} key={item.uuid}><Icon type={item.icon || 'dash'} /></span>
        } else if (card.bottom.show === 'text') {
          _action = <span className="action-cell" onClick={() => this.triggerAction(item)} key={item.uuid}>{item.label}</span>
        } else {
          _action = <span className="action-cell" onClick={() => this.triggerAction(item)} key={item.uuid}><Icon type={item.icon || 'dash'} /> {item.label}</span>
        }
        return _action
      })
    }
    this.setState({
      actions: _actions,
      extra: extra
    })
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  triggerAction = (btn) => {
    this.props.triggerBtn(btn, [this.props.data])
  }
  getMark = (record, marks) => {
    const { colMap } = this.props
    let className = ''
    let isIcon = false
    let position = 'back'
    let icon = ''
    colMap && marks.some(mark => {
      let originType = colMap.get(mark.field).type
      let originVal = record.hasOwnProperty(mark.field) ? record[mark.field] : ''
      let contrastVal = ''
      if (mark.contrastType === 'static') {
        contrastVal = mark.contrastValue
      } else {
        contrastVal = record.hasOwnProperty(mark.contrastField) ? record[mark.contrastField] : ''
      }
      if (originType === 'text') {
        originVal = '' + originVal
        contrastVal = '' + contrastVal
      } else if (originType === 'number' && originVal !== '' && contrastVal !== '') {
        try {
          originVal = parseFloat(originVal)
          contrastVal = parseFloat(contrastVal)
          if (isNaN(originVal) || isNaN(contrastVal)) {
            originVal = ''
          }
        } catch {
          originVal = ''
        }
      }
      if (originVal === '' || contrastVal === '') return false
      if (mark.match === '=' && originVal === contrastVal) {
        className = mark.color[1]
      } else if (mark.match === 'like' && originVal.indexOf(contrastVal) > -1) {
        className = mark.color[1]
      } else if (mark.match === '>' && originVal > contrastVal) {
        className = mark.color[1]
      } else if (mark.match === '<' && originVal < contrastVal) {
        className = mark.color[1]
      }
      if (!className) return false
      if (mark.signType === 'font') {
        className = 'font ' + className
      } else if (mark.signType === 'icon') {
        isIcon = true
        if (mark.position === 'front') {
          position = 'front'
        }
        icon = <Icon className={'font ' + className} type={mark.icon} />
        className = ''
      }
      return true
    })
    return {
      className: className,
      isIcon: isIcon,
      position: position,
      icon: icon
    }
  }
  getContent = (col) => {
    const { data } = this.props
    if (col.type === 'text') {
      let content = ''
      let className = ''
      if (data.hasOwnProperty(col.field)) {
        content = `${data[col.field]}`
      }
      content = content ? (col.prefix || '') + content + (col.postfix || '') : ''
      if (col.marks) {
        let result = this.getMark(data, col.marks)
        if (result.className) {
          className = result.className
        } else if (result.isIcon) {
          if (result.position === 'front') {
            content = <span>{result.icon} {content}</span>
          } else {
            content = <span>{content} {result.icon}</span>
          }
        }
      }
      return (
        <div className={className}>
          {content}
        </div>
      )
    } else if (col.type === 'number') {
      let content = ''
      let className = ''
      if (data.hasOwnProperty(col.field)) {
        try {
          content = parseFloat(data[col.field])
          if (isNaN(content)) {
            content = ''
          }
        } catch {
          content = ''
        }
      }
      if (content !== '') {
        if (col.format === 'percent') {
          content = content * 100
        }
        content = content.toFixed(col.decimal || 0)
        if (col.format === 'thdSeparator') {
          content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
        }
        content = (col.prefix || '') + content + (col.postfix || '')
      }
      if (col.marks) {
        let result = this.getMark(data, col.marks)
        if (result.className) {
          className = result.className
        } else if (result.isIcon) {
          if (result.position === 'front') {
            content = <span>{result.icon} {content}</span>
          } else {
            content = <span>{content} {result.icon}</span>
          }
        }
      }
      return (
        <div className={className}>
          {content}
        </div>
      )
    }
  }
  getAvatar = () => {
    const { card, data } = this.props
    if (card.avatar.type === 'picture') {
      if (card.avatar.field && data.hasOwnProperty(card.avatar.field) && data[card.avatar.field]) {
        return <img src={data[card.avatar.field]} alt=""/>
      } else {
        return null
      }
    } else if (card.avatar.type === 'icon') {
      let result = this.getMark(data, card.avatar.marks)
      if (result.isIcon) {
        return result.icon
      } else {
        return null
      }
    }
  }
  switchCard = () => {
    const { card, data } = this.props
    if (!card.switch) return
    this.props.switchCard(data)
  }
  render() {
    const { card, selectKey, data } = this.props
    const { extra, actions } = this.state
    let title = null
    if (card.header) {
      if (card.header.column) {
        title = this.getContent(card.header.column)
      } else {
        title = card.header.content
      }
    }
    return (
      <div className={'chart-card-box ' + card.outclass} style={card.outstyle || null} >
        <Card
          size="small"
          className={'chart-card ' + (selectKey === data.key ? 'chart-card-selected' : '')}
          title={title}
          bordered={card.bordered}
          extra={extra}
          actions={actions}
        >
          <div className={'ant-card-meta' + (card.switch ? ' switch' : '')} onClick={this.switchCard}>
            {card.avatar ?
              <div className="ant-card-meta-avatar">
                <span className="ant-avatar ant-avatar-circle ant-avatar-image" style={card.avatar.class}>
                  {this.getAvatar()}
                </span>
              </div> : null
            }
            <div className="ant-card-meta-detail" style={card.marginLeft || null}>
              {card.details.map((detail, i) => {
                return (
                  <div className={detail.class} key={i}>
                    {this.getContent(detail.column)}
                  </div>
                )
              })}
            </div>
          </div>
        </Card>
      </div>
    )
  }
}
class CardChart extends Component {
  static propTpyes = {
    plot: PropTypes.object,
    config: PropTypes.object,
    tableId: PropTypes.string,
    loading: PropTypes.bool,
    data: PropTypes.array,
    buttonTrigger: PropTypes.func,
    handleTableId: PropTypes.func
  }
  state = {
    card: null,
    colMap: null,
    selectKey: ''
  }
  UNSAFE_componentWillMount () {
    const { plot, config } = this.props
    let card = {}
    let colMap = new Map()    // 显示列
    let actionMap = new Map() // 按钮组
    let columns = fromJS(config.columns).toJS()
    let actions = fromJS(config.action).toJS()
    columns.forEach(col => {
      if (col.field) {
        colMap.set(col.field, col)
      }
    })
    actions.forEach(item => {
      if (item.Ot && item.Ot !== 'notRequired' && !['excelIn', 'excelOut'].includes(item.OpenType)) {
        actionMap.set(item.uuid, item)
      }
    })
    if (plot.subelement.includes('header')) {
      card.header = { actions: [], show: plot.header.show }
      if (plot.header.datatype === 'dynamic' && colMap.get(plot.header.field)) {
        let col = fromJS(colMap.get(plot.header.field)).toJS()
        if (col.marks) {
          col.marks = col.marks.filter(mark => mark.signType === 'font' || mark.signType === 'icon')
        }
        card.header.column = col
      } else if (plot.header.content) {
        card.header.content = plot.header.content
      }
      if (plot.header.actions && plot.header.actions.length > 0) {
        plot.header.actions.forEach(item => {
          if (!actionMap.get(item.value)) return
          card.header.actions.push(actionMap.get(item.value))
        })
      }
      if (card.header.actions.length === 0) {
        card.header.actions = null
      }
    }
    if (plot.subelement.includes('avatar')) {
      card.avatar = { type: plot.avatar.type }
      if (card.avatar.type === 'icon' && colMap.get(plot.avatar.field)) {
        let col = fromJS(colMap.get(plot.avatar.field)).toJS()
        let _marks = []
        if (col.marks) {
          _marks = col.marks.filter(mark => mark.signType === 'icon')
        }
        if (_marks.length === 0) {
          card.avatar = null
        } else {
          card.avatar.marks = _marks
          card.avatar.outWidth = plot.avatar.size + 16
          card.avatar.class = {width: plot.avatar.size, fontSize: plot.avatar.size + 'px'}
        }
      } else if (card.avatar.type === 'picture' && colMap.get(plot.avatar.field)) {
        card.avatar.field = plot.avatar.field
        card.avatar.outWidth = plot.avatar.width + 16
        card.avatar.class = {width: plot.avatar.width}
      }
    }
    if (card.avatar) {
      card.marginLeft = {marginLeft: card.avatar.outWidth}
    }
    card.details = []
    if (plot.details.length > 0) {
      card.details = plot.details.map(item => {
        if (item.datatype === 'dynamic' && colMap.get(item.field)) {
          item.column = colMap.get(item.field)
        } else {
          item.datatype = 'static'
        }
        let _class = ''
        if (item.bold === 'true') {
          _class = ' ant-card-meta-title'
        } else {
          _class = ' ant-card-meta-description'
        }
        if (item.width) {
          _class += ' ' + item.width
        }
        if (item.align) {
          _class += ' ' + item.align
        }
        item.class = _class
        return item
      })
    }
    if (plot.subelement.includes('bottom')) {
      card.bottom = { actions: [], show: plot.bottom.show }
      if (plot.bottom.actions && plot.bottom.actions.length > 0) {
        plot.bottom.actions.forEach(item => {
          if (!actionMap.get(item.value)) return
          card.bottom.actions.push(actionMap.get(item.value))
        })
      }
      if (card.bottom.actions.length === 0) {
        card.bottom = null
      }
    }
    let outclass = ''
    if (plot.widthType === 'ratio' && plot.over !== 'roll') {
      outclass += ' ant-col ant-col-' + plot.cardWidth
    }
    card.outclass = outclass
    card.bordered = plot.border !== 'hidden'
    if (plot.widthType === 'absolute') {
      card.outstyle = { width: plot.cardWidth }
    }
    if (plot.bgfield && colMap.get(plot.bgfield)) {
      let col = fromJS(colMap.get(plot.bgfield)).toJS()
      let _marks = []
      if (col.marks) {
        _marks = col.marks.filter(mark => mark.signType === 'card')
      }
      if (_marks.length > 0) {
        card.bgmarks = _marks
      }
    }
    card.switch = plot.switch !== 'false'
    this.setState({card: card, colMap: colMap})
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { card } = this.state
    if (card && card.switch && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
      this.setState({selectKey: ''})
    }
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
  triggerBtn = (btn, data) => {
    this.props.buttonTrigger(btn, data)
  }
  switchCard = (data) => {
    const { config } = this.props
    let _id = data[config.setting.primaryKey] || ''
    this.setState({selectKey: data.key})
    this.props.handleTableId(this.props.tableId, _id, data)
  }
  render() {
    const { plot, data, loading } = this.props
    const { card, colMap, selectKey } = this.state
    return (
      <div className="card-row-box mingke-table">
        {loading ?
          <div className="loading-mask">
            <div className="ant-spin-blur"></div>
            <Spin />
          </div> : null
        }
        {plot.title ? <p className="chart-title">{plot.title}</p> : null}
        {plot.over !== 'roll' && data && data.length > 0 &&
          data.map((item, i) => (
            <CardCell
              key={i}
              card={card}
              data={item}
              colMap={colMap}
              selectKey={selectKey}
              triggerBtn={this.triggerBtn}
              switchCard={this.switchCard}
            />
          ))
        }
        {plot.over === 'roll' && data && data.length > 0 ?
          <Tabs activeKey="">
            {data.map((item, i) => (
              <TabPane tab={<CardCell
                // key={i}
                card={card}
                data={item}
                colMap={colMap}
                selectKey={selectKey}
                triggerBtn={this.triggerBtn}
                switchCard={this.switchCard}
              />} key={i}></TabPane>
            ))}
          </Tabs> : null
        }
        {!data || data.length === 0 ? <Empty description={false}/> : null}
      </div>
    )
  }
}
export default CardChart
src/tabviews/zshare/cardcomponent/index.scss
New file
@@ -0,0 +1,203 @@
.card-row-box {
  min-height: 50px;
  margin-bottom: 30px;
  padding: 0px 10px;
  .chart-card-box {
    padding: 0 10px;
  }
  .chart-card-box:not(.ant-col) {
    display: inline-block;
    margin-bottom: 20px;
  }
  >.ant-tabs {
    .ant-tabs-bar {
      border: 0;
      margin: 0;
      .ant-tabs-nav-scroll {
        .ant-tabs-tab {
          margin: 0;
          padding: 12px 5px;
          .chart-card-box:not(.ant-col) {
            margin-bottom: 0px;
          }
        }
      }
    }
  }
  .ant-empty {
    .ant-empty-image {
      height: 60px;
    }
  }
  .loading-mask {
    position: absolute;
    left: 20px;
    top: 0;
    right: 20px;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: justify;
    z-index: 1;
    .ant-spin-blur {
      position: absolute;
      width: 100%;
      height: 100%;
      opacity: 0.5;
      background: #ffffff;
    }
  }
  .ant-card.chart-card {
    transition: all 0.3s;
    .ant-card-head {
      min-height: 40px;
      line-height: 2;
      .ant-card-head-title {
        font-weight: 500;
      }
      .ant-card-extra {
        color: #1890ff;
        .action-cell {
          cursor: pointer;
        }
      }
    }
    .ant-card-actions {
      height: 48px;
    }
  }
  .ant-card.chart-card:not(.ant-card-bordered) {
    .ant-card-head {
      border-bottom: 0;
    }
    .ant-card-actions {
      border-top: 0;
    }
  }
  .ant-card.chart-card.chart-card-selected {
    border: 1px solid #1890ff;
    box-shadow: 0px 0px 8px #c4ebfd;
  }
  .ant-card.chart-card .ant-card-body {
    padding: 0px;
    zoom: 1;
    .ant-card-meta.switch {
      cursor: pointer;
    }
    .ant-card-meta {
      margin: 0px;
      padding: 20px;
      position: relative;
      .ant-card-meta-avatar {
        position: absolute;
        top: 0px;
        left: 0px;
        padding-top: 15px;
        padding-left: 15px;
      }
      .ant-avatar-image {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        font-variant: tabular-nums;
        line-height: 1.5;
        list-style: none;
        font-feature-settings: 'tnum';
        position: relative;
        display: inline-block;
        overflow: hidden;
        color: #fff;
        white-space: nowrap;
        text-align: center;
        vertical-align: middle;
        border-radius: 50%;
        img {
          width: 100%;
        }
        .font {
          background: transparent;
        }
      }
      .ant-card-meta-title {
        font-size: 14px;
      }
      .ant-card-meta-detail > div {
        height: 23px;
      }
      .ant-card-meta-detail > div:not(:last-child) {
        margin-bottom: 2px;
      }
    }
  }
  .chart-title {
    margin-bottom: 10px;
    margin-left: 0px;
    margin-right: 0px;
  }
  .ant-card.chart-card {
    .ant-card-actions {
      li {
        color: rgba(0, 0, 0, 0.45);
        span {
          overflow: hidden;
          word-break: break-word;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
        .anticon {
          width: unset;
          margin-right: 3px;
          color: rgba(0, 0, 0, 0.45);
        }
      }
      li:hover {
        color: #1890ff;
        .anticon {
          color: #1890ff;
        }
      }
    }
  }
  .ant-card.chart-card.background {
    .ant-card-meta-title {
      color: unset;
    }
    .ant-card-meta-description {
      color: unset;
    }
    .ant-card-head {
      color: unset;
      .ant-card-head-title {
        color: unset;
      }
    }
    .ant-card-actions {
      background: transparent;
      li {
        white-space: nowrap;
        color: unset;
        .anticon {
          color: unset;
        }
      }
    }
  }
}
src/tabviews/zshare/topSearch/index.jsx
@@ -216,6 +216,7 @@
              })(
                <Select
                  showSearch
                  // allowClear={true}
                  onChange={(value) => {this.selectChange(item, value)}}
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  getPopupContainer={() => document.getElementById(this.state.formId)}
@@ -419,7 +420,7 @@
    Object.keys(values).forEach(key => {
      let _value = ''
      if (this.state.style[key] === 'daterange') {
        if (values[key].length > 0) {
        if (values[key].length > 0 && values[key][0] && values[key][1]) {
          _value = [moment(values[key][0]).format('YYYY-MM-DD'), moment(values[key][1]).format('YYYY-MM-DD')]
        }
      } else if (this.state.style[key] === 'dateweek') {
src/templates/comtableconfig/index.jsx
@@ -680,7 +680,7 @@
                  supMenuList: _supMenuList
                }
              })
              this.props.reloadmenu()
              
              this.submitAction(btnParam, tabParam)
@@ -951,7 +951,7 @@
   */
  setSubConfig = (item, type) => {
    const { menu } = this.props
    const { config, originMenu, optionLibs, activeKey } = this.state
    const { config, originMenu, optionLibs, activeKey, openEdition } = this.state
    if (!originMenu.MenuID) { // menuID不存在时,为新建菜单,提示菜单尚未保存
      notification.warning({
@@ -1003,8 +1003,8 @@
          isbutton = false
        }
        // 保存当前打开页签
        _originMenu.activeKey = activeKey
        _originMenu.activeKey = activeKey       // 保存当前打开页签
        _originMenu.open_edition = openEdition  // 更新版本号
        let param = {
          optionLibs: optionLibs,
src/templates/formtabconfig/index.jsx
@@ -1551,7 +1551,7 @@
   */
  setSubConfig = (btn) => {
    const {menu, btnTab} = this.props
    const { config, originMenu, activeKey } = this.state
    const { config, originMenu, activeKey, openEdition } = this.state
    if (config.isAdd) {
      notification.warning({
@@ -1574,8 +1574,8 @@
            loading: true
          })
          // 保存当前打开页签
          btnTab.activeKey = activeKey
          btnTab.activeKey = activeKey       // 保存当前打开页签
          btnTab.open_edition = openEdition  // 更新版本号
          let param = {
            editMenu: menu,
src/templates/sharecomponent/cardcomponent/carddetailform/index.jsx
@@ -275,7 +275,9 @@
          }
          if (['avatar'].includes(values.elemType)) {
            if (values.type === 'icon') {
              values.icon = columns.filter(col => col.value === values.field)[0].icon
              let column = columns.filter(col => col.value === values.field)[0]
              values.icon = column.icon
              values.color = column.color
            }
          }
src/templates/sharecomponent/cardcomponent/index.jsx
@@ -176,7 +176,8 @@
            uuid: col.uuid,
            value: col.field,
            text: col.label,
            icon: mark.icon
            icon: mark.icon,
            color: mark.color[1]
          })
        }
      }
@@ -268,7 +269,24 @@
      },
      onCancel() {}
    })
  }
  deleteElem = (type) => {
    const { dict } = this.state
    let _this = this
    confirm({
      content: dict['model.confirm'] + dict['model.delete'] + '?',
      okText: dict['model.confirm'],
      cancelText: dict['header.cancel'],
      onOk() {
        let _subelement = fromJS(_this.props.card.subelement).toJS()
        _subelement = _subelement.filter(_type => _type !== type)
        _this.plotChange({subelement: _subelement})
      },
      onCancel() {}
    })
  }
  render() {
@@ -279,37 +297,52 @@
      _width = Math.floor((100 / card.bottom.actions.length) * 10000) / 10000 + '%'
    }
    let outclass = card.widthType === 'ratio' ? ' ant-col ant-col-' + card.cardWidth : ''
    if (card.background && card.background[1]) {
      outclass += ' background ' + card.background[1]
    if (card.background) {
      outclass += ' background ' + card.background
    }
    console.log(card)
    if (card.border === 'hidden') {
      outclass += ' without-border'
    } else {
      outclass += ' ant-card-bordered'
    }
    return (
      <div className="line-card-edit-box mingke-table">
        {card.title ? <p className="chart-title">{card.title}</p> : null}
        <div
          className={'ant-card ant-card-bordered chart-card ' + outclass}
          className={'ant-card chart-card ' + outclass}
          style={card.widthType === 'absolute' ? { width: card.cardWidth } : null}
        >
          {card.subelement.includes('header') ?
            <div className="ant-card-head">
              <Icon className="edit" title="Edit" type="edit" onClick={this.editHeader} />
              <Icon className="edit close" title="close" type="close" onClick={() => this.deleteElem('header')} />
              <div className="ant-card-head-wrapper">
                <div className="ant-card-head-title">{card.header.content}</div>
                {card.header.actions && card.header.actions.length > 0 ? <div className="ant-card-extra">
                  <span>{card.header.actions.length === 1 ? card.header.actions[0].text : 'Action'}</span>
                </div> : null}
                {card.header.actions && card.header.actions.length > 0 ?
                  <div className="ant-card-extra">
                    {card.header.actions.length === 1 ?
                      <span>
                        {['icon', 'all'].includes(card.header.show) ? <Icon type={card.header.actions[0].icon || 'dash'}/> : null}
                        {['text', 'all'].includes(card.header.show) ? card.header.actions[0].text : null}
                      </span> : null
                    }
                    {card.header.actions.length > 1 ? <span>Action</span> : null}
                  </div> : null
                }
              </div>
            </div> : null
          }
          {card.subelement.includes('content') ? <div className="ant-card-body">
          <div className="ant-card-body">
            <div className="ant-card-meta">
              <Icon type="plus" onClick={() => this.editdetail()} />
              {card.subelement.includes('avatar') ?
                <div className="ant-card-meta-avatar">
                  <Icon className="edit" title="Edit" type="edit" onClick={this.editAvatar} />
                  <Icon className="edit close" title="close" type="close" onClick={() => this.deleteElem('avatar')} />
                  <span className="ant-avatar ant-avatar-circle ant-avatar-image" style={{width: card.avatar.width || card.avatar.size || 32}}>
                    {card.avatar.type === 'picture' ? <img src={avatar} alt=""/> : null}
                    {card.avatar.type === 'icon' ? <Icon className="avatar-icon" style={{fontSize: card.avatar.size + 'px'}} type={card.avatar.icon} /> : null}
                    {card.avatar.type === 'icon' ? <Icon className={'font ' + card.avatar.color} style={{fontSize: card.avatar.size + 'px'}} type={card.avatar.icon} /> : null}
                  </span>
                </div> : null
              }
@@ -320,10 +353,11 @@
                deleteMenu={this.deletedetail}
              />
            </div>
          </div> : null}
          </div>
          {card.subelement.includes('bottom') ?
            <ul className="ant-card-actions">
              <Icon className="edit" title="Edit" type="edit" onClick={this.editBottom} />
              <Icon className="edit close" title="close" type="close" onClick={() => this.deleteElem('bottom')} />
              {card.bottom.actions.map((item, i) => (<li key={i} style={{width: _width}}>
                <span>
                  {['icon', 'all'].includes(card.bottom.show) ? <Icon type={item.icon || 'dash'}/> : null}
src/templates/sharecomponent/cardcomponent/index.scss
@@ -8,12 +8,16 @@
    .ant-card-head {
      min-height: 40px;
      line-height: 2;
      font-size: 14px;
      .ant-card-head-title {
        color: #000000;
        color: rgba(0, 0, 0, 0.85);
        font-weight: 500;
      }
      .ant-card-extra {
        color: #1890ff;
        i {
          margin-right: 5px;
        }
      }
    }
    .ant-card-actions {
@@ -21,16 +25,22 @@
    }
  }
  .ant-card.ant-card-bordered .ant-card-body {
  .ant-card.chart-card.without-border {
    .ant-card-head {
      border-bottom: 0;
    }
    .ant-card-actions {
      border-top: 0;
    }
  }
  .ant-card.chart-card .ant-card-body {
    padding: 20px;
    zoom: 1;
    .ant-card-meta {
      position: relative;
      .avatar-icon {
        color: rgba(0, 0, 0, 0.45);
      }
      >.anticon-plus {
        color: #26C281;
        position: absolute;
@@ -46,9 +56,7 @@
        padding-top: 15px;
        padding-left: 15px;
      }
      // .ant-card-meta-avatar + .ant-card-meta-detail {
      //   float: left;
      // }
      .ant-avatar-image {
        box-sizing: border-box;
        margin: 0;
@@ -69,6 +77,9 @@
        img {
          width: 100%;
        }
        .font {
          background: transparent;
        }
      }
    }
  }
@@ -84,12 +95,16 @@
      .edit {
        position: absolute;
        left: 0;
        top: 5px;
        top: 3px;
        font-size: 13px;
        color: #1890ff;
        cursor: pointer;
        display: none;
        padding: 0 5px;
      }
      .edit.close {
        left: 20px;
        color: #ff4d4f;
      }
    }
    .ant-card-head:hover {
@@ -109,6 +124,10 @@
        cursor: pointer;
        display: none;
        padding: 0 5px;
      }
      .edit.close {
        left: 20px;
        color: #ff4d4f;
      }
    }
    .ant-card-actions:hover {
@@ -130,10 +149,36 @@
        padding: 0 5px;
        z-index: 1;
      }
      .edit.close {
        left: 20px;
        color: #ff4d4f;
      }
    }
    .ant-card-meta-avatar:hover {
      .edit {
        display: inline-block;
      }
    }
    .ant-card-actions {
      li {
        color: rgba(0, 0, 0, 0.45);
        span {
          overflow: hidden;
          word-break: break-word;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
        .anticon {
          width: unset;
          margin-right: 3px;
          color: rgba(0, 0, 0, 0.45);
        }
      }
      li:hover {
        color: #1890ff;
        .anticon {
          color: #1890ff;
        }
      }
    }
  }
@@ -153,7 +198,11 @@
    .ant-card-actions {
      background: transparent;
      li {
        white-space: nowrap;
        color: unset;
        .anticon {
          color: unset;
        }
      }
    }
  }
src/templates/sharecomponent/chartcomponent/chartcompile/index.jsx
@@ -221,9 +221,9 @@
        >
          {view !== 'custom' ? <Form {...formItemLayout}>
            <Row gutter={16}>{this.getFields()}</Row>
            <Row gutter={16}>
            {/* <Row gutter={16}>
              <Button onClick={this.changeView} style={{border: 0, boxShadow: 'unset',float: 'right', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}>自定义设置<Icon style={{marginLeft: 5}} type="right" /></Button>
            </Row>
            </Row> */}
          </Form> : null}
          {/* <Form {...formItemLayout}>
            <Row gutter={16}>
src/templates/sharecomponent/chartgroupcomponent/chartform/index.jsx
@@ -13,9 +13,11 @@
import bar4 from '@/assets/img/bar4.png'
import pie1 from '@/assets/img/pie1.png'
import pie2 from '@/assets/img/pie2.png'
import card1 from '@/assets/img/card1.jpg'
import card2 from '@/assets/img/card2.jpg'
import card3 from '@/assets/img/card3.jpg'
import card1 from '@/assets/img/card1.png'
import card2 from '@/assets/img/card2.png'
import card3 from '@/assets/img/card3.png'
import card4 from '@/assets/img/card4.png'
import card5 from '@/assets/img/card5.png'
import './index.scss'
const syslegends = {
@@ -121,6 +123,16 @@
    {
      uuid: 'card3',
      url: card3,
      subelement: ['content', 'avatar', 'header']
    },
    {
      uuid: 'card4',
      url: card4,
      subelement: ['content', 'avatar', 'bottom']
    },
    {
      uuid: 'card5',
      url: card5,
      subelement: ['content', 'avatar', 'header', 'bottom']
    }
  ]
@@ -138,6 +150,7 @@
  state = {
    formlist: null,
    legends: null,
    columns: null,
    selectlegend: null
  }
@@ -148,6 +161,14 @@
    let _type = card.chartType || 'line'
    let _legends = null
    let _selectlegend = null
    let _columns = []
    // 获取标记卡片列,用于颜色赋值
    formlist.forEach(item => {
      if (item.key === 'bgfield') {
        _columns = item.options
      }
    })
    if (_type === 'line' || _type === 'bar' || _type === 'line') {
      _legends = syslegends[_type]
@@ -161,15 +182,14 @@
      if (card.subelement) {
        _selectlegend = _legends.filter(item => JSON.stringify(item.subelement) === JSON.stringify(card.subelement))[0]
      }
      if (!_selectlegend) {
      } else {
        _selectlegend = _legends[0]
      }
    }
    this.setState({
      legends: _legends,
      columns: _columns,
      selectlegend: _selectlegend,
      formlist: formlist.map(item => {
        if (item.key === 'height' && ['table', 'card'].includes(_type)) {
@@ -179,6 +199,10 @@
        } else if (item.key === 'cardWidth' && _type === 'card') {
          item.hidden = false
        } else if (item.key === 'over' && _type === 'card') {
          item.hidden = false
        } else if (item.key === 'border' && _type === 'card') {
          item.hidden = false
        } else if (item.key === 'switch' && _type === 'card') {
          item.hidden = false
        } else if (item.key === 'bgfield') {
          item.hidden = _type !== 'card'
@@ -228,6 +252,10 @@
            item.hidden = false
          } else if (item.key === 'over' && value === 'card') {
            item.hidden = false
          } else if (item.key === 'border' && value === 'card') {
            item.hidden = false
          } else if (item.key === 'switch' && value === 'card') {
            item.hidden = false
          } else if (item.key === 'bgfield') {
            item.hidden = value !== 'card'
          }
@@ -246,6 +274,32 @@
          if (item.key === 'cardWidth') {
            item.min = val === 'absolute' ? 50 : 1
            item.max = val === 'absolute' ? 1000 : 24
          }
          return item
        })
      })
    } else if (key === 'over' && val === 'roll') {
      this.setState({
        formlist: formlist.map(item => {
          if (item.key === 'cardWidth') {
            item.min = 50
            item.max = 1000
          } else if (item.key === 'widthType') {
            item.readonly = true
          }
          return item
        })
      })
      if (this.props.form.getFieldValue('widthType') !== undefined) {
        this.props.form.setFieldsValue({widthType: 'absolute'})
      }
    } else if (key === 'over' && val === 'whole') {
      this.setState({
        formlist: formlist.map(item => {
          if (item.key === 'widthType') {
            item.readonly = false
          }
          return item
@@ -355,7 +409,7 @@
                  }
                ]
              })(
                <Radio.Group onChange={(e) => this.radioChange(e.target.value, item.key)}>
                <Radio.Group onChange={(e) => this.radioChange(e.target.value, item.key)} disabled={item.readonly}>
                  {
                    item.options.map(option => {
                      return (
@@ -394,7 +448,7 @@
  }
  handleConfirm = () => {
    const { selectlegend } = this.state
    const { selectlegend, columns } = this.state
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
@@ -424,7 +478,9 @@
              result.Yaxis = result.Yaxis[0] || ''
            }
          } else if (result.chartType === 'card') {
            result.subelement = selectlegend.subelement
            if (selectlegend) {
              result.subelement = selectlegend.subelement
            }
            if (!result.details) {
              result.details = [
@@ -440,6 +496,7 @@
                elemType: 'header',
                content: 'Card title',
                datatype: 'static',
                show: 'icon',
                actions: []
              }
              result.avatar = {
@@ -452,6 +509,12 @@
                width: 32
              }
            }
            if (result.bgfield) {
              result.background = columns.filter(col => col.value === result.bgfield)[0].background
            } else {
              result.background = ''
            }
          }
          result.icon = icons[result.chartType]
src/templates/sharecomponent/chartgroupcomponent/chartform/index.scss
@@ -11,11 +11,15 @@
    left: -3px;
  }
  .chart-model-image {
    .ant-col-6 {
      min-height: 110px;
    }
    img {
      max-width: 100%;
      cursor: pointer;
      border: 1px solid #ebedf0;
      transition: all .3s;
      margin-bottom: 15px;
    }
    img.active {
      background-color: rgba(135,59,244,.1);
src/templates/sharecomponent/chartgroupcomponent/index.jsx
@@ -93,15 +93,42 @@
      }
    }
    let _columns = config.columns.filter(col => ['text', 'number'].includes(col.type) && col.marks && col.marks.filter(_mark => _mark.signType === 'card').length > 0)
    _columns = _columns.map(col => {
      return {
    let _columns = [{
      uuid: 'x',
      value: '',
      text: '空',
      background: ''
    }]
    config.columns.forEach(col => {
      if (!['text', 'number'].includes(col.type)) return
      if (!col.marks) return
      let _marks = col.marks.filter(_mark => _mark.signType === 'card')
      if (_marks.length === 0) return
      _columns.push({
        uuid: col.uuid,
        value: col.field,
        text: col.label
      }
        text: col.label,
        background: _marks[0].color ? _marks[0].color[1] : ''
      })
    })
    if (item.chartType === 'card') { // 检验已添加背景是否修改
      if (item.bgfield) {
        let _column = _columns.filter(col => col.value === item.bgfield)[0]
        if (_column) {
          item.background = _column.background
        } else {
          item.bgfield = ''
          item.background = ''
        }
      } else {
        item.background = ''
      }
    }
    this.setState({
      card: item,
      modaltype: _type,
src/templates/sharecomponent/columncomponent/markcolumn/markform/index.jsx
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types'
import { Form, Row, Col, Select, Button, Input, InputNumber, Radio, Icon, Cascader, Tooltip } from 'antd'
import { minkeColorSystem } from '@/utils/option.js'
import { minkeColorSystem, minkeIconSystem } from '@/utils/option.js'
import './index.scss'
class UniqueForm extends Component {
@@ -19,7 +19,8 @@
    originField: this.props.card,
    signType: 'background',
    selectIcon: '',
    options: minkeColorSystem
    options: minkeColorSystem,
    icons: minkeIconSystem.direction
  }
  UNSAFE_componentWillMount() {
@@ -57,6 +58,9 @@
    })
  }
  /**
   * @description 字段切换
   */
  fieldChange = (value) => {
    const { columns } = this.props
    let item = columns.filter(col => col.field === value)[0]
@@ -72,12 +76,18 @@
    }
  }
  /**
   * @description 对比值类型切换
   */
  changeType = (val) => {
    this.setState({
      contrastType: val
    })
  }
  /**
   * @description 标记类型切换
   */
  changeSignType = (val) => {
    let _type = 'background '
    if (val === 'icon' || val === 'font') {
@@ -103,6 +113,20 @@
    this.setState(newState)
  }
  /**
   * @description 图标类型切换
   */
  changeIconType = (val) => {
    this.setState({
      icons: minkeIconSystem[val],
      selectIcon: ''
    })
    this.props.form.setFieldsValue({icon: ''})
  }
  /**
   * @description 切换图标
   */
  changeIcon = (val) => {
    this.setState({
      selectIcon: val,
@@ -141,7 +165,7 @@
  render() {
    const { columns } = this.props
    const { originField, contrastType, signType, options, selectIcon } = this.state
    const { originField, contrastType, signType, options, selectIcon, icons } = this.state
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
@@ -288,6 +312,22 @@
            </Form.Item>
          </Col> : null}
          {signType === 'icon' ? <Col span={6}>
            <Form.Item label={'图标类型'}>
              {getFieldDecorator('iconType', {
                initialValue: 'direction'
              })(
                <Select onChange={this.changeIconType}>
                  <Select.Option value="direction">方向性图标</Select.Option>
                  <Select.Option value="hint">提示建议性图标</Select.Option>
                  <Select.Option value="edit">编辑类图标</Select.Option>
                  <Select.Option value="data">数据类图标</Select.Option>
                  <Select.Option value="trademark">品牌和标识</Select.Option>
                  <Select.Option value="normal">网站通用图标</Select.Option>
                </Select>
              )}
            </Form.Item>
          </Col> : null}
          {signType === 'icon' ? <Col span={6}>
            <Form.Item label={'图标'}>
              {getFieldDecorator('icon', {
                initialValue: '',
@@ -299,7 +339,8 @@
                ]
              })(
                <Select onChange={this.changeIcon} getPopupContainer={() => document.getElementById('model-mark-form-box')}>
                  <Select.Option value="arrow-up"><Icon type="arrow-up" /></Select.Option>
                  {icons.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)}
                  {/* <Select.Option value="arrow-up"><Icon type="arrow-up" /></Select.Option>
                  <Select.Option value="arrow-down"><Icon type="arrow-down" /></Select.Option>
                  <Select.Option value="arrow-left"><Icon type="arrow-left" /></Select.Option>
                  <Select.Option value="arrow-right"><Icon type="arrow-right" /></Select.Option>
@@ -317,7 +358,7 @@
                  <Select.Option value="question"><Icon type="question" /></Select.Option>
                  <Select.Option value="fall"><Icon type="fall" /></Select.Option>
                  <Select.Option value="rise"><Icon type="rise" /></Select.Option>
                  <Select.Option value="link"><Icon type="link" /></Select.Option>
                  <Select.Option value="link"><Icon type="link" /></Select.Option> */}
                  {/* <Select.Option value="link"></Select.Option> */}
                </Select>
              )}
@@ -343,7 +384,7 @@
              )}
            </Form.Item>
          </Col> : null}
          <Col span={signType === 'icon' ? 24 : 12} style={{textAlign: 'right', marginBottom: 10}}>
          <Col span={signType === 'icon' ? (!selectIcon ? 24 : 18) : 12} style={{textAlign: 'right', marginBottom: 10}}>
            <Button onClick={this.handleConfirm} type="primary" className="mk-green">
              保存
            </Button>
src/templates/subtableconfig/index.jsx
@@ -779,7 +779,7 @@
   */
  setSubConfig = (btn) => {
    const {menu, editTab, tabConfig, editSubTab, btnTab, btnTabConfig} = this.props
    const { config, originConfig, activeKey } = this.state
    const { config, originConfig, activeKey, openEdition } = this.state
    if (originConfig.isAdd) {
      notification.warning({
@@ -815,8 +815,10 @@
          if (editSubTab) {
            editSubTab.activeKey = activeKey
            editSubTab.open_edition = openEdition  // 更新版本号
          } else {
            editTab.activeKey = activeKey
            editTab.open_edition = openEdition     // 更新版本号
          }
          let param = {
src/templates/zshare/formconfig.jsx
@@ -1267,17 +1267,6 @@
      required: true
    },
    {
      type: 'number',
      key: 'width',
      min: 1,
      max: 24,
      decimal: 0,
      label: '宽度',
      tooltip: '每行等分为24列,24即为100%。',
      initVal: card.width || 24,
      required: true
    },
    {
      type: 'radio',
      key: 'Hide',
      label: Formdict['header.form.Hide'],
@@ -1292,12 +1281,39 @@
      }]
    },
    {
      type: 'number',
      key: 'width',
      min: 1,
      max: 24,
      decimal: 0,
      label: '图表宽度',
      tooltip: '每行等分为24列,24即为100%。',
      initVal: card.width || 24,
      required: true
    },
    {
      type: 'radio',
      key: 'widthType',
      label: '宽度类型',
      initVal: card.widthType || 'ratio',
      key: 'over',
      label: '超出时',
      initVal: card.over || 'whole',
      required: true,
      hidden: true,
      options: [{
        value: 'whole',
        text: '展示全部'
      }, {
        value: 'roll',
        text: '滚动'
      }]
    },
    {
      type: 'radio',
      key: 'widthType',
      label: '宽度设置',
      initVal: card.over === 'roll' ? 'absolute' : card.widthType || 'ratio',
      required: true,
      hidden: true,
      readonly: card.over === 'roll',
      options: [{
        value: 'ratio',
        text: '比例'
@@ -1319,21 +1335,6 @@
      required: true
    },
    {
      type: 'radio',
      key: 'over',
      label: '超出时',
      initVal: card.over || 'roll',
      required: true,
      hidden: true,
      options: [{
        value: 'whole',
        text: '展示全部'
      }, {
        value: 'roll',
        text: '滚动'
      }]
    },
    {
      type: 'select',
      key: 'bgfield',
      label: '背景控制',
@@ -1342,6 +1343,36 @@
      readonly: false,
      hidden: true,
      options: _columns
    },
    {
      type: 'radio',
      key: 'border',
      label: '边框',
      initVal: card.border || 'show',
      required: false,
      hidden: true,
      options: [{
        value: 'show',
        text: '显示'
      }, {
        value: 'hidden',
        text: '隐藏'
      }]
    },
    {
      type: 'radio',
      key: 'switch',
      label: '数据切换',
      initVal: card.switch || 'true',
      required: false,
      hidden: true,
      options: [{
        value: 'true',
        text: '是'
      }, {
        value: 'false',
        text: '否'
      }]
    },
    {
      type: 'multiselect',
@@ -2236,9 +2267,9 @@
      type: 'radio',
      key: 'show',
      label: '显示',
      initVal: card.show || '',
      initVal: card.show || 'icon',
      required: false,
      forbid: !['bottom'].includes(_type),
      forbid: !['bottom', 'header'].includes(_type),
      options: [{
        value: 'icon',
        text: '图标'
src/utils/option.js
@@ -504,4 +504,285 @@
  }
]
export const minkeIconSystem = {
  direction: [
    'step-backward',
    'step-forward',
    'fast-backward',
    'fast-forward',
    'shrink',
    'arrows-alt',
    'down',
    'up',
    'left',
    'right',
    'caret-up',
    'caret-down',
    'caret-left',
    'caret-right',
    'up-circle',
    'down-circle',
    'left-circle',
    'right-circle',
    'double-right',
    'double-left',
    'vertical-left',
    'vertical-right',
    'vertical-align-top',
    'vertical-align-middle',
    'vertical-align-bottom',
    'forward',
    'backward',
    'rollback',
    'enter',
    'retweet',
    'swap',
    'swap-left',
    'swap-right',
    'arrow-up',
    'arrow-down',
    'arrow-left',
    'arrow-right',
    'play-circle',
    'up-square',
    'down-square',
    'left-square',
    'right-square',
    'login',
    'logout',
    'menu-fold',
    'menu-unfold',
    'border-bottom',
    'border-horizontal',
    'border-inner',
    'border-outer',
    'border-left',
    'border-right',
    'border-top',
    'border-verticle',
    'pic-center',
    'pic-left',
    'pic-right',
    'radius-bottomleft',
    'radius-bottomright',
    'radius-upleft',
    'radius-upright',
    'fullscreen',
    'fullscreen-exit'
  ],
  hint: [
    'question',
    'question-circle',
    'plus',
    'plus-circle',
    'pause',
    'pause-circle',
    'minus',
    'minus-circle',
    'plus-square',
    'minus-square',
    'info',
    'info-circle',
    'exclamation',
    'exclamation-circle',
    'close',
    'close-circle',
    'close-square',
    'check',
    'check-circle',
    'check-square',
    'clock-circle',
    'warning',
    'issues-close',
    'stop'
  ],
  edit: [
    'edit',
    'form',
    'copy',
    'scissor',
    'delete',
    'snippets',
    'diff',
    'highlight',
    'align-center',
    'align-left',
    'align-right',
    'bg-colors',
    'bold',
    'italic',
    'underline',
    'strikethrough',
    'redo',
    'undo',
    'zoom-in',
    'zoom-out',
    'font-colors',
    'font-size',
    'line-height',
    'dash',
    'small-dash',
    'sort-ascending',
    'sort-descending',
    'drag',
    'ordered-list',
    'unordered-list',
    'radius-setting',
    'column-width',
    'column-height'
  ],
  data: [
    'area-chart',
    'pie-chart',
    'bar-chart',
    'dot-chart',
    'line-chart',
    'radar-chart',
    'heat-map',
    'fall',
    'rise',
    'stock',
    'box-plot',
    'fund',
    'sliders'
  ],
  trademark: [
    'android',
    'apple',
    'windows',
    'ie',
    'chrome',
    'github',
    'aliwangwang',
    'dingding',
    'weibo-square',
    'weibo-circle',
    'taobao-circle',
    'html5',
    'weibo',
    'twitter',
    'wechat',
    'youtube',
    'alipay-circle',
    'taobao',
    'skype',
    'qq',
    'medium-workmark',
    'gitlab',
    'medium',
    'linkedin',
    'google-plus',
    'dropbox',
    'facebook',
    'codepen',
    'code-sandbox',
    'amazon',
    'google',
    'codepen-circle',
    'alipay',
    'ant-design',
    'ant-cloud',
    'aliyun',
    'zhihu',
    'slack',
    'slack-square',
    'behance',
    'behance-square',
    'dribbble',
    'dribbble-square',
    'instagram',
    'yuque',
    'alibaba',
    'yahoo',
    'reddit',
    'sketch'
  ],
  normal: [
    'account-book',
    'alert',
    'api',
    'appstore',
    'audio',
    'bank',
    'bell',
    'book',
    'bug',
    'bulb',
    'calculator',
    'build',
    'calendar',
    'camera',
    'car',
    'carry-out',
    'cloud',
    'code',
    'compass',
    'contacts',
    'container',
    'control',
    'credit-card',
    'crown',
    'customer-service',
    'dashboard',
    'database',
    'dislike',
    'environment',
    'experiment',
    'eye-invisible',
    'eye',
    'file-add',
    'file-excel',
    'file-exclamation',
    'file-image',
    'file-markdown',
    'file-pdf',
    'file-ppt',
    'file-text',
    'file-unknown',
    'file-word',
    'file-zip',
    'file',
    'filter',
    'fire',
    'flag',
    'folder-add',
    'folder',
    'folder-open',
    'frown',
    'funnel-plot',
    'gift',
    'hdd',
    'heart',
    'home',
    'hourglass',
    'idcard',
    'insurance',
    'interaction',
    'layout',
    'like',
    'lock',
    'mail',
    'medicine-box',
    'meh',
    'message',
    'mobile',
    'phone',
    'picture',
    'red-envelope',
    'smile',
    'star',
    'thunderbolt',
    'trophy',
    'unlock',
    'barcode',
    'key',
    'man',
    'woman',
    'poweroff',
    'search',
    'shopping-cart',
    'link'
  ]
}
export const queryTableSql = 'select TbName,Remark from (select TbName,Remark from sDataDictb where appkey= @appkey@ and Deleted=0 union select a.TbName,Remark from (select TbName,Remark from sDataDictb where appkey= \'\' and Deleted=0 ) a left join (select TbName from sDataDictb where appkey= @appkey@ and Deleted=0 ) b on a.TbName=b.TbName where b.TbName is null ) t'