king
2020-05-03 6def3330d1d1cf4036916ed04c8bbc4128e1e5d0
2020-05-03
19个文件已修改
6个文件已添加
2834 ■■■■ 已修改文件
src/store/reducer.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/commontable/index.jsx 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/managetable/index.jsx 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtable/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/subtabtable/index.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.jsx 391 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/comtableconfig/index.scss 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.jsx 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/index.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/index.jsx 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/index.scss 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/customscript/index.scss 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.jsx 851 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/settingcomponent/settingform/index.scss 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tablecomponent/index.jsx 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/index.jsx 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/subtableconfig/index.scss 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/createinterface/index.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/reducer.js
@@ -15,7 +15,8 @@
  permAction: {},       // 用户按钮权限
  permMenus: {},        // 用户三级菜单权限
  permFuncField: [],    // 系统模块
  sysRoles: []          // 系统角色列表
  sysRoles: [],         // 系统角色列表
  dataManager: false    // 数据管理员
}
// 用户消息
src/tabviews/commontable/index.jsx
@@ -636,18 +636,11 @@
    }
    if (setting.queryType === 'statistics') { // 统计数据源,内容替换
      let fieldmap = new Map()
      let options = search.map(item => {
        let _field = item.key
      let allSearch = Utils.getAllSearchOptions(search)
        if (fieldmap.has(_field)) {
          _field = _field + '1'
        }
        fieldmap.set(item.key, true)
      let options = allSearch.map(item => {
        return {
          reg: new RegExp('@' + _field + '@', 'ig'),
          reg: new RegExp('@' + item.key + '@', 'ig'),
          value: item.value
        }
      })
src/tabviews/managetable/index.jsx
@@ -404,18 +404,10 @@
    }
    if (setting.queryType === 'statistics') { // 统计数据源,内容替换
      let fieldmap = new Map()
      let options = search.map(item => {
        let _field = item.key
        if (fieldmap.has(_field)) {
          _field = _field + '1'
        }
        fieldmap.set(item.key, true)
      let allSearch = Utils.getAllSearchOptions(search)
      let options = allSearch.map(item => {
        return {
          reg: new RegExp('@' + _field + '@', 'ig'),
          reg: new RegExp('@' + item.key + '@', 'ig'),
          value: item.value
        }
      })
src/tabviews/subtable/index.jsx
@@ -554,23 +554,14 @@
    }
    if (setting.queryType === 'statistics') { // 统计数据源,内容替换
      let fieldmap = new Map()
      let options = search.map(item => {
        let _field = item.key
      let allSearch = Utils.getAllSearchOptions(search)
        if (fieldmap.has(_field)) {
          _field = _field + '1'
        }
        fieldmap.set(item.key, true)
      let options = allSearch.map(item => {
        return {
          reg: new RegExp('@' + _field + '@', 'ig'),
          reg: new RegExp('@' + item.key + '@', 'ig'),
          value: item.value
        }
      })
      // options.reverse()
      options.forEach(item => {
        _dataresource = _dataresource.replace(item.reg, `'${item.value}'`)
src/tabviews/subtabtable/index.jsx
@@ -430,23 +430,14 @@
    }
    if (setting.queryType === 'statistics') { // 统计数据源,内容替换
      let fieldmap = new Map()
      let options = search.map(item => {
        let _field = item.key
      let allSearch = Utils.getAllSearchOptions(search)
        if (fieldmap.has(_field)) {
          _field = _field + '1'
        }
        fieldmap.set(item.key, true)
      let options = allSearch.map(item => {
        return {
          reg: new RegExp('@' + _field + '@', 'ig'),
          reg: new RegExp('@' + item.key + '@', 'ig'),
          value: item.value
        }
      })
      // options.reverse()
      options.forEach(item => {
        _dataresource = _dataresource.replace(item.reg, `'${item.value}'`)
src/templates/comtableconfig/index.jsx
@@ -11,7 +11,9 @@
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import { getMainMenuForm } from '@/templates/zshare/formconfig'
import asyncComponent from '@/utils/asyncComponent'
import TableComponent from '@/templates/sharecomponent/tablecomponent'
import FieldsComponent from '@/templates/sharecomponent/fieldscomponent'
// import ChartGroupComponent from '@/templates/sharecomponent/chartgroupcomponent'
@@ -19,20 +21,21 @@
import ActionComponent from '@/templates/sharecomponent/actioncomponent'
import ColumnComponent from '@/templates/sharecomponent/columncomponent'
import SettingForm from './settingform'
// import SettingForm from './settingform'
import TabForm from '@/templates/zshare/tabform'
import MenuForm from '@/templates/zshare/menuform'
import TabDragElement from '@/templates/zshare/tabdragelement'
import EditComponent from '@/templates/zshare/editcomponent'
import SourceElement from '@/templates/zshare/dragsource'
import CreateFunc from '@/templates/zshare/createfunc'
import CreateInterface from '@/templates/zshare/createinterface'
// import CreateFunc from '@/templates/zshare/createfunc'
// import CreateInterface from '@/templates/zshare/createinterface'
import Source from './source'
import './index.scss'
const { Panel } = Collapse
const { confirm } = Modal
const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS
const SettingComponent = asyncComponent(() => import('@/templates/sharecomponent/settingcomponent'))
class ComTableConfig extends Component {
  static propTpyes = {
@@ -54,10 +57,8 @@
    menuloading: false,      // 菜单保存中
    menucloseloading: false, // 菜单关闭时,选择保存
    loading: false,          // 加载中,页面spin
    settingVisible: false,   // 全局配置模态框
    closeVisible: false,     // 关闭模态框
    tables: [],              // 可用表名
    selectedTables: [],      // 已选表名
    originMenu: null,        // 原始菜单
    originActions: null,     // 原始按钮信息,使用已有用户模板
    delActions: [],          // 删除按钮列表
@@ -82,7 +83,7 @@
    let _config = ''
    if (!_LongParam) {
      _config = JSON.parse(JSON.stringify(Source.baseConfig))
      _config = fromJS(Source.baseConfig).toJS()
      if (!menu.isSubtable) { // 不是选择主子表时,隐藏标签页
        _config.tabs = []
      }
@@ -124,13 +125,13 @@
        if (item.OpenType === 'pop') { // 含有子配置项的按钮(表单)
          _oriActions.push({
            prebtn: JSON.parse(JSON.stringify(item)),
            prebtn: fromJS(item).toJS(),
            curuuid: uuid,
            Template: 'Modal'
          })
        } else if (item.OpenType === 'tab' || item.OpenType === 'blank') { // 含有子配置项的按钮(标签后当前页打开)
          _oriActions.push({
            prebtn: JSON.parse(JSON.stringify(item)),
            prebtn: fromJS(item).toJS(),
            curuuid: uuid,
            Template: item.tabTemplate
          })
@@ -159,100 +160,16 @@
      activeKey: menu.activeKey || '0',
      optionLibs: optionLibs,
      originActions: _oriActions,
      originMenu: JSON.parse(JSON.stringify(menu)),
      selectedTables: _config.tables || [],
      menuformlist: [
        {
          type: 'select',
          key: 'fstMenuId',
          label: '一级菜单',
          initVal: menu.fstMenuId,
          required: true,
          readonly: false,
          options: menu.fstMenuList
        },
        {
          type: 'select',
          key: 'parentId',
          label: '二级菜单',
          initVal: menu.ParentID,
          required: true,
          readonly: false,
          options: menu.supMenuList
        },
        {
          type: 'text',
          key: 'menuName',
          label: this.state.dict['header.menu.menuName'],
          initVal: menu.MenuName,
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'menuNo',
          label: this.state.dict['header.menu.menuNo'],
          initVal: menu.MenuNo,
          required: true,
          readonly: false
        },
        {
          type: 'select',
          key: 'opentype',
          label: this.state.dict['header.menu.openType'],
          initVal: menu.PageParam.OpenType,
          required: true,
          options: [{
            MenuID: 'newtab',
            text: this.state.dict['header.form.tab']
          }, {
            MenuID: 'newpage',
            text: this.state.dict['header.form.newpage']
          }, {
            MenuID: 'currenttab',
            text: this.state.dict['header.form.currenttab']
          }]
        },
        {
          type: 'text',
          key: 'easyCode',
          label: this.state.dict['header.form.easyCode'],
          initVal: _config.easyCode,
          required: false,
          readonly: false
        }
      ]
      originMenu: fromJS(menu).toJS(),
      menuformlist: getMainMenuForm(menu, _config)
    })
  }
  /**
   * @description 加载完成后
   * 1、获取系统可使用表
   * 2、根据配置信息中已使用表获取相关字段信息
   * 3、获取所有标签页信息
   * @description 加载完成后, 获取所有标签页信息
   */
  componentDidMount () {
    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
      if (res.status) {
        this.setState({
          tabviews: res.UserTemp.map(temp => {
            return {
              uuid: temp.MenuID,
              value: temp.MenuID,
              text: temp.MenuName,
              type: temp.Template,
              MenuNo: temp.MenuNo
            }
          })
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
    this.reloadTab(false)
  }
  /**
@@ -267,9 +184,9 @@
  /**
   * @description 加载或刷新标签信息
   */
  reloadTab = () => {
  reloadTab = (type) => {
    this.setState({
      loading: true,
      loading: type,
      tabviews: []
    })
    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
@@ -286,11 +203,14 @@
            }
          })
        })
        notification.success({
          top: 92,
          message: '刷新成功。',
          duration: 2
        })
        if (type) {
          notification.success({
            top: 92,
            message: '刷新成功。',
            duration: 2
          })
        }
      } else {
        this.setState({
          loading: false
@@ -506,69 +426,6 @@
    }
  }
  /**
   * @description 创建表格存储过程
   */
  tableCreatFunc = () => {
    const { menu } = this.props
    const { config } = this.state
    this.settingRef.handleConfirm().then(setting => {
      if (!(setting.interType === 'inner') || !setting.innerFunc) {
        notification.warning({
          top: 92,
          message: '接口类型为-内部,且存在内部函数时,才可以创建存储过程!',
          duration: 5
        })
        return
      }
      let _config = {...config, setting: setting}
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, menu, _config)) // 创建存储过程sql
      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 删除存储过程sql
      this.refs.tableCreatFunc.exec(setting.innerFunc, newLText, DelText).then(result => {
        if (result === 'success') {
          this.setState({
            config: _config
          })
        }
      })
    })
  }
  /**
   * @description 创建表格接口(读出)
   */
  tableCreatInterface = () => {
    const { menu } = this.props
    const { config } = this.state
    this.menuformRef.handleConfirm().then(res => {
      this.settingRef.handleConfirm().then(setting => {
        if (setting.interType !== 'inner' || setting.innerFunc) {
          notification.warning({
            top: 92,
            message: '接口类型为-内部,且不存在内部函数时,才可以创建接口!',
            duration: 5
          })
          return
        }
        let _config = {...config, setting: setting}
        let _menu = {
          type: 'main',
          MenuID: menu.MenuID,
          menuName: res.menuName,
          menuNo: res.menuNo
        }
        this.refs.tableCreatInterface.triggerOutInterface(_menu, _config)
      })
    })
  }
  deleteElement = (element) => {
    const { config, thawButtons } = this.state
    let _this = this
@@ -645,7 +502,7 @@
    const { menu } = this.props
    const { originMenu, delActions, thawButtons } = this.state
    let config = JSON.parse(JSON.stringify(this.state.config))
    let config = fromJS(this.state.config).toJS()
    this.menuformRef.handleConfirm().then(res => {
      if (config.isAdd) {
@@ -873,7 +730,7 @@
          func: 'sPC_Button_AddUpt',
          Type: 40,                  // 添加菜单下的按钮type为40,按钮下的按钮type为60
          ParentID: menu.MenuID,
          MenuNo: res.menuNo,
          MenuNo: res.MenuNo,
          Template: menu.PageParam.Template || '',
          PageParam: '',
          LongParam: '',
@@ -931,10 +788,10 @@
          SndID: res.parentId,
          ParentID: res.parentId,
          MenuID: menu.MenuID,
          MenuNo: res.menuNo,
          MenuNo: res.MenuNo,
          EasyCode: res.easyCode,
          Template: menu.PageParam.Template || '',
          MenuName: res.menuName,
          MenuName: res.MenuName,
          PageParam: JSON.stringify(_pageParam),
          LongParam: _LongParam,
          LText: _vals.func.map(item => `select '${menu.MenuID}' as MenuID,'${item.func}' as ProcName,'${item.label}' as MenuName`),
@@ -1054,7 +911,7 @@
          }
        }).then(resp => {
          if (resp === false) return
          let localParam = JSON.parse(JSON.stringify(param))
          let localParam = fromJS(param).toJS()
          Api.getSystemConfig(param).then(response => {
            if (response.status) {
@@ -1070,8 +927,8 @@
                  ...originMenu,
                  LongParam: _config,
                  PageParam: _pageParam,
                  MenuName: res.menuName,
                  MenuNo: res.menuNo,
                  MenuName: res.MenuName,
                  MenuNo: res.MenuNo,
                  ParentID: res.parentId,
                  fstMenuId: res.fstMenuId,
                  supMenuList: _supMenuList
@@ -1306,8 +1163,8 @@
          ...originMenu,
          LongParam: _config,
          PageParam: _pageParam,
          MenuName: res.menuName,
          MenuNo: res.menuNo,
          MenuName: res.MenuName,
          MenuNo: res.MenuNo,
          ParentID: res.parentId,
          fstMenuId: res.fstMenuId
        }
@@ -1328,110 +1185,6 @@
  }
  /**
   * @description 页面配置信息模态框显示
   */
  changeSetting = () => {
    this.setState({
      settingVisible: true
    })
  }
  /**
   * @description 保存页面配置信息
   */
  settingSave = () => {
    const { menu } = this.props
    const {config} = this.state
    this.settingRef.handleConfirm().then(res => {
      if (
        res.interType === 'inner' &&
        !res.innerFunc &&
        /[^\s]+\s+[^\s]+/ig.test(res.dataresource) &&
        config.setting.dataresource !== res.dataresource
      ) {
        let param = {
          func: 's_DataSrc_Save',
          LText: res.dataresource,
          MenuID: menu.MenuID
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        Api.getLocalConfig(param)
      }
      if (res.interType === 'inner' && !res.innerFunc && /\s/.test(res.dataresource)) {
        this.setState({
          sqlVerifing: true
        })
        let _dataresource = res.dataresource
        if (res.queryType === 'statistics') {
          let fieldmap = new Map()
          let options = config.search.map(item => {
            let _field = item.key
            let _val = ''
            if (fieldmap.has(_field)) {
              _field = _field + '1'
            }
            fieldmap.set(item.key, true)
            if (/date/.test(item.type)) {
              _val = '1900-01-01'
            }
            return {
              reg: new RegExp('@' + _field + '@', 'ig'),
              value: _val
            }
          })
          options.forEach(item => {
            _dataresource = _dataresource.replace(item.reg, `'${item.value}'`)
          })
        }
        let param = {
          func: 's_debug_sql',
          LText: _dataresource
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        Api.getLocalConfig(param).then(result => {
          if (result.status) {
            this.setState({
              sqlVerifing: false,
              config: {...config, setting: res},
              settingVisible: false
            })
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        })
      } else {
        this.setState({
          config: {...config, setting: res},
          settingVisible: false
        })
      }
    })
  }
  /**
   * @description 设置可配置按钮
   */
  setSubConfig = (item, type) => {
@@ -1446,14 +1199,14 @@
      })
    } else {
      this.menuformRef.handleConfirm().then(res => {
        let _config = {...config, tables: this.state.selectedTables, easyCode: res.easyCode}
        let _config = {...config, easyCode: res.easyCode}
        let _pageParam = {...menu.PageParam, OpenType: res.opentype}
        let _originMenu = {
          ...originMenu,
          LongParam: _config,
          PageParam: _pageParam,
          MenuName: res.menuName,
          MenuNo: res.menuNo,
          MenuName: res.MenuName,
          MenuNo: res.MenuNo,
          ParentID: res.parentId,
          fstMenuId: res.fstMenuId
        }
@@ -1602,7 +1355,7 @@
   */
  addTabGroup = () => {
    let _this = this
    let _config = JSON.parse(JSON.stringify(this.state.config))
    let _config = fromJS(this.state.config).toJS()
    confirm({
      content: `确定新建标签组吗?`,
@@ -1627,7 +1380,7 @@
   */
  delTabGroup = (groupId) => {
    let _this = this
    let _config = JSON.parse(JSON.stringify(this.state.config))
    let _config = fromJS(this.state.config).toJS()
    confirm({
      content: `确定删除标签组吗?`,
@@ -1647,7 +1400,7 @@
  }
  handleGroup = (index, type) => {
    let config = JSON.parse(JSON.stringify(this.state.config))
    let config = fromJS(this.state.config).toJS()
    
    if (type === 'up') {
      config.tabgroups.splice(index, 0, config.tabgroups.splice(index - 1, 1)[0])
@@ -1683,7 +1436,7 @@
  /**
   * @description 编辑功能完成更新,包括解冻按钮、粘贴、替换等
   */
  updateConfig = (res) => {
  editConfig = (res) => {
    if (res.type === 'thaw') {
      this.setState({
        thawButtons: res.thawButtons,
@@ -1726,15 +1479,6 @@
  }
  /**
   * @description 更新显示列配置信息
   */
  updatecolumn = (config) => {
    this.setState({
      config: config
    })
  }
  /**
   * @description 更新图表组配置信息
   */
  updatechartgroup = (config, _chartview) => {
@@ -1757,9 +1501,9 @@
  }
  /**
   * @description 批量添加,更新配置信息
   * @description 更新配置信息
   */
  updatefield = (config) => {
  updateconfig = (config) => {
    this.setState({
      config: config
    })
@@ -1777,7 +1521,6 @@
    return (
      <div className="common-table-board">
        {/* <div className="ant-modal-mask"></div> */}
        <DndProvider backend={HTML5Backend}>
          {/* 工具栏 */}
          <div className="tools">
@@ -1809,7 +1552,7 @@
                  config={config}
                  type="search"
                  tableFields={this.state.tableFields}
                  updatefield={this.updatefield}
                  updatefield={this.updateconfig}
                />
              </Panel>
              {/* 按钮添加 */}
@@ -1853,7 +1596,7 @@
                  config={config}
                  type="columns"
                  tableFields={this.state.tableFields}
                  updatefield={this.updatefield}
                  updatefield={this.updateconfig}
                />
              </Panel>
              {/* 添加标签 */}
@@ -1890,18 +1633,25 @@
            <Card title={
              <div>
                {this.state.dict['header.menu.page.configurable']} 
                <Icon type="redo" style={{marginLeft: '10px'}} title="刷新标签列表" onClick={this.reloadTab} />
                <Icon type="redo" style={{marginLeft: '10px'}} title="刷新标签列表" onClick={() => this.reloadTab(true)} />
              </div>
            } bordered={false} extra={
              <div>
                <EditComponent dict={this.state.dict} type="maintable" config={this.state.config} MenuID={this.props.menu.MenuID} thawButtons={this.state.thawButtons} refresh={this.updateConfig}/>
                <EditComponent dict={this.state.dict} type="maintable" config={this.state.config} MenuID={this.props.menu.MenuID} thawButtons={this.state.thawButtons} refresh={this.editConfig}/>
                <Switch className="big" checkedChildren="启" unCheckedChildren="停" checked={this.state.config.enabled} onChange={this.onEnabledChange} />
                <Button type="primary" onClick={this.changeTemplate}>{this.state.dict['header.menu.template.change']}</Button>
                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['header.save']}</Button>
                <Button onClick={this.cancelConfig}>{this.state.dict['header.return']}</Button>
              </div>
            } style={{ width: '100%' }}>
              <Icon type="setting" onClick={this.changeSetting} />
              <SettingComponent
                type="main"
                config={config}
                MenuID={this.props.menu.MenuID}
                menuformRef={this.menuformRef}
                permFuncField={this.props.permFuncField}
                updatesetting={this.updateconfig}
              />
              <SearchComponent
                menu={{MenuID: this.props.menu.MenuID, MenuName: this.props.menu.MenuName}}
                config={config}
@@ -1912,9 +1662,10 @@
              />
              <ActionComponent
                type="main"
                menu={{MenuID: this.props.menu.MenuID, MenuName: this.props.menu.MenuName, MenuNo: this.props.menu.MenuNo}}
                menu={{ MenuID: this.props.menu.MenuID, MenuName: this.props.menu.MenuName, MenuNo: this.props.menu.MenuNo }}
                config={config}
                tabs={this.state.tabviews}
                menuformRef={this.menuformRef}
                pasteContent={this.state.pasteContent}
                usefulFields={this.props.permFuncField}
                setSubConfig={(_btn) => this.setSubConfig(_btn, 'button')}
@@ -1926,7 +1677,7 @@
                menu={this.props.menu}
                sysRoles={this.props.sysRoles}
                pasteContent={this.state.pasteContent}
                updatecolumn={this.updatecolumn}
                updatecolumn={this.updateconfig}
              />
              {/* 标签组 */}
              {config.tabgroups.map((groupId, index) => {
@@ -1976,35 +1727,7 @@
            wrappedComponentRef={(inst) => this.tabsFormRef = inst}
          />
        </Modal>
        {/* 设置全局配置及列表数据源 */}
        <Modal
          title={this.state.dict['model.edit']}
          visible={this.state.settingVisible}
          width={750}
          maskClosable={false}
          onCancel={() => { // 取消修改
            this.setState({
              settingVisible: false
            })
          }}
          footer={[
            <CreateInterface key="interface" dict={this.state.dict} ref="tableCreatInterface" trigger={this.tableCreatInterface}/>,
            <CreateFunc key="create" dict={this.state.dict} ref="tableCreatFunc" trigger={this.tableCreatFunc}/>,
            <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>,
            <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['model.confirm']}</Button>
          ]}
          destroyOnClose
        >
          <SettingForm
            dict={this.state.dict}
            menu={this.props.menu}
            inputSubmit={this.settingSave}
            data={config.setting}
            columns={config.columns}
            usefulFields={this.props.permFuncField}
            wrappedComponentRef={(inst) => this.settingRef = inst}
          />
        </Modal>
        {/* 返回时未保存提示 */}
        <Modal
          bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
          closable={false}
src/templates/comtableconfig/index.scss
@@ -218,6 +218,7 @@
          }
        }
        > .anticon-question-circle {
          color: #c49f47;
          position: absolute;
          left: 5px;
          top: 20px;
@@ -265,21 +266,21 @@
          margin-right: 50px;
        }
      }
      > .anticon-setting {
        position: absolute;
        font-size: 18px;
        right: 7px;
        top: 10px;
        padding: 10px;
        z-index: 1;
      }
      // > .anticon-setting {
      //   position: absolute;
      //   font-size: 18px;
      //   right: 7px;
      //   top: 10px;
      //   padding: 10px;
      //   z-index: 1;
      // }
    }
    .anticon-question-circle {
      color: #c49f47;
      position: relative;
      left: -15px;
      top: 5px;
    }
    // .anticon-question-circle {
    //   color: #c49f47;
    //   position: relative;
    //   left: -15px;
    //   top: 5px;
    // }
  }
  .setting {
    overflow-y: scroll;
src/templates/sharecomponent/actioncomponent/index.jsx
@@ -28,6 +28,7 @@
    type: PropTypes.string,          // 菜单类型,主表或子表
    menu: PropTypes.object,          // 菜单信息(菜单id,菜单参数,菜单名称)
    config: PropTypes.object,        // 菜单配置信息
    menuformRef: PropTypes.any,      // 菜单基本信息表单对象
    pasteContent: PropTypes.object,  // 粘贴配置信息
    usefulFields: PropTypes.array,   // 自定义函数可用字段
    tabs: PropTypes.array,           // 所有标签
@@ -130,9 +131,14 @@
   * 4、下拉菜单数据源语法验证
   */
  handleSubmit = () => {
    const { config, menu } = this.props
    const { config, menuformRef } = this.props
    const { card } = this.state
    let _actionlist = fromJS(this.state.actionlist).toJS()
    let menu = fromJS(this.props.menu).toJS() // 菜单信息,存在表单对象时,从菜单中更新
    if (menuformRef) {
      menu = {...menu, MenuName: menuformRef.props.form.getFieldValue('MenuName'), MenuNo: menuformRef.props.form.getFieldValue('MenuNo')}
    }
    this.actionFormRef.handleConfirm().then(btn => {
      _actionlist = _actionlist.filter(item => !item.origin || item.uuid === btn.uuid)
@@ -620,8 +626,13 @@
   * @description 创建按钮存储过程
   */
  creatFunc = () => {
    const { menu, config } = this.props
    const { config, menuformRef } = this.props
    let _config = fromJS(this.props.config).toJS()
    let menu = fromJS(this.props.menu).toJS() // 菜单信息,存在表单对象时,从菜单中更新
    if (menuformRef) {
      menu = {...menu, MenuName: menuformRef.props.form.getFieldValue('MenuName'), MenuNo: menuformRef.props.form.getFieldValue('MenuNo')}
    }
    this.actionFormRef.handleConfirm().then(res => {
      let btn = res         // 按钮信息
@@ -787,7 +798,12 @@
   * @description 创建按钮接口(写入)
   */
  btnCreatInterface = () => {
    const { config, menu, type } = this.props
    const { config, type, menuformRef } = this.props
    let menu = fromJS(this.props.menu).toJS() // 菜单信息,存在表单对象时,从菜单中更新
    if (menuformRef) {
      menu = {...menu, MenuName: menuformRef.props.form.getFieldValue('MenuName'), MenuNo: menuformRef.props.form.getFieldValue('MenuNo')}
    }
    this.actionFormRef.handleConfirm().then(result => {
      
src/templates/sharecomponent/actioncomponent/index.scss
@@ -2,10 +2,14 @@
  position: relative;
  padding: 0px 25px 15px;
  min-height: 82px;
  .anticon-question-circle {
    color: #c49f47;
    position: absolute;
    left: 5px;
    top: 5px;
  }
  > .ant-row {
    min-height: 80px;
  }
src/templates/sharecomponent/chartgroupcomponent/index.jsx
@@ -162,7 +162,7 @@
      cancelText: dict['header.cancel'],
      onOk() {
        let _chartlist = fromJS(_this.state.chartlist).toJS()
        let _chartview = this.state.chartview
        let _chartview = _this.state.chartview
        _chartlist = _chartlist.filter(item => item.uuid !== plot.uuid)
src/templates/sharecomponent/columncomponent/index.scss
@@ -1,6 +1,13 @@
.model-table-column-list {
  position: relative;
  padding: 0px 20px 100px;
  .anticon-question-circle {
    color: #c49f47;
    position: relative;
    left: -15px;
    top: 5px;
  }
  .ant-switch {
    position: absolute;
    right: 20px;
src/templates/sharecomponent/searchcomponent/index.scss
@@ -2,6 +2,13 @@
  padding: 1px 24px 20px;
  min-height: 87px;
  border-bottom: 1px solid #d9d9d9;
  .anticon-question-circle {
    color: #c49f47;
    position: relative;
    left: -15px;
    top: 5px;
  }
  > .ant-row {
    min-height: 65px;
  }
src/templates/sharecomponent/settingcomponent/index.jsx
New file
@@ -0,0 +1,197 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Icon, Modal, Button, notification } from 'antd'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import { getSettingForm } from '@/templates/zshare/formconfig'
import SettingForm from './settingform'
import CreateFunc from '@/templates/zshare/createfunc'
import CreateInterface from '@/templates/zshare/createinterface'
import './index.scss'
// const { Option } = Select
// **悲观者往往正确,乐观者往往成功
class TablesComponent extends Component {
  static propTpyes = {
    type: PropTypes.string,          // 菜单类型
    MenuID: PropTypes.string,        // 菜单ID
    config: PropTypes.object,        // 菜单配置信息
    permFuncField: PropTypes.array,  // 存储过程可用开头字段
    menuformRef: PropTypes.any,      // 菜单基本信息表单
    updatesetting: PropTypes.func
  }
  state = {
    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
    menu: null,          // 菜单信息
    formlist: null,      // 表单信息
    visible: false,      // 模态框控制
    loading: false       // 设置信息验证保存中
  }
  /**
   * @description 全局设置触发
   */
  changeSetting = () => {
    const { menuformRef, MenuID, config, type, permFuncField } = this.props
    let menu = {MenuID: MenuID}
    if (menuformRef) {
      menu = {MenuID: MenuID, MenuName: menuformRef.props.form.getFieldValue('MenuName') || '', MenuNo: menuformRef.props.form.getFieldValue('MenuNo') || ''}
    }
    let _columns = fromJS(config.columns).toJS()
    let primaryKey = config.setting.primaryKey || ''
    if (!primaryKey || _columns.filter(column => column.field === primaryKey).length === 0) {
      _columns.forEach(col => {
        if (col.field.toLowerCase() === 'id') {
          primaryKey = col.field
        }
      })
    }
    _columns = _columns.filter(item => item.field && item.type !== 'colspan')
    _columns = _columns.map(item => {
      return {
        value: item.field,
        text: item.label
      }
    })
    _columns.unshift({value: '', text: '未设置'})
    this.setState({
      visible: true,
      formlist: getSettingForm(config.setting, permFuncField, MenuID, primaryKey, _columns, type),
      menu: menu
    })
  }
  /**
   * @description 保存页面配置信息
   */
  settingSave = () => {
    const { config } = this.props
    this.setState({
      loading: true
    })
    this.settingRef.handleConfirm().then(res => {
      this.setState({
        visible: false,
        loading: false
      })
      this.props.updatesetting({...config, setting: res})
    }, () => {
      this.setState({
        loading: false
      })
    })
  }
  /**
   * @description 创建表格存储过程
   */
  tableCreatFunc = () => {
    const { config } = this.props
    const { menu } = this.state
    this.settingRef.handleConfirm().then(setting => {
      if (!(setting.interType === 'inner') || !setting.innerFunc) {
        notification.warning({
          top: 92,
          message: '接口类型为-内部,且存在内部函数时,才可以创建存储过程!',
          duration: 5
        })
        return
      }
      let _config = {...config, setting: setting}
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, menu, _config)) // 创建存储过程sql
      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 删除存储过程sql
      this.refs.funcCreatComponent.exec(setting.innerFunc, newLText, DelText).then(result => {
        if (result === 'success') {
          this.props.updatesetting(_config)
        }
      })
    })
  }
  /**
   * @description 创建表格接口(读出)
   */
  tableCreatInterface = () => {
    const { config, type } = this.props
    const { menu } = this.state
    this.settingRef.handleConfirm().then(setting => {
      if (setting.interType !== 'inner' || setting.innerFunc) {
        notification.warning({
          top: 92,
          message: '接口类型为-内部,且不存在内部函数时,才可以创建接口!',
          duration: 5
        })
        return
      }
      let _config = {...config, setting: setting}
      let _menu = {
        type: type,
        MenuID: menu.MenuID,
        menuName: menu.MenuName,
        menuNo: menu.MenuNo
      }
      this.refs.tableCreatInterface.triggerOutInterface(_menu, _config)
    })
  }
  render() {
    const { config, type } = this.props
    const { dict, visible } = this.state
    return (
      <div className="model-menu-setting">
        <Icon type="setting" onClick={this.changeSetting} />
        {/* 设置全局配置及列表数据源 */}
        <Modal
          wrapClassName="model-table-setting-verify-modal"
          title={dict['model.edit']}
          visible={visible}
          width={900}
          maskClosable={false}
          onCancel={() => { this.setState({ visible: false })}}
          footer={[
            <CreateInterface key="interface" dict={dict} ref="tableCreatInterface" trigger={this.tableCreatInterface}/>,
            <CreateFunc key="create" dict={dict} ref="funcCreatComponent" trigger={this.tableCreatFunc}/>,
            <Button key="cancel" onClick={() => { this.setState({ visible: false }) }}>{this.state.dict['header.cancel']}</Button>,
            <Button key="confirm" type="primary" loading={this.state.loading} onClick={this.settingSave}>{this.state.dict['model.confirm']}</Button>
          ]}
          destroyOnClose
        >
          <SettingForm
            type={type}
            dict={dict}
            menu={this.state.menu}
            config={config}
            inputSubmit={this.settingSave}
            formlist={this.state.formlist}
            wrappedComponentRef={(inst) => this.settingRef = inst}
          />
        </Modal>
      </div>
    )
  }
}
export default TablesComponent
src/templates/sharecomponent/settingcomponent/index.scss
New file
@@ -0,0 +1,38 @@
.model-menu-setting {
  > .anticon-setting {
    position: absolute;
    font-size: 18px;
    right: 7px;
    top: 5px;
    padding: 10px;
    z-index: 1;
  }
}
.model-table-setting-verify-modal {
  .ant-modal {
    top: 50px;
    padding-bottom: 5px;
    .ant-modal-body {
      max-height: calc(100vh - 190px);
      overflow-y: auto;
      // .ant-empty {
      //   margin: 15vh 8px;
      // }
    }
    .ant-modal-body::-webkit-scrollbar {
      width: 7px;
    }
    .ant-modal-body::-webkit-scrollbar-thumb {
      border-radius: 5px;
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
      background: rgba(0, 0, 0, 0.13);
    }
    .ant-modal-body::-webkit-scrollbar-track {
      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
      border-radius: 3px;
      border: 1px solid rgba(0, 0, 0, 0.07);
      background: rgba(0, 0, 0, 0);
    }
  }
}
src/templates/sharecomponent/settingcomponent/settingform/customscript/index.jsx
New file
@@ -0,0 +1,231 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Button, notification, Modal, Menu, Icon, Radio, Dropdown } from 'antd'
import moment from 'moment'
import Utils from '@/utils/utils.js'
import Api from '@/api'
import './index.scss'
const { TextArea } = Input
class CustomForm extends Component {
  static propTpyes = {
    dict: PropTypes.object,         // 字典项
    tableName: PropTypes.string,    // 表名
    systemScripts: PropTypes.array, // 系统脚本
    customScripts: PropTypes.array, // 自定义脚本
    scriptsChange: PropTypes.func   // 表单
  }
  state = {
    editItem: null,
    loading: false
  }
  edit = (record) => {
    this.setState({
      editItem: record
    })
    this.props.form.setFieldsValue({
      sql: record.sql,
      initsql: record.initsql || 'false'
    })
  }
  handleConfirm = () => {
    // 表单提交时检查输入值是否正确
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
        let _quot = values.sql.match(/'{1}/g)
        let _lparen = values.sql.match(/\({1}/g)
        let _rparen = values.sql.match(/\){1}/g)
        _quot = _quot ? _quot.length : 0
        _lparen = _lparen ? _lparen.length : 0
        _rparen = _rparen ? _rparen.length : 0
        if (_quot % 2 !== 0) {
          notification.warning({
            top: 92,
            message: 'sql中\'必须成对出现',
            duration: 5
          })
          return
        } else if (_lparen !== _rparen) {
          notification.warning({
            top: 92,
            message: 'sql中()必须成对出现',
            duration: 5
          })
          return
        } else if (/--/ig.test(values.sql)) {
          notification.warning({
            top: 92,
            message: '自定义sql语句中,不可出现字符 -- ,注释请用 /*内容*/',
            duration: 5
          })
          return
        }
        let error = Utils.verifySql(values.sql, 'customscript')
        if (error) {
          notification.warning({
            top: 92,
            message: 'sql中不可使用' + error,
            duration: 5
          })
          return
        }
        let tail = `
          aaa:
        `
        let _initsql = ''
        this.props.customScripts.forEach(script => {
          if (this.state.editItem && this.state.editItem.uuid === script.uuid) return
          if (script.status === 'false' || script.initsql !== 'true') return
          _initsql += `
            ${script.sql}
            `
        })
        let param = {
          func: 's_debug_sql',
          LText: _initsql + values.sql + tail
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        this.setState({loading: true})
        Api.getLocalConfig(param).then(res => {
          if (res.status) {
            this.setState({
              loading: false,
              editItem: null
            }, () => {
              this.props.scriptsChange(values)
            })
            this.props.form.setFieldsValue({
              sql: ''
            })
          } else {
            this.setState({loading: false})
            Modal.error({
              title: res.message
            })
          }
        })
      }
    })
  }
  selectScript = (e) => {
    const { systemScripts } = this.props
    let option = systemScripts[+e.key]
    let _sql = this.props.form.getFieldValue('sql')
    if (_sql) {
      _sql = _sql + `
      `
    }
    _sql = _sql.replace(/\s{6}$/, '')
    _sql = _sql + `/*${option.name}*/
    `
    _sql = _sql.replace(/\s{4}$/, '')
    _sql = _sql + option.value
    this.props.form.setFieldsValue({
      sql: _sql
    })
  }
  render() {
    const { systemScripts, tableName } = this.props
    const { getFieldDecorator } = this.props.form
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <Form {...formItemLayout} className="modal-menu-setting-script">
        <Row gutter={24}>
          <Col span={24} className="sqlfield">
            <Form.Item label={'可用字段'}>
              id, bid, loginuid, sessionuid, userid, appkey
            </Form.Item>
          </Col>
          <Col span={8} style={{whiteSpace: 'nowrap'}}>
            <Form.Item style={{marginBottom: 0}} label="初始化sql">
              {getFieldDecorator('initsql', {
                initialValue: 'false'
              })(
                <Radio.Group>
                  <Radio value="true">是</Radio>
                  <Radio value="false">否</Radio>
                </Radio.Group>
              )}
            </Form.Item>
          </Col>
          <Col span={4} style={{lineHeight: '40px', textAlign: 'center'}}>
            <Dropdown trigger={['click']} overlayClassName="mk-normal-dropdown" overlay={
              <Menu onClick={this.selectScript}>
                {systemScripts.map((option, i) =>
                  <Menu.Item key={i}>{option.name}</Menu.Item>
                )}
              </Menu>
            }>
              <span style={{color: '#1890ff', display: 'inline-block', cursor: 'pointer'}}>
                快捷添加 <Icon type="down" style={{marginRight: '5px'}} />
              </span>
            </Dropdown>
          </Col>
          <Col span={4} className="add">
            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 40}}>
              保存
            </Button>
          </Col>
          <Col span={8} style={{textAlign: 'right'}}>
            {tableName ? <span style={{maxWidth: '100%', display: 'inline-block', position: 'relative', top: '20px', whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden'}}>
              表名:  {tableName}
            </span> : null}
          </Col>
          <Col span={24} className="sql">
            <Form.Item label={'sql'}>
              {getFieldDecorator('sql', {
                initialValue: '',
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + 'sql!'
                  }
                ]
              })(<TextArea rows={15} />)}
            </Form.Item>
          </Col>
        </Row>
      </Form>
    )
  }
}
export default Form.create()(CustomForm)
src/templates/sharecomponent/settingcomponent/settingform/customscript/index.scss
New file
@@ -0,0 +1,31 @@
.modal-menu-setting-script {
  .sqlfield {
    .ant-form-item {
      margin-bottom: 5px;
    }
    .ant-form-item-control {
      line-height: 24px;
    }
    .ant-form-item-label {
      line-height: 25px;
    }
    .ant-form-item-children {
      line-height: 22px;
    }
    .ant-col-sm-8 {
      width: 10.5%;
    }
    .ant-col-sm-16 {
      width: 89.5%;
    }
  }
  .sql {
    .ant-col-sm-8 {
      width: 10.5%;
    }
    .ant-col-sm-16 {
      width: 89.5%;
      padding-top: 4px;
    }
  }
}
src/templates/sharecomponent/settingcomponent/settingform/index.jsx
New file
@@ -0,0 +1,851 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { fromJS } from 'immutable'
import { Form, Row, Col, Input, Radio, Select, Tooltip, Icon, notification, InputNumber, Modal, Button, Table, Popconfirm } from 'antd'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import CustomScript from './customscript'
import './index.scss'
const { TextArea } = Input
const { confirm } = Modal
class SettingForm extends Component {
  static propTpyes = {
    type: PropTypes.string,      // 菜单类型
    dict: PropTypes.object,      // 字典项
    menu: PropTypes.object,      // 菜单信息
    config: PropTypes.object,    // 页面配置信息
    formlist: PropTypes.array,   // 表单信息
    inputSubmit: PropTypes.any   // 回车提交事件
  }
  state = {
    formlist: [],
    setting: null,
    view: 'normal',
    systemScripts: [],
    scriptsColumns: [
      {
        title: 'SQL',
        dataIndex: 'sql',
        width: '60%'
      },
      {
        title: '初始化sql',
        dataIndex: 'initsql',
        width: '12%',
        render: (text, record) => {
          if (record.initsql === 'true') {
            return '是'
          } else {
            return '否'
          }
        }
      },
      {
        title: '状态',
        dataIndex: 'status',
        width: '8%',
        render: (text, record) => record.status === 'false' ?
          (
            <div>
              {this.props.dict['header.form.status.forbidden']}
              <Icon style={{marginLeft: '5px'}} type="stop" theme="twoTone" twoToneColor="#ff4d4f" />
            </div>
          ) :
          (
            <div>
              {this.props.dict['header.form.status.open']}
              <Icon style={{marginLeft: '5px'}} type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
            </div>
          )
      },
      {
        title: '操作',
        align: 'center',
        width: '20%',
        dataIndex: 'operation',
        render: (text, record) =>
          (<div>
            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><Icon type="edit" /></span>
            <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
            <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span>
            <Popconfirm
              title={this.props.dict['header.form.query.delete']}
              okText={this.props.dict['model.confirm']}
              cancelText={this.props.dict['header.cancel']}
              onConfirm={() => this.handleDelete(record)
            }>
              <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
            </Popconfirm>
          </div>)
      }
    ]
  }
  UNSAFE_componentWillMount() {
    let _formlist = fromJS(this.props.formlist).toJS()
    let interType = 'inner'
    _formlist.forEach(item => {
      if (item.key === 'interType') {
        interType = item.initVal
      }
    })
    let _setting = fromJS(this.props.config.setting).toJS()
    _setting.scripts = _setting.scripts || []
    _setting.default = _setting.default || 'true'
    this.setState({
      setting: _setting,
      formlist: _formlist.map(item => {
        if (interType === 'inner' && ['sysInterface', 'interface', 'outerFunc'].includes(item.key)) {
          item.hidden = true
        } else if (interType === 'outer' && ['innerFunc', 'dataresource', 'queryType'].includes(item.key)) {
          item.hidden = true
        }
        return item
      })
    })
  }
  componentDidMount () {
    this.getsysScript()
  }
  getsysScript = () => {
    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from  s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
    _scriptSql = Utils.formatOptions(_scriptSql)
    let _sParam = {
      func: 'sPC_Get_SelectedList',
      LText: _scriptSql,
      obj_name: 'data',
      arr_field: 'funcname,longparam'
    }
    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
    Api.getSystemConfig(_sParam).then(res => {
      if (res.status) {
        let _scripts = []
        _scripts.push({
          name: '默认sql',
          value: ''
        })
        res.data.forEach(item => {
          let _item = {
            name: item.funcname,
            value: Utils.formatOptions(item.longparam, true)
          }
          _scripts.push(_item)
        })
        this.setState({
          systemScripts: _scripts
        })
      } else {
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
  }
  handleConfirm = (otype) => {
    const { menu, config, type } = this.props
    const { view, setting } = this.state
    // 表单提交时检查输入值是否正确
    if (view !== 'custom') {
      return new Promise((resolve, reject) => {
        this.props.form.validateFieldsAndScroll((err, values) => {
          if (!err) {
            if (type === 'main') {
              values.actionfixed = values.actionfixed === 'true'
              values.columnfixed = values.columnfixed === 'true'
            }
            values = {...setting, ...values}
            // 数据源前端验证
            if (values.interType === 'inner' && !values.innerFunc && !values.dataresource) {
              notification.warning({
                top: 92,
                message: '请自定义函数或填写数据源!',
                duration: 5
              })
              return
            } else {
              let error = Utils.verifySql(values.dataresource)
              if (error) {
                notification.warning({
                  top: 92,
                  message: '数据源中不可使用' + error,
                  duration: 5
                })
                return
              }
            }
            // 数据源保存
            if (
              values.interType === 'inner' && !values.innerFunc &&
              /[^\s]+\s+[^\s]+/ig.test(values.dataresource) &&
              this.props.config.setting.dataresource !== values.dataresource
            ) {
              let param = {
                func: 's_DataSrc_Save',
                LText: values.dataresource,
                MenuID: menu.MenuID
              }
              param.LText = Utils.formatOptions(param.LText)
              param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
              param.secretkey = Utils.encrypt(param.LText, param.timestamp)
              Api.getLocalConfig(param)
            }
            // 合成自定义script
            let _customScript = ''
            values.scripts.forEach(item => {
              if (item.status === 'false' || item.initsql !== 'true') return
              _customScript += `
                ${item.sql}
              `
            })
            values.scripts.forEach(item => {
              if (item.status === 'false' || item.initsql === 'true') return
              _customScript += `
                ${item.sql}
              `
            })
            values.customScript = _customScript
            // 数据源后台语法验证
            if (values.interType === 'inner' && !values.innerFunc && /\s/.test(values.dataresource)) {
              if (otype === 'change') { // 切换自定义设置
                this.setState({
                  sqlVerifing: true
                })
              }
              let _dataresource = values.dataresource
              if (values.queryType === 'statistics') {
                let allSearch = Utils.initMainSearch(config.search)
                allSearch = Utils.getAllSearchOptions(allSearch)
                let options = allSearch.map(item => {
                  return {
                    reg: new RegExp('@' + item.key + '@', 'ig'),
                    value: item.value
                  }
                })
                options.forEach(item => {
                  _dataresource = _dataresource.replace(item.reg, `'${item.value}'`)
                })
              }
              let param = {
                func: 's_debug_sql',
                LText: _dataresource
              }
              param.LText = Utils.formatOptions(param.LText)
              param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
              param.secretkey = Utils.encrypt(param.LText, param.timestamp)
              Api.getLocalConfig(param).then(result => {
                if (result.status) {
                  if (otype === 'change') {
                    this.setState({
                      sqlVerifing: false,
                      setting: values
                    }, () => {
                      resolve()
                    })
                  } else {
                    resolve(values)
                  }
                } else {
                  this.setState({sqlVerifing: false})
                  Modal.error({
                    title: result.message
                  })
                }
              })
            } else if (otype === 'change') {
              this.setState({
                setting: values,
              }, () => {
                resolve()
              })
            } else {
              resolve(values)
            }
          } else {
            reject(err)
          }
        })
      })
    } else {
      let _loading = false
      let _setting = fromJS(this.state.setting).toJS()
      if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) {
        _loading = true
      }
      let _customScript = ''
      _setting.scripts.forEach(item => {
        if (item.status === 'false' || item.initsql !== 'true') return
        _customScript += `
          ${item.sql}
        `
      })
      _setting.scripts.forEach(item => {
        if (item.status === 'false' || item.initsql === 'true') return
        _customScript += `
          ${item.sql}
        `
      })
      _setting.customScript = _customScript
      return new Promise((resolve, reject) => {
        if (_loading) {
          confirm({
            content: `存在未保存项,确定提交吗?`,
            okText: this.props.dict['model.confirm'],
            cancelText: this.props.dict['header.cancel'],
            onOk() {
              resolve(_setting)
            },
            onCancel() {
              reject()
            }
          })
        } else {
          resolve(_setting)
        }
      })
    }
  }
  selectChange = (key, val) => {
    if (key === 'primaryKey' && val) {
      this.props.form.setFieldsValue({
        order: `${val} desc`
      })
    }
  }
  onRadioChange = (e, key) => {
    let value = e.target.value
    let _formlist = fromJS(this.state.formlist).toJS()
    if (key === 'interType') {
      this.setState({
        formlist: _formlist.map(item => {
          item.hidden = false
          if (value === 'inner' && ['sysInterface', 'interface', 'outerFunc'].includes(item.key)) {
            item.initVal = this.props.form.getFieldValue(item.key)
            item.hidden = true
          } else if (value === 'outer' && ['innerFunc', 'dataresource', 'queryType'].includes(item.key)) {
            item.initVal = this.props.form.getFieldValue(item.key)
            item.hidden = true
          }
          return item
        })
      })
    } else if (key === 'sysInterface') {
      if (value === 'true') {
        this.props.form.setFieldsValue({
          interface: window.GLOB.mainSystemApi || ''
        })
      }
      this.setState({
        formlist: _formlist.map(item => {
          if (item.key === 'interface') {
            item.readonly = value === 'true'
          }
          return item
        })
      })
    }
  }
  formatSearch (searches) {
    if (!searches || searches.length === 0) return []
    let newsearches = []
    searches.forEach(search => {
      let item = {
        key: search.field,
        match: search.match,
        type: search.type,
        label: search.label,
        value: search.initval,
        required: search.required === 'true'
      }
      if (item.type === 'date') {
        item.value = moment().format('YYYY-MM-DD')
      } else if (item.type === 'datemonth') {
        item.value = moment().format('YYYY-MM')
      } else if (item.type === 'dateweek') {
        item.value = [moment().startOf('week').format('YYYY-MM-DD'), moment().endOf('week').format('YYYY-MM-DD')]
      } else if (item.type === 'daterange') {
        item.value = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')]
      } else if (item.type === 'multiselect') {
        item.value = ['@$@']
      } else {
        item.value = '@$@'
      }
      newsearches.push(item)
    })
    return newsearches
  }
  changeView = () => {
    const { view } = this.state
    if (view === 'normal') {
      this.handleConfirm('change').then(() => {
        const { config } = this.props
        const { setting } = this.state
        if (setting.interType !== 'inner' || (setting.interType === 'inner' && setting.innerFunc)) {
          notification.warning({
            top: 92,
            message: '使用外部接口或内部接口的自定义函数,不可添加自定义设置!',
            duration: 5
          })
          return
        }
        let _search = this.formatSearch(config.search)
        _search = Utils.joinMainSearchkey(_search)
        _search = _search.replace(/@\$@/ig, '')
        _search = _search ? 'where ' + _search : ''
        let arr_field = []
        config.columns.forEach(col => {
          if (col.field) {
            arr_field.push(col.field)
          }
        })
        arr_field = arr_field.join(',')
        let _dataresource = setting.dataresource
        if (/\s/.test(_dataresource)) {
          _dataresource = '(' + _dataresource + ') tb'
        }
        if (setting.queryType === 'statistics') { // 统计数据源,内容替换
          let allSearch = Utils.initMainSearch(config.search)
          allSearch = Utils.getAllSearchOptions(allSearch)
          let options = allSearch.map(item => {
            return {
              reg: new RegExp('@' + item.key + '@', 'ig'),
              value: item.value
            }
          })
          options.forEach(item => {
            _dataresource = _dataresource.replace(item.reg, `'${item.value}'`)
          })
          _search = ''
        }
        let LText = `select ${setting.laypage !== 'false' ?  'top 10' : ''} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource} ${_search}) tmptable ${setting.laypage !== 'false' ?  'where rows > 0' : ''} order by tmptable.rows`
        let _scripts = fromJS(this.state.systemScripts).toJS()
        _scripts[0].value = LText
        this.setState({
          view: 'custom',
          systemScripts: _scripts
        })
        this.scrolltop()
      }, () => {
        this.setState({sqlVerifing: false})
      })
    } else {
      let _loading = false
      let _this = this
      if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql')) {
        _loading = true
      }
      if (_loading) {
        confirm({
          content: `存在未保存项,确定切换吗?`,
          okText: this.props.dict['model.confirm'],
          cancelText: this.props.dict['header.cancel'],
          onOk() {
            _this.setState({
              view: 'normal'
            })
            _this.scrolltop()
          },
          onCancel() {}
        })
      } else {
        this.setState({
          view: 'normal'
        })
        this.scrolltop()
      }
    }
  }
  handleSubmit = (e) => {
    e.preventDefault()
    if (this.props.inputSubmit) {
      this.props.inputSubmit()
    }
  }
  getFields(formlist) {
    const { getFieldDecorator } = this.props.form
    const fields = []
    formlist.forEach((item, index) => {
      if (item.hidden || item.forbid) return
      if (item.type === 'text') { // 文本搜索
        let rules = item.rules || []
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  },
                  ...rules
                ]
              })(<Input placeholder={item.placeholder || ''} autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'number') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || 6,
                rules: [
                  {
                    required: item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<InputNumber min={item.min} max={item.max} precision={0} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉搜索
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select
                  showSearch
                  filterOption={(input, option) => {
                    return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
                      option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
                  }}
                  onChange={(value) => {this.selectChange(item.key, value)}}
                  getPopupContainer={() => document.getElementById('model-table-setting-form')}
                >
                  {item.options.map((option, i) =>
                    <Select.Option id={i} key={i} value={option.value}>
                      {option.text}
                    </Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.tooltip ?
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip> : item.label
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Radio.Group onChange={(e) => {this.onRadioChange(e, item.key)}}>
                  {
                    item.options.map((option, i) => {
                      return (
                        <Radio key={i} value={option.value}>{option.text}</Radio>
                      )
                    })
                  }
                </Radio.Group>,
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'datasource') {
        fields.push(
          <Col span={24} key={index} style={{paddingLeft: '7px'}}>
            <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } help={item.help} label={
              <Tooltip placement="topLeft" title={item.tooltip}>
                <Icon type="question-circle" />
                {item.label}
              </Tooltip>
            }>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal
              })(<TextArea rows={4} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'textarea') {
        fields.push(
          <Col span={20} offset={4} key={index}>
            <Form.Item className="text-area">
              {getFieldDecorator(item.key, {
                initialValue: item.initVal,
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                  }
                ]
              })(<TextArea rows={4} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'multiselect') { // 多选
        fields.push(
          <Col span={12} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || []
              })(
                <Select
                  showSearch
                  mode="multiple"
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                >
                  {item.options.map((option, i) =>
                    <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      }
    })
    return fields
  }
  handleEdit = (record) => {
    this.scriptsForm.edit(record)
    this.scrolltop()
  }
  scrolltop = () => {
    let node = document.getElementById('model-table-setting-form-box').parentNode
    if (node && node.scrollTop) {
      let inter = Math.ceil(node.scrollTop / 10)
      let timer = setInterval(() => {
        if (node.scrollTop - inter > 0) {
          node.scrollTop = node.scrollTop - inter
        } else {
          node.scrollTop = 0
          clearInterval(timer)
        }
      }, 10)
    }
  }
  handleUpDown = (record, direction) => {
    let scripts = fromJS(this.state.setting.scripts).toJS()
    let index = 0
    scripts = scripts.filter((item, i) => {
      if (item.uuid === record.uuid) {
        index = i
      }
      return item.uuid !== record.uuid
    })
    if ((index === 0 && direction === 'up') || (index === scripts.length && direction === 'down')) {
      return
    }
    if (direction === 'up') {
      scripts.splice(index - 1, 0, record)
    } else {
      scripts.splice(index + 1, 0, record)
    }
    this.setState({
      setting: {...this.state.setting, scripts: scripts}
    })
  }
  handleStatus = (record) => {
    let scripts = fromJS(this.state.setting.scripts).toJS()
    record.status = record.status === 'false' ? 'true' : 'false'
    scripts = scripts.map(item => {
      if (item.uuid === record.uuid) {
        return record
      } else {
        return item
      }
    })
    this.setState({
      setting: {...this.state.setting, scripts: scripts}
    })
  }
  handleDelete = (record) => {
    let scripts = fromJS(this.state.setting.scripts).toJS()
    scripts = scripts.filter(item => item.uuid !== record.uuid)
    this.setState({ setting: {...this.state.setting, scripts: scripts} })
  }
  scriptsChange = (values) => {
    let scripts = fromJS(this.state.setting.scripts).toJS()
    if (values.uuid) {
      scripts = scripts.map(item => {
        if (item.uuid === values.uuid) {
          return values
        } else {
          return item
        }
      })
    } else {
      values.uuid = Utils.getuuid()
      scripts.push(values)
    }
    this.setState({
      setting: {...this.state.setting, scripts: scripts}
    })
  }
  render() {
    const { formlist, view, setting, scriptsColumns, systemScripts } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      }
    }
    return (
      <div className="model-table-setting-form-box" id="model-table-setting-form-box">
        {view ==='custom' ? <div>
          <CustomScript
            dict={this.props.dict}
            tableName={setting.tableName}
            customScripts={setting.scripts}
            systemScripts={systemScripts}
            scriptsChange={this.scriptsChange}
            wrappedComponentRef={(inst) => this.scriptsForm = inst}
          />
          <Table
            bordered
            rowKey="uuid"
            className="custom-table"
            dataSource={setting.scripts}
            columns={scriptsColumns}
            pagination={false}
          />
        </div> : null }
        <Form {...formItemLayout} className="model-table-setting-form" id="model-table-setting-form">
          {view !=='custom' ? <Row gutter={24}>{this.getFields(formlist)}</Row> : null}
          <Row gutter={24}>
            {view !=='custom' ? <Button loading={this.state.sqlVerifing} onClick={this.changeView} style={{border: 0, boxShadow: 'unset',float: 'right', color: '#1890ff', marginRight: 12, cursor: 'pointer'}}>自定义设置<Icon style={{marginLeft: 5}} type="right" /></Button> : null}
            {view ==='custom' ? <span onClick={this.changeView} style={{float: 'left', color: '#1890ff', marginLeft: 12, marginTop: 15, cursor: 'pointer'}}><Icon style={{marginRight: 5}} type="left" />基础设置</span> : null}
          </Row>
        </Form>
      </div>
    )
  }
}
export default Form.create()(SettingForm)
src/templates/sharecomponent/settingcomponent/settingform/index.scss
New file
@@ -0,0 +1,25 @@
.model-table-setting-form-box {
  .model-table-setting-form {
    .textarea {
      .ant-form-item-label {
        width: 16.3%;
      }
      .ant-form-item-control-wrapper {
        width: 83.33333333%;
      }
    }
    .anticon-question-circle {
      color: #c49f47;
      margin-right: 3px;
    }
  }
  .operation-btn {
    display: inline-block;
    font-size: 16px;
    padding: 0 5px;
    cursor: pointer;
  }
  td {
    word-break: break-all;
  }
}
src/templates/sharecomponent/tablecomponent/index.jsx
@@ -149,179 +149,9 @@
    })
  }
  queryField = (type) => {
    const {selectedTables, tableFields, config} = this.state
    // 判断是否已选择表名
    if (selectedTables.length === 0) {
      notification.warning({
        top: 92,
        message: '请选择表名!',
        duration: 5
      })
      return
    }
    // 表字段集转为map数据
    let columns = new Map()
    tableFields.forEach(table => {
      table.columns.forEach(column => {
        columns.set(column.field, column)
      })
    })
    if (type === 'search') {
      // 添加搜索条件,字段集中存在搜索条件字段,使用搜索条件对象替换字段集,设置数据类型
      config.search.forEach(item => {
        if (columns.has(item.field)) {
          let _datatype = columns.get(item.field).datatype
          columns.set(item.field, {...item, selected: true, datatype: _datatype})
        }
      })
    } else if (type === 'columns') {
      // 添加显示列,字段集中存在显示列字段,使用显示列对象替换字段集,设置数据类型
      config.columns.forEach(item => {
        if (columns.has(item.field)) {
          let _datatype = columns.get(item.field).datatype
          columns.set(item.field, {...item, selected: true, datatype: _datatype})
        }
      })
    }
    // 显示字段集弹窗
    this.setState({
      addType: type,
      tableVisible: true,
      fields: [...columns.values()]
    })
  }
  addFieldSubmit = () => {
    // 字段集为空,关闭弹窗
    if (!this.state.fields || this.state.fields.length === 0) {
      this.setState({
        tableVisible: false,
        addType: ''
      })
    }
    const {addType, config} = this.state
    // 获取已选字段集合
    let cards = this.refs.searchcard.state.selectCards
    let columnsMap = new Map()
    cards.forEach(card => {
      columnsMap.set(card.field, card)
    })
    let items = []
    if (addType === 'search') {
      config.search.forEach(item => {
        if (columnsMap.has(item.field)) {
          let cell = columnsMap.get(item.field)
          if (cell.selected && cell.type === item.type) { // 数据未修改
            items.push(item)
          } else if (cell.selected) { // 数据类型修改
            if (cell.type === 'select') {
              item.match = '='
            } else if (cell.type === 'daterange') {
              item.match = 'between'
            } else {
              cell.type = 'text'
              item.match = 'like'
            }
            item.type = cell.type
            item.initval = ''
            items.push(item)
          }
          columnsMap.delete(item.field)
        } else if (!item.origin) {
          items.push(item)
        }
      })
      let _columns = [...columnsMap.values()]
      _columns.forEach(item => {
        if (item.selected) {
          let _match = ''
          if (item.type === 'select') {
            _match = '='
          } else if (item.type === 'daterange') {
            _match = 'between'
          } else {
            item.type = 'text'
            _match = 'like'
          }
          let newcard = {
            uuid: Utils.getuuid(),
            label: item.label,
            field: item.field,
            initval: '',
            type: item.type,
            resourceType: '0',
            setAll: 'false',
            options: [],
            dataSource: '',
            linkField: '',
            valueField: '',
            valueText: '',
            orderBy: '',
            orderType: 'asc',
            match: _match,
            display: 'dropdown'
          }
          items.push(newcard)
        }
      })
    } else {
      config.columns.forEach(item => {
        if (columnsMap.has(item.field)) {
          let cell = columnsMap.get(item.field)
          if (cell.selected) {
            items.push(item)
          }
          columnsMap.delete(item.field)
        } else if (!item.origin) {
          items.push(item)
        }
      })
      let _columns = [...columnsMap.values()]
      _columns.forEach(item => {
        if (item.selected) {
          let newcard = {
            uuid: Utils.getuuid(),
            Align: 'left',
            label: item.label,
            field: item.field,
            Hide: 'false',
            IsSort: item.type === 'picture' ? 'false' : 'true',
            type: item.type,
            Width: 120
          }
          items.push(newcard)
        }
      })
    }
    this.setState({
      config: {...config, [addType]: items}
    })
    notification.success({
      top: 92,
      message: '操作成功',
      duration: 2
    })
  }
  /**
   * @description 添加表名
   */
  onTableChange = (value) => {
    const { config } = this.props
    const { tables, tableFields, selectedTables } = this.state
@@ -383,6 +213,9 @@
    }
  }
  /**
   * @description 删除表名
   */
  deleteTable = (table) => {
    const { config } = this.props
    const {selectedTables, tableFields} = this.state
@@ -396,12 +229,6 @@
    })
    this.props.updatetable({...config, tables: _tables}, _fields)
  }
  changeSetting = () => {
    this.setState({
      settingVisible: true
    })
  }
  render() {
src/templates/subtableconfig/index.jsx
@@ -11,7 +11,9 @@
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import Utils from '@/utils/utils.js'
import { getSubMenuForm } from '@/templates/zshare/formconfig'
import asyncComponent from '@/utils/asyncComponent'
import TableComponent from '@/templates/sharecomponent/tablecomponent'
import FieldsComponent from '@/templates/sharecomponent/fieldscomponent'
import ChartGroupComponent from '@/templates/sharecomponent/chartgroupcomponent'
@@ -19,12 +21,9 @@
import ActionComponent from '@/templates/sharecomponent/actioncomponent'
import ColumnComponent from '@/templates/sharecomponent/columncomponent'
import SettingForm from './settingform'
import MenuForm from '@/templates/zshare/menuform'
import EditComponent from '@/templates/zshare/editcomponent'
import SourceElement from '@/templates/zshare/dragsource'
import CreateFunc from '@/templates/zshare/createfunc'
import CreateInterface from '@/templates/zshare/createinterface'
import ChartComponent from '@/templates/zshare/chartcomponent'
import Source from './source'
import './index.scss'
@@ -32,6 +31,7 @@
const { Panel } = Collapse
const { confirm } = Modal
const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS
const SettingComponent = asyncComponent(() => import('@/templates/sharecomponent/settingcomponent'))
class SubTableConfig extends Component {
  static propTpyes = {
@@ -57,7 +57,6 @@
    menuloading: false,      // 菜单保存中
    menucloseloading: false, // 菜单关闭时,选择保存
    loading: false,          // 加载中,页面spin
    settingVisible: false,   // 全局配置模态框
    closeVisible: false,     // 关闭模态框
    originConfig: null,      // 原配置
    originActions: null,     // 原始按钮信息,使用已有用户模板
@@ -67,7 +66,6 @@
    optionLibs: null,        // 自定义下拉选项库
    thawButtons: [],         // 已选择要解冻的按钮
    activeKey: '0',          // 默认展开基本信息
    sqlVerifing: false,      // sql验证
    chartview: null,         // 当前视图
    pasteContent: null       // 粘贴内容
  }
@@ -148,32 +146,7 @@
      config: _config,
      activeKey: _activeKey || '0',
      originConfig: _config,
      menuformlist: [
        {
          type: 'text',
          key: 'tabName',
          label: this.state.dict['header.menu.viewName'],
          initVal: _config.tabName,
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'tabNo',
          label: this.state.dict['header.menu.menuNo'],
          initVal: _config.tabNo,
          required: true,
          readonly: false
        },
        {
          type: 'text',
          key: 'Remark',
          label: this.state.dict['header.menu.Remark'],
          initVal: _config.Remark,
          required: false,
          readonly: false
        }
      ]
      menuformlist: getSubMenuForm(_config)
    })
  }
@@ -289,37 +262,6 @@
  }
  /**
   * @description 创建表格存储过程
   */
  tableCreatFunc = () => {
    const { config } = this.state
    this.settingRef.handleConfirm().then(setting => {
      if (!(setting.interType === 'inner') || !setting.innerFunc) {
        notification.warning({
          top: 92,
          message: '接口类型为-内部,且存在内部函数时,才可以创建存储过程!',
          duration: 5
        })
        return
      }
      let _config = {...config, setting: setting}
      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, {MenuID: _config.uuid, MenuName: _config.tabName, MenuNo: _config.tabNo}, _config)) // 创建存储过程sql
      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 删除存储过程sql
      this.refs.tableCreatFunc.exec(setting.innerFunc, newLText, DelText).then(result => {
        if (result === 'success') {
          this.setState({
            config: _config
          })
        }
      })
    })
  }
  /**
   * @description 标签页保存
   */
  submitConfig = () => {
@@ -341,7 +283,7 @@
      }
      let _LongParam = ''
      let _config = {...config, ...res}
      let _config = {...config, tabName: res.MenuName, tabNo: res.MenuNo, Remark: res.Remark}
      // 未设置数据源或主键时,启用状态为false
      if (_config.setting.interType === 'inner' && !_config.setting.innerFunc && !_config.setting.dataresource) {
@@ -471,7 +413,7 @@
          func: 'sPC_Button_AddUpt',
          Type: 40,
          ParentID: _config.uuid,
          MenuNo: res.tabNo,
          MenuNo: res.MenuNo,
          Template: 'SubTable',
          PageParam: '',
          LongParam: '',
@@ -505,9 +447,9 @@
        let param = {
          func: 'sPC_Tab_AddUpt',
          MenuID: _config.uuid,
          MenuNo: res.tabNo,
          MenuNo: res.MenuNo,
          Template: 'SubTable',
          MenuName: res.tabName,
          MenuName: res.MenuName,
          Remark: res.Remark,
          Sort: 0,
          PageParam: JSON.stringify({Template: 'SubTable'}),
@@ -814,101 +756,6 @@
    }
  }
  changeSetting = () => {
    this.setState({
      settingVisible: true
    })
  }
  settingSave = () => {
    const { config } = this.state
    this.settingRef.handleConfirm().then(res => {
      if (
        res.interType === 'inner' &&
        !res.innerFunc &&
        /[^\s]+\s+[^\s]+/ig.test(res.dataresource) &&
        config.setting.dataresource !== res.dataresource
      ) {
        let param = {
          func: 's_DataSrc_Save',
          LText: res.dataresource,
          MenuID: config.uuid
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        Api.getLocalConfig(param)
      }
      if (res.interType === 'inner' && !res.innerFunc && res.dataresource && /\s/.test(res.dataresource)) {
        this.setState({
          sqlVerifing: true
        })
        let _dataresource = res.dataresource
        if (res.queryType === 'statistics') {
          let fieldmap = new Map()
          let options = config.search.map(item => {
            let _field = item.key
            let _val = ''
            if (fieldmap.has(_field)) {
              _field = _field + '1'
            }
            fieldmap.set(item.key, true)
            if (/date/.test(item.type)) {
              _val = '1900-01-01'
            }
            return {
              reg: new RegExp('@' + _field + '@', 'ig'),
              value: _val
            }
          })
          options.forEach(item => {
            _dataresource = _dataresource.replace(item.reg, `'${item.value}'`)
          })
        }
        let param = {
          func: 's_debug_sql',
          LText: _dataresource
        }
        param.LText = Utils.formatOptions(param.LText)
        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
        Api.getLocalConfig(param).then(result => {
          if (result.status) {
            this.setState({
              sqlVerifing: false,
              config: {...config, setting: res},
              settingVisible: false
            })
          } else {
            this.setState({sqlVerifing: false})
            Modal.error({
              title: result.message
            })
          }
        })
      } else {
        this.setState({
          config: {...config, setting: res},
          settingVisible: false
        })
      }
    })
  }
  /**
   * @description 设置可配置按钮
   */
@@ -1041,36 +888,6 @@
  }
  /**
   * @description 创建表格接口
   */
  tableCreatInterface = () => {
    const { config } = this.state
    this.menuformRef.handleConfirm().then(res => {
      this.settingRef.handleConfirm().then(setting => {
        if (setting.interType !== 'inner' || setting.innerFunc) {
          notification.warning({
            top: 92,
            message: '接口类型为-内部,且不存在内部函数时,才可以创建接口!',
            duration: 5
          })
          return
        }
        let _config = {...config, setting: setting}
        let _menu = {
          type: 'subtable',
          MenuID: config.uuid,
          menuName: res.tabName,
          menuNo: res.tabNo
        }
        this.refs.tableCreatInterface.triggerOutInterface(_menu, _config)
      })
    })
  }
  /**
   * @description 编辑功能完成更新,包括解冻按钮、粘贴、替换等
   */
  updateConfig = (res) => {
@@ -1143,7 +960,7 @@
  /**
   * @description 更新显示列配置信息
   */
  updatecolumn = (config) => {
  updateconfig = (config) => {
    this.setState({
      config: config
    })
@@ -1281,9 +1098,16 @@
                <Button onClick={this.cancelConfig}>{this.state.dict['header.return']}</Button>
              </div>
            } style={{ width: '100%' }}>
              <Icon type="setting" onClick={this.changeSetting} />
              <SettingComponent
                type="subtable"
                config={config}
                MenuID={config.uuid}
                menuformRef={this.menuformRef}
                permFuncField={this.props.permFuncField}
                updatesetting={this.updateconfig}
              />
              <SearchComponent
                menu={{MenuID: this.state.config.uuid, MenuName: this.state.config.tabName}}
                menu={{MenuID: config.uuid, MenuName: config.tabName}}
                config={config}
                pasteContent={this.state.pasteContent}
                sysRoles={this.props.sysRoles}
@@ -1309,6 +1133,7 @@
                          menu={{MenuID: config.uuid, MenuName: config.tabName, MenuNo: config.tabNo}}
                          config={config}
                          tabs={this.state.tabviews}
                          menuformRef={this.menuformRef}
                          pasteContent={this.state.pasteContent}
                          usefulFields={this.props.permFuncField}
                          setSubConfig={this.setSubConfig}
@@ -1319,7 +1144,7 @@
                          menu={this.props.menu}
                          sysRoles={this.props.sysRoles}
                          pasteContent={this.state.pasteContent}
                          updatecolumn={this.updatecolumn}
                          updatecolumn={this.updateconfig}
                        />
                      </Col>
                    )
@@ -1341,35 +1166,6 @@
            </Card>
          </div>
        </DndProvider>
        {/* 设置全局配置及列表数据源 */}
        <Modal
          title={this.state.dict['model.edit']}
          visible={this.state.settingVisible}
          width={750}
          maskClosable={false}
          onCancel={() => { // 取消修改
            this.setState({
              settingVisible: false
            })
          }}
          footer={[
            <CreateInterface key="interface" dict={this.state.dict} ref="tableCreatInterface" trigger={this.tableCreatInterface}/>,
            <CreateFunc key="create" dict={this.state.dict} ref="tableCreatFunc" trigger={this.tableCreatFunc}/>,
            <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>,
            <Button key="confirm" type="primary" loading={this.state.sqlVerifing} onClick={this.settingSave}>{this.state.dict['model.confirm']}</Button>
          ]}
          destroyOnClose
        >
          <SettingForm
            dict={this.state.dict}
            tabId={this.state.config.uuid}
            inputSubmit={this.settingSave}
            data={this.state.config.setting}
            columns={this.state.config.columns}
            usefulFields={this.props.permFuncField}
            wrappedComponentRef={(inst) => this.settingRef = inst}
          />
        </Modal>
        <Modal
          bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
          closable={false}
src/templates/subtableconfig/index.scss
@@ -184,12 +184,12 @@
        top: 10px;
      }
    }
    .anticon-question-circle {
      color: #c49f47;
      position: relative;
      left: -15px;
      top: 5px;
    }
    // .anticon-question-circle {
    //   color: #c49f47;
    //   position: relative;
    //   left: -15px;
    //   top: 5px;
    // }
  }
  .setting {
    overflow-y: scroll;
src/templates/zshare/createinterface/index.jsx
@@ -119,11 +119,14 @@
      Ltextsearchparam: _search.join(' union all '),
      AppendWhere: config.setting.queryType === 'query' ? searchText.join(' AND ') : '',
      WhereType: config.setting.queryType === 'statistics' ? 'Statistics' : 'query',
      custom_script: config.setting.customScript || '',
      // default_sql: config.setting.default || 'true',
      OrderCol: config.setting.order
    }
    param.Ltextsearchparam = Utils.formatOptions(param.Ltextsearchparam)
    param.AppendWhere = Utils.formatOptions(param.AppendWhere)
    param.custom_script = Utils.formatOptions(param.custom_script)
    this.setState({
      type: 'out',
src/templates/zshare/formconfig.jsx
@@ -1,11 +1,346 @@
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import { formRule } from '@/utils/option.js'
const Formdict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
/**
 * @description 获取页面设置表单配置信息
 * @param {object} setting   // 菜单全局设置信息
 * @param {string} type      // 菜单类型
 */
export function getSettingForm (setting, usefulFields = [], MenuID, primaryKey, columns, type) {
  let str = '^(' + usefulFields.join('|') + ')'
  let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
  return [
    {
      type: 'text',
      key: 'tableName',
      label: '表名',
      initVal: setting.tableName || '',
      required: true,
      readonly: false,
      rules: [
        {
          max: formRule.input.max,
          message: formRule.input.message
        }
      ]
    },
    {
      type: 'select',
      key: 'tableType',
      label: '表格属性',
      initVal: setting.tableType,
      required: false,
      readonly: false,
      options: [
        { value: '', text: '不可选' },
        { value: 'radio', text: '单选' },
        { value: 'checkbox', text: '多选' }
      ]
    },
    {
      type: 'radio',
      key: 'interType',
      label: Formdict['header.form.intertype'],
      initVal: setting.interType || 'inner',
      required: false,
      readonly: false,
      options: [
        { value: 'inner', text: Formdict['header.form.interface.inner'] },
        { value: 'outer', text: Formdict['header.form.interface.outer'] }
      ]
    },
    {
      type: 'radio',
      key: 'sysInterface',
      label: Formdict['header.form.sysInterface'],
      initVal: setting.sysInterface || 'false',
      required: false,
      readonly: false,
      options: [
        { value: 'true', text: Formdict['header.form.true'] },
        { value: 'false', text: Formdict['header.form.false'] }
      ]
    },
    {
      type: 'text',
      key: 'interface',
      label: Formdict['header.form.interface'],
      initVal: setting.sysInterface === 'true' ? (window.GLOB.mainSystemApi || '') : (setting.interface || ''),
      required: true,
      readonly: setting.sysInterface === 'true',
      rules: [
        {
          max: formRule.input.max,
          message: formRule.input.message
        }
      ]
    },
    {
      type: 'text',
      key: 'outerFunc',
      label: Formdict['header.form.outerFunc'],
      initVal: setting.outerFunc || '',
      required: false,
      readonly: false,
      rules: [
        {
          pattern: formRule.func.pattern,
          message: formRule.func.message
        }, {
          max: formRule.func.max,
          message: formRule.func.maxMessage
        }
      ]
    },
    {
      type: 'text',
      key: 'innerFunc',
      label: Formdict['header.form.innerFunc'],
      initVal: setting.innerFunc || '',
      tooltip: '开头可用字符:' + usefulFields.join(', '),
      required: false,
      readonly: false,
      rules: [
        {
          pattern: _patten,
          message: formRule.func.innerMessage
        }, {
          max: formRule.func.max,
          message: formRule.func.maxMessage
        }
      ]
    },
    {
      type: 'datasource',
      key: 'dataresource',
      label: '数据源',
      initVal: setting.dataresource || '',
      tooltip: '使用系统函数时,需填写数据源。',
      help: '数据ID:' + MenuID,
      required: false,
      readonly: false,
      rules: [
        {
          pattern: _patten,
          message: formRule.func.innerMessage
        }, {
          max: formRule.func.max,
          message: formRule.func.maxMessage
        }
      ]
    },
    {
      type: 'select',
      key: 'primaryKey',
      label: '主键',
      initVal: primaryKey,
      required: false,
      readonly: false,
      options: columns
    },
    {
      type: 'text',
      key: 'order',
      label: '默认排序',
      initVal: setting.order || (primaryKey ? primaryKey + ' desc' : ''),
      placeholder: 'ID asc, UID desc',
      required: true,
      readonly: false,
      rules: [
        {
          max: formRule.input.max,
          message: formRule.input.message
        }
      ]
    },
    {
      type: 'radio',
      key: 'queryType',
      label: Formdict['header.form.queryType'],
      initVal: setting.queryType || 'query',
      tooltip: '查询时,搜索条件以where条件拼接进入sql,统计时,将数据源中以“@+搜索字段”的内容,以搜索条件中的值进行替换后,提交查询,注:查询类型仅在使用系统函数时有效。',
      required: false,
      readonly: false,
      options: [
        { value: 'query', text: Formdict['header.form.query'] },
        { value: 'statistics', text: Formdict['header.form.statistics'] }
      ]
    },
    {
      type: 'radio',
      key: 'actionfixed',
      label: '按钮固定',
      initVal: setting.actionfixed ? 'true' : 'false',
      required: false,
      readonly: false,
      forbid: type !== 'main',
      options: [
        { value: 'true', text: Formdict['header.form.true'] },
        { value: 'false', text: Formdict['header.form.false'] }
      ]
    },
    {
      type: 'radio',
      key: 'columnfixed',
      label: '表头固定',
      initVal: setting.columnfixed ? 'true' : 'false',
      required: false,
      readonly: false,
      forbid: type !== 'main',
      options: [
        { value: 'true', text: Formdict['header.form.true'] },
        { value: 'false', text: Formdict['header.form.false'] }
      ]
    },
    {
      type: 'radio',
      key: 'onload',
      label: '初始化',
      initVal: setting.onload || 'true',
      required: false,
      readonly: false,
      options: [
        { value: 'true', text: '加载数据' },
        { value: 'false', text: '不加载数据' }
      ]
    },
    {
      type: 'radio',
      key: 'laypage',
      label: '是否分页',
      initVal: setting.laypage || 'true',
      required: false,
      readonly: false,
      options: [
        { value: 'true', text: Formdict['header.form.true'] },
        { value: 'false', text: Formdict['header.form.false'] }
      ]
    },
    {
      type: 'radio',
      key: 'default',
      label: '默认sql',
      initVal: setting.default || 'true',
      required: false,
      readonly: false,
      options: [
        { value: 'true', text: '执行' },
        { value: 'false', text: '不执行' }
      ]
    },
  ]
}
/**
 * @description 获取主菜单基本信息表单配置信息
 * @param {object} menu    // 主表基本信息
 * @param {object} config  // 主表配置信息
 */
export function getMainMenuForm (menu, _config) {
  return [
    {
      type: 'select',
      key: 'fstMenuId',
      label: '一级菜单',
      initVal: menu.fstMenuId,
      required: true,
      readonly: false,
      options: menu.fstMenuList
    },
    {
      type: 'select',
      key: 'parentId',
      label: '二级菜单',
      initVal: menu.ParentID,
      required: true,
      readonly: false,
      options: menu.supMenuList
    },
    {
      type: 'text',
      key: 'MenuName',
      label: Formdict['header.menu.menuName'],
      initVal: menu.MenuName,
      required: true,
      readonly: false
    },
    {
      type: 'text',
      key: 'MenuNo',
      label: Formdict['header.menu.menuNo'],
      initVal: menu.MenuNo,
      required: true,
      readonly: false
    },
    {
      type: 'select',
      key: 'opentype',
      label: Formdict['header.menu.openType'],
      initVal: menu.PageParam.OpenType,
      required: true,
      options: [{
        MenuID: 'newtab',
        text: Formdict['header.form.tab']
      }, {
        MenuID: 'newpage',
        text: Formdict['header.form.newpage']
      }, {
        MenuID: 'currenttab',
        text: Formdict['header.form.currenttab']
      }]
    },
    {
      type: 'text',
      key: 'easyCode',
      label: Formdict['header.form.easyCode'],
      initVal: _config.easyCode,
      required: false,
      readonly: false
    }
  ]
}
/**
 * @description 获取子菜单基本信息表单配置信息
 * @param {object} config  // 子表配置信息
 */
export function getSubMenuForm (config) {
  return [
    {
      type: 'text',
      key: 'MenuName',
      label: Formdict['header.menu.viewName'],
      initVal: config.tabName,
      required: true,
      readonly: false
    },
    {
      type: 'text',
      key: 'MenuNo',
      label: Formdict['header.menu.menuNo'],
      initVal: config.tabNo,
      required: true,
      readonly: false
    },
    {
      type: 'text',
      key: 'Remark',
      label: Formdict['header.menu.Remark'],
      initVal: config.Remark,
      required: false,
      readonly: false
    }
  ]
}
/**
 * @description 获取搜索条件表单配置信息
 * @param {*} card
 * @param {object} card       // 搜索条件对象
 * @param {Array}  roleList   // 角色列表
 */
export function getSearchForm (card, roleList) {
  return [
@@ -634,7 +969,9 @@
/**
 * @description 获取显示列表单配置信息
 * @param {*} card
 * @param {object} card       // 搜索条件对象
 * @param {Array}  roleList   // 角色列表-黑名单
 * @param {Array}  menulist   // 菜单列表-用于字段透视
 */
export function getColumnForm (card, roleList = [], menulist = []) {
  return [
@@ -886,7 +1223,8 @@
/**
 * @description 获取图表视图外部配置表单
 * @param {*} card
 * @param {object} card       // 搜索条件对象
 * @param {Array}  roleList   // 角色列表-黑名单
 */
export function getChartViewForm (card, roleList = []) {
  let _charts = [{
@@ -972,7 +1310,9 @@
/**
 * @description 获取图表视图配置表单
 * @param {*} card
 * @param {object} card       // 搜索条件对象
 * @param {Array}  columns    // 显示列
 * @param {String} type       // 图表类型
 */
export function getChartOptionForm (card, columns, type) {
  let shapes = []
@@ -1175,8 +1515,12 @@
/**
 * @description 获取表单配置信息
 * @param {*} card
 * @param {*} inputfields
 * @param {*} card            // 表单对象
 * @param {*} inputfields     // 可关联表单
 * @param {*} linkableFields  // 可关联表单
 * @param {*} linksupFields   // 上级表单
 * @param {*} subtable        // 是否为子表表单
 * @param {*} roleList        // 角色列表-黑名单
 */
export function getModalForm (card, inputfields, linkableFields, linksupFields, subtable = false, roleList = []) {
  let _openType = []
src/templates/zshare/verifycard/index.jsx
@@ -444,6 +444,10 @@
            _fieldlen = _f.decimal ? _f.decimal : 0
          }
          if (_fieldlen > 2048) {
            _fieldlen = 'max'
          }
          let _type = `nvarchar(${_fieldlen})`
          if (_f.type.match(/date/ig)) {
@@ -468,12 +472,22 @@
          _usefulfields.push(_f.field)
          let _type = `nvarchar(${_f.fieldlength || 50})`
          let _fieldlen = _f.fieldlength || 50
          if (_f.type === 'picture' || _f.type === 'textarea') {
            _fieldlen = _f.fieldlength || 512
          }
          if (_fieldlen > 2048) {
            _fieldlen = 'max'
          }
          let _type = `nvarchar(${_fieldlen})`
          if (_f.type === 'number') {
            _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
          } else if (_f.type === 'picture' || _f.type === 'textarea') {
            _type = `nvarchar(${_f.fieldlength || 512})`
            _type = `nvarchar(${_fieldlen})`
          }
          if (_f.type === 'number') {
@@ -662,6 +676,10 @@
                _fieldlen = _f.decimal ? _f.decimal : 0
              }
              if (_fieldlen > 2048) {
                _fieldlen = 'max'
              }
              let _type = `nvarchar(${_fieldlen})`
              if (_f.type.match(/date/ig)) {
@@ -698,12 +716,22 @@
              _usefulfields.push(_f.field)
              let _type = `nvarchar(${_f.fieldlength || 50})`
              let _fieldlen = _f.fieldlength || 50
              if (_f.type === 'picture' || _f.type === 'textarea') {
                _fieldlen = _f.fieldlength || 512
              }
              if (_fieldlen > 2048) {
                _fieldlen = 'max'
              }
              let _type = `nvarchar(${_fieldlen})`
              if (_f.type === 'number') {
                _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
              } else if (_f.type === 'picture' || _f.type === 'textarea') {
                _type = `nvarchar(${_f.fieldlength || 512})`
                _type = `nvarchar(${_fieldlen})`
              }
              if (_f.type === 'number') {
@@ -828,12 +856,22 @@
          _usefulfields.push(_f.field)
          let _type = `nvarchar(${_f.fieldlength || 50})`
          let _fieldlen = _f.fieldlength || 50
          if (_f.type === 'picture' || _f.type === 'textarea') {
            _fieldlen = _f.fieldlength || 512
          }
          if (_fieldlen > 2048) {
            _fieldlen = 'max'
          }
          let _type = `nvarchar(${_fieldlen})`
          if (_f.type === 'number') {
            _type = `decimal(18,${_f.decimal ? _f.decimal : 0})`
          } else if (_f.type === 'picture' || _f.type === 'textarea') {
            _type = `nvarchar(${_f.fieldlength || 512})`
            _type = `nvarchar(${_fieldlen})`
          }
          if (_f.type === 'number') {
src/utils/utils.js
@@ -360,6 +360,95 @@
  }
  /**
   * @description 拼接搜索条件main
   * @param {Array}   searches     搜索条件
   * @return {String}  searchText  拼接结果
   */
  static getAllSearchOptions (searches) {
    if (!searches || searches.length === 0) return []
    let options = []
    let fieldmap = new Map()
    searches.forEach(search => {
      let item = {
        key: search.key,
        match: search.match,
        type: search.type,
        label: search.label,
        value: search.value,
        required: search.required
      }
      if (fieldmap.has(item.key)) {
        item.key = item.key + '1'
      }
      fieldmap.set(item.key, true)
      if (item.type === 'date') {
        if (['>=', '>'].includes(item.match)) {
          item.value = item.value ? item.value + ' 00:00:00.000' : '1990-01-01 00:00:00.000'
        } else if (['<=', '<'].includes(item.match)) {
          item.value = item.value ? moment(item.value, 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' : '2030-01-01 00:00:00.000'
        }
        options.push(item)
      } else if (item.type === 'datemonth') {
        let _startval = item.value ? moment(item.value, 'YYYY-MM').startOf('month').format('YYYY-MM-DD') + ' 00:00:00.000' : '1990-01-01 00:00:00.000'
        let _endval = item.value ? moment(item.value, 'YYYY-MM').endOf('month').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' : '2030-01-01 00:00:00.000'
        let copy = JSON.parse(JSON.stringify(item))
        copy.key = copy.key + '1'
        copy.value = _endval
        item.value = _startval
        options.push(item)
        options.push(copy)
      } else if (item.type === 'dateweek') {
        let _startval = item.value && item.value[0] ? moment(item.value[0], 'YYYY-MM-DD').format('YYYY-MM-DD') + ' 00:00:00.000' : '1990-01-01 00:00:00.000'
        let _endval = item.value && item.value[1] ? moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' : '2030-01-01 00:00:00.000'
        let copy = JSON.parse(JSON.stringify(item))
        copy.key = copy.key + '1'
        copy.value = _endval
        item.value = _startval
        options.push(item)
        options.push(copy)
      } else if (item.type === 'daterange') {
        let _startval = item.value && item.value[0] ? item.value[0] + ' 00:00:00.000' : '1990-01-01 00:00:00.000'
        let _endval = item.value && item.value[1] ? moment(item.value[1], 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD') + ' 00:00:00.000' : '2030-01-01 00:00:00.000'
        let copy = JSON.parse(JSON.stringify(item))
        copy.key = copy.key + '1'
        copy.value = _endval
        item.value = _startval
        options.push(item)
        options.push(copy)
      } else if (item.type === 'multiselect') {
        item.value = item.value ? item.value.join(',') : item.value
        options.push(item)
      } else if (item.type === 'text') {
        item.key.split(',').forEach(field => { // 综合搜索,所字段拼接
          let cell = JSON.parse(JSON.stringify(item))
          cell.key = field
          options.push(item)
        })
      } else {
        options.push(item)
      }
    })
    return options
  }
  /**
   * @description 拼接搜索条件datamanage
   * @param {Array}   searches     搜索条件
   * @return {String}  searchText  拼接结果