king
2020-11-02 880a41a2135d944169d94028f19344ca66b673a0
2020-11-02
18个文件已修改
510 ■■■■ 已修改文件
public/README.txt 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/options.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/index.jsx 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/index.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/normalbutton/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/actionList/printbutton/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/normalTable/index.jsx 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/topSearch/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editthdmenu/index.jsx 104 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/menuconfig/editthdmenu/menuform/index.jsx 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/columnform/index.jsx 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/formconfig.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/option.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/README.txt
@@ -1,9 +1,9 @@
-----options.json-------
appId         -- 云端生成的应用ID
appkey        -- 云端生成的应用密钥
mainSystemApi -- sso系统的接口路径,注:业务系统需要填写,且值为通用接口的完整路径
systemType    -- 判断业务系统为测试 (空) 或正式 (production) ,正式系统开发权限只含有系统升级等限定功能
lineColor     -- 登录页分割线颜色
webStorage    -- 前端存储,使用时填入websql
filter        -- 页面滤镜,值为'true'时,页面显示为黑白色
appId             -- 云端生成的应用ID
appkey            -- 云端生成的应用密钥
mainSystemApi     -- sso系统的接口路径,注:业务系统需要填写,且值为通用接口的完整路径
systemType        -- 判断业务系统为测试 (空) 或正式 (production) ,正式系统开发权限只含有系统升级等限定功能
externalDatabase  -- 外联库,不使用时默认为false
lineColor         -- 登录页分割线颜色
filter            -- 页面滤镜,值为'true'时,页面显示为黑白色
public/options.json
@@ -3,6 +3,7 @@
  "appkey": "20191106103859640976D6E924E464D029CF0",
  "mainSystemApi": "http://sso.mk9h.cn/cloud/webapi/dostars",
  "systemType": "",
  "externalDatabase": "false",
  "lineColor": "",
  "filter": "false"
}
src/components/header/index.jsx
@@ -510,8 +510,11 @@
  }
  changeSystem = (system) => {
    let _param = window.btoa('ud=' + sessionStorage.getItem('UserID') + '&ld=' + sessionStorage.getItem('LoginUID') + '&un=' + sessionStorage.getItem('User_Name'))
    window.location.href = system.LinkUrl1 + '#/ssologin/' + _param
    window.location.href = system.LinkUrl1 + '#/ssologin/' + window.btoa(window.encodeURIComponent(JSON.stringify({
      UserID: sessionStorage.getItem('UserID'),
      LoginUID: sessionStorage.getItem('LoginUID'),
      User_Name: sessionStorage.getItem('User_Name')
    })))
  }
  dropdownMenuChange = (visible) => {
@@ -740,11 +743,11 @@
        {this.props.editLevel === 'HS' ? <Button className="level4-close" type="primary" onClick={this.exitManage}>退出</Button> : null}
        {/* 进入编辑按钮 */}
        {this.props.editState && !this.props.editLevel ? <Icon onClick={this.enterEdit} className="edit-check" type="edit" /> : null}
        {this.props.editState && !this.props.editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ?
        {/* {this.props.editState && !this.props.editLevel && options.sysType === 'local' && window.GLOB.systemType !== 'production' ?
          <a href="#/mobmanage" target="_blank" className="mobile" type="edit"> 应用管理 <Icon type="arrow-right" /></a> : null
        }
        } */}
        {/* window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'home', MenuId: 'home_page_id', MenuName: '首页' }))) */}
        {this.props.editState && !this.props.editLevel && window.GLOB.systemType !== 'production' ?
        {this.props.editState && !this.props.editLevel && window.GLOB.systemType !== 'production' && this.props.memberLevel >= 20 ?
          <a className="home-edit" href={`#/menudesign/JTdCJTIyTWVudVR5cGUlMjIlM0ElMjJob21lJTIyJTJDJTIyTWVudUlkJTIyJTNBJTIyaG9tZV9wYWdlX2lkJTIyJTJDJTIyTWVudU5hbWUlMjIlM0ElMjIlRTklQTYlOTYlRTklQTElQjUlMjIlN0Q=`} target="_blank" rel="noopener noreferrer">
            首页 <Icon type="arrow-right" />
          </a> : null
@@ -834,6 +837,7 @@
    editLevel: state.editLevel,
    permAction: state.permAction,
    sysRoles: state.sysRoles,
    memberLevel: state.memberLevel,
    permFuncField: state.permFuncField
  }
}
src/components/sidemenu/index.jsx
@@ -1,7 +1,7 @@
import React, {Component} from 'react'
import { withRouter } from 'react-router-dom'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { connect } from 'react-redux'
import { is, fromJS } from 'immutable'
import { Menu, Icon, notification } from 'antd'
@@ -70,9 +70,16 @@
      let SubMenuId = sessionStorage.getItem('SubMenu')   // 是否为打开新页面
      let ThirdMenuId = sessionStorage.getItem('ThirdMenu') // 是否为打开新页面
      let msg = sessionStorage.getItem('UserID') + '&ld=' + sessionStorage.getItem('LoginUID') + '&un=' + sessionStorage.getItem('User_Name') + '&mlogo=' + window.GLOB.mainlogo + '&mstyle=' + window.GLOB.style
      let submenuId = '' // 展开二级菜单ID
      let tabId = '' // 打开的tab页id
      let msg = {
        UserID: sessionStorage.getItem('UserID'),
        LoginUID: sessionStorage.getItem('LoginUID'),
        User_Name: sessionStorage.getItem('User_Name'),
        mainlogo: window.GLOB.mainlogo,
        mstyle: window.GLOB.style,
        MainMenu: menu.MenuID
      }
      
      if (SubMenuId && ThirdMenuId) {
        submenuId = SubMenuId
@@ -110,11 +117,9 @@
        if (item.FunMenu) {
          _smenu.children = item.FunMenu.map(child => {
            let _tmenu = {
              ParentId: item.ParentID
              ParentId: item.ParentID,
              OpenType: 'newtab'
            }
            // 打开新页面链接
            _tmenu.src = '#/paramsmain/' + window.btoa('mm=' + menu.MenuID + '&sm=' + _smenu.MenuID + '&tm=' + child.MenuID + '&ud=' + msg)
            if (child.LinkUrl === 'CommonTable') {
              _tmenu.type = 'CommonTable'
@@ -133,8 +138,33 @@
                _tmenu.PageParam = {OpenType: 'newtab'}
              }
              _tmenu.type = _tmenu.PageParam.Template || _tmenu.type
              _tmenu.OpenType = _tmenu.PageParam.OpenType
            }
            if (_tmenu.type === 'NewPage') {
              _tmenu.src = _tmenu.PageParam.url
              if (this.props.memberLevel < 20) { // 会员等级大于等于20时,有编辑权限
                _tmenu.forbidden = true
              }
              if (_tmenu.src.indexOf('paramsmain/') > -1) {
                try {
                  let _url = _tmenu.src.split('paramsmain/')[0] + 'paramsmain/'
                  let _param = JSON.parse(window.decodeURIComponent(window.atob(_tmenu.src.split('paramsmain/')[1])))
                  _param.UserID = sessionStorage.getItem('UserID')
                  _param.LoginUID = sessionStorage.getItem('LoginUID')
                  _param.User_Name = sessionStorage.getItem('User_Name')
                  _tmenu.src = _url + window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
                } catch {
                  console.warn('菜单参数解析错误!')
                }
              }
            } else {
              _tmenu.LinkUrl = child.LinkUrl
              // 打开新页面链接
              _tmenu.src = '#/paramsmain/' + window.btoa(window.encodeURIComponent(JSON.stringify({
                ...msg,
                SubMenu: _smenu.MenuID,
                ThirdMenu: child.MenuID
              })))
            }
            _tmenu.id = child.MenuID
@@ -142,7 +172,6 @@
            _tmenu.MenuNo = child.MenuNo
            _tmenu.MenuName = child.MenuName
            _tmenu.text = child.MenuName
            _tmenu.OpenType = _tmenu.PageParam ? _tmenu.PageParam.OpenType : 'newtab'
            return _tmenu
          })
        }
@@ -159,6 +188,20 @@
        let _menu = menulist.filter(menu => menu.MenuID === submenuId)[0]
        let opentab = _menu && _menu.children.filter(tab => tab.MenuID === tabId)[0]
        if (opentab) {
          if (sessionStorage.getItem('MenuParam')) {
            try {
              let thParam = JSON.parse(sessionStorage.getItem('MenuParam'))
              if (tabId === thParam.ThirdMenu) {
                delete thParam.ThirdMenu
                opentab.param = thParam
              }
            } catch {
              console.warn('菜单参数解析错误!')
            }
            sessionStorage.removeItem('MenuParam')
          }
          opentab.selected = true
          let home = this.props.tabviews[0]
          home.selected = false
@@ -207,6 +250,9 @@
    let menu = JSON.parse(e.target.dataset.item)
    if (menu.OpenType === 'newpage') {
      e.preventDefault()
      window.open(menu.src)
    } else if (menu.OpenType === 'NewPage') {
      e.preventDefault()
      window.open(menu.src)
    } else if (menu.OpenType === 'blank') {
@@ -360,6 +406,7 @@
    collapse: state.collapse,
    isiframe: state.isiframe,
    mainMenu: state.selectedMainMenu,
    memberLevel: state.memberLevel,
    editState: state.editState,
    editLevel: state.editLevel
  }
src/index.js
@@ -59,6 +59,12 @@
    GLOB.lineColor = config.lineColor || ''
    GLOB.filter = config.filter || ''
    if (config.externalDatabase !== false && config.externalDatabase !== 'false' && config.externalDatabase !== undefined) {
      GLOB.externalDatabase = config.externalDatabase || ''
    } else {
      GLOB.externalDatabase = null
    }
    // 只有业务系统才可以设置为正式系统
    if (options.sysType === 'local' && (config.systemType === 'official' || config.systemType === 'production')) {
      GLOB.systemType = 'production'
src/menu/menushell/card.jsx
@@ -29,7 +29,6 @@
      } else if (draggedId && floor === card.floor) {
        if (draggedId !== id) {
          const { index: overIndex } = findCard(id)
          console.log(item)
          moveCard(draggedId, overIndex)
        }
      }
src/router/index.js
@@ -34,38 +34,61 @@
    }
    if (item.name === 'pmain') { // 新窗口打开,取url参数放入sessionStorage
      let _param = window.atob(props.match.params.param)
      let p = {}
      _param.split('&').forEach(cell => {
        let _cell = cell.split('=')
        p[_cell[0]] = _cell[1]
      })
      !sessionStorage.getItem('UserID') && sessionStorage.setItem('UserID', p.ud)
      !sessionStorage.getItem('LoginUID') && sessionStorage.setItem('LoginUID', p.ld)
      !sessionStorage.getItem('User_Name') && sessionStorage.setItem('User_Name', p.un)
      try {
        let _param = JSON.parse(window.decodeURIComponent(window.atob(props.match.params.param)))
      if (p.mlogo) {
        window.GLOB.mainlogo = p.mlogo
        if (typeof(_param) === 'object') {
          if (_param.UserID && !sessionStorage.getItem('UserID')) {
            sessionStorage.setItem('UserID', _param.UserID)
          }
          if (_param.LoginUID && !sessionStorage.getItem('LoginUID')) {
            sessionStorage.setItem('LoginUID', _param.LoginUID)
          }
          if (_param.User_Name && !sessionStorage.getItem('User_Name')) {
            sessionStorage.setItem('User_Name', _param.User_Name)
          }
          if (_param.mainlogo) {
            window.GLOB.mainlogo = _param.mainlogo
          }
          if (_param.mstyle && options.styles[_param.mstyle]) {
            document.getElementById('root').className = options.styles[_param.mstyle]
          }
          if (_param.MainMenu) {
            sessionStorage.setItem('MainMenu', _param.MainMenu)
          }
          if (_param.SubMenu) {
            sessionStorage.setItem('SubMenu', _param.SubMenu)
          }
          if (_param.ThirdMenu) {
            sessionStorage.setItem('ThirdMenu', _param.ThirdMenu)
          }
          if (_param.param) {
            _param.param.ThirdMenu = _param.ThirdMenu
            sessionStorage.setItem('MenuParam', JSON.stringify(_param.param))
          }
        }
      } catch {
        console.warn('菜单参数解析错误!')
      }
      if (options.styles[p.mstyle]) {
        document.getElementById('root').className = options.styles[p.mstyle]
      }
      sessionStorage.setItem('MainMenu', p.mm)
      sessionStorage.setItem('SubMenu', p.sm)
      sessionStorage.setItem('ThirdMenu', p.tm)
      return (<item.component {...props}/>)
    } else if (item.name === 'ssologin') {
      let _param = window.atob(props.match.params.param)
      let p = {}
      _param.split('&').forEach(cell => {
        let _cell = cell.split('=')
        p[_cell[0]] = _cell[1]
      })
      sessionStorage.setItem('UserID', p.ud)
      sessionStorage.setItem('LoginUID', p.ld)
      sessionStorage.setItem('User_Name', p.un)
      try {
        let _param = JSON.parse(window.decodeURIComponent(window.atob(props.match.params.param)))
        if (typeof(_param) === 'object') {
          if (_param.UserID) {
            sessionStorage.setItem('UserID', _param.UserID)
          }
          if (_param.LoginUID) {
            sessionStorage.setItem('LoginUID', _param.LoginUID)
          }
          if (_param.User_Name) {
            sessionStorage.setItem('User_Name', _param.User_Name)
          }
        }
      } catch {
        console.warn('菜单参数解析错误!')
      }
      return (<Redirect to={{ pathname: '/main'}}/>)
    }
src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -954,6 +954,10 @@
                  } else {
                    _option.sql = _option.sql.replace(/@\$|\$@/ig, '')
                  }
                  // 外联数据库替换
                  if (window.GLOB.externalDatabase !== null) {
                    _option.sql = _option.sql.replace(/@db@/ig, `[${window.GLOB.externalDatabase}]..`)
                  }
                  cell.data_sql = Utils.formatOptions(_option.sql)
                  cell.base_sql = window.btoa(window.encodeURIComponent(_option.sql))
src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -1065,6 +1065,10 @@
                  } else {
                    _option.sql = _option.sql.replace(/@\$|\$@/ig, '')
                  }
                  // 外联数据库替换
                  if (window.GLOB.externalDatabase !== null) {
                    _option.sql = _option.sql.replace(/@db@/ig, `[${window.GLOB.externalDatabase}]..`)
                  }
                  cell.data_sql = Utils.formatOptions(_option.sql)
                  cell.base_sql = window.btoa(window.encodeURIComponent(_option.sql))
src/tabviews/zshare/normalTable/index.jsx
@@ -203,55 +203,82 @@
  // 字段透视
  triggerLink = (item, record) => {
    const { tabviews, MenuID } = this.props
    let tabmenu = item.linkThdMenu
    let iframes = ['Main/Index', 'bda/rdt', 'Home/rdt']
    const { tabviews, MenuID, setting } = this.props
    if (tabmenu.LinkUrl === 'CommonTable') {
      tabmenu.type = 'CommonTable'
    } else if (tabmenu.LinkUrl === 'DataManage') {
      tabmenu.type = 'DataManage'
    } else if (tabmenu.LinkUrl && iframes.includes(tabmenu.LinkUrl.split('?')[0])) {
      tabmenu.type = 'iframe'
    }
    if (tabmenu.type !== 'iframe') {
      try {
        tabmenu.PageParam = JSON.parse(tabmenu.PageParam)
      } catch (e) {
        tabmenu.PageParam = {}
    if (item.linkThdMenu) {
      let tabmenu = item.linkThdMenu
      let iframes = ['Main/Index', 'bda/rdt', 'Home/rdt']
      if (tabmenu.LinkUrl === 'CommonTable') {
        tabmenu.type = 'CommonTable'
      } else if (tabmenu.LinkUrl === 'DataManage') {
        tabmenu.type = 'DataManage'
      } else if (tabmenu.LinkUrl && iframes.includes(tabmenu.LinkUrl.split('?')[0])) {
        tabmenu.type = 'iframe'
      }
      tabmenu.type = tabmenu.PageParam.Template || tabmenu.type
    }
      if (tabmenu.type !== 'iframe') {
        try {
          tabmenu.PageParam = JSON.parse(tabmenu.PageParam)
        } catch (e) {
          tabmenu.PageParam = {}
        }
        tabmenu.type = tabmenu.PageParam.Template || tabmenu.type
      }
      tabmenu.param = {
        searchkey: item.field,
        searchval: record[item.field] || '',
        BID: record[setting.primaryKey]
      }
      tabmenu.selected = true
      let index = 0
      let isexit = false
      let tabs = tabviews.map((tab, i) => {
        tab.selected = false
        if (tab.MenuID === MenuID) {
          index = i
        } else if (tab.MenuID === tabmenu.MenuID) {
          tab.param = tabmenu.param
          tab.selected = true
          isexit = true
        }
        return tab
      })
      if (!isexit) {
        tabs.splice(index + 1, 0, tabmenu)
      }
      this.props.modifyTabview(tabs)
    } else {
      let src = item.linkurl
    tabmenu.param = {
      searchkey: item.field,
      searchval: record[item.field] || ''
    }
    tabmenu.selected = true
    let index = 0
    let isexit = false
    let tabs = tabviews.map((tab, i) => {
      tab.selected = false
      if (tab.MenuID === MenuID) {
        index = i
      } else if (tab.MenuID === tabmenu.MenuID) {
        tab.param = tabmenu.param
        tab.selected = true
        isexit = true
      if (item.linkurl.indexOf('paramsmain/') > -1) {
        try {
          let _url = item.linkurl.split('paramsmain/')[0] + 'paramsmain/'
          let _param = JSON.parse(window.decodeURIComponent(window.atob(item.linkurl.split('paramsmain/')[1])))
          let dataparam = {
            searchkey: item.field,
            searchval: record[item.field] || '',
            BID: record[setting.primaryKey]
          }
          _param.UserID = sessionStorage.getItem('UserID')
          _param.LoginUID = sessionStorage.getItem('LoginUID')
          _param.User_Name = sessionStorage.getItem('User_Name')
          _param.param = dataparam
          src = _url + window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
        } catch {
          console.warn('菜单参数解析错误!')
        }
      }
      return tab
    })
    if (!isexit) {
      tabs.splice(index + 1, 0, tabmenu)
      window.open(src)
    }
    this.props.modifyTabview(tabs)
  }
  getMark = (record, marks) => {
@@ -368,7 +395,7 @@
        content = md5(content)
      }
      if (item.linkThdMenu) {
      if (item.linkThdMenu || item.linkurl) {
        if (item.rowspan === 'true') {
          return {
            children: (
@@ -465,7 +492,7 @@
        content = md5(content)
      }
      if (item.linkThdMenu) {
      if (item.linkThdMenu || item.linkurl) {
        return (
          <div className={className}>
            <div className="baseboard link-menu" onDoubleClick={() => this.triggerLink(item, record)}></div>
src/tabviews/zshare/topSearch/index.jsx
@@ -82,6 +82,10 @@
              data_sql: Utils.formatOptions(_option.sql)
            })
          } else { // 合并请求,区分本地及系统
            // 外联数据库替换
            if (window.GLOB.externalDatabase !== null) {
              _option.sql = _option.sql.replace(/@db@/ig, `[${window.GLOB.externalDatabase}]..`)
            }
            if (item.database === 'sso') {
              mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql))}' as LText`)
            } else {
src/templates/menuconfig/editthdmenu/index.jsx
@@ -1,7 +1,9 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { connect } from 'react-redux'
import { DndProvider } from 'react-dnd'
import { withRouter } from 'react-router-dom'
import HTML5Backend from 'react-dnd-html5-backend'
import { notification, Modal, Button, Spin, Icon, Col, Card, Tabs, Row, Input } from 'antd'
import moment from 'moment'
@@ -81,6 +83,15 @@
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  /**
   * @description 菜单顺序改变时,保存中间状态
   */
  handlePreviewList = (List) => {
@@ -134,8 +145,9 @@
      delete _menu.src
      delete _menu.text
      if (_menu.PageParam && _menu.PageParam.Template === 'RolePermission') { // 单页面修改
      if (_menu.PageParam && (_menu.PageParam.Template === 'RolePermission' || _menu.PageParam.Template === 'NewPage')) { // 单页面修改
        _menu.Template = _menu.PageParam.Template
        _menu.url = _menu.PageParam.url
        if (!this.state.fstMenuId) {
          notification.warning({
@@ -441,13 +453,32 @@
      editMenu.fstMenuList = this.state.fstMenuList
    }
    if (useType === 'sys' && (template.type === 'RolePermission' || template.type === 'CustomPage')) { // 独立页面
    if (useType === 'sys' && (template.type === 'RolePermission' || template.type === 'NewPage')) { // 独立页面
      let _menu = {
        ...editMenu,
        MenuID: Utils.getuuid(),
        MenuName: template.title,
        Template: template.type,
        ParentId: this.props.supMenu.MenuID,
        menuSort: (this.props.menulist.length + 1) * 10,
        isSystem: true
      }
      this.setState({
        handleMVisible: true,
        sysMenu: _menu
      })
      return
    } else if (template.type === 'CustomPage') {
      let _menu = {
        ...editMenu,
        MenuID: Utils.getuuid(),
        MenuName: template.title,
        Template: template.type,
        ParentId: this.props.supMenu.MenuID,
        OriginMenuId: template.uuid || '',
        menuSort: (this.props.menulist.length + 1) * 10,
        isSystem: true
      }
      this.setState({
@@ -519,7 +550,7 @@
      this.setState({
        loading: false,
        tabview: template.type === 'CustomPage' ? '' : template.type,
        tabview: template.type,
        editMenu: {
          ...editMenu,
          type: template.type,
@@ -529,26 +560,12 @@
        }
      })
      if (template.type === 'CustomPage') { // 使用自定义的已有菜单
        // let _menu = {
        //   ...editMenu,
        //   MenuID: Utils.getuuid(),
        //   MenuName: template.title,
        //   Template: template.type,
        //   ParentID: this.props.supMenu.MenuID,
        // }
        // this.setState({
        //   handleMVisible: true,
        //   sysMenu: _menu
        // })
        return
      }
      document.getElementById('root').style.overflowY = 'hidden'
    })
  }
  getUsedTemplate = () => {
    const { memberLevel } = this.props
    let { sysTemplates } = this.state
    const illust = { // 模板图片,用于已使用模板
      CommonTable: mainsubtable,
@@ -562,8 +579,12 @@
      let hasRolePermission = false
      res.UserTemp.forEach(temp => {
        if (temp.Template === 'RolePermission') {
        if (temp.Template === 'NewPage') {
          return
        } else if (temp.Template === 'RolePermission') {
          hasRolePermission = true
          return
        } else if (temp.Template === 'CustomPage' && memberLevel < 20) {
          return
        }
@@ -575,15 +596,15 @@
        })
      })
      if (!hasRolePermission) {
        sysTemplates = sysTemplates.map(temp => {
          if (temp.type === 'RolePermission') {
            temp.hidden = false
          }
      sysTemplates = sysTemplates.map(temp => {
        if (temp.type === 'RolePermission' && !hasRolePermission) {
          temp.hidden = false
        } else if (temp.type === 'CustomPage' && memberLevel < 20) {
          temp.hidden = true
        }
          return temp
        })
      }
        return temp
      })
      this.setState({
        usedTemplates: _templates,
@@ -629,6 +650,17 @@
    }
    this.menuFormRef.handleConfirm().then(res => {
      let PageParam = {
        Template: sysMenu.Template,
        OpenType: 'newtab'
      }
      if (sysMenu.OriginMenuId && sysMenu.Template === 'CustomPage') {
        PageParam.originMenuId = sysMenu.OriginMenuId
      } else if (sysMenu.Template === 'NewPage') {
        PageParam.OpenType = 'NewPage'
        PageParam.url = res.url
      }
      let param = {
        func: 'sPC_TrdMenu_AddUpt',
@@ -639,10 +671,14 @@
        MenuNo: res.MenuNo,
        Template: sysMenu.Template,
        MenuName: res.MenuName,
        PageParam: JSON.stringify({Template: sysMenu.Template, OpenType: 'newtab'}),
        PageParam: JSON.stringify(PageParam),
        LongParam: '',
        LText: '',
        LTexttb: ''
      }
      if (sysMenu.menuSort) { // 菜单新建时设置排序
        param.Sort = sysMenu.menuSort
      }
      param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -947,4 +983,14 @@
  }
}
export default EditMenu
const mapStateToProps = (state) => {
  return {
    memberLevel: state.memberLevel
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(EditMenu))
src/templates/menuconfig/editthdmenu/menuform/index.jsx
@@ -136,6 +136,19 @@
              })(<Input placeholder="" autoComplete="off" />)}
            </Form.Item>
          </Col>
          {menu.Template === 'NewPage' ? <Col span={24}>
            <Form.Item label={'链接地址'}>
              {getFieldDecorator('url', {
                initialValue: menu.url || '',
                rules: [
                  {
                    required: true,
                    message: this.props.dict['form.required.input'] + '页面地址!'
                  }
                ]
              })(<Input placeholder="" autoComplete="off" />)}
            </Form.Item>
          </Col> : null}
        </Row>
      </Form>
    )
src/templates/sharecomponent/columncomponent/columnform/index.jsx
@@ -8,8 +8,8 @@
import './index.scss'
const columnTypeOptions = {
  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'linkmenu', 'rowspan'],
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'linkmenu', 'sum'],
  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'perspective', 'rowspan'],
  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum'],
  link: ['label', 'field', 'type', 'nameField', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist'],
  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'fieldlength', 'blacklist'],
  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'maxHeight']
@@ -26,6 +26,7 @@
  state = {
    formlist: null,
    type: '',
    menulist: null
  }
@@ -34,8 +35,16 @@
    let _menulist = this.props.formlist.filter(form => form.key === 'linkmenu')[0] || ''
    let _options = JSON.parse(JSON.stringify(columnTypeOptions[card.type]))
    if (card.type === 'text' || card.type === 'number') {
      if (card.perspective !== 'linkurl') {
        _options.push('linkmenu')
      } else {
        _options.push('linkurl')
      }
    }
    this.setState({
      type: card.type,
      menulist: _menulist.options || [],
      formlist: this.props.formlist.map(item => {
        item.hidden = !_options.includes(item.key)
@@ -62,8 +71,18 @@
  }
  typeChange = (key, value) => {
    const { card } = this.props
    if (key === 'type') {
      let _options = JSON.parse(JSON.stringify(columnTypeOptions[value]))
      if (card.type === 'text' || card.type === 'number') {
        if (card.perspective !== 'linkurl') {
          _options.push('linkmenu')
        } else {
          _options.push('linkurl')
        }
      }
      let fieldlength = 50
      if (value !== 'text') {
@@ -71,6 +90,7 @@
      }
      this.setState({
        type: value,
        formlist: this.props.formlist.map(item => {
          item.hidden = !_options.includes(item.key)
@@ -84,6 +104,27 @@
    } else if (key === 'format' && value === 'percent') {
      this.props.form.setFieldsValue({postfix: '%'})
    }
  }
  changeRadio = (key, value) => {
    if (key === 'perspective') {
      let _options = JSON.parse(JSON.stringify(columnTypeOptions[this.state.type]))
      if (value !== 'linkurl') {
        _options.push('linkmenu')
      } else {
        _options.push('linkurl')
      }
      this.setState({
        formlist: this.props.formlist.map(item => {
          item.hidden = !_options.includes(item.key)
          return item
        })
      })
    }
  }
  handleSubmit = (e) => {
@@ -110,7 +151,7 @@
            max: formRule.field.max,
            message: formRule.field.maxMessage
          }]
        } else {
        } else if (item.key !== 'linkurl') {
          rules = [{
            max: formRule.input.max,
            message: formRule.input.message
@@ -206,7 +247,7 @@
                  }
                ]
              })(
                <Radio.Group>
                <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}>
                  {
                    item.options.map(option => {
                      return (
@@ -318,7 +359,6 @@
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          values.id = this.props.card.id
          values.uuid = this.props.card.uuid
          values.marks = this.props.card.marks || ''
          
src/templates/sharecomponent/columncomponent/index.jsx
@@ -232,7 +232,6 @@
        let rowspanLabel = ''  // 已存在的行合并字段
        _columnlist = _columnlist.filter(item => !item.origin || item.uuid === res.uuid) // 去除初始列
        _columnlist = _columnlist.map(item => {
          if (item.uuid !== res.uuid && res.field && item.field) {
            if (item.field === res.field) {
src/templates/zshare/formconfig.jsx
@@ -1260,14 +1260,34 @@
      }]
    },
    {
      type: 'radio',
      key: 'perspective',
      label: '字段透视',
      initVal: card.perspective || 'linkmenu',
      options: [{
        value: 'linkmenu',
        text: '菜单'
      }, {
        value: 'linkurl',
        text: '链接'
      }]
    },
    {
      type: 'cascader',
      key: 'linkmenu',
      label: Formdict['model.form.linkmenu'],
      label: Formdict['model.menu'],
      initVal: card.linkmenu || [],
      required: false,
      options: menulist
    },
    {
      type: 'text',
      key: 'linkurl',
      label: '链接地址',
      initVal: card.linkurl || '',
      required: false
    },
    {
      type: 'multiselect',
      key: 'blacklist',
      label: Formdict['header.form.blacklist'],
src/utils/option.js
@@ -91,6 +91,13 @@
    url: rolemanage,
    isSystem: true,
    hidden: true
  },
  {
    title: '新页面',
    type: 'NewPage',
    url: customImg,
    baseconfig: '',
    isSystem: true
  }
]
src/utils/utils.js
@@ -163,6 +163,10 @@
    })
    // 替换%符(数据库中解析后sql报错)
    value = value.replace(/%/ig, ' mpercent ')
    // 外联数据库替换
    if (window.GLOB.externalDatabase !== null) {
      value = value.replace(/@db@/ig, `[${window.GLOB.externalDatabase}]..`)
    }
    // encode编码(中文字符超出base64加密范围)
    value = window.btoa(window.encodeURIComponent(value))
    // 插入字符
@@ -230,6 +234,10 @@
    // 1、替换%符(数据库中解析后sql报错)
    value = value.replace(/%/ig, ' mpercent ')
    // 外联数据库替换
    if (window.GLOB.externalDatabase !== null) {
      value = value.replace(/@db@/ig, `[${window.GLOB.externalDatabase}]..`)
    }
    let encodesql = (val) => {
      if (!val) return ''